:root { --shelfd-mylist-css-patch: "v374-footer-desktop-mobile-layout-fix"; }

/* ============================================================================
   v10.409: Rating Guide overlay — slides down from the top of the
   screen when the user taps the Shelfd logo (or wordmark) in the header.
   Read-only reference page; back button + share button in the top bar;
   editorial dark styling, charcoal black background.
   ============================================================================ */
.rating-guide-overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
  transform: translate3d(0, -100%, 0);
  transition: transform 360ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
  /* Belt-and-suspenders: visually hide ancestors aren't always reliable
     with iOS WebView animations, so keep aria-hidden + pointer-events
     in sync. */
}
.rating-guide-overlay.is-open {
  pointer-events: auto;
  transform: translate3d(0, 0, 0);
}
.rating-guide-surface {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  /* Charcoal black — matches the existing app shell + media-review /
     episode-page overlays. */
  background: #0e0e0e;
  color: #f5f2ff;
  font-family: 'Sohne', 'DM Sans', sans-serif;
}
.rating-guide-topbar {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 40px;
  align-items: center;
  gap: 8px;
  /* Capacitor iOS safe-area top + a little extra so the back button
     clears the Dynamic Island. */
  padding:
    max(env(safe-area-inset-top, 0px), 12px)
    14px
    10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  flex: 0 0 auto;
}
.rating-guide-back,
.rating-guide-share {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: #f5f2ff;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 150ms ease, transform 120ms ease;
}
.rating-guide-back:active,
.rating-guide-share:active {
  transform: scale(0.92);
  opacity: 0.78;
}
.rating-guide-share {
  justify-self: end;
}
.rating-guide-title {
  text-align: center;
  font: 800 18px/1 'Sohne', 'DM Sans', sans-serif;
  letter-spacing: -0.02em;
  color: #ffffff;
}
.rating-guide-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 26px 20px max(28px, calc(env(safe-area-inset-bottom, 0px) + 18px));
}
.rating-guide-intro {
  margin: 0 0 18px;
  color: rgba(245, 242, 255, 0.82);
  font: 500 14px/1.55 'Sohne', 'DM Sans', sans-serif;
  letter-spacing: 0;
}
.rating-guide-intro--secondary {
  margin-bottom: 30px;
  color: rgba(245, 242, 255, 0.62);
  font-style: italic;
  font-weight: 400;
}
.rating-guide-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.rating-guide-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 0 18px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.rating-guide-row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}
.rating-guide-row-head {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  row-gap: 4px;
}
.rating-guide-num {
  color: #ffffff;
  font: 800 18px/1 'Sohne', 'DM Sans', sans-serif;
  letter-spacing: -0.02em;
  min-width: 22px;
}
.rating-guide-stars {
  color: #F5B301;
  font-size: 14px;
  line-height: 1;
  letter-spacing: 1px;
  /* Keep wrap behavior natural — glyphs wrap to a second line on
     narrow phones, which is fine. */
  word-break: break-word;
}
/* v10.539: half-star glyph shown at reduced opacity so it reads as
   "halfway filled" compared to the full gold stars beside it. */
.rating-guide-half-star {
  color: #F5B301;
  opacity: 0.35;
}
.rating-guide-row-body {
  color: rgba(245, 242, 255, 0.82);
  font: 500 13.5px/1.55 'Sohne', 'DM Sans', sans-serif;
  letter-spacing: 0;
}
.rating-guide-row-body strong {
  color: #ffffff;
  font-weight: 800;
  letter-spacing: -0.01em;
}
/* Lock page scrolling while the guide is open. */
body.rating-guide-open {
  overflow: hidden !important;
  overscroll-behavior: none !important;
}
  /* Section toggle */
  .section-toggle {
    display: flex; margin-top: 20px; background: rgba(255,255,255,0.035); border-radius: 999px;
    padding: 4px; width: fit-content; margin-left: auto; margin-right: auto;
    border: 1px solid rgba(139,92,246,0.2); gap: 4px; flex-wrap: wrap; justify-content: center;
  }
  .section-btn {
    padding: 8px 16px; border-radius: 999px; border: none; cursor: pointer;
    font-size: 14px; font-weight: 700; font-family: 'Sohne', 'DM Sans', sans-serif;
    background: transparent; color: #9990b3; transition: color 0.2s, background-color 0.2s;
    letter-spacing: 0.5px; display: inline-flex; align-items: center; white-space: nowrap;
  }
  .section-btn.active {
    background: rgba(139, 92, 246, 0.15); color: #fff;
  }

  /* My Lists edit controls */
  .mylist-edit-controls {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
    margin-top: 10px;
    min-height: 34px;
  }
  .mylist-edit-row {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
  }
  .mylist-edit-btn {
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid rgba(167,139,250,0.36);
    background: rgba(124,58,237,0.12);
    color: #c4b5fd;
    font-size: 10px;
    font-weight: 800;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    cursor: pointer;
    letter-spacing: 0.2px;
  }
  .mylist-edit-btn.confirming {
    background: linear-gradient(135deg, #7c3aed, #9333ea);
    color: #fff;
    border-color: rgba(255,255,255,0.16);
  }
  .mylist-toggle-bubbles {
    display: inline-flex;
    gap: 8px;
    align-items: center;
  }
  .mylist-toggle-bubble {
    min-width: 34px;
    height: 34px;
    padding: 0 10px;
    border-radius: 999px;
    border: 1px solid rgba(167,139,250,0.34);
    background: rgba(255,255,255,0.06);
    color: #e8e3f3;
    font-size: 12px;
    font-weight: 800;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    transition: opacity 0.18s, transform 0.18s, background 0.18s, border-color 0.18s;
  }
  .mylist-toggle-bubble:hover { transform: translateY(-1px); border-color: #a78bfa; }
  .mylist-toggle-bubble.off {
    opacity: 0.44;
    background: rgba(0,0,0,0.18);
    border-color: rgba(122,111,153,0.26);
    text-decoration: line-through;
  }
  body.light-mode .mylist-edit-btn {
    background: rgba(124,58,237,0.08);
    color: #5b21b6;
    border-color: rgba(124,58,237,0.24);
  }
  body.light-mode .mylist-edit-btn.confirming {
    color: #fff;
  }
  body.light-mode .mylist-toggle-bubble {
    background: rgba(124,58,237,0.06);
    color: #12082e;
    border-color: rgba(124,58,237,0.18);
  }

  /* Toolbar */
  .toolbar {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 20px; flex-wrap: wrap; gap: 12px;
  }
  .tabs { display: flex; gap: 4px; }
  .tab-btn {
    padding: 7px 16px; border-radius: 4px; border: none; cursor: pointer;
    font-size: 21px; font-weight: 400; font-family: 'Sohne', 'DM Sans', sans-serif;
    background: transparent; color: #ffffff; transition: color 0.15s, background-color 0.15s;
    letter-spacing: 0.2px;
  }
  .tab-btn.active { background: rgba(255,255,255,0.06); font-weight: 600; }
  .tab-btn.active[data-tab="watching"] { color: #a78bfa; }
  .tab-btn.active[data-tab="planned"] { color: #fbbf24; }
  .tab-btn.active[data-tab="watched"] { color: #67e8f9; }
  .tab-btn.active[data-tab="paused"] { color: #f97316; }
  .tab-btn.active[data-tab="dropped"] { color: #ef4444; }
  .tab-btn.active[data-tab="live"] { color: #22c55e; }
  .tab-btn.active[data-tab="competitive"] { color: #818cf8; }
  .status-pill.live-active { border-color: #16a34a; background: #052e16; color: #22c55e; }
  .status-pill.competitive-active { border-color: #4f46e5; background: #1e1b4b; color: #818cf8; }
  .tab-count {
    margin-left: 6px; font-size: 10px; padding: 1px 6px; border-radius: 4px;
  }
  .tab-btn.active .tab-count { background: rgba(255,255,255,0.08); }
  .toolbar-right { display: flex; gap: 8px; }
  .games-playing-subfilter {
    width: 100%;
    margin: -2px 0 18px;
    display: flex;
    justify-content: center;
  }
  /* v10.232: REBUILT as a single source of truth (the redundant
     `#mylist-view` override that re-imposed an opaque dark gradient was
     deleted, not layered over). Glassy finish: a 6% white fill that lets
     the page show through, lifted by a strong backdrop blur. Cleaner +
     sharper — the heavy purple radial glow and big drop shadow are gone,
     replaced by a crisp 1px hairline border, a tighter 16px radius, and a
     single inset top-highlight for the glass edge. */
  .games-playing-subfilter-card {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    width: min(100%, 420px);
    /* v11.262: whole bar condensed to 24px total height = 18px button + 2px
       top/bottom padding + 1px top/bottom border. */
    padding: 2px 5px;
    border-radius: 12px;
    border: 1px solid rgba(255,255,255,0.10);
    background: rgba(255,255,255,0.06);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.08);
    backdrop-filter: blur(22px) saturate(140%);
    -webkit-backdrop-filter: blur(22px) saturate(140%);
  }
  /* v10.233: the sliding active "fill". It's a single absolutely-positioned
     element inside the card; JS sets its width/height to the active tab's
     box and moves it with `transform: translate(x, y)`. Because only the
     transform animates, the slide stays on the GPU compositor — buttery and
     ProMotion-ready (120Hz). The active button itself is now transparent;
     THIS provides the lavender fill + ring. */
  .games-playing-toggle-indicator {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    z-index: 0;
    border-radius: 12px;
    background: rgba(167,139,250,0.16);
    box-shadow: inset 0 0 0 1px rgba(196,181,253,0.30);
    opacity: 0;
    pointer-events: none;
    will-change: transform;
    transform: translate(0, 0);
    transition: transform 480ms cubic-bezier(0.32, 0.72, 0, 1);
  }
  .games-playing-toggle {
    position: relative;
    z-index: 1;
    flex: 1 1 0;
    min-width: 0;
    /* v11.267: toggle button height = 36px. */
    min-height: 36px;
    border: 0;
    border-radius: 15px;
    padding: 0 12px;
    background: transparent;
    color: rgba(255,255,255,0.62);
    font-family: 'Sohne', 'DM Sans', sans-serif;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    transition: color 0.22s ease;
    -webkit-tap-highlight-color: transparent;
  }
  .games-playing-toggle span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    letter-spacing: -0.01em;
  }
  .games-playing-toggle small {
    display: none;
    min-width: 18px;
    height: 18px;
    margin-left: 7px;
    border-radius: 999px;
    align-items: center;
    justify-content: center;
    padding: 0 5px;
    background: rgba(255,255,255,0.12);
    color: rgba(255,255,255,0.88);
    font-size: 9px;
    font-weight: 700;
    line-height: 1;
  }
  .games-playing-toggle.active small { display: inline-flex; }
  /* v10.233: the active fill moved to .games-playing-toggle-indicator (it
     slides between tabs). The active BUTTON now only brightens its text —
     no background of its own, or it would double up on the indicator and
     kill the slide illusion. */
  .games-playing-toggle.active {
    color: #fff;
  }
  .games-playing-toggle:not(.active):hover {
    color: rgba(255,255,255,0.82);
    background: rgba(255,255,255,0.06);
  }
  body.light-mode .games-playing-subfilter-card {
    background: rgba(255,255,255,0.86);
    border-color: rgba(124,58,237,0.16);
    box-shadow: 0 10px 28px rgba(31,17,64,0.08);
  }
  body.light-mode .games-playing-toggle { color: #6b5f86; }
  body.light-mode .games-playing-toggle.active { color: #fff; }

  /* Inputs & buttons */
  input[type="text"], input[type="number"], input[type="url"] {
    padding: 18px 26px; background: #0a081a; border: 1px solid #3d3466;
    border-radius: 4px; color: #e8e3f3; font-size: 14px; outline: none;
    font-family: 'Sohne', 'DM Sans', sans-serif;
  }
  input:focus { border-color: #8b5cf6; }
  .search-input { padding: 7px 12px; font-size: 13px; width: 160px; }
  .btn-primary {
    padding: 8px 20px; background: linear-gradient(135deg, #7c3aed, #9333ea);
    border: none; border-radius: 4px; color: #fff; font-size: 13px;
    font-weight: 600; cursor: pointer; font-family: 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0.3px;
  }
  .btn-secondary {
    padding: 8px 20px; background: #1a1430; border: 1px solid #3d3466;
    border-radius: 4px; color: #b8afd1; font-size: 13px; cursor: pointer;
    font-family: 'Sohne', 'DM Sans', sans-serif;
  }
  .btn-sm { padding: 4px 10px; font-size: 11px; }

  /* Sort dropdown */
  .sort-btn {
    display: flex; align-items: center; gap: 5px;
    padding: 7px 10px; white-space: nowrap;
  }
  .sort-btn-icon { font-size: 16px; line-height: 1; color: #9990b3; transition: color 0.15s; }
  .sort-btn-icon.sort-active { color: #a78bfa; }
  .sort-btn-label { font-size: 11px; color: #a78bfa; max-width: 100px; overflow: hidden; text-overflow: ellipsis; }

  /* v10.508: pencil-icon badge on the OWN-shelf profile picture. Signals
     to the user that their avatar is editable. The badge is rendered
     inside the `.mylist-own-profile-shortcut` button, which is only
     emitted when `viewingUser` is falsy (see 15-profile-settings.js line
     264-271) — so this badge automatically never appears on someone
     else's shelf. The parent button has `overflow: hidden` in
     11-patch-notes-friends-refinements.css:697 (to clip the rectangular
     <img> to the circular border-radius). We override that to `visible`
     specifically WHEN the pencil child is present so the badge can sit
     at the visible edge of the circle; the <img> itself stays circular
     via its `border-radius: inherit` rule. */
  #mylist-view .mylist-own-profile-shortcut:has(.mylist-own-profile-edit-pencil) {
    overflow: visible;
  }
  .mylist-own-profile-edit-pencil {
    position: absolute;
    right: -2px;
    /* v11.205: moved badge bottom-right → top-right per request, so the
       pencil sits at the top corner of the avatar to signal it's editable. */
    top: -2px;
    width: 22px;
    height: 22px;
    border-radius: 999px;
    background: #c4b5fd;
    color: #0E0E0E;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(0,0,0,0.45), 0 0 0 2px #0E0E0E;
    /* v11.206: 3px backdrop blur behind the circular badge so it stays
       legible over light/white profile pictures (the badge was blending in
       on white avatars). Paired with the existing dark 2px ring for crisp
       separation. */
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
    pointer-events: none;
    z-index: 2;
  }
  .mylist-own-profile-edit-pencil svg {
    width: 12px;
    height: 12px;
    color: #0E0E0E;
  }
  /* v11.240: Liquid Glass treatment (canonical recipe — see SHELFD_CONTEXT.md).
     Was a solid #000 panel; now the frosted liquid-glass material: layered
     translucent gradient fill + heavy backdrop blur + inset top highlight. */
  .sort-dropdown-menu {
    position: absolute; z-index: 9999;
    background:
      linear-gradient(155deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0.04) 38%, rgba(255,255,255,0.02) 100%),
      linear-gradient(180deg, rgba(40,34,58,0.46), rgba(20,18,28,0.40));
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 22px;
    padding: 6px;
    min-width: 185px;
    max-height: min(520px, calc(100dvh - 120px));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    box-shadow:
      0 24px 64px rgba(0,0,0,0.58),
      inset 0 1px 0 rgba(255,255,255,0.30),
      inset 0 0 0 0.5px rgba(255,255,255,0.10),
      inset 0 -18px 40px rgba(255,255,255,0.04);
    -webkit-backdrop-filter: blur(40px) saturate(180%) brightness(1.08);
    backdrop-filter: blur(40px) saturate(180%) brightness(1.08);
    display: flex; flex-direction: column; gap: 1px;
    /* v11.241: smooth scale+opacity open/close, matching the cogwheel popover.
       Desktop is right-anchored, so it grows from its top-right corner. */
    transform-origin: 100% 0%;
    animation: sortDropdownIn 0.24s cubic-bezier(0.34,1.4,0.5,1) both;
  }
  .sort-dropdown-menu.closing {
    animation: sortDropdownOut 0.15s ease-in both;
  }
  @keyframes sortDropdownIn {
    from { opacity: 0; transform: scale(0.82); }
    to   { opacity: 1; transform: scale(1); }
  }
  @keyframes sortDropdownOut {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0; transform: scale(0.82); }
  }
  @media (max-width: 600px) {
    /* v11.243: was force-centered (position:fixed; top/left:50%), which made
       the menu open right over the sort/filter button row. Now it stays
       ANCHORED to the button — the JS sets top/right from the button rect, so
       it drops below the button and clears it. Keep the right-anchored grow. */
    .sort-dropdown-menu {
      width: min(78vw, 300px); min-width: 210px;
      max-height: min(76dvh, 620px);
    }
  }

  .sort-direction-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 12px;
    padding: 10px 12px;
    margin-bottom: 4px;
    border: 1px solid rgba(167,139,250,0.24);
    border-radius: 12px;
    background: rgba(124,58,237,0.16);
    color: #f8f4ff;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    font-size: 12px;
    font-weight: 850;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .sort-direction-toggle strong {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 999px;
    background: rgba(255,255,255,0.08);
    color: #c4b5fd;
    font-size: 15px;
    line-height: 1;
  }
  .sort-direction-toggle:active { transform: scale(0.985); }

  .sort-dropdown-item {
    display: flex; align-items: center; width: 100%; text-align: left;
    padding: 10px 14px; border: none; border-radius: 10px;
    background: transparent; color: #ffffff; font-size: 14px;
    font-family: 'Sohne', 'DM Sans', sans-serif; cursor: pointer; letter-spacing: -0.01em;
    transition: background 0.12s;
    -webkit-tap-highlight-color: transparent;
  }
  .sort-dropdown-item:hover { background: rgba(255,255,255,0.07); }
  .sort-dropdown-item.active {
    background: rgba(124,58,237,0.18);
    color: #c4b5fd;
    font-weight: 600;
  }
  /* v10.259: music sort menu uses a directional arrow instead of the dot
     indicator. The arrow is rendered as inline content next to the active
     option's label. Suppress the dot only when inside the music variant. */
  .sort-dropdown-menu--music .sort-dropdown-item {
    justify-content: space-between;
  }
  .sort-dropdown-menu--music .sort-dropdown-item.active::after { display: none !important; }
  .sort-dropdown-arrow {
    color: #c4b5fd;
    font-size: 16px;
    line-height: 1;
    margin-left: 8px;
    font-variant-numeric: tabular-nums;
  }
  /* v11.244: Pro-locked filter rows — visible but gated. Label dims, a lock
     glyph sits at the right edge. The first <span> holds the label so the lock
     pushes to the far right via space-between. */
  .sort-dropdown-item-locked {
    justify-content: space-between;
    color: rgba(255,255,255,0.42) !important;
    cursor: default;
  }
  .sort-dropdown-item-locked:hover { background: rgba(255,255,255,0.04); }
  .sort-dropdown-item-locked.active::after { display: none !important; }
  .sort-dropdown-lock {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 8px;
    color: rgba(196,181,253,0.85);
    flex: 0 0 auto;
  }
  .sort-dropdown-lock svg { width: 13px; height: 13px; display: block; }
  .sort-dropdown-item.active::after {
    content: '';
    display: block;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: #7c3aed;
    margin-left: auto;
    flex-shrink: 0;
  }

  /* Drag-and-drop custom order */
  .card-draggable { cursor: grab; }
  .card-draggable:active { cursor: grabbing; }
  .card.drag-over { outline: 2px solid #7c3aed; outline-offset: 2px; opacity: 0.8; }

  /* Cards */
  .grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
  @media (min-width: 700px) { .grid { grid-template-columns: 1fr 1fr; } }
  @media (max-width: 600px) {
    .tabs { flex-wrap: wrap; gap: 2px; }
    .tab-btn { padding: 6px 10px; font-size: 12px; }
    .tab-count { margin-left: 4px; font-size: 9px; padding: 1px 4px; }
    .toolbar { flex-direction: row; align-items: center; }
    .toolbar-right { width: auto; display: flex; gap: 8px; align-items: center; }
    .games-playing-subfilter { justify-content: stretch; margin: 0 0 14px; }
    /* v11.263: THIS mobile override (max-width:600px) was re-imposing 5px card
       padding + 38px button height on phones — overriding the v11.262 condense
       so it "looked unchanged". Matched to the 24px-total spec. */
    .games-playing-subfilter-card { width: 100%; gap: 6px; padding: 2px 5px; }
    .games-playing-toggle { flex: 1; justify-content: center; min-height: 36px; padding: 0 10px; font-size: 11px; }
    .search-input { width: 100px; flex: 0; }
    #add-btn { flex-grow: 1; min-width: 80px; }
    .section-toggle { width: 100%; }
    .section-btn { flex: 1; font-size: 13px; padding: 8px 10px; text-align: center; }
    .header-top { flex-direction: column; align-items: flex-start; gap: 8px; }
    .stats { align-self: flex-start; }
    .status-pills { gap: 4px; }
    .status-pill { font-size: 10px; padding: 3px 8px; }
    .container { padding: 0 12px; }
    .community-grid { grid-template-columns: 1fr; }
    .viewing-banner { flex-direction: column; gap: 8px; align-items: flex-start; }
    .main-nav-btn { padding: 14px 20px; font-size: 13px; }
    .edit-profile-btn { padding: 8px 12px; font-size: 12px; }
    .header-top { align-items: stretch; }
    .header-actions {
      width: 100%;
      align-items: flex-start;
      justify-content: space-between;
    }
    .user-area {
      margin-top: -12px;
      margin-left: auto;
      align-self: flex-start;
      gap: 7px;
    }
    .user-avatar {
      width: 33px;
      height: 33px;
    }
    .stat-label { font-size: 8px; }
  }
  .card {
    background: #060510; border-radius: 6px; overflow: hidden;
    border: 1px solid #3d3466; transition: border-color 0.2s, box-shadow 0.2s;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06);
    /* v443/v445: opt out of scroll anchoring AND isolate paint so the
       title card's box doesn't shimmer/shake while the ep-list height
       animates inside it. `contain: paint` prevents the card's repaint
       work from forcing a sibling/parent repaint, eliminating the visible
       1-px sub-pixel shimmer that was the residual "card shake". */
    overflow-anchor: none;
    contain: paint;
  }
  .card:hover { border-color: #3d3466; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06), 0 2px 12px rgba(0,0,0,0.5); }
  #mylist-view .card[data-mylist-review-card] { cursor: pointer; }
  #mylist-view .card[data-mylist-review-card] button,
  #mylist-view .card[data-mylist-review-card] a,
  #mylist-view .card[data-mylist-review-card] input,
  #mylist-view .card[data-mylist-review-card] textarea,
  #mylist-view .card[data-mylist-review-card] select,
  #mylist-view .card[data-mylist-review-card] .card-cover { cursor: auto; }
  .card-header { display: flex; gap: 14px; padding: 14px; }
  .card-cover {
    width: 100px; aspect-ratio: 1400 / 2100; border-radius: 3.3px; overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0; align-self: flex-start; font-size: 28; background-size: cover; background-position: center;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06);
  }
  #mylist-view .card-cover { border-radius: 3.3px; }
  .card-cover.no-img { background: linear-gradient(135deg, #2a1f5e 0%, #2d1b4e 100%); }
  /* v10.236: album art is always square. Lock the cover element to a 1:1
     aspect ratio when the card is a music section item so it visually reads
     as an album, not a portrait poster. The base .card-cover sets a 1400×2100
     (2:3) portrait ratio for movies/TV/games — this rule overrides it. */
  .card-cover.card-cover-music {
    aspect-ratio: 1 / 1 !important;
    background-position: center center !important;
  }
  /* v10.237 / v10.241: music my-list cards are visually shorter — collapse
     the internal padding + unused slot heights so the card hugs the square
     art. Movies/TV/games keep their taller layout. v10.241 bumps the cover
     to 100×100 and removes the status-pill selector + tabs toolbar so the
     section reads like a single "Albums" surface. */
  #mylist-view .card[data-library-section="music"] .card-header {
    padding: 10px 12px !important;
  }
  #mylist-view .card[data-library-section="music"] { min-height: 0 !important; }
  #mylist-view .card[data-library-section="music"] .card-action-row {
    min-height: 0 !important;
    padding-top: 6px !important;
    padding-bottom: 6px !important;
  }
  /* v10.241 / v10.243: 120×120 px cover on the my-lists music card.
     v10.393: bumped DOWN 18px (120 -> 102).
     v10.410: bumped BACK UP 18px (102 -> 120) per spec. Action row's
     `left` value in the absolute-positioning rule below is recalculated
     to match the new cover width. */
  #mylist-view .card[data-library-section="music"] .card-cover.card-cover-music {
    width: 120px !important;
  }
  /* v10.393 / v10.408 / v10.410: music section action row is HOISTED UP
     into the card-info column, aligned with the BOTTOM of the album
     cover. Implementation:
       - Card is `position: relative`.
       - Action row is `position: absolute`, anchored at:
           bottom: 10px  (= card-header bottom-padding, so the row's
                          bottom edge sits exactly at the cover's
                          bottom y-position)
           left:   137px (v10.410: 12 padding + 120 cover + 14 gap = 146
                          (card-info's left edge), minus 9px to cancel
                          the rating-bubble chip's internal padding-left
                          so the bubble's ★ glyph lands at x=146 — i.e.
                          flush left with the title text. Without that
                          -9px offset, the chip border sat at card-info
                          left but the visible ★ glyph appeared 9px
                          indented from the title.)
           right:  12px  (= card-header padding-right)
       - Width auto + min-height 0 + zero padding/margin so nothing
         from the legacy bottom-row layout interferes. */
  #mylist-view .card[data-library-section="music"] {
    position: relative;
  }
  #mylist-view .card[data-library-section="music"] .card-action-row {
    position: absolute !important;
    bottom: 10px !important;
    left: 137px !important;
    right: 12px !important;
    top: auto !important;
    width: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    min-height: 0 !important;
    background: transparent !important;
  }
  /* v10.413 / v10.414: TV SHOWS section gets the same action-row hoist
     as music (v10.408 / v10.410). v10.414 corrects the left position —
     was 119px (which pulled the bubble's BORDER 9px to the LEFT of the
     title text to put the chip's ★ glyph at the title's x). Per user
     feedback that read as the bubble being "too far left." New rule
     puts the bubble BORDER flush with card-info's left edge so the
     gold pill outline visually aligns with the title text. The ★ glyph
     itself ends up 9px inside the bubble — that's fine, the user wants
     the bubble box outline to match the meta-column edge.
       - `.card-header { padding: 14px; gap: 14px; }` defaults
       - `.card-cover { width: 100px; aspect-ratio: 1400/2100; }`
         => 100px wide × 150px tall (2:3 portrait)
       - Card-info left edge: 14 padding + 100 cover + 14 gap = 128px
       - left: 128px (bubble border aligned with title text)
       - bottom: 14px (card-header bottom padding) places the row's
         bottom edge at 178 – 14 = 164px = poster's bottom edge. */
  #mylist-view .card[data-library-section="shows"] {
    position: relative;
  }
  #mylist-view .card[data-library-section="shows"] .card-action-row {
    position: absolute !important;
    bottom: 14px !important;
    left: 128px !important;
    right: 14px !important;
    top: auto !important;
    width: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    min-height: 0 !important;
    background: transparent !important;
  }
  /* v10.442: mobile-cover math fix — on screens ≤ 700px the
     `05-messages-early-polish.css` rule bumps `.card-cover` width to
     120px AND `.card-header` gap to 13px, so the meta-column edge
     shifts from `14 + 100 + 14 = 128` to `14 + 120 + 13 = 147`. The
     desktop `left: 128px` above pulls the entire action row ~19px
     left of the meta column on mobile, which was visible as the
     watchlist priority widget sitting too far left of the title
     text on TV shows + planned. Same fix that was applied to games
     in v10.427 — extend to TV shows here so the rating bubble (on
     watching/watched/paused) and the priority widget (on planned)
     both line up with the metadata column on phones. */
  @media (max-width: 700px) {
    #mylist-view .card[data-library-section="shows"] .card-action-row {
      left: 147px !important;
    }
  }
  /* v10.438: MOVIES gets the SAME action-row hoist as TV Shows so the
     Watched movie cards display the rating bubble + Comments + plus
     button cluster aligned with the cover's bottom-left, identical
     to shows-watching. Cover dimensions match shows (100×150 portrait
     on desktop, 120×180 on mobile via the 05-messages-early-polish.css
     override), so the same `bottom: 14px / left: 128px / right: 14px`
     values land the row at the correct anchor without a separate
     mobile media query.
     Movies-planned (watchlist) cards also pick this up — they have an
     action row too (Comments + priority widget). The new positioning
     hoists their action row up onto the cover-bottom line as well,
     which keeps the watchlist + watched surfaces visually consistent. */
  #mylist-view .card[data-library-section="movies"] {
    position: relative;
  }
  #mylist-view .card[data-library-section="movies"] .card-action-row {
    position: absolute !important;
    bottom: 14px !important;
    left: 128px !important;
    right: 14px !important;
    top: auto !important;
    width: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    min-height: 0 !important;
    background: transparent !important;
  }
  /* v10.442: same mobile-cover math fix as TV shows above — at
     ≤ 700px the meta-column edge shifts to 147px, so the action
     row needs to follow. Keeps the watched-state rating bubble
     and the watchlist priority widget aligned with the title
     text on phones. */
  @media (max-width: 700px) {
    #mylist-view .card[data-library-section="movies"] .card-action-row {
      left: 147px !important;
    }
  }
  /* v10.426: GAMES section gets the SAME action-row hoist as TV Shows
     for every status that uses the rating bubble — Playing (single),
     Playing (live), Playing (competitive), and Played. Scoped to
     `.card-uses-rating-bubble` so it ONLY fires on the four statuses
     that use the bubble (filtered in `useRatingBubble`) — wishlist +
     Backloggd cards keep their existing layout (Backloggd never gets
     the action row markup at all, see the `!isGameBackloggdCard` JS
     gate).
     v10.427: split into desktop + mobile media-query branches because
     the card cover changes width across breakpoints. Desktop base
     (.card-cover width:100, .card-header padding:14, gap:14) puts the
     meta-column edge at 14 + 100 + 14 = 128. Mobile override in
     05-messages-early-polish.css (max-width:700) bumps the cover to
     120 and the gap to 13, shifting the meta-column edge to
     14 + 120 + 13 = 147. Without this split the bubble's border sat
     ~19px LEFT of the title text on mobile — visibly under the
     cover's right edge rather than flush with the title. Both branches
     anchor the action row's bottom at card-header padding-bottom so
     the row lines up with the cover's bottom edge. */
  #mylist-view .card[data-library-section="games"].card-uses-rating-bubble {
    position: relative;
  }
  #mylist-view .card[data-library-section="games"].card-uses-rating-bubble .card-action-row {
    position: absolute !important;
    bottom: 14px !important;
    left: 128px !important;
    right: 14px !important;
    top: auto !important;
    width: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    min-height: 0 !important;
    background: transparent !important;
    display: flex !important;
  }
  @media (max-width: 700px) {
    #mylist-view .card[data-library-section="games"].card-uses-rating-bubble .card-action-row {
      left: 147px !important;
    }
  }

  /* v10.429: GAMES — universal cover aspect with 12px corners. The
     base `.card-cover` rule sets `aspect-ratio: 1400/2100` (a 2:3
     portrait poster meant for movies/TV). Game covers get their own
     ratio + softer "platform tile" rounding.
     v10.431: aspect bumped 5:4 (landscape) → 5:6.38 (portrait) per
     spec. This matches the native Steam/IGDB box-art ratio so the
     cover frames the title art the way the publisher intended. */
  #mylist-view .card[data-library-section="games"] .card-cover {
    aspect-ratio: 5 / 6.38 !important;
    border-radius: 12px !important;
  }

  /* v10.429: GAMES action-row anchored to the COVER's bottom edge,
     not the card's bottom. Technique: anchor the row's TOP at
     `cover-bottom-Y` from card top, then `transform: translateY(-100%)`
     lifts the row up by its own rendered height so its BOTTOM edge
     lands at that Y. This is robust to variable row heights — no
     fixed-height assumption.
     v10.431: recomputed for the new 5:6.38 portrait aspect.
     Desktop cover: 100 × (100 × 6.38/5) = 100 × 127.6 → cover-
     bottom-Y = 14 (card-header padding-top) + 127.6 ≈ 142. Mobile
     cover: 120 × (120 × 6.38/5) = 120 × 153.12 → cover-bottom-Y =
     14 + 153.12 ≈ 167. Rounded to whole pixels because subpixel
     `top` values get smeared by sub-pixel anti-aliasing on iOS. */
  #mylist-view .card[data-library-section="games"].card-uses-rating-bubble .card-action-row {
    top: 142px !important;
    bottom: auto !important;
    transform: translateY(-100%) !important;
  }
  @media (max-width: 700px) {
    #mylist-view .card[data-library-section="games"].card-uses-rating-bubble .card-action-row {
      top: 167px !important;
    }
  }

  /* v10.429: FULL-PAGE game profile cover (`.mylist-game-profile-cover`)
     — used on the dedicated MyList → game profile route (opened from
     competitive title cards via `openMyListGameProfilePage`). The
     existing rules across this file set `aspect-ratio: 3 / 4`
     (portrait) and `border-radius: 8px–10px`. Override for visual
     consistency with the title cards. `!important` on every
     property because the existing rules use it too — without it
     the cascade ties at multiple specificities and source order
     would decide.
     v10.431: aspect updated to 5:6.38 (native Steam/IGDB box-art
     ratio) per spec. */
  .mylist-game-profile-cover {
    aspect-ratio: 5 / 6.38 !important;
    border-radius: 12px !important;
  }

  /* v10.429: Discover-style game media profile poster
     (`.game-media-profile-overlay .discover-media-poster`) — the
     route opened when a game is tapped from outside MyList. Was
     2:3 portrait + 8px radius.
     v10.431: aspect updated to 5:6.38 to match the title-card
     cover and the MyList profile cover. */
  .game-media-profile-overlay .discover-media-poster {
    aspect-ratio: 5 / 6.38 !important;
    border-radius: 12px !important;
  }

  /* v10.430: ANIME — mirror the TV SHOWS layout exactly across the
     three statuses the user listed (watching / watched / paused).
     Every shows-specific style above gets a parallel rule keyed on
     `data-library-section="anime"` or `body.mylist-section-anime`
     so anime cards render identically to shows cards.
     Companion JS change (`shouldShiftTvShowRatingLayout` extended
     to include anime) drives the `.tv-show-progress-rating-shift-card`
     class + inline-next-episode slot for watching/paused; the rules
     below add the same action-row hoist, text-only status pill,
     status hue palette, popped-out option chrome, and tray strip
     that v10.413–v10.425 introduced for the shows surface. */
  #mylist-view .card[data-library-section="anime"] {
    position: relative;
  }
  #mylist-view .card[data-library-section="anime"] .card-action-row {
    position: absolute !important;
    bottom: 14px !important;
    left: 128px !important;
    right: 14px !important;
    top: auto !important;
    width: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    min-height: 0 !important;
    background: transparent !important;
  }
  /* v10.442: same mobile-cover math fix as TV shows + movies — at
     ≤ 700px the meta-column edge shifts to 147px. Without this,
     the anime priority widget on planned + the rating bubble on
     watching/watched/paused sit ~19px left of where the title
     text starts. */
  @media (max-width: 700px) {
    #mylist-view .card[data-library-section="anime"] .card-action-row {
      left: 147px !important;
    }
  }

  /* v10.445: zero the padding-left on bubble-using shows/anime/movies
     action rows. Root cause: the older rule
     `#mylist-view .card.card-uses-rating-bubble .card-action-row {
        padding-left: 12px !important; }`
     (line ~1281, declared LATER in this file with !important and the
     same (1, 3, 0) specificity as the section-only rules above) was
     winning the source-order tiebreak and pushing the bubble + every
     other action-row child 12px right of the `left: 128px / 147px`
     anchor. Adding `.card-uses-rating-bubble` to the selector below
     bumps the specificity to (1, 4, 0) so it wins regardless of
     source order. Targets watching/watched/paused (shows, anime),
     watched (movies) — the four statuses that get the bubble class.
     Planned/wishlist cards never get the bubble class so the v10.405
     rule never applies to them; their action-row padding stays 0
     from the section-only rule above.
     v10.453: there's ANOTHER padding-left override in
     17-auth-flow-setup.css (v10.380) that uses TWO IDs in its
     selector (`#mylist-view #cards-grid .card.tv-show-progress-rating-shift-card .card-action-row`)
     — specificity (2, 3, 0). My v10.445 rule at (1, 4, 0) was
     losing the ID-count comparison to that rule, so for any card
     that gets the `.tv-show-progress-rating-shift-card` class
     (shows watching/paused + anime watching/paused via v10.430)
     the bubble was still being shifted 14px right. Fix: split
     into two rule blocks. The first (1, 4, 0) still handles
     watched cards. The second adds `#cards-grid` for (2, 4, 0)
     to beat the v10.380 rule on shift-layout cards. */
  #mylist-view .card[data-library-section="shows"].card-uses-rating-bubble .card-action-row,
  #mylist-view .card[data-library-section="anime"].card-uses-rating-bubble .card-action-row,
  #mylist-view .card[data-library-section="movies"].card-uses-rating-bubble .card-action-row {
    padding-left: 0 !important;
  }
  #mylist-view #cards-grid .card[data-library-section="shows"].card-uses-rating-bubble .card-action-row,
  #mylist-view #cards-grid .card[data-library-section="anime"].card-uses-rating-bubble .card-action-row,
  #mylist-view #cards-grid .card[data-library-section="movies"].card-uses-rating-bubble .card-action-row {
    padding-left: 0 !important;
  }

  /* Text-only status pill — drops the border/background chrome so
     the label sits flush in the meta column. */
  /* v11.142: re-scoped off the cold-load-fragile body.mylist-section-anime
     class onto the card's own data-library-section attribute (always in the
     DOM at first paint) so the text-only chrome doesn't flash the bordered
     pill before switchSection()/syncMyListBodySectionClass() runs. Mirrors
     the v11.137 authoritative fix in 07. */
  #mylist-view .card[data-library-section="anime"] .status-pill,
  #mylist-view .card[data-library-section="anime"] .game-status-current-pill,
  #mylist-view .card[data-library-section="anime"] .game-status-options .status-pill {
    border: 0 !important;
    background: transparent !important;
    background-image: none !important;
    padding: 0 6px 0 0 !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    box-shadow: none !important;
  }
  /* Pull the status-pill wrap tight against the line above. */
  #mylist-view .card[data-library-section="anime"] .status-pills,
  #mylist-view .card[data-library-section="anime"] .status-pills-selector-wrap {
    margin-top: 0 !important;
  }
  /* Per-status hue palette mirrors shows. */
  #mylist-view .card[data-library-section="anime"] .status-pill.watching-active {
    color: #a78bfa !important; /* lavender — Watching */
  }
  #mylist-view .card[data-library-section="anime"] .status-pill.watched-active {
    color: #67e8f9 !important; /* cyan — Watched */
  }
  #mylist-view .card[data-library-section="anime"] .status-pill.planned-active {
    color: #fbbf24 !important; /* amber — Planned */
  }
  #mylist-view .card[data-library-section="anime"] .status-pill.paused-active {
    color: #f97316 !important; /* orange — Paused */
  }
  /* Unselected pop-out options stay muted so the active one stands out. */
  body.mylist-section-anime #mylist-view .game-status-options .status-pill:not(.watching-active):not(.watched-active):not(.planned-active):not(.paused-active) {
    color: rgba(216, 208, 233, 0.55) !important;
  }
  /* Restore PILL CHROME on the popped-out alternatives (matches the
     v10.423 fix for music + shows). Without this the alternatives
     fuse visually into a single text block. */
  body.mylist-section-anime #mylist-view .game-status-selector .game-status-options .status-pill {
    border: 1px solid rgba(216, 208, 233, 0.22) !important;
    background: rgba(255, 255, 255, 0.04) !important;
    border-radius: 999px !important;
    padding: 4px 10px !important;
  }
  body.mylist-section-anime #mylist-view .game-status-selector .game-status-options .status-pill:hover {
    background: rgba(255, 255, 255, 0.08) !important;
    border-color: rgba(216, 208, 233, 0.34) !important;
  }
  body.mylist-section-anime #mylist-view .game-status-selector.expanded .game-status-options {
    gap: 6px;
  }
  /* Strip the gray container tray off the popped-out options (matches
     the v10.425 fix). Uses `.game-status-selector` parent in the chain
     so specificity beats the 06-profile.css true-dark-mode rule. */
  body.mylist-section-anime #mylist-view .game-status-selector .game-status-options {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
  }

  /* v10.430: title clamped to 2 lines + ellipsis. Spec was anime-
     specific in phrasing but the rule is intentionally universal
     since the same overflow happens on any section with long
     titles (Mubi, Final Fantasy XIV: Endwalker, etc.). The flex
     parent (`.card-title-row`) is unaffected because line-clamp
     is a CONTENT-LEVEL clamp — it doesn't change the box model
     of the flex item, so existing min-width:0 + flex sizing
     still works. Both the `.card-title` wrapper AND the inner
     button/span need to be the webkit-box for the clamp to
     propagate through the nested element. */
  .card-title,
  .card-title .card-title-profile-btn,
  .card-title .media-title-profile-btn,
  .card-title .game-title-profile-btn,
  .card-title > span {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
  }
  /* v10.433: COMPETITIVE game cards drop the title clamp from 2
     lines to 1. The competitive surface has dense secondary content
     (status pill, platform line, dedicated competitive-stats card,
     rating bubble) below the title, so allocating two lines to the
     title makes the card overly tall and pushes everything down.
     Single line + ellipsis keeps the card compact regardless of
     title length. Hooks the new `.game-competitive-card` class
     added to the card markup whenever `isCompetitiveGameCard` is
     true. */
  .game-competitive-card .card-title,
  .game-competitive-card .card-title .card-title-profile-btn,
  .game-competitive-card .card-title .media-title-profile-btn,
  .game-competitive-card .card-title .game-title-profile-btn,
  .game-competitive-card .card-title > span {
    -webkit-line-clamp: 1;
    line-clamp: 1;
  }

  /* v10.428: GAMES — move the status pill directly under the title for
     EVERY status (Single Player / Live / Competitive / Played /
     Backloggd / Wishlist). `.card-info` is already a flex column
     (set in 05-messages-early-polish.css line 2558+), so we don't
     need to move JS markup — flex `order` reorders the children
     visually without touching the DOM. Default order is 0 for
     every child; bumping every direct child to `order: 2` and then
     pinning `.card-title-row` + `.status-pills-selector-wrap` to
     `order: 1` lifts both to the top of the column. When two flex
     children share the same `order`, the spec resolves the tie by
     DOM order — and `.card-title-row` is declared before
     `.status-pills-selector-wrap` in the markup, so the title
     stays first and the status pill lands directly beneath it.
     All other meta (year, artist, genre, game stats, progress,
     next-episode line, etc.) flow below as `order: 2`.
     v10.432: status-pill margin-top tightened from the default 6px
     down to 2px per spec ("0.5 spacing"). Without this override the
     `.game-status-pills-wrap, .status-pills-selector-wrap` rule
     elsewhere in this file applies a 6px top margin meant for the
     legacy non-stacked layout — visibly too airy when the pill
     sits directly beneath the title. 2px reads as a tight, almost-
     touching break that still gives the pill room to render its
     own click-target without the title text appearing to crash
     into it. Scoped to games only; music / shows / anime keep
     their existing `margin-top: 0` flush-against-meta treatment. */
  #mylist-view .card[data-library-section="games"] .card-info > * {
    order: 2;
  }
  #mylist-view .card[data-library-section="games"] .card-info > .card-title-row,
  #mylist-view .card[data-library-section="games"] .card-info > .status-pills-selector-wrap {
    order: 1;
  }
  #mylist-view .card[data-library-section="games"] .status-pills,
  #mylist-view .card[data-library-section="games"] .status-pills-selector-wrap {
    /* v10.436: line spacing reverted from 0.9px (v10.434) to 6px
       per spec ("change back the spacing... 1 line spacing"). 6px
       matches the original `.game-status-pills-wrap,
       .status-pills-selector-wrap { margin-top: 6px }` default and
       reads as a single line break between meta rows. Applies
       across every game status (playing / backlog / played /
       wishlist). */
    margin-top: 6px !important;
  }

  /* v10.434: 0.9px gap between game-card stat rows.
     v10.436: reverted to 6px / 3px per spec ("1 line spacing") —
     same one-line-break feel as the title→status gap above.
     - margin-top 6px: status → hours-played gap
     - gap 3px: between stat rows inside the block (currently only
       one row exists after the v10.434 trim, but reserved for
       future row additions to stay in rhythm). */
  #mylist-view .card[data-library-section="games"] .game-card-stats-inline {
    margin-top: 6px !important;
    gap: 3px !important;
  }

  /* v10.436: vertically center every child of the games action row
     so the rating bubble (min-height 30px) and the + button
     (height 32px) line up on the same horizontal axis. Without
     this, the default flex `align-items: stretch` was producing
     subtle vertical drift on the Played surface because the
     bubble's intrinsic height differed from the +'s explicit
     height. Center-alignment keeps both items pegged to the row's
     midline regardless of their individual heights. */
  #mylist-view .card[data-library-section="games"].card-uses-rating-bubble .card-action-row {
    align-items: center !important;
  }

  /* v10.436: reduce the horizontal width of every status pill on
     game cards so the chip hugs its label instead of carrying the
     legacy 10px side padding. Applies to the current-pill (visible
     in the meta column) AND each alternative in the pop-out
     flyout. Padding 3px 10px -> 3px 5px snugs the border around
     short labels like "Played" / "Live" / "Backloggd" without
     ever clipping longer ones because `white-space: nowrap` is
     already in place. */
  #mylist-view .card[data-library-section="games"] .game-status-current-pill,
  #mylist-view .card[data-library-section="games"] .game-status-options .status-pill {
    padding-left: 5px !important;
    padding-right: 5px !important;
  }

  /* v10.436: hide the wishlist-specific meta lines (genre,
     platforms, release date) so the wishlist card's vertical
     length matches the playing / live game cards. Without this
     the wishlist card-info column ran an extra ~50px past the
     other surfaces' meta heights and the card visibly stretched
     down past the cover's natural bottom. The wishlist priority
     bubble (rendered at the end of card-info via
     `gamesWishlistPriorityHtml`) is preserved — only the
     descriptive meta lines are dropped. */
  #mylist-view .games-wishlist-card .games-wishlist-card-genre,
  #mylist-view .games-wishlist-card .games-wishlist-card-platforms,
  #mylist-view .games-wishlist-card .games-wishlist-card-release {
    display: none !important;
  }

  /* v10.438: 8.4px line spacing between every meta line on movies
     cards (watchlist surface specifically per spec, but applied
     universally to movies since the meta layout is the same across
     watching / watched / planned and a consistent rhythm reads
     better than per-tab branching). Targets the elements that
     stack vertically in the card-info column: card-year (year
     line), card-genre, card-availability-line (Where to Watch /
     release date), and the status-pill wrap. card-title-row is
     skipped (it's the first child, no top gap needed). */
  #mylist-view .card[data-library-section="movies"] .card-year,
  #mylist-view .card[data-library-section="movies"] .card-genre,
  #mylist-view .card[data-library-section="movies"] .card-availability-line,
  #mylist-view .card[data-library-section="movies"] .mylist-availability-where-to-watch,
  #mylist-view .card[data-library-section="movies"] .status-pills-selector-wrap {
    margin-top: 8.4px !important;
  }
  #mylist-view .card[data-library-section="music"] .music-bottom-rating-slot {
    flex: 0 1 auto;
    min-width: 0;
    margin-right: auto;
    overflow: visible;
  }
  #mylist-view .card[data-library-section="music"] .music-bottom-rating-slot .rating-area {
    margin: 0;
  }
  #mylist-view .card[data-library-section="music"] .music-bottom-rating-slot .stars[data-prefix="overall"] {
    width: auto;
    max-width: none;
    overflow: visible;
  }
  /* v10.403: music title-card rating label = 12px (matches the TV-show
     `.star-label` override at 17-auth-flow-setup.css line 2352). Without
     this rule the `.music-rating-value` would inherit the calc(--music-
     star-size * 0.7) which at the new 16px star size yields ~11px. */
  #mylist-view .card[data-library-section="music"] .music-bottom-rating-slot .music-rating-value {
    font-size: 12px !important;
    margin-left: 5px !important;
  }
  /* ============================================================================
     v10.404 / v10.405: RATING BUBBLE — unified pill.
     ----------------------------------------------------------------------------
     v10.404 originally placed the popout as a SEPARATE floating pill
     anchored next to the chip. v10.405 collapses the two into ONE pill:
     the chip icon + value sit at the LEFT, and the star strip lives
     inside the SAME container, hidden by default. On `.is-expanded` the
     stars track animates from max-width:0 → its natural width, pushing
     the right edge of the pill outward. There's no separate popout
     anymore — it's all one continuous bubble that just grows.

     Color: pulled from the bright amber #fbbf24 / pale #f8d973 to a more
     muted pale gold (#d4b86a). Less saturated, reads softer against the
     dark card background.
     ============================================================================ */
  .rating-bubble {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: flex-start;
    border: 1px solid rgba(212, 184, 106, 0.30);
    /* v10.411: tried solid background to hide the Details/+ buttons
       behind the expanded bubble.
       v10.412: REVERTED — keeping the original 72% rgba and instead
       fading out the Details / + / Comments cluster when the bubble
       expands (see rule below). Cleaner UX — the buttons disappear,
       reappear smoothly, and the bubble retains its translucent feel. */
    background: rgba(15, 15, 15, 0.72);
    color: #d4b86a;
    border-radius: 999px;
    /* v10.439: vertical height reduced 30px -> 29.5px per spec
       ("slightly reduced... by zero point five p x"). Half-pixel
       value is intentional — on DPR >= 2 displays this renders as a
       crisp 29.5 logical-px tap target; on integer-DPR screens it
       rounds visually but the cascaded 0.5px still tightens the
       overall row rhythm noticeably. Applies to every surface that
       uses `.rating-bubble` (games / anime / music / TV shows
       title cards + the music album-details "Your rating"
       widget). */
    /* v10.713: collapsed-state min-dimensions tightened � 44x29.5 -> 39x27
       per spec. Width stays `min-width` so the bubble can still grow
       horizontally when expanded to reveal the inline stars track. */
    min-height: 27px;
    min-width: 39px;
    padding: 0 9px;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
    transform: translateZ(0);
    transition:
      transform 180ms cubic-bezier(0.16, 1, 0.3, 1),
      border-color 220ms ease,
      background 180ms ease;
  }
  .rating-bubble:active {
    transform: translateZ(0) scale(0.97);
  }
  .rating-bubble[aria-disabled="true"] {
    cursor: default;
    color: rgba(212, 184, 106, 0.72);
    background: rgba(15, 15, 15, 0.48);
  }
  /* v10.419: when the title hasn't been rated yet, the bubble collapses
     down to a snug square around just the star icon so the padding is
     visually identical on both sides. Previously the bubble inherited
     `min-width: 44px` + `justify-content: flex-start` from the rated
     state, which (with a ~13px-wide star glyph and a 9px left pad)
     left ~22px of empty space to the right of the star. By dropping
     the floor to match `min-height` (30px) and recentering the
     contents only while unrated, the closed pill becomes a round-ish
     chip with equal breathing room either side of the star. This
     applies to every surface that uses the rating bubble (TV shows /
     anime / movies / games / music) because the `.is-rated` class is
     applied universally by `buildRatingBubbleMarkup` whenever rating
     > 0. The rule reverts itself the instant a rating is committed
     (the markup re-renders with `.is-rated`), so the bubble grows back
     out to its rated-state width without any extra JS. Expanded state
     is unaffected — once the inner stars track grows, the bubble's
     content width far exceeds the 30px floor so the justify-content
     rule is a no-op on that surface. */
  .rating-bubble:not(.is-rated) {
    /* v10.439: paired with the v10.439 height reduction (30 -> 29.5)
       above, the unrated bubble's square floor was 30×30. Keeping
       min-width at 30 so the chip stays close-to-circular even
       though min-height is now 29.5; the 0.5px difference is
       imperceptible vs. preserving the round-pill silhouette. */
    min-width: 30px;
    justify-content: center;
    /* v10.421: when the title is unrated, swap the muted gold border
       + glyph color for a neutral lavender-tinted gray. The original
       gold color implied "this title has a rating" even when it
       didn't — only the missing chip value hinted at the empty
       state. The grayed-out treatment makes the empty state read as
       intentionally inert, matching the same muted-gray treatment
       the per-track widget uses for unrated rows
       (`rgba(216, 208, 233, 0.42)`). The instant a rating is
       committed the markup re-renders with `.is-rated`, which drops
       these overrides and restores the gold treatment. */
    border-color: rgba(216, 208, 233, 0.22);
    color: rgba(216, 208, 233, 0.42);
  }
  .rating-bubble:not(.is-rated) .rating-bubble-chip-icon {
    /* v10.513: replaced the 42% alpha gray with a SOLID neutral grey so
       the empty-state star icon renders at 100% opacity (no semi-
       transparency) per the spec that all rating-bubble glyphs must be
       fully opaque. The visual weight matches what `rgba(216,208,233,
       0.42)` produced against the dark page background — just without
       the alpha channel. */
    color: #6e6880;
    opacity: 1;
  }
  .rating-bubble-chip-icon {
    color: #d4b86a;
    /* v11.201: closed-state star icon → 12px / weight 500 (was 11px). */
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    /* v10.513: explicit 100% opacity guard so nothing in the cascade
       (parent transitions, hover dims, etc.) can ever fade the star
       icon during a rate/scrub gesture or at rest. */
    opacity: 1;
    transition: font-size 280ms cubic-bezier(0.32, 0.72, 0, 1);
  }
  .rating-bubble-chip-value {
    /* v10.514: tightened from 4px → 3px so the star glyph and the
       rating value sit one pixel closer together inside the chip.
       v10.515: tightened again 3px → 2px per spec.
       v10.516: tightened again 2px → 0px per spec (another 2px
       closer). Star glyph and value now sit flush. */
    margin-left: 0;
    color: #d4b86a;
    /* v11.201: closed-state value → 12px / weight 500 (was 10px / 700). */
    font-size: 12px;
    transition: font-size 280ms cubic-bezier(0.32, 0.72, 0, 1);
    font-weight: 500;
    line-height: 1;
    /* v10.513: explicit 100% opacity guard, paired with the chip-icon
       rule above. The rating value text must always render fully solid. */
    opacity: 1;
    /* v10.512: reserve enough width for the widest possible 5-star
       half-step display ("4.5" = 3 characters) so the chip — and the
       whole bubble — doesn't reflow / resize while the user scrubs
       across half-step crossovers. Without this, the chip text shifted
       between "3" (1 char) and "3.5" (3 chars) and the bubble's inline-
       flex width changed on every half-step, producing the visible
       "growing pop-out" the user reported. `tabular-nums` keeps digit
       glyph widths constant so the integer→half transition doesn't
       shift the number column either. text-align:center holds the
       value centered inside the reserved space at all values. */
    min-width: 2.6ch;
    text-align: center;
    font-variant-numeric: tabular-nums;
    display: inline-block;
  }
  /* v10.512: when the bubble carries the "/5" suffix (album-shelf "Your
     rating" pill), reserve enough width for "X.X/5" — the widest
     possible display in that mode. Without this override, the bubble
     would still grow during scrub on the album-shelf path. */
  .rating-bubble[data-out-of-five="1"] .rating-bubble-chip-value {
    min-width: 4.6ch;
  }
  /* The stars track lives INSIDE the pill. Collapsed = zero-width slot,
     hidden + pointer-events:none so taps fall through to the outer
     toggle. Expanded = grows to fit, slides in via the same cubic-
     bezier the season-card popout used. */
  .rating-bubble-stars-track {
    display: inline-flex;
    align-items: center;
    flex-wrap: nowrap;
    white-space: nowrap;
    max-width: 0;
    margin-left: 0;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    /* v11.202: smoother CLOSE. Three problems were making the collapse
       feel un-smooth:
         1. max-width animated to 280px (see below) while the actual star
            content is ~130px wide, so ~150px of the sweep was a "dead zone"
            where nothing visibly moved — the collapse looked delayed then
            abrupt. Ceiling tightened to 150px below to remove it.
         2. opacity ran 260ms while width/margin ran 340ms, so on close the
            stars faded out before the track finished shrinking — a hitch at
            the tail. All three are now the SAME 300ms + same curve so they
            start and finish together.
         3. The sibling action-row fade (:has rule further down) ran 200ms —
            now matched to 300ms so the buttons reappear in lockstep.
       max-width still forces layout, but with the dead-zone gone and every
       timeline synchronized the motion reads clean. */
    transition:
      max-width 300ms cubic-bezier(0.32, 0.72, 0, 1),
      margin-left 300ms cubic-bezier(0.32, 0.72, 0, 1),
      opacity 300ms cubic-bezier(0.32, 0.72, 0, 1);
  }
  .rating-bubble.is-expanded .rating-bubble-stars-track {
    /* v11.202: tightened 280px → 150px. The expanded star content is
       ~130px wide (5 slots × 26px half-step). The old 280px ceiling meant
       the close animation spent its first ~150px of travel collapsing
       empty space with NO visible movement, then snapped — the main cause
       of the un-smooth close. 150px clears the content with a small buffer
       while making the max-width sweep map 1:1 to visible motion. */
    max-width: 150px;
    margin-left: 8px;
    opacity: 1;
    pointer-events: auto;
  }
  .rating-bubble-star {
    appearance: none;
    -webkit-appearance: none;
    border: 0;
    background: transparent;
    color: rgba(245, 242, 255, 0.30);
    width: 18px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transform: translateZ(0);
    transition: color 130ms ease, transform 130ms cubic-bezier(0.16, 1, 0.3, 1);
  }
  /* v10.510: REBUILT half-step star visuals.
     Old approach used two side-by-side ★ glyph buttons per visual star
     with `text-indent` and `overflow:hidden` to fake a "left half / right
     half" split. The seam between the two halves became visible at
     larger sizes (v10.509 bump), producing the doubled-star artifact.
     New approach mirrors the activity card pattern: ONE slot per visual
     star containing a grey base ★ + a gold fill ★ clipped via clip-path
     to the per-slot fill percent (0/50/100). Two invisible
     `.rating-bubble-star-hit` buttons absolutely positioned as left and
     right half hit zones carry the data-score values the existing
     rate() pipeline expects (1–10 half-units), so the storage and
     commit semantics are unchanged. */
  .rating-bubble-star-slot {
    position: relative;
    display: inline-flex;
    width: 18px;
    height: 22px;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    line-height: 1;
  }
  .rating-bubble-star-base,
  .rating-bubble-star-fill {
    position: absolute;
    inset: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    line-height: 1;
    pointer-events: none;
    transition: opacity 130ms ease;
  }
  .rating-bubble-star-base {
    color: rgba(245, 242, 255, 0.30);
    z-index: 1;
  }
  .rating-bubble-star-fill {
    color: #d4b86a;
    z-index: 2;
    /* clip-path crops the gold glyph to the fill percent from the LEFT.
       0% = nothing visible, 50% = left half only, 100% = whole glyph. */
    clip-path: inset(0 calc(100% - var(--star-fill, 0%)) 0 0);
    -webkit-clip-path: inset(0 calc(100% - var(--star-fill, 0%)) 0 0);
    /* v10.511: clip-path transition gated to NON-scrubbing state. During
       scrub, every touchmove updates --star-fill, and a CSS transition
       would interpolate FROM the current mid-animation value to the
       new target over 140ms — producing a visual that constantly chases
       the finger and never catches up (the "itchy/glitchy" feel the
       user reported). Disabled during scrub via the
       `[data-scrubbing="true"]` selector below; re-enabled in the
       resting state so external commits (post-rate re-render edge
       cases, future preview-tap state changes) still feel smooth. */
    transition: clip-path 140ms cubic-bezier(0.16, 1, 0.3, 1),
                -webkit-clip-path 140ms cubic-bezier(0.16, 1, 0.3, 1);
  }
  .rating-bubble[data-scrubbing="true"] .rating-bubble-star-fill {
    transition: none !important;
  }
  .rating-bubble-star-hit {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50%;
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    z-index: 3;
    -webkit-tap-highlight-color: transparent;
  }
  .rating-bubble-star-hit-left { left: 0; }
  .rating-bubble-star-hit-right { right: 0; }
  /* When the bubble expands, the slots grow so half-star taps are easier
     to land — the same intent as the v10.509 size bump, but applied to
     the new clean structure. The fill glyph scales in lockstep via its
     font-size override. */
  .rating-bubble.is-expanded .rating-bubble-star-slot {
    width: 26px;
    height: 30px;
  }
  .rating-bubble.is-expanded .rating-bubble-star-base,
  .rating-bubble.is-expanded .rating-bubble-star-fill {
    font-size: 22px;
  }
  .rating-bubble-star.lit,
  .rating-bubble-star:active {
    color: #d4b86a;
  }
  .rating-bubble-star:active {
    transform: translateZ(0) scale(1.18);
  }
  .rating-bubble-star.star-pop {
    animation: star-pop 0.42s ease-out;
  }
  /* v10.515: star-pop animation hook for the new v10.510 fill element.
     `playRatingAnimation` in 06-mylists-render-episodes-ratings.js
     toggles `.star-pop` on each lit slot's `.rating-bubble-star-fill`
     after a rate commits; this rule wires that class to the same
     keyframe the legacy `.rating-bubble-star.star-pop` rule used, so
     the scale + brightness pop runs on the new slot structure too.
     The intensity-scaled glow + magenta shift is applied via WAAPI
     `Element.animate()` in the same playRatingAnimation, so this CSS
     rule is the CSS-fallback half of the unified bubble-rates pop
     effect (matching the per-track widget). */
  .rating-bubble-star-fill.star-pop {
    animation: star-pop 0.42s ease-out;
  }
  /* v10.405 / v10.407: half-step variant — used to render 10 side-by-
     side ★ glyph buttons (5 visual stars × 2 halves) with text-indent
     and overflow:hidden to fake the half-fill.
     v10.510: REMOVED — the half-step bubble now uses the clean
     `.rating-bubble-star-slot` + `.rating-bubble-star-base` +
     `.rating-bubble-star-fill` (clip-path) + `.rating-bubble-star-hit`
     pattern defined above. The `.rating-bubble-star-half-*` selectors
     no longer match any rendered markup and are removed.
     The legacy `.rating-bubble-star` rules (without `-half`) are kept
     for the dormant 10-scale rollback path. */
  /* Bottom-left slot in the card action row — pushed flush-left,
     `margin-right: auto` shoves the action row's right cluster
     (Comments, Tracklist/+, etc.) to the far right. Action row padding
     is also pulled tight so the bubble sits aligned with the card
     poster's left edge (matches what the music section already does
     via .music-bottom-rating-slot). */
  .rating-bubble-bottom-left-slot {
    flex: 0 1 auto;
    min-width: 0;
    margin-right: auto;
    overflow: visible;
  }
  #mylist-view .card.card-uses-rating-bubble .card-action-row {
    padding-left: 12px !important;
  }
  /* v10.412: when the rating bubble is expanded, fade out everything
     else in the action row (Comments button, Details, +, etc.) so the
     bubble's popout has clean space to expand into. Uses CSS `:has()`
     so no JS hooks needed — when `.rating-bubble.is-expanded` is
     present anywhere inside the action row, every direct child of the
     row that ISN'T the bubble's own slot gets opacity:0 +
     pointer-events:none with a 200ms ease transition.
     Supported on iOS Safari 15.4+ / Chrome 105+, both of which the
     Capacitor WKWebView matches on iOS 16+. */
  #mylist-view .card.card-uses-rating-bubble .card-action-row > * {
    /* v11.202: matched to the bubble's 300ms + curve so the Details/+/
       Comments buttons fade back in exactly in lockstep with the track
       collapsing — no more buttons popping in early during the close. */
    transition: opacity 300ms cubic-bezier(0.32, 0.72, 0, 1);
  }
  #mylist-view .card.card-uses-rating-bubble .card-action-row:has(.rating-bubble.is-expanded) > *:not(.rating-bubble-bottom-left-slot) {
    opacity: 0;
    pointer-events: none;
  }

  /* v10.395: dedicated music rating widget. v10.394's specificity-based
     override lost to a `:not(:first-of-type)` pseudo-class in
     17-auth-flow-setup.css (their (1,7,0) beat our (1,6,0)). Switching
     strategy: NEW class names that don't share with .star-btn so no
     global rule can touch them. Self-contained, no specificity fight.

     Geometry: 10 half-step buttons composing 5 stars, 11px wide each
     (= 22px per full star = 110px for all five). Glyph drawn at 22px
     font, naturally ~22px wide; left-half shows the left half of the
     glyph via overflow:hidden + text-align:left, right-half shows the
     right half via text-indent:-11px shifting the same glyph leftward
     out of the box. */
  .music-rating {
    display: inline-flex;
    align-items: center;
    gap: 0;
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
            user-select: none;
  }
  /* v10.396: sizes are driven by inline CSS variables on the
     `.music-rating` container (`--music-star-size`, `--music-half-width`).
     Title card sets 20/10, album shelf page sets 28/14. One ruleset,
     two surfaces. */
  .music-rating-half {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    width: var(--music-half-width, 10px);
    min-width: var(--music-half-width, 10px);
    height: calc(var(--music-star-size, 20px) + 4px);
    line-height: 1;
    font-size: var(--music-star-size, 20px);
    font-family: inherit;
    color: #443d60;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    transition: color 150ms ease, transform 150ms ease;
    -webkit-tap-highlight-color: transparent;
  }
  .music-rating-half.music-rating-half-left {
    text-align: left;
    text-indent: 0;
    justify-content: flex-start;
    /* v10.400: anchor scale animations at the right edge of this box —
       i.e. the shared boundary between this half and its pair-mate.
       When the pair-mate's right half has transform-origin: left center
       (the same boundary in document coords), both halves scale outward
       from one shared anchor point. That's what makes a star pop as a
       single unified shape instead of pulling apart into two half-stars
       with their own tips. */
    transform-origin: right center;
  }
  .music-rating-half.music-rating-half-right {
    text-align: left;
    text-indent: calc(var(--music-half-width, 10px) * -1);
    justify-content: flex-start;
    /* v10.400: paired with .music-rating-half-left's `right center` —
       see comment above. */
    transform-origin: left center;
  }
  .music-rating-half.lit,
  .music-rating-half.lit-hover {
    color: #F5B301;
  }
  .music-rating-half:hover {
    transform: scale(1.18);
  }
  .music-rating-half:active {
    transform: scale(0.95);
  }
  /* Reuses the global star-pop keyframe defined in this same file
     around line 1198; same brightness/scale flare the .star-btn family
     gets on click. */
  .music-rating-half.star-pop {
    animation: star-pop 0.42s ease-out;
  }
  /* v10.407: full-star button used by the 10-star music variant
     (`.music-rating--ten`). Same sizing model as `.music-rating-half`
     (driven by the `--music-star-size` CSS variable) but no text-indent
     trick — each button renders a full ★ glyph at its native size. */
  .music-rating-full {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    width: var(--music-star-size, 20px);
    min-width: var(--music-star-size, 20px);
    height: calc(var(--music-star-size, 20px) + 4px);
    line-height: 1;
    font-size: var(--music-star-size, 20px);
    font-family: inherit;
    color: #443d60;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: color 150ms ease, transform 150ms ease;
    -webkit-tap-highlight-color: transparent;
  }
  .music-rating-full.lit,
  .music-rating-full.lit-hover {
    color: #F5B301;
  }
  /* v11.216: while scrubbing, the live preview is driven ONLY by `.lit-hover`.
     The committed rating's `.lit` class stays on the stars, so without this a
     downward scrub (which only REMOVES lit-hover) left the saved stars gold —
     the number dropped but the stars stayed stuck at the committed rating.
     During `.is-scrubbing`, a star that's `.lit` but NOT `.lit-hover` reverts
     to the unlit color, making lit-hover the single source of truth so the
     fill tracks the finger down as well as up. */
  .music-rating.is-scrubbing .music-rating-half.lit:not(.lit-hover),
  .music-rating.is-scrubbing .music-rating-full.lit:not(.lit-hover) {
    color: #443d60;
  }
  .music-rating-full:hover {
    transform: scale(1.18);
  }
  .music-rating-full:active {
    transform: scale(0.95);
  }
  .music-rating-full.star-pop {
    animation: star-pop 0.42s ease-out;
  }
  /* v10.407: per-track collapsed full ★ — rendered when music is in
     10-star mode (no half-step composition needed for the collapsed
     icon). */
  .mylist-album-shelf-track-rate-star--full {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--music-star-size, 22px);
    min-width: var(--music-star-size, 22px);
    height: var(--music-star-size, 22px);
    font-size: var(--music-star-size, 22px);
    line-height: 1;
    color: #443d60;
    transition: color 150ms ease;
  }
  .mylist-album-shelf-track-rate-star--full.lit {
    color: #F5B301;
  }

  .music-rating-value {
    margin-left: 8px;
    color: #ffffff;
    font: 700 calc(var(--music-star-size, 20px) * 0.7)/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: -0.01em;
    white-space: nowrap;
  }
  /* v11.211: album-details "Your rating" scrub stability. The .music-rating
     widget is centered in its column; the value label is appended AFTER the
     stars inside the same inline-flex row. While scrubbing, the label text
     changes width ("" → "3" → "3.5") and — because rating 0 has no label at
     all, so scrubbing CREATES the element — the row's content width changes
     every tick, and the centered column re-centers it, shifting the ENTIRE
     rating portion left/right. Fix: in the album-shelf context, give the
     value a FIXED-WIDTH, right-aligned, tabular-num slot that's always the
     same size regardless of text (empty, "3", or "4.5"), so only the digits
     change — the stars never move. */
  /* v11.216: center the 5 STARS in the column; offset the number to the right
     WITHOUT it pulling the stars off-center. The value is taken out of the
     inline-flex flow (absolute, anchored to the right edge of the widget) so
     only the stars participate in the column's centering. Fixed-width +
     tabular-nums keeps it from shifting during scrub. */
  .mylist-album-shelf-rating .music-rating {
    position: relative;
  }
  .mylist-album-shelf-rating .music-rating-value {
    position: absolute;
    left: 100%;
    margin-left: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 3.4ch;
    min-width: 3.4ch;
    text-align: left;
    font-variant-numeric: tabular-nums;
  }
  /* v10.261 / v10.403: music tab order is now In Rotation → Listened
     → Planned (was Planned → In Rotation → Listened). The static HTML
     order is Watching · Planned · Watched; CSS flex order maps them
     to the new visual sequence when active section is music. */
  body.mylist-section-music #mylist-toolbar .tab-btn[data-tab="watching"] { order: 1; }
  body.mylist-section-music #mylist-toolbar .tab-btn[data-tab="watched"]  { order: 2; }
  body.mylist-section-music #mylist-toolbar .tab-btn[data-tab="planned"]  { order: 3; }

  /* v10.403: music status pill = JUST TEXT — no outline, no background.
     The status hue (purple for In Rotation, cyan for Listened, amber for
     Planned) is preserved as the TEXT color so the pill still reads as
     colored even without chrome. Applies to:
       - the current pill on the card (`.game-status-current-pill`)
       - each option in the pop-out (`.game-status-options .status-pill`)
       - any bare `.status-pill` rendered on a music card */
  /* v10.414: same text-only status-pill treatment now applied to TV
     SHOWS in addition to music. The selectors below double up so the
     ruleset fires under both `body.mylist-section-music` and
     `body.mylist-section-shows`. Status-color → text color preserves
     the per-status hue without the border/background chrome. TV adds
     a `paused-active` orange that music doesn't have. */
  /* v11.142: re-scoped off body.mylist-section-music/-shows onto the card's
     own data-library-section attribute (always in the DOM) so the text-only
     status chrome holds at first paint and never flashes the bordered pill.
     Mirrors the v11.137 authoritative fix in 07. */
  #mylist-view .card[data-library-section="music"] .status-pill,
  #mylist-view .card[data-library-section="music"] .game-status-current-pill,
  #mylist-view .card[data-library-section="music"] .game-status-options .status-pill,
  #mylist-view .card[data-library-section="shows"] .status-pill,
  #mylist-view .card[data-library-section="shows"] .game-status-current-pill,
  #mylist-view .card[data-library-section="shows"] .game-status-options .status-pill {
    border: 0 !important;
    background: transparent !important;
    background-image: none !important;
    /* v10.408: padding-left = 0 so the status pill TEXT lines up with
       the title/artist text in the meta column. Right padding kept at
       6px so the pop-out options have a small visual gap before the
       next pill in the list.
       v10.410: top/bottom padding dropped from 4px -> 0 so the pill
       hugs the next meta line tighter (paired with the wrap margin-top
       reset below). */
    padding: 0 6px 0 0 !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    box-shadow: none !important;
  }
  /* v10.410 / v10.414: pull the status pill UP closer to the artist /
     meta line so the gap reads as a single line break rather than the
     legacy 6px margin. Applies to both music and TV shows now. */
  #mylist-view .card[data-library-section="music"] .status-pills,
  #mylist-view .card[data-library-section="music"] .status-pills-selector-wrap,
  #mylist-view .card[data-library-section="shows"] .status-pills,
  #mylist-view .card[data-library-section="shows"] .status-pills-selector-wrap {
    margin-top: 0 !important;
  }
  /* Status-color → text color (replaces the bg/border-driven coloring).
     Shared between music + shows. */
  #mylist-view .card[data-library-section="music"] .status-pill.watching-active,
  #mylist-view .card[data-library-section="shows"] .status-pill.watching-active {
    color: #a78bfa !important; /* lavender (music: In Rotation / shows: Watching) */
  }
  #mylist-view .card[data-library-section="music"] .status-pill.watched-active,
  #mylist-view .card[data-library-section="shows"] .status-pill.watched-active {
    color: #67e8f9 !important; /* cyan (music: Listened / shows: Watched) */
  }
  #mylist-view .card[data-library-section="music"] .status-pill.planned-active,
  #mylist-view .card[data-library-section="shows"] .status-pill.planned-active {
    color: #fbbf24 !important; /* amber (Planned) */
  }
  /* TV-only status: Paused gets the existing brand orange. */
  #mylist-view .card[data-library-section="shows"] .status-pill.paused-active {
    color: #f97316 !important;
  }
  /* Unselected pop-out options stay in the standard muted color so the
     active one visually stands out. */
  body.mylist-section-music #mylist-view .game-status-options .status-pill:not(.watching-active):not(.watched-active):not(.planned-active),
  body.mylist-section-shows #mylist-view .game-status-options .status-pill:not(.watching-active):not(.watched-active):not(.planned-active):not(.paused-active) {
    color: rgba(216, 208, 233, 0.55) !important;
  }

  /* v10.423: restore PILL CHROME to popped-out status options on music
     + TV cards. The v10.408 / v10.414 "text-only pill" override above
     (border: 0 + background: transparent + padding: 0 6px 0 0) was
     intentional for the ACTIVE pill so its label sits flush with the
     title/artist meta line. But that same rule cascaded onto every
     pill inside `.game-status-options`, so the popped-out "In Rotation"
     and "Planned" alternatives lost their borders and backgrounds and
     visually fused into a single block of text. By scoping THIS rule
     to `.game-status-selector .game-status-options .status-pill`, we
     add one more class to the selector (4 classes vs. 3) and win the
     specificity battle without `!important`-stacking — but we add it
     anyway since the upstream uses `!important` for every property.
     Each alternative now reads as its own tappable button: rounded
     hairline border, faint translucent background, equal padding all
     around, and a hover state that lifts the surface slightly. The
     `gap: 4px` already set on `.game-status-options` adds spatial
     separation between the chips. */
  body.mylist-section-music #mylist-view .game-status-selector .game-status-options .status-pill,
  body.mylist-section-shows #mylist-view .game-status-selector .game-status-options .status-pill {
    border: 1px solid rgba(216, 208, 233, 0.22) !important;
    background: rgba(255, 255, 255, 0.04) !important;
    border-radius: 999px !important;
    padding: 4px 10px !important;
  }
  body.mylist-section-music #mylist-view .game-status-selector .game-status-options .status-pill:hover,
  body.mylist-section-shows #mylist-view .game-status-selector .game-status-options .status-pill:hover {
    background: rgba(255, 255, 255, 0.08) !important;
    border-color: rgba(216, 208, 233, 0.34) !important;
  }
  /* Widen the gap a touch now that the chips have their own visible
     edges — 4px reads tight when chrome is present. */
  body.mylist-section-music #mylist-view .game-status-selector.expanded .game-status-options,
  body.mylist-section-shows #mylist-view .game-status-selector.expanded .game-status-options {
    gap: 6px;
  }

  /* v10.424: strip the gray container surface off the popped-out
     options on music + TV cards. The true-dark-mode override in
     06-profile.css (line 1588) sets background: #2c2c2c and a
     hairline border on `.game-status-options`, which is the right
     treatment for Games cards (whose pop-out lives inline next to a
     dense stat block and needs a contrasting tray to read) but on
     music + TV the alternative pills now have their own chrome
     (v10.423) and that outer tray duplicates them as a single gray
     rectangle.
     v10.425: first attempt at this override used the same specificity
     as the upstream rule (1 id + 2 classes + 1 type) — they tied, and
     `06-profile.css` loads AFTER `01-mylists-cards-episodes.css` in
     `index.html`, so the upstream still won despite both having
     `!important`. Fix: insert `.game-status-selector` (the immediate
     parent of `.game-status-options` in the markup) into the chain
     so the selector becomes 1 id + 3 classes + 1 type, beating the
     upstream's 1 id + 2 classes + 1 type regardless of file load
     order. `!important` kept on every property so any later cascade
     layer still loses. */
  body.mylist-section-music #mylist-view .game-status-selector .game-status-options,
  body.mylist-section-shows #mylist-view .game-status-selector .game-status-options {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
  }

  /* v10.241 / v10.258 / v10.259: music title card now shows the status pill
     (so the user can swap between Listened / Planned), the artist line, and
     the rating. Year + genre are hidden — only title + artist + status +
     rating + cover. */
  #mylist-view .card[data-library-section="music"] .card-year.mylist-watchlist-year {
    display: none !important;
  }
  #mylist-view .card[data-library-section="music"] .card-genre {
    display: none !important;
  }
  /* v10.241 / v10.254: music section now shows the status toolbar again
     with two tabs only (Listened + Planned) — JS label logic in
     06-mylists-render-episodes-ratings.js handles the per-section text. */

  /* v10.245 / v10.259 / v10.402: "Details" pill (formerly "Tracklist")
     on the music my-list card. Black fill + white-rgba border to match
     the "+" plus-button style. v10.402 retunes the pill to fit the new
     10px font (was 6px via the 17-auth-flow-setup.css override): height
     32 -> 24 and padding 12 -> 9 so the border hugs the text more
     tightly. */
  #mylist-view .card-action-row .card-tracklist-btn {
    appearance: none;
    -webkit-appearance: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 24px;
    min-width: 0;
    padding: 0 9px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,0.30);
    background: rgba(5,5,10,0.94);
    color: rgba(255,255,255,0.72);
    font: 500 12px/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0.01em;
    cursor: pointer;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background 160ms ease, border-color 160ms ease, color 160ms ease, transform 140ms ease;
  }
  #mylist-view .card-action-row .card-tracklist-btn:hover {
    color: #ffffff;
    background: rgba(12,12,18,0.98);
    border-color: rgba(255,255,255,0.40);
  }
  #mylist-view .card-action-row .card-tracklist-btn:active { transform: scale(0.94); }

  /* v10.245: My-List Album Shelf Page — full-screen slide-in-from-right
     overlay. Hero (cover + title + artist) centered, tracklist below with
     pop-out rating row to the LEFT of each track's star toggle. Shelfd
     palette + same .star-btn animations as every other rating surface. */
  body.mylist-album-shelf-open { overflow: hidden; }
  .mylist-album-shelf-page {
    position: fixed;
    inset: 0;
    z-index: 7320;
    pointer-events: auto;
    background: transparent;
  }
  .mylist-album-shelf-shell {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: #0f0f12;
    color: #f8f4ff;
    /* v11.112: the album details page now slides UP from the bottom of the
       screen (was in from the right), matching the TV-show episode detail page
       animation — same easing + ~450ms + slight opacity fade. */
    transform: translate3d(0, 100%, 0);
    opacity: 0.98;
    transition:
      transform 450ms cubic-bezier(0.22, 1, 0.36, 1),
      opacity 260ms ease;
    will-change: transform, opacity;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    overflow: hidden;
  }
  .mylist-album-shelf-page.is-open .mylist-album-shelf-shell {
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
  .mylist-album-shelf-topbar {
    flex: 0 0 auto;
    min-height: 56px;
    padding: max(12px, env(safe-area-inset-top, 0px)) 16px 10px;
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr) auto;
    align-items: center;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    background: #0f0f12;
    /* v10.508: anchor so the absolutely-positioned title can center on the
       full topbar width (not the asymmetric middle grid column). */
    position: relative;
  }
  html.shelfd-capacitor-ios .mylist-album-shelf-topbar {
    min-height: 46px;
    padding: max(calc(env(safe-area-inset-top, 0px) - 18px), 10px) 14px 6px;
  }
  .mylist-album-shelf-back {
    width: 38px;
    height: 38px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    background: rgba(255,255,255,0.05);
    color: #f8f4ff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
    cursor: pointer;
  }
  .mylist-album-shelf-back svg { width: 24px; height: 24px; }
  .mylist-album-shelf-back:active { transform: scale(0.94); }
  .mylist-album-shelf-title-bar {
    text-align: center;
    font: 500 14px/1 'Sohne', 'DM Sans', sans-serif;
    color: #f8f4ff;
    /* v10.508: float the "Album" label absolutely on the topbar so it sits
       at the exact horizontal center of the viewport. Without this, the
       grid layout (40px back | 1fr title | auto actions) makes the middle
       column visually off-center because the right "actions" column is
       wider than the left "back" column. pointer-events: none so the label
       can't intercept taps meant for the back / action buttons below it. */
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    /* Keep the label compact so it never overlaps the back/actions even on
       narrow phones. */
    max-width: calc(100% - 120px);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mylist-album-shelf-actions {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    justify-self: end;
  }
  .mylist-album-shelf-action {
    width: 38px;
    height: 38px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    background: rgba(255,255,255,0.05);
    color: #f8f4ff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms ease, border-color 140ms ease, transform 140ms ease;
  }
  .mylist-album-shelf-action svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .mylist-album-shelf-action:active { transform: scale(0.94); }
  .mylist-album-shelf-fav { flex-shrink: 0; }
  .mylist-album-shelf-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    padding: 24px 18px max(28px, calc(env(safe-area-inset-bottom, 0px) + 24px));
    /* v10.507: hide the right-edge scroll indicator on the album details
       overlay. WebKit (iOS Capacitor + Safari) honors the ::-webkit-scrollbar
       block; Firefox honors scrollbar-width; legacy IE honors ms-overflow-style.
       Scroll behavior itself is unchanged — content still scrolls, just
       without the visible indicator. */
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .mylist-album-shelf-content::-webkit-scrollbar { display: none; width: 0 !important; height: 0 !important; }

  /* v10.507: disable iOS double-tap-to-zoom on the album details overlay.
     `touch-action: manipulation` specifically suppresses the 300ms double-
     tap-to-zoom gesture while still permitting pinch-zoom (if the user
     wants to pinch) and normal panning. Applied to the page shell so the
     hero, tracklist, rating buttons, and footer all share the behavior. */
  .mylist-album-shelf-page,
  .mylist-album-shelf-shell,
  .mylist-album-shelf-content {
    touch-action: manipulation;
  }
  html.shelfd-capacitor-ios .mylist-album-shelf-content {
    padding-top: 8px;
  }
  .mylist-album-shelf-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 14px;
    margin-bottom: 26px;
  }
  .mylist-album-shelf-cover {
    width: min(72vw, 260px);
    aspect-ratio: 1 / 1;
    border-radius: 0.9px;
    background-size: cover;
    background-position: center center;
    background-color: #1c1535;
    /* v10.402 / v10.403: outer 1px @ 30% white outline (first shadow,
       was 54% in v10.402 — softened per spec) stacked with the existing
       drop shadow (second shadow). Multiple box-shadows draw layered
       from front to back — the hairline lives on top of the drop shadow
       so it's visible even when the cover image itself is fully black. */
    box-shadow:
      0 0 0 1px rgba(255,255,255,0.30),
      0 24px 60px rgba(0,0,0,0.5);
    display: grid;
    place-items: center;
    font-size: 56px;
    color: rgba(196,181,253,0.6);
  }
  .mylist-album-shelf-cover.no-img {
    background: linear-gradient(135deg, rgba(42,31,94,0.92), rgba(45,27,78,0.92));
  }
  .mylist-album-shelf-album-title {
    margin: 0;
    color: #fff;
    font: 500 24px/1.18 'Sohne', 'DM Sans', sans-serif;
    word-break: break-word;
  }
  .mylist-album-shelf-album-artist {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 0;
    color: rgba(216,208,233,0.78);
    font: 500 15px/1.2 'Sohne', 'DM Sans', sans-serif;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color 140ms ease;
  }
  .mylist-album-shelf-album-artist:hover { color: #f8f4ff; }
  .mylist-album-shelf-album-artist:active { opacity: 0.7; }
  /* v10.257: year · genre meta line under the artist. */
  .mylist-album-shelf-album-meta {
    color: rgba(216,208,233,0.55);
    font: 400 13px/1.3 'Sohne', 'DM Sans', sans-serif;
  }

  .mylist-album-shelf-tracks {
    padding-top: 22px;
    border-top: 1px solid rgba(255,255,255,0.08);
  }
  .mylist-album-shelf-tracks-heading {
    color: #ffffff;
    font: 500 16px/1.2 'Sohne', 'DM Sans', sans-serif;
    margin: 0 0 12px;
  }
  .mylist-album-shelf-track-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
  }
  /* v10.397: track row is now `title | rating-widget`. Track number
     column dropped so the title aligns flush-left with the "Tracks"
     section heading (which has no left padding). Rating widget on the
     right is the new collapsible 5-star toggle. */
  .mylist-album-shelf-track {
    display: grid;
    /* v10.440: 3-column grid — [track number] [title] [rating widget].
       The track number sits flush-left, the title fills the middle
       (with min-width:0 so it ellipses cleanly), and the widget
       hangs off the right edge. */
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    /* v11.040: anchor for the episode-style `.ep-rating-popup` that now
       opens from each track's star button (absolute, right-aligned to
       the row — same as an episode row). */
    position: relative;
    /* v10.435: vertical padding tightened 10 -> 7 per spec ("track
       list titles thirty percent closer").
       v11.104: +3px top + 3px bottom (7 -> 10) so the vertical gap between
       track rows grows by 6px total.
       v11.105: bumped to 14.1px top + bottom per spec. */
    padding: 14.1px 0;
    border-bottom: 1px solid rgba(255,255,255,0.05);
  }
  .mylist-album-shelf-track:last-child { border-bottom: 0; }
  /* v11.040: track-row star button — same `.ep-rating-btn` UX as episode
     rows, just right-aligned in its grid cell. */
  .track-rating-btn { justify-self: end; }
  /* v11.101: per-track 5-star rating replaced with a single favorite STAR —
     reuses the `.ep-rating-btn` star (muted by default, champagne-gold via
     `.has-rating` when favorited). A touch larger than a rating star so it's an
     easy favorite tap target. */
  .track-fav-btn { font-size: 19px; }
  /* v10.440: track-number element re-shown after the v10.397 hide.
     Muted lavender-gray color so it reads as secondary metadata
     alongside the title; min-width keeps double-digit numbers
     (10+) aligned with single-digit ones. */
  .mylist-album-shelf-track-num {
    display: inline-flex !important;
    align-items: center;
    justify-content: flex-end;
    min-width: 16px;
    color: rgba(216, 208, 233, 0.55);
    font: 500 12px/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
  }
  /* v10.398: track title bumped DOWN 1px (14 -> 13) per spec — pulls
     the tracklist into tighter visual rhythm with the now-smaller
     "Your rating" widget and the per-track value text. */
  .mylist-album-shelf-track-title {
    color: #f8f4ff;
    /* v11.103: track titles set to 16.2px / 400 weight. */
    font: 400 16.2px/1.35 'Sohne', 'DM Sans', sans-serif;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
    /* v10.440: prep the title for the gradient-fade behavior below.
       When the per-track rating popout opens (`.mylist-album-shelf-track-rate.is-expanded`),
       the title gets a left-to-right alpha mask so the leftmost
       characters stay fully opaque while the right edge fades to
       transparent BEFORE running into the popout's rating widget.
       Mask transition lets the fade-in / fade-out match the
       popout's slide animation tempo. */
    transition: -webkit-mask-image 240ms cubic-bezier(0.22, 1, 0.36, 1),
                mask-image 240ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* When the sibling rating widget is in `.is-expanded`, mask the
     title from full-opaque on the left to fully transparent on the
     right. The 40%/100% stops give the title's first ~40% safe-zone
     of 100% opacity, then a gradient fade across the remaining 60%
     of the title's natural width, blending behind the popout. */
  .mylist-album-shelf-track:has(.mylist-album-shelf-track-rate.is-expanded) .mylist-album-shelf-track-title {
    -webkit-mask-image: linear-gradient(to right, #000 0%, #000 40%, transparent 100%);
            mask-image: linear-gradient(to right, #000 0%, #000 40%, transparent 100%);
  }
  /* v10.440: live scrub-value readout — the number that updates as
     the user drags across stars in the 10-star popout. Hidden until
     `.is-active` is set by the scrub handler, then fades in with
     champagne color matching the lit stars. Sits flush-right of the
     last star with a small gap. */
  .music-rating-scrub-value {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 8px;
    min-width: 22px;
    color: #E6C766;
    font: 700 13px/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: -0.01em;
    line-height: 1;
    opacity: 0;
    transition: opacity 120ms ease;
    pointer-events: none;
    white-space: nowrap;
  }
  .music-rating-scrub-value.is-active {
    opacity: 1;
  }
  .mylist-album-shelf-track-length { display: none !important; }
  /* v10.253: simple favorite-toggle button (now hidden by v10.397 — kept
     as a defensive style guard for any cached HTML still in flight). */
  .mylist-album-shelf-track-fav { display: none !important; }

  /* v10.397: per-track 5-star rating widget (collapsed / expanded). The
     container is the absolute-position anchor for the expanded sub-widget
     that slides leftward, so it must have a fixed right edge and enough
     vertical room (36px) to host the lit-star animation overflow. */
  .mylist-album-shelf-track-rate {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    min-height: 36px;
    min-width: 36px;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-album-shelf-track-rate-toggle {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 4px 4px 4px 8px;
    margin: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    color: rgba(216,208,233,0.42);
    transition: color 150ms ease, opacity 180ms ease, transform 150ms ease;
    -webkit-tap-highlight-color: transparent;
    line-height: 1;
  }
  .mylist-album-shelf-track-rate-toggle:hover { transform: scale(1.05); }
  .mylist-album-shelf-track-rate-toggle:active { transform: scale(0.94); }
  .mylist-album-shelf-track-rate-toggle:disabled {
    cursor: default;
    opacity: 0.45;
    transform: none;
  }
  .mylist-album-shelf-track-rate-toggle.is-rated {
    color: #F5B301;
  }
  /* v10.399: collapsed-state star is now a flex wrapper holding TWO
     `.music-rating-half` boxes (left + right halves of one ★ glyph),
     mirroring the album-level rendering. The boxes inside derive their
     size from the `--music-star-size` CSS variable set inline on this
     wrapper, so identical glyph shape / pointer tips as the
     "Your rating" widget above the tracklist. */
  .mylist-album-shelf-track-rate-star {
    display: inline-flex;
    align-items: center;
    line-height: 1;
  }
  /* The .music-rating-half default rule below (in the same file) sets
     cursor: pointer and a hover transform. We DON'T want either of those
     on the collapsed star — it's just a static composed glyph. */
  .mylist-album-shelf-track-rate-star .music-rating-half {
    cursor: default;
    pointer-events: none;
    transition: color 150ms ease;
  }
  .mylist-album-shelf-track-rate-star .music-rating-half:hover,
  .mylist-album-shelf-track-rate-star .music-rating-half:active {
    transform: none;
  }
  /* v10.398: per-track "4.5 / 5" label — weight 700 -> 600 (lighter by
     one weight step / 100) and font 13 -> 12 (1px smaller). Star icon
     in the same toggle keeps its 20px size; only the value text shrinks.
     v10.418: pinned to a fixed width with left-anchored text. Without
     this, "10 / 10" rendered ~6–8px wider than "9 / 10" / "8 / 10",
     which (combined with the toggle being right-justified in its
     container) pushed the star tip on those narrower-numeric rows to
     the right of the "10 / 10" rows' tips. With a fixed value-slot,
     the toggle's overall width is constant and every row's star tip
     sits on the same invisible vertical line. The min-width was sized
     to fit the widest case ("10 / 10") at Sohne 600 12px with a
     small safety margin. */
  .mylist-album-shelf-track-rate-value {
    color: #ffffff;
    /* v10.420: dropped font-weight 600 -> 500 (one weight step / 100
       lighter) per spec. The number reads as a quieter companion to
       the star glyph now instead of competing with it visually. */
    font: 500 12px/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: -0.01em;
    white-space: nowrap;
    display: inline-block;
    /* v10.420: with the "/ 10" denominator gone, the widest possible
       value is "10" (2 chars at Sohne 500 12px ≈ 14px) and the
       narrowest is "0" or empty. Shrunk the min-width floor from 44px
       to 18px so the bubble doesn't have a wide dead zone next to
       the star, while still being just wide enough that the
       single-digit "9" and the two-digit "10" rows keep the star tip
       aligned on a single invisible vertical line.
       v10.422: text-align flipped left -> center so the numbers
       themselves stack vertically on a single centered axis down the
       column. With left-align the digits sat flush against the
       slot's left edge, which meant "9" (one char) ended ~7px before
       "10"'s right edge — the rows lined up on the star but the
       numbers looked ragged. Center-align in a fixed 18px slot puts
       each number's visual center at the slot's midpoint regardless
       of digit count, so both axes (star tip + number center) are
       column-aligned now. */
    min-width: 18px;
    text-align: center;
  }

  /* v10.418: actionable post-add popup shown after the user adds an
     item from Universal Search. Floats above the search overlay so
     they can keep adding without losing context, fades on its own
     after 3.3s, or routes them to the just-added item on tap. */
  .shelfd-go-to-shelf-popup {
    position: fixed;
    left: 50%;
    bottom: max(env(safe-area-inset-bottom, 20px), 28px);
    transform: translate(-50%, 18px);
    z-index: 9500;
    display: inline-flex;
    align-items: center;
    gap: 14px;
    padding: 10px 10px 10px 18px;
    background: #181c20;
    border: 1px solid rgba(196,181,253,0.22);
    border-radius: 999px;
    box-shadow: 0 16px 48px rgba(0,0,0,0.55), 0 0 0 0.5px rgba(255,255,255,0.04);
    color: rgba(255,255,255,0.92);
    font: 600 14px/1.2 Aptos, 'Aptos Display', 'Segoe UI', sans-serif;
    opacity: 0;
    transition: opacity 0.22s ease, transform 0.26s cubic-bezier(0.22,1,0.36,1);
    pointer-events: auto;
    max-width: min(92vw, 420px);
  }
  .shelfd-go-to-shelf-popup.is-open {
    opacity: 1;
    transform: translate(-50%, 0);
  }
  .shelfd-go-to-shelf-popup-text {
    white-space: nowrap;
    color: rgba(255,255,255,0.85);
  }
  .shelfd-go-to-shelf-popup-action {
    appearance: none;
    -webkit-appearance: none;
    background: rgba(196,181,253,0.18);
    border: 1px solid rgba(196,181,253,0.32);
    color: #d8c9ff;
    padding: 8px 14px;
    border-radius: 999px;
    font: 600 13px/1 Aptos, 'Aptos Display', 'Segoe UI', sans-serif;
    cursor: pointer;
    letter-spacing: 0.02em;
    transition: background 0.15s ease, transform 0.12s ease;
    -webkit-tap-highlight-color: transparent;
  }
  .shelfd-go-to-shelf-popup-action:hover { background: rgba(196,181,253,0.24); }
  .shelfd-go-to-shelf-popup-action:active { background: rgba(196,181,253,0.30); transform: scale(0.97); }

  .shelfd-added-to-shelf-prompt {
    position: fixed;
    left: 50%;
    bottom: max(env(safe-area-inset-bottom, 20px), 34px);
    transform: translate3d(-50%, 18px, 0) scale(0.98);
    z-index: 9600;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    padding: 10px 16px 10px 12px;
    background: rgba(13, 18, 16, 0.94);
    border: 1px solid rgba(34, 197, 94, 0.42);
    border-radius: 999px;
    box-shadow: 0 18px 48px rgba(0,0,0,0.48), 0 0 22px rgba(34,197,94,0.14);
    color: rgba(236,253,245,0.96);
    font: 700 14px/1.15 Aptos, 'Aptos Display', 'Segoe UI', sans-serif;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease, transform 0.24s cubic-bezier(0.22,1,0.36,1);
  }
  .shelfd-added-to-shelf-prompt.is-open {
    opacity: 1;
    transform: translate3d(-50%, 0, 0) scale(1);
  }
  .shelfd-added-to-shelf-prompt-icon {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(34, 197, 94, 0.18);
    color: #34d399;
    flex: 0 0 auto;
  }
  .shelfd-added-to-shelf-prompt-icon svg {
    width: 16px;
    height: 16px;
    display: block;
  }
  .shelfd-added-to-shelf-prompt-text {
    white-space: nowrap;
  }

  .mylist-game-profile-saved-modal {
    position: fixed;
    inset: 0;
    z-index: 10450;
    display: grid;
    place-items: center;
    padding: 24px;
    opacity: 0;
    pointer-events: none;
    transform: scale(0.98);
    transition: opacity 0.18s ease, transform 0.22s cubic-bezier(0.22,1,0.36,1);
  }
  .mylist-game-profile-saved-modal.is-open {
    opacity: 1;
    transform: scale(1);
  }
  .mylist-game-profile-saved-modal-card {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 48px;
    max-width: min(86vw, 340px);
    padding: 12px 17px 12px 13px;
    border-radius: 999px;
    color: rgba(240, 253, 244, 0.98);
    background: rgba(13, 30, 21, 0.78);
    border: 1px solid rgba(74, 222, 128, 0.38);
    box-shadow: 0 24px 60px rgba(0,0,0,0.44), inset 0 1px 0 rgba(255,255,255,0.08);
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    backdrop-filter: blur(18px) saturate(1.2);
    font: 400 15px/1.2 "S�hne", "Sohne", Aptos, "Aptos Display", "Segoe UI", sans-serif;
    letter-spacing: 0;
  }
  .mylist-game-profile-saved-modal-icon {
    width: 25px;
    height: 25px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    background: rgba(34, 197, 94, 0.18);
    color: #86efac;
  }
  .mylist-game-profile-saved-modal-icon svg {
    width: 16px;
    height: 16px;
    display: block;
  }
  /* Expanded view: anchored to the right edge of the container, scales
     in from a right origin so it visually GLIDES LEFTWARD as it opens.
     Pill background + hairline lavender border give it visual weight
     above the row underneath. */
  .mylist-album-shelf-track-rate-expanded {
    position: absolute;
    right: 0;
    top: 50%;
    display: flex;
    align-items: center;
    padding: 4px 8px;
    border-radius: 999px;
    background: rgba(15, 13, 22, 0.96);
    border: 1px solid rgba(196, 181, 253, 0.16);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.36);
    transform: translate(0, -50%) scaleX(0);
    transform-origin: right center;
    opacity: 0;
    pointer-events: none;
    transition:
      transform 240ms cubic-bezier(0.22, 1, 0.36, 1),
      opacity 180ms ease;
    white-space: nowrap;
    z-index: 6;
  }
  .mylist-album-shelf-track-rate.is-expanded .mylist-album-shelf-track-rate-expanded {
    transform: translate(0, -50%) scaleX(1);
    opacity: 1;
    pointer-events: auto;
  }
  .mylist-album-shelf-track-rate.is-expanded .mylist-album-shelf-track-rate-toggle {
    opacity: 0;
    pointer-events: none;
  }

  /* v10.253: album-level rating widget — sits between hero and tracklist.
     Uses the standard Shelfd `.stars .star-btn` pattern.
     v10.435: layout flipped from column → 3-column row to host
     [Number of ratings] | [Your rating] | [Average rating]. Each
     column stacks its label above its value; the row centers in
     the section so the three blocks read as a balanced trio. The
     legacy single-column `.mylist-album-shelf-rating` (without the
     `--three-col` modifier) is no longer emitted; keeping the base
     rule above as a safety net for any stale read-only paths. */
  .mylist-album-shelf-rating {
    margin: 6px 0 22px;
    padding-top: 18px;
    border-top: 1px solid rgba(255,255,255,0.08);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
  }
  .mylist-album-shelf-rating.mylist-album-shelf-rating--three-col {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
  }
  .mylist-album-shelf-rating-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    flex: 1 1 0;
    min-width: 0;
  }
  .mylist-album-shelf-rating-col--count,
  .mylist-album-shelf-rating-col--avg {
    /* Side columns are narrower so the center "Your rating" bubble
       sits as the visual anchor — they hold their label + a single
       compact value (number-of-votes or "★ 4.6").
       v10.439: smooth fade + collapse transitions added here so
       when the user taps the center bubble to expand into the 10-
       star rate widget, the side columns gracefully fade to 0
       opacity AND collapse to 0 width — freeing horizontal space
       for the expanded bubble and giving the rate gesture sole
       visual focus. Same UX pattern as the title-card v10.412 fade
       of Details / + / Comments siblings when the bubble expands. */
    flex: 0 1 auto;
    transition:
      opacity 220ms ease,
      max-width 280ms cubic-bezier(0.22, 1, 0.36, 1),
      margin 280ms cubic-bezier(0.22, 1, 0.36, 1);
    overflow: hidden;
  }
  /* When the center bubble is in the `.is-expanded` state, fade
     out the count + average side columns and collapse their width
     to 0 so the expanded bubble has the full row to fan its 10
     stars into. Uses `:has()` for parent-aware selection — same
     pattern as the v10.412 title-card fade rule. On `.is-expanded`
     removal (rating committed or user taps outside), the rules
     reverse: opacity returns to 1, max-width grows back to its
     natural content size, and the columns spring back. */
  .mylist-album-shelf-rating:has(.rating-bubble.is-expanded) .mylist-album-shelf-rating-col--count,
  .mylist-album-shelf-rating:has(.rating-bubble.is-expanded) .mylist-album-shelf-rating-col--avg {
    opacity: 0;
    pointer-events: none;
    max-width: 0;
    margin: 0;
  }
  /* The center column itself grows to claim the freed space when
     the bubble expands, giving the stars track a wide canvas. */
  .mylist-album-shelf-rating:has(.rating-bubble.is-expanded) .mylist-album-shelf-rating-col--your {
    flex: 1 1 100%;
  }
  .mylist-album-shelf-rating-count-val {
    color: rgba(255,255,255,0.92);
    font: 600 18px/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: -0.01em;
    white-space: nowrap;
  }
  .mylist-album-shelf-rating-avg-val {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: rgba(255,255,255,0.92);
    font: 600 18px/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: -0.01em;
    white-space: nowrap;
  }
  .mylist-album-shelf-rating-avg-star {
    color: #d4b86a;
    font-size: 18px;
    line-height: 1;
  }
  .mylist-album-shelf-rating-avg-num {
    color: rgba(255,255,255,0.92);
  }
  .mylist-album-shelf-rating-label {
    color: rgba(216,208,233,0.62);
    font: 500 11px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }
  .mylist-album-shelf-rating-stars {
    display: inline-flex;
    gap: 4px;
    touch-action: none;
  }
  .mylist-album-shelf-rating-stars .star-btn {
    font-size: var(--star-size, 26px);
    line-height: 1;
  }
  /* v10.255: favorite-ratio readout below the rating widget. Lives inside
     the same `.mylist-album-shelf-rating` block so the section reads as one
     "your engagement" cluster. Lavender accent on the star, muted text.
     v10.417: now displays "Avg rating <value>" — pair the muted label with
     the same-weight value, small gap between them so the row stays compact
     under the star widget. */
  .mylist-album-shelf-fav-ratio {
    margin-top: 2px;
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    color: rgba(216,208,233,0.72);
    font: 600 13px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
  }
  .mylist-album-shelf-avg-rating-label {
    color: rgba(216,208,233,0.55);
    font-weight: 500;
    letter-spacing: 0.01em;
  }
  .mylist-album-shelf-track-empty {
    padding: 14px 0;
    color: rgba(216,208,233,0.55);
    font: 400 13px/1.3 'Sohne', 'DM Sans', sans-serif;
    text-align: center;
  }
  /* v10.258: release date + record label sit at the very bottom of the
     tracklist as a small facts block. */
  .mylist-album-shelf-album-footer {
    margin: 22px 0 0;
    padding: 18px 0 0;
    border-top: 1px solid rgba(255,255,255,0.08);
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px 18px;
  }
  .mylist-album-shelf-footer-fact dt {
    margin: 0 0 2px;
    color: rgba(216,208,233,0.55);
    font: 500 11px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .mylist-album-shelf-footer-fact dd {
    margin: 0;
    color: #f8f4ff;
    font: 500 14px/1.25 'Sohne', 'DM Sans', sans-serif;
    word-break: break-word;
  }
  @media (min-width: 720px) {
    .mylist-album-shelf-shell {
      max-width: 720px;
      left: auto;
      right: 0;
      box-shadow: -24px 0 60px rgba(0,0,0,0.4);
    }
    .mylist-album-shelf-cover { width: 300px; }
  }

  /* v10.246: Music Artist Profile page — full-screen slide-in. Hero =
     name + disambig + facts grid (type / DOB / age / place). Below =
     discography list. Tap any album → opens the existing Album Profile. */
  body.music-artist-profile-open { overflow: hidden; }
  .music-artist-profile-page {
    position: fixed;
    inset: 0;
    z-index: 7340;
    pointer-events: auto;
    background: transparent;
  }
  .music-artist-profile-shell {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: #0f0f12;
    color: #f8f4ff;
    transform: translate3d(100%, 0, 0);
    transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    overflow: hidden;
  }
  .music-artist-profile-page.is-open .music-artist-profile-shell {
    transform: translate3d(0, 0, 0);
  }
  .music-artist-profile-topbar {
    flex: 0 0 auto;
    min-height: 56px;
    padding: max(12px, env(safe-area-inset-top, 0px)) 16px 10px;
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr) 40px;
    align-items: center;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    background: #0f0f12;
  }
  .music-artist-profile-back {
    width: 38px; height: 38px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    background: rgba(255,255,255,0.05);
    color: #f8f4ff;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
    cursor: pointer;
  }
  .music-artist-profile-back svg { width: 24px; height: 24px; }
  .music-artist-profile-back:active { transform: scale(0.94); }
  .music-artist-profile-title-bar {
    text-align: center;
    font: 500 14px/1 'Sohne', 'DM Sans', sans-serif;
    color: #f8f4ff;
  }
  /* v10.258: heart-favorite button in the artist profile topbar. Mirrors the
     actor/actress heart pattern — outline when unfav, filled rose when fav. */
  .music-artist-profile-fav {
    width: 38px;
    height: 38px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    background: rgba(255,255,255,0.05);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms ease, border-color 140ms ease, transform 140ms ease;
    justify-self: end;
  }
  .music-artist-profile-fav svg {
    width: 20px;
    height: 20px;
    fill: rgba(248,244,255,0.6);
    transition: fill 140ms ease, transform 140ms ease;
  }
  .music-artist-profile-fav.is-favorited svg { fill: #ff6b7f; }
  .music-artist-profile-fav.is-favorited {
    background: rgba(255,107,127,0.10);
    border-color: rgba(255,107,127,0.36);
  }
  .music-artist-profile-fav:active { transform: scale(0.94); }
  .music-artist-profile-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    padding: 24px 18px max(28px, calc(env(safe-area-inset-bottom, 0px) + 24px));
  }

  .music-artist-profile-hero {
    margin-bottom: 22px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 14px;
  }
  /* v10.247: circular portrait hero (best-effort Wikipedia thumbnail). */
  .music-artist-profile-portrait {
    width: min(56vw, 200px);
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    background: linear-gradient(135deg, rgba(42,31,94,0.92), rgba(45,27,78,0.92));
    background-size: cover;
    background-position: center center;
    box-shadow: 0 22px 56px rgba(0,0,0,0.5);
    display: grid;
    place-items: center;
    overflow: hidden;
    flex-shrink: 0;
  }
  .music-artist-profile-portrait.has-img { background-color: #1c1535; }
  .music-artist-profile-portrait-initial {
    color: rgba(248,244,255,0.7);
    font: 600 56px/1 'Sohne', 'DM Sans', sans-serif;
  }
  .music-artist-profile-portrait.has-img .music-artist-profile-portrait-initial {
    display: none;
  }
  .music-artist-profile-name {
    margin: 0;
    color: #fff;
    font: 500 28px/1.12 'Sohne', 'DM Sans', sans-serif;
    word-break: break-word;
  }
  .music-artist-profile-disambig {
    margin-top: 6px;
    color: rgba(216,208,233,0.62);
    font: 400 14px/1.3 'Sohne', 'DM Sans', sans-serif;
  }
  .music-artist-profile-facts {
    margin: 16px 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px 18px;
  }
  .music-artist-profile-fact dt {
    margin: 0 0 2px;
    color: rgba(216,208,233,0.55);
    font: 500 11px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .music-artist-profile-fact dd {
    margin: 0;
    color: #f8f4ff;
    font: 500 14px/1.25 'Sohne', 'DM Sans', sans-serif;
    word-break: break-word;
  }

  .music-artist-profile-albums {
    margin-top: 8px;
    padding-top: 22px;
    border-top: 1px solid rgba(255,255,255,0.08);
  }
  .music-artist-profile-albums-heading {
    color: #ffffff;
    font: 500 16px/1.2 'Sohne', 'DM Sans', sans-serif;
    margin: 0 0 12px;
  }
  .music-artist-profile-album-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
  }
  .music-artist-profile-album {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px solid rgba(255,255,255,0.05);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .music-artist-profile-album:last-child { border-bottom: 0; }
  /* v10.403: removed the v10.402 hairline outline here. Per spec the
     outline belongs only on the album shelf cover (My List Full Page
     Album Details). */
  .music-artist-profile-album-cover {
    width: 56px;
    height: 56px;
    border-radius: 0.9px;
    background-size: cover;
    background-position: center center;
    background-color: #1c1535;
    flex-shrink: 0;
  }
  .music-artist-profile-album-cover.no-img {
    background: linear-gradient(135deg, rgba(42,31,94,0.92), rgba(45,27,78,0.92));
  }
  .music-artist-profile-album-meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
  }
  .music-artist-profile-album-title {
    color: #f8f4ff;
    font: 500 14px/1.25 'Sohne', 'DM Sans', sans-serif;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
  }
  .music-artist-profile-album-year {
    color: rgba(216,208,233,0.55);
    font: 400 12px/1.2 'Sohne', 'DM Sans', sans-serif;
  }
  .music-artist-profile-album-chevron {
    width: 18px;
    height: 18px;
    color: rgba(216,208,233,0.45);
    flex-shrink: 0;
  }
  .music-artist-profile-album:active {
    background: rgba(255,255,255,0.04);
  }
  .music-artist-profile-album-loading,
  .music-artist-profile-album-empty {
    padding: 14px 0;
    color: rgba(216,208,233,0.55);
    font: 400 13px/1.3 'Sohne', 'DM Sans', sans-serif;
    text-align: center;
  }
  @media (min-width: 720px) {
    .music-artist-profile-shell {
      max-width: 720px;
      left: auto;
      right: 0;
      box-shadow: -24px 0 60px rgba(0,0,0,0.4);
    }
  }

  /* v10.241: artist line on the FPReview hero for music albums. */
  .mylist-media-review-page.is-music-review .mylist-media-review-artist {
    margin-top: 6px;
    color: rgba(216,208,233,0.78);
    font: 500 15px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
    word-break: break-word;
  }
  /* v10.247: tracklist dropdown on the FPReview music hero. Sits below the
     rating chip. Closed by default — tap to expand.
     v10.894: moved out of the hero's left column to live between the
     hero strip and the body. Picks up its own side padding (16px) so it
     aligns with the hero/body strips above and below. */
  .mylist-review-tracklist {
    margin-top: 0;
    padding: 14px 16px 4px;
  }
  .mylist-review-tracklist-toggle {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 4px 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: #c4b5fd;
    font: 500 13px/1.2 'Sohne', 'DM Sans', sans-serif;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-review-tracklist-chevron {
    width: 14px;
    height: 14px;
    transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .mylist-review-tracklist-toggle.is-open .mylist-review-tracklist-chevron {
    transform: rotate(180deg);
  }
  .mylist-review-tracklist-toggle:hover { color: #f8f4ff; }
  .mylist-review-tracklist-toggle:active { opacity: 0.7; }
  .mylist-review-tracklist-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height 280ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .mylist-review-tracklist-list.is-open {
    max-height: 1600px;
    margin-top: 8px;
  }
  .mylist-review-tracklist-row {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px solid rgba(255,255,255,0.05);
  }
  .mylist-review-tracklist-row:last-child { border-bottom: 0; }
  .mylist-review-tracklist-num {
    color: rgba(216,208,233,0.45);
    font: 500 12px/1 'Sohne', 'DM Sans', sans-serif;
    text-align: right;
  }
  /* v10.894: titles now use the full section width (tracklist moved out
     of the hero's left column). Allow up to 2 lines via line-clamp so
     long features-credit titles like "The Girl Is Mine (with Paul
     McCartney) (feat. Paul McCartney)" don't break to 3+ rows. */
  .mylist-review-tracklist-title {
    color: #f8f4ff;
    font: 500 13px/1.3 'Sohne', 'DM Sans', sans-serif;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
    word-break: normal;
  }
  /* v10.894: star + per-track rating value next to it. Star keeps the
     gold accent; the numeric value follows spec � 300 weight, white,
     81% opacity. */
  .mylist-review-tracklist-rating {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
  .mylist-review-tracklist-rating-star {
    color: #f59e0b;
    font-size: 15px;
    line-height: 1;
  }
  .mylist-review-tracklist-rating-value {
    color: rgba(255,255,255,0.81);
    font: 300 13px/1 'Sohne', 'DM Sans', sans-serif;
  }
  /* Override the page-wide `* { font-weight: 500 !important }` so the
     spec's 300 weight survives on the per-track rating value. */
  .mylist-media-review-page .mylist-review-tracklist-rating-value { font-weight: 300 !important; }
  /* v10.253: filled star marker for favorited (but unrated) tracks. */
  .mylist-review-tracklist-fav {
    color: #f59e0b;
    font-size: 15px;
    line-height: 1;
  }

  /* v10.237 / v10.241: music FPReview + composer covers — 1:1 square,
     0.9px corners. v10.241 bumps the FPR cover to 150×150 px (same on
     mobile and the desktop breakpoint, since music art doesn't need the
     extra portrait height that movies do). */
  .mylist-media-review-page.is-music-review .mylist-media-review-poster {
    aspect-ratio: 1 / 1 !important;
    width: 150px !important;
    border-radius: 0.9px !important;
    background-position: center center !important;
  }
  .shelf-log-composer.is-music-composer .shelf-log-composer-poster {
    aspect-ratio: 1 / 1 !important;
    border-radius: 0.9px !important;
    background-position: center center !important;
  }
  /* Override the existing 720px+ rule that resets the FPR poster to 132px. */
  @media (min-width: 720px) {
    .mylist-media-review-page.is-music-review .mylist-media-review-poster {
      width: 150px !important;
    }
  }
  /* The hero grid's right column is locked at 104px (132px on tablet+).
     Widen it to 150px when music so the bigger square poster fits. */
  .mylist-media-review-page.is-music-review .mylist-media-review-hero {
    grid-template-columns: minmax(0, 1fr) 150px !important;
  }
  .card-info { flex: 1; min-width: 0; }
  .card-title-row { position: relative; display: flex; align-items: flex-start; padding-right: 38px; min-width: 0; }
  .card-title { flex: 1 1 auto; min-width: 0; font-size: 16.3px; font-weight: 600; letter-spacing: -0.03em; color: #e8e3f3; font-family: 'Sohne', 'DM Sans', sans-serif; }
  /* v11.247: the title text lives inside a <button> (.card-title-profile-btn),
     which does NOT inherit font-family/size/weight by default — that's why the
     title didn't look like Söhne. Force the full type spec onto the button. */
  #mylist-view #cards-grid .card .card-title,
  #mylist-view #cards-grid .card .card-title > span,
  #mylist-view #cards-grid .card .card-title-profile-btn,
  #mylist-view #cards-grid .card .media-title-profile-btn,
  #mylist-view #cards-grid .card .game-title-profile-btn {
    font-family: 'Sohne', 'DM Sans', sans-serif !important;
    font-size: 16.3px !important;
    font-weight: 600 !important;
    letter-spacing: -0.03em !important;
  }
  .card-genre { font-size: 11px; color: #a99dc6; text-transform: uppercase; letter-spacing: 1.2px; margin-top: 4px; }
  .card-release-date { font-size: 11px; color: rgba(139, 92, 246, 0.85); font-weight: 600; letter-spacing: 0.3px; margin-top: 2px; font-family: 'Sohne', 'DM Sans', sans-serif; }
  body.light-mode .card-release-date { color: rgba(109,40,217,0.8); }
  .delete-btn {
    background: none; border: none; color: #9990b3; cursor: pointer;
    font-size: 20px; padding: 4px 8px; min-width: 36px; min-height: 36px;
    display: flex; align-items: center; justify-content: center;
    position: absolute; top: -2px; right: -8px;
  }
  .delete-btn:hover { color: #ef4444; }
  .friend-card-add-btn {
    width: 34px; height: 34px; border-radius: 999px; border: 1px solid rgba(103,232,249,0.42);
    background: rgba(103,232,249,0.10); color: #67e8f9; font-size: 22px; line-height: 1;
    font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
    flex-shrink: 0; transition: background 0.2s, border-color 0.2s, transform 0.2s, opacity 0.2s;
    position: absolute; top: -1px; right: -6px;
  }
  .friend-card-add-btn:hover { background: rgba(103,232,249,0.18); border-color: #67e8f9; transform: scale(1.05); }
  .friend-card-add-btn.added { cursor: default; opacity: 0.75; transform: none; }
  body.light-mode .friend-card-add-btn { background: rgba(8,145,178,0.08); border-color: rgba(8,145,178,0.32); color: #0891b2; }
  body.light-mode .friend-card-add-btn:hover { background: rgba(8,145,178,0.14); border-color: #0891b2; }

  /* Status pills */
  .status-pills { display: flex; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
  .status-pill {
    padding: 3px 10px; border-radius: 4px; font-size: 11px; font-weight: 600;
    text-transform: uppercase; cursor: pointer; border: 1.5px solid #2a2248;
    background: transparent; color: #a99dc6; transition: all 0.2s;
    letter-spacing: 0.5px;
  }
  .status-pill.watching-active { border-color: transparent; background: linear-gradient(135deg, #7c3aed, #9333ea); color: #fff; }
  .status-pill.competitive-active { border-color: #4f46e5; background: #1e1b4b; color: #818cf8; }
  .status-pill.planned-active { border-color: #d97706; background: #352a1a; color: #fbbf24; }
  .status-pill.watched-active { border-color: #0891b2; background: #0c1f2e; color: #67e8f9; }
  .status-pill.paused-active { border-color: #c2410c; background: #3b2313; color: #f97316; }
  .status-pill.dropped-active { border-color: #dc2626; background: #3b1325; color: #ef4444; }

  /* Progress bar */
  .progress-area { margin-top: 8px; }
  .progress-meta { display: flex; justify-content: space-between; margin-bottom: 4px; font-size: 11px; color: #9990b3; }
  .progress-meta span:last-child { color: #a99dc6; }
  .progress-bar-row {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
  }
  .progress-bar-row .progress-bar {
    flex: 1 1 auto;
    min-width: 0;
  }
  .progress-percent-inline {
    flex: 0 0 auto;
    min-width: 28px;
    color: #a99dc6;
    font-size: 11px;
    text-align: right;
    white-space: nowrap;
  }
  .progress-bar { height: 5px; background: #1a1430; border-radius: 3px; overflow: hidden; }
  .progress-fill {
    height: 100%; background: linear-gradient(90deg, #7c3aed, #a855f7);
    border-radius: 3px; transition: width 0.4s ease;
  }

  /* Stars */
  .stars { display: flex; gap: 2px; align-items: center; }
  @keyframes star-pop {
    0%   { transform: scale(1); filter: brightness(1); }
    30%  { transform: scale(1.55); filter: brightness(1.5) drop-shadow(0 0 8px rgba(251,191,36,0.9)); }
    60%  { transform: scale(1.1);  filter: brightness(1.15); }
    100% { transform: scale(1); filter: brightness(1); }
  }
  @keyframes label-pop {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.3); color: #fbbf24; }
    100% { transform: scale(1); }
  }
  .star-label { display: inline-block; transform-origin: left center; }
  .ep-rating-btn { transform-origin: center; }
  .star-btn {
    background: none; border: none; cursor: pointer; padding: 0;
    color: #b8afd1; transition: color 0.15s, transform 0.15s;
  }
  .stars.rating-scale-five { gap: 0; }
  .stars.rating-scale-five .star-btn.half-step {
    width: calc(var(--star-size, 14px) * 0.54);
    overflow: hidden;
    line-height: 1;
  }
  .stars.rating-scale-five .star-btn.half-step.left { text-align: left; }
  .stars.rating-scale-five .star-btn.half-step.right { text-indent: calc(var(--star-size, 14px) * -0.46); }
  .star-btn.lit { color: #f59e0b; }
  .star-btn:hover { transform: scale(1.2); }
  .star-btn.star-pop { animation: star-pop 0.42s ease-out; }
  .star-label.label-pop { animation: label-pop 0.5s ease-out; }
  .star-label { font-size: 12px; color: #9990b3; margin-left: 6px; }
  #mylist-view .star-label { color: #ffffff !important; }
  .rating-area { margin-top: 6px; }
  .rating-label { font-size: 11px; color: #ffffff; margin-bottom: 2px; font-weight: 300; }
  #cards-grid .card .rating-area {
    margin-top: 7px;
  }
  #cards-grid .card .rating-area .rating-label {
    display: none;
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"] {
    --star-size: 22px !important;
    width: auto;
    max-width: 66px;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 0;
    overflow: hidden;
    vertical-align: middle;
    transform-origin: left center;
    transition:
      max-width 260ms cubic-bezier(0.22, 1, 0.36, 1),
      gap 220ms cubic-bezier(0.22, 1, 0.36, 1),
      padding 220ms ease,
      transform 180ms ease;
    -webkit-tap-highlight-color: transparent;
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"]:active {
    transform: scale(0.97);
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"] .star-btn {
    flex: 0 0 auto;
    width: 22px;
    min-width: 22px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 22px !important;
    line-height: 1;
    transform-origin: center;
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"]:not(.is-expanded) .star-btn:not(:first-of-type) {
    display: none;
  }
  /* v10.390: unify title-card rating star color to #F5B301. Two rules
     drive this — the collapsed-state forced first star (here), and a
     scoped `.star-btn.lit` override below. Both share the same value so
     the collapsed badge and every expanded lit star match exactly. */
  #cards-grid .card .rating-area .stars[data-prefix="overall"]:not(.is-expanded) .star-btn:first-of-type {
    color: #F5B301 !important;
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"] .star-btn.lit {
    color: #F5B301 !important;
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"] .star-label {
    flex: 0 0 auto;
    min-width: 18px;
    margin-left: 1px;
    color: #ffffff !important;
    font: 800 18px/1 'Sohne', 'DM Sans', sans-serif !important;
    letter-spacing: 0;
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"].is-expanded {
    max-width: min(100%, 292px);
    gap: 3px;
    padding-right: 8px;
    overflow: visible;
    position: relative;
    z-index: 6;
  }
  #cards-grid .card .rating-area .stars[data-prefix="overall"].is-expanded .star-btn {
    display: inline-flex;
  }
  #cards-grid .card .rating-area .stars.rating-scale-five[data-prefix="overall"] {
    max-width: 66px;
  }
  #cards-grid .card .rating-area .stars.rating-scale-five[data-prefix="overall"] .star-btn.half-step {
    width: 13px;
    min-width: 13px;
    height: 28px;
  }
  #cards-grid .card .rating-area .stars.rating-scale-five[data-prefix="overall"]:not(.is-expanded) .star-btn:first-of-type {
    width: 22px;
    min-width: 22px;
    overflow: visible;
    text-indent: 0;
    text-align: center;
  }
  #cards-grid .card .rating-area .stars.rating-scale-five[data-prefix="overall"].is-expanded {
    max-width: min(100%, 204px);
    gap: 0;
  }
  @media (max-width: 420px) {
    #cards-grid .card .rating-area .stars[data-prefix="overall"].is-expanded {
      max-width: min(100%, 260px);
      gap: 1px;
    }
    #cards-grid .card .rating-area .stars[data-prefix="overall"].is-expanded .star-btn {
      width: 20px;
      min-width: 20px;
      font-size: 20px !important;
    }
    #cards-grid .card .rating-area .stars.rating-scale-five[data-prefix="overall"].is-expanded .star-btn.half-step {
      width: 11px;
      min-width: 11px;
    }
  }

  body.mylist-media-review-open { overflow: hidden; }
  .mylist-media-review-page {
    position: fixed;
    inset: 0;
    z-index: 7200;
    background: #0f0f12;
    color: #f8f4ff;
    transform: translate3d(100%, 0, 0);
    transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform;
    overflow: hidden;
  }
  .mylist-media-review-page.is-open { transform: translate3d(0, 0, 0); }
  .mylist-media-review-page,
  .mylist-media-review-page * { font-weight: 500 !important; }
  .mylist-media-review-shell {
    position: relative;
    z-index: 1;
    height: 100dvh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: #0f0f12;
    transition: filter 220ms ease, transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: filter, transform;
  }
  .mylist-media-review-page.actions-open .mylist-media-review-shell {
    filter: blur(9px);
    transform: scale3d(0.985, 0.985, 1);
  }
  .mylist-media-review-topbar {
    flex: 0 0 auto;
    min-height: 56px;
    padding: max(12px, env(safe-area-inset-top, 0px)) 16px 10px;
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr) 40px;
    align-items: center;
    border-bottom: 1px solid rgba(255,255,255,0.08);
  }
  .mylist-media-review-topbar span {
    text-align: center;
    font: 500 14px/1 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
  }
  .mylist-media-review-back,
  .mylist-media-review-menu {
    width: 38px;
    height: 38px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    background: rgba(255,255,255,0.05);
    color: #f8f4ff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-media-review-menu {
    justify-self: end;
  }
  .mylist-media-review-back svg {
    width: 24px;
    height: 24px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.1;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .mylist-media-review-menu svg {
    width: 24px;
    height: 24px;
    fill: currentColor;
  }
  .mylist-media-review-share-top svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .mylist-media-review-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* v10.263: side padding moved into the inner hero + body so the hero
       slate strip can extend full-width like the composer's meta strip. */
    padding: 0 0 max(32px, calc(env(safe-area-inset-bottom, 0px) + 24px));
  }
  .mylist-media-review-hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 104px;
    gap: 18px;
    align-items: start;
    /* v10.263: composer-style meta strip — `#17171b` slate plate behind the
       title/poster/rating block, hairline divider below. Mirrors the
       `.shelf-log-composer-meta` look. */
    background: #17171b;
    padding: 18px 16px;
    border-bottom: 1px solid rgba(255,255,255,0.06);
  }
  .mylist-media-review-main {
    min-width: 0;
    padding-top: 2px;
  }
  .mylist-media-review-author {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
  }
  .mylist-media-review-avatar {
    width: 38px;
    height: 38px;
    border-radius: 999px;
    object-fit: cover;
    background: #1c1535;
    box-shadow: 0 10px 24px rgba(0,0,0,0.32);
  }
  .mylist-media-review-author strong {
    display: block;
    color: #fff;
    font: 500 15px/1.12 'Sohne', 'DM Sans', sans-serif;
  }
  .mylist-media-review-author span {
    display: block;
    margin-top: 4px;
    color: rgba(216,208,233,0.64);
    font: 500 12px/1.1 'Sohne', 'DM Sans', sans-serif;
  }
  .mylist-media-review-main h1 {
    margin: 0;
    color: #fff;
    font: 500 27px/0.98 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
  }
  .mylist-media-review-year {
    margin-top: 8px;
    color: rgba(216,208,233,0.58);
    font: 500 13px/1 'Sohne', 'DM Sans', sans-serif;
  }
  .mylist-media-review-rating {
    margin-top: 14px;
    display: flex;
    align-items: center;
    gap: 14px;
    color: #f6c84c;
  }
  .mylist-review-filled-stars {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    color: #f6c84c;
    line-height: 1;
  }
  .mylist-review-filled-star {
    font-size: 17px;
    line-height: 1;
  }
  /* v10.516: full-page review rating row — give the star cluster and the
     numeric label breathing room. Without this, the spans rendered
     inline with effectively zero gap (no parent flex / no margin) so the
     stars sat flush against the number ("★★★3.5"). The 10px gap matches
     the rest of the review page's compact-row rhythm. */
  .mylist-review-rating {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
  }
  .mylist-review-rating .mylist-review-filled-stars {
    margin-right: 0;
  }

  /* v10.516: disable iOS WKWebView auto-zoom on the shelf-page bio.
     iOS Safari + Capacitor WebView auto-zoom into any focusable text
     control whose computed `font-size` is < 16px. The bio is styled
     at 11px in `/css/16-light-mode-contrast.css:1060` (and that file
     is in the do-not-edit list per project memory), so when the user
     taps the bio the WebView snaps the viewport to it and zooms in.
     Workaround: override the computed font-size to 16px (above the
     auto-zoom threshold) and visually shrink the rendered text via
     a fractional `transform: scale()`. The text reads at the same
     visual size as before but iOS sees a 16px target → no auto-zoom.
     `transform-origin: top center` keeps the bio centered under the
     name. `text-size-adjust: 100%` prevents iOS from re-scaling on
     top. The selector body-prefix gives this rule enough specificity
     to win over the do-not-touch base rule without `!important`
     wars. */
  body #mylist-view #mylist-profile-controls .mylist-own-profile-bio {
    font-size: 16px !important;
    transform: scale(0.6875);
    transform-origin: top center;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    /* Compensate for the scaled-down visual: the element's box still
       reports the 16px height, but the rendered text only takes ~11px
       vertically. A negative margin-bottom claws back the empty space
       below the scaled text so the layout matches the pre-fix rhythm. */
    margin-bottom: -6px;
  }
  .mylist-review-rating-label,
  .mylist-review-rating-empty {
    color: rgba(248,244,255,0.72);
    font: 500 13px/1 'Sohne', 'DM Sans', sans-serif;
  }
  .mylist-review-rating-empty { margin-top: 14px; }
  .mylist-media-review-poster {
    width: 104px;
    aspect-ratio: 2 / 3;
    border-radius: 2.7px;
    background-size: cover;
    background-position: top center;
    display: grid;
    place-items: center;
    color: #c4b5fd;
    font-size: 30px;
    overflow: hidden;
    box-shadow: 0 18px 38px rgba(0,0,0,0.44), inset 0 0 0 1px rgba(255,255,255,0.08);
  }
  .mylist-media-review-poster.no-img {
    background: linear-gradient(135deg, rgba(42,31,94,0.92), rgba(45,27,78,0.92));
  }
  .mylist-media-review-body {
    /* v10.263: body sits on the base `#0f0f12` and inherits its own side
       padding now that the parent .mylist-media-review-content no longer
       provides it. The hero strip above already has a border-bottom, so
       the body's prior border-top + margin-top are redundant. */
    margin-top: 0;
    padding: 22px 16px 0;
    border-top: 0;
    background: #0f0f12;
  }
  .mylist-media-review-body p {
    margin: 0;
    color: rgba(248,244,255,0.92);
    font: 400 18px/1.55 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
    white-space: pre-wrap;
  }
  /* v10.221: explicit override that beats the universal weight cap above
     (`.mylist-media-review-page * { font-weight: 500 !important; }`).
     Higher selector specificity wins among same-priority !important rules. */
  .mylist-media-review-page .mylist-media-review-body p { font-weight: 400 !important; }
  .mylist-media-review-reply {
    margin-top: 18px;
    min-height: 34px;
    padding: 0 16px;
    border: 1px solid rgba(196,181,253,0.24);
    border-radius: 999px;
    background: rgba(196,181,253,0.08);
    color: #f8f4ff;
    font: 500 13px/1 'Sohne', 'DM Sans', sans-serif;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-media-review-body > .mylist-media-review-reply:first-child {
    margin-top: 0;
  }
  .mylist-media-review-replies {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid rgba(255,255,255,0.07);
  }
  .mylist-media-review-reply-composer {
    margin: 0 0 16px;
    padding: 12px;
    border: 1px solid rgba(196,181,253,0.16);
    border-radius: 12px;
    background: rgba(255,255,255,0.035);
  }
  .mylist-media-review-reply-composer[hidden] {
    display: none !important;
  }
  .mylist-media-review-reply-bubble > .mylist-media-review-reply-composer {
    margin: 10px 0 2px;
  }
  .mylist-media-review-reply-context {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 0 0 9px;
    color: rgba(216,208,233,0.66);
    font: 500 12px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
  }
  .mylist-media-review-reply-context[hidden] {
    display: none !important;
  }
  .mylist-media-review-reply-context strong {
    color: rgba(248,244,255,0.88);
    font: 500 12px/1.2 'Sohne', 'DM Sans', sans-serif;
  }
  .mylist-media-review-reply-context button {
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 999px;
    background: rgba(255,255,255,0.055);
    color: rgba(248,244,255,0.78);
    font: 500 18px/1 'Sohne', 'DM Sans', sans-serif;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 0 2px;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-media-review-reply-input {
    width: 100%;
    min-height: 42px;
    max-height: 120px;
    resize: none;
    border: 0;
    outline: none;
    background: transparent;
    color: #f8f4ff;
    font: 400 15px/1.35 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
    padding: 0;
    -webkit-appearance: none;
  }
  .mylist-media-review-page .mylist-media-review-reply-input { font-weight: 400 !important; }
  .mylist-media-review-reply-input::placeholder { color: rgba(216,208,233,0.45); }
  .mylist-media-review-reply-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
  }
  .mylist-media-review-reply-cancel,
  .mylist-media-review-reply-post {
    min-height: 34px;
    padding: 0 14px;
    border-radius: 999px;
    font: 500 13px/1 'Sohne', 'DM Sans', sans-serif;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-media-review-reply-cancel {
    border: 1px solid rgba(255,255,255,0.10);
    background: transparent;
    color: rgba(248,244,255,0.72);
  }
  .mylist-media-review-reply-post {
    border: 1px solid rgba(196,181,253,0.34);
    background: rgba(196,181,253,0.16);
    color: #f8f4ff;
  }
  .mylist-media-review-reply-post:disabled {
    opacity: 0.45;
  }
  .mylist-media-review-replies-head {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 12px;
    color: rgba(248,244,255,0.82);
    font: 500 13px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
  }
  .mylist-media-review-replies-head [data-review-reply-count] {
    color: rgba(216,208,233,0.52);
    font-size: 12px;
  }
  .mylist-media-review-replies-list {
    display: flex;
    flex-direction: column;
    gap: 0;
  }
  .mylist-media-review-replies-empty {
    color: rgba(216,208,233,0.48);
    font: 400 13px/1.35 'Sohne', 'DM Sans', sans-serif;
    padding: 4px 0 2px;
  }
  .mylist-media-review-page .mylist-media-review-replies-empty { font-weight: 400 !important; }
  .mylist-media-review-reply-item {
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr);
    gap: 10px;
    padding: 0 0 16px;
    margin-left: calc(var(--review-reply-depth, 0) * 18px);
  }
  .mylist-media-review-reply-item.is-child-reply {
    padding-top: 10px;
    padding-bottom: 0;
  }
  .mylist-media-review-reply-avatar {
    position: relative;
    display: flex;
    justify-content: center;
  }
  .mylist-media-review-reply-avatar img {
    width: 32px;
    height: 32px;
    border-radius: 999px;
    object-fit: cover;
    background: #1c1535;
    box-shadow: 0 0 0 1px rgba(255,255,255,0.08);
    z-index: 1;
  }
  .mylist-media-review-reply-line {
    position: absolute;
    top: 36px;
    bottom: -14px;
    width: 1px;
    background: rgba(196,181,253,0.18);
  }
  .mylist-media-review-reply-bubble {
    min-width: 0;
    padding-bottom: 16px;
    border-bottom: 1px solid rgba(255,255,255,0.055);
  }
  .mylist-media-review-reply-item:last-child {
    padding-bottom: 0;
  }
  .mylist-media-review-reply-item:last-child .mylist-media-review-reply-bubble {
    border-bottom: 0;
    padding-bottom: 0;
  }
  .mylist-media-review-reply-meta {
    display: flex;
    align-items: baseline;
    gap: 7px;
    min-width: 0;
    margin-bottom: 4px;
  }
  .mylist-media-review-reply-meta strong {
    color: #f8f4ff;
    font: 500 13px/1.2 'Sohne', 'DM Sans', sans-serif;
    min-width: 0;
  }
  .mylist-media-review-reply-meta span {
    color: rgba(216,208,233,0.48);
    font: 500 11px/1.2 'Sohne', 'DM Sans', sans-serif;
    flex-shrink: 0;
  }
  .mylist-media-review-reply-text {
    color: rgba(248,244,255,0.88);
    font: 400 14px/1.45 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  .mylist-media-review-page .mylist-media-review-reply-text { font-weight: 400 !important; }
  .mylist-media-review-reply-inline {
    appearance: none;
    border: 0;
    background: transparent;
    color: rgba(196,181,253,0.76);
    font: 500 12px/1 'Sohne', 'DM Sans', sans-serif;
    margin: 8px 0 0;
    padding: 6px 0;
    display: inline-flex;
    align-items: center;
    justify-content: flex-start;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-media-review-reply-inline:active {
    color: #f8f4ff;
    transform: scale(0.97);
  }
  .mylist-media-review-reply-children {
    margin-top: 2px;
  }
  .mylist-media-review-action-backdrop {
    position: fixed;
    inset: 0;
    z-index: 2;
    border: 0;
    padding: 0;
    background: rgba(0,0,0,0.36);
    opacity: 0;
    pointer-events: none;
    transition: opacity 220ms ease;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-media-review-page.actions-open .mylist-media-review-action-backdrop {
    opacity: 1;
    pointer-events: auto;
  }
  .mylist-media-review-action-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;
    padding: 16px 16px max(18px, calc(env(safe-area-inset-bottom, 0px) + 14px));
    border-radius: 24px 24px 0 0;
    border: 1px solid rgba(255,255,255,0.1);
    border-bottom: 0;
    background: #17171b;
    box-shadow: 0 -24px 54px rgba(0,0,0,0.46);
    transform: translate3d(0, 110%, 0);
    transition: transform 300ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform;
  }
  .mylist-media-review-page.actions-open .mylist-media-review-action-sheet {
    transform: translate3d(0, 0, 0);
  }
  .mylist-media-review-action-meta {
    padding: 2px 4px 14px;
    text-align: center;
  }
  .mylist-media-review-action-meta strong {
    display: block;
    color: #fff;
    font: 500 16px/1.18 'Sohne', 'DM Sans', sans-serif;
  }
  .mylist-media-review-action-meta span {
    display: block;
    margin-top: 5px;
    color: rgba(216,208,233,0.64);
    font: 500 12px/1.1 'Sohne', 'DM Sans', sans-serif;
  }
  .mylist-media-review-action-list {
    display: grid;
    gap: 8px;
  }
  .mylist-media-review-action {
    width: 100%;
    min-height: 49px;
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 14px;
    background: rgba(255,255,255,0.055);
    color: #f8f4ff;
    font: 500 15px/1 'Sohne', 'DM Sans', sans-serif;
    text-align: center;
    -webkit-tap-highlight-color: transparent;
  }
  .mylist-media-review-action.danger {
    color: #ff6b7f;
  }
  .mylist-media-review-action.done {
    background: rgba(196,181,253,0.14);
    border-color: rgba(196,181,253,0.22);
  }
  @media (min-width: 720px) {
    .mylist-media-review-shell { align-items: center; }
    .mylist-media-review-topbar,
    .mylist-media-review-content {
      width: min(100%, 720px);
    }
    .mylist-media-review-hero {
      grid-template-columns: minmax(0, 1fr) 132px;
    }
    .mylist-media-review-poster { width: 132px; }
    .mylist-media-review-action-sheet {
      left: 50%;
      right: auto;
      width: min(100%, 520px);
      transform: translate3d(-50%, 110%, 0);
    }
    .mylist-media-review-page.actions-open .mylist-media-review-action-sheet {
      transform: translate3d(-50%, 0, 0);
    }
  }

  /* v10.217 / v10.218: "I Watched..." / "I Played..." intermediate log
     composer. Slides in from the right when a user taps the + on a
     Watched/Played title card. On Save, hands off to .mylist-media-review-page.
     v10.218 — repalleted to match the Shelfd app scheme used in the FPReview:
       - page bg #0f0f12 (deep near-black) instead of slate
       - meta strip #17171b (Shelfd action-sheet surface) with subtle border
       - lavender #c4b5fd accents (Save, focused chips)
       - gold #f6c84c stars (matches FPReview rating)
       - rose #ff6b7f heart (matches FPReview danger / liked accent)
       - muted text rgba(216,208,233, .55-.64) (matches existing meta lines)
     Animation is transform-only (no layout writes) for ProMotion smoothness. */
  body.shelf-log-composer-open { overflow: hidden; }
  .shelf-log-composer {
    position: fixed;
    inset: 0;
    z-index: 7250;
    pointer-events: auto;
    background: transparent;
  }
  .shelf-log-composer-shell {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: #0f0f12;
    color: #f8f4ff;
    transform: translate3d(100%, 0, 0);
    transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform;
    overflow: hidden;
    font-family: 'Sohne', 'DM Sans', sans-serif;
  }
  .shelf-log-composer.is-open .shelf-log-composer-shell {
    transform: translate3d(0, 0, 0);
  }

  /* ----- Topbar ----- */
  .shelf-log-composer-topbar {
    flex: 0 0 auto;
    padding: max(12px, env(safe-area-inset-top, 0px)) 18px 12px;
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 12px;
    background: #0f0f12;
    border-bottom: 1px solid rgba(255,255,255,0.08);
  }
  .shelf-log-composer-cancel,
  .shelf-log-composer-save {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 6px 0;
    font-family: inherit;
    font-size: 16px;
    font-weight: 500;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .shelf-log-composer-cancel { color: rgba(216,208,233,0.64); justify-self: start; }
  .shelf-log-composer-save   { color: #c4b5fd; justify-self: end; }
  .shelf-log-composer-cancel:active { opacity: 0.6; }
  .shelf-log-composer-save:active   { opacity: 0.7; transform: scale(0.96); }
  .shelf-log-composer-title {
    text-align: center;
    font-size: 17px;
    font-weight: 500;
    color: #f8f4ff;
    letter-spacing: 0;
  }

  /* ----- Meta strip (poster + title + year) ----- */
  .shelf-log-composer-meta {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 18px;
    background: #17171b;
    border-bottom: 1px solid rgba(255,255,255,0.06);
  }
  .shelf-log-composer-poster {
    width: 54px;
    aspect-ratio: 2 / 3;
    border-radius: 4px;
    background-size: cover;
    background-position: center;
    background-color: #1c1535;
    flex: 0 0 auto;
    box-shadow: 0 8px 22px rgba(0,0,0,0.44), inset 0 0 0 1px rgba(255,255,255,0.06);
  }
  .shelf-log-composer-poster.no-img {
    background: linear-gradient(135deg, rgba(42,31,94,0.92), rgba(45,27,78,0.92));
  }
  .shelf-log-composer-meta-text {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
    flex-wrap: wrap;
  }
  .shelf-log-composer-meta-title {
    color: #fff;
    font-size: 17px;
    font-weight: 500;
  }
  .shelf-log-composer-meta-year {
    color: rgba(216,208,233,0.55);
    font-size: 13px;
    font-weight: 400;
  }

  /* ----- Scrollable body ----- */
  .shelf-log-composer-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    background: #0f0f12;
  }

  /* ----- Generic row ----- */
  .shelf-log-composer-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 18px;
    border-bottom: 1px solid rgba(255,255,255,0.06);
    background: transparent;
    color: inherit;
    text-align: left;
  }
  .shelf-log-composer-row-label {
    color: #f8f4ff;
    font-size: 15px;
    font-weight: 500;
  }
  .shelf-log-composer-row-value {
    color: rgba(216,208,233,0.62);
    font-size: 15px;
    font-weight: 400;
  }

  /* ----- Date row ----- */
  .shelf-log-composer-date-row {
    position: relative;
    width: 100%;
    appearance: none;
    -webkit-appearance: none;
    border: 0;
    border-bottom: 1px solid rgba(255,255,255,0.06);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .shelf-log-composer-date-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    pointer-events: auto;
    border: 0;
    padding: 0;
    background: transparent;
  }

  /* ----- Rated row (Shelfd 10-star, no half steps) ----- */
  .shelf-log-composer-rate-row {
    display: flex !important;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    padding: 18px 18px;
  }
  /* Reuse the global .stars / .star-btn rules (defined above) so the visual,
     hover scale, and `star-pop` animation match the rest of the app exactly.
     We just scope a few size + color tweaks for the composer surface. */
  .shelf-log-composer-stars {
    --star-size: 28px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  /* v10.521: canonical 5-star half-step slot pattern (matches the
     title-card bubble's v10.510 rebuild). One slot per visual star,
     containing a grey base ★ + a gold fill ★ clipped via clip-path
     to the slot's `--star-fill` percent, plus two invisible left/right
     half-zone hit buttons. Clean single-glyph rendering — no
     side-by-side glyph stacking, no seam between halves. */
  .shelf-log-star-slot {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--star-size);
    height: calc(var(--star-size) + 4px);
    flex-shrink: 0;
    line-height: 1;
  }
  .shelf-log-star-base,
  .shelf-log-star-fill {
    position: absolute;
    inset: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--star-size);
    line-height: 1;
    pointer-events: none;
  }
  .shelf-log-star-base {
    /* v10.523: match the canonical empty-star grey used by the title-
       card bubble's `.rating-bubble-star-base` (line 1455) so empty
       stars read consistently across all surfaces. */
    color: rgba(245, 242, 255, 0.30);
    z-index: 1;
  }
  .shelf-log-star-fill {
    /* v10.523: switched to the canonical champagne gold `#E6C766`
       per the project spec (see 01-mylists-cards-episodes.css:8631
       comment: "every rating bubble / star / lit star all share ONE
       color: #E6C766 — soft champagne. 100% opacity per spec"). The
       earlier `#f59e0b` (amber) was inconsistent with the bubble,
       the album-shelf rating, and the full-page review stars. */
    color: #E6C766;
    z-index: 2;
    clip-path: inset(0 calc(100% - var(--star-fill, 0%)) 0 0);
    -webkit-clip-path: inset(0 calc(100% - var(--star-fill, 0%)) 0 0);
    transition: clip-path 140ms cubic-bezier(0.16, 1, 0.3, 1),
                -webkit-clip-path 140ms cubic-bezier(0.16, 1, 0.3, 1);
  }
  .shelf-log-star-hit {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50%;
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    z-index: 3;
    -webkit-tap-highlight-color: transparent;
  }
  .shelf-log-star-hit-left  { left: 0; }
  .shelf-log-star-hit-right { right: 0; }
  /* Pop animation on the fill glyph after commit — same keyframe as
     the title-card bubble's `.rating-bubble-star-fill.star-pop`. */
  .shelf-log-star-fill.star-pop {
    animation: star-pop 0.42s ease-out;
  }

  /* ----- Review textarea ----- */
  .shelf-log-composer-review-row {
    display: block;
    padding: 14px 18px 8px;
  }
  .shelf-log-composer-review {
    width: 100%;
    min-height: 160px;
    border: 0;
    padding: 6px 0;
    background: transparent;
    color: #f8f4ff;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    font-size: 16px;
    font-weight: 400;
    line-height: 1.5;
    resize: none;
    outline: none;
  }
  .shelf-log-composer-review::placeholder { color: rgba(216,208,233,0.48); }
  /* v11.250: kill the purple focus outline/box-shadow/border on the review
     field (and its row) — a focus ring was showing when the user tapped in. */
  .shelf-log-composer-review:focus,
  .shelf-log-composer-review:focus-visible,
  .shelf-log-composer-review-row:focus-within {
    outline: none !important;
    box-shadow: none !important;
    border-color: transparent !important;
  }

  /* v11.250: center-screen saving spinner for the review composer. Shown the
     instant Save is tapped so the ~library-add wait reads as "processing"
     instead of a frozen screen. */
  .shelf-log-saving-overlay {
    position: fixed;
    inset: 0;
    z-index: 2147483647;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(8, 6, 14, 0.42);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    opacity: 0;
    transition: opacity 140ms ease;
    pointer-events: all;
  }
  .shelf-log-saving-overlay.is-on { opacity: 1; }
  .shelf-log-saving-spinner {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 3px solid rgba(196, 181, 253, 0.25);
    border-top-color: #c4b5fd;
    animation: shelfLogSavingSpin 0.7s linear infinite;
  }
  @keyframes shelfLogSavingSpin { to { transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) {
    .shelf-log-saving-spinner { animation-duration: 1.4s; }
  }

  /* ----- Tags ----- */
  .shelf-log-composer-tags-row {
    display: block;
    padding: 14px 18px;
  }
  .shelf-log-composer-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
  }
  .shelf-log-composer-tags:empty { margin-bottom: 0; }
  .shelf-log-composer-tag {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 4px 4px 4px 10px;
    border-radius: 999px;
    background: rgba(196,181,253,0.14);
    color: #c4b5fd;
    font-size: 13px;
    font-weight: 500;
    border: 1px solid rgba(196,181,253,0.22);
  }
  .shelf-log-composer-tag-remove {
    appearance: none;
    border: 0;
    background: transparent;
    width: 20px;
    height: 20px;
    border-radius: 999px;
    color: #c4b5fd;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .shelf-log-composer-tag-input {
    width: 100%;
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 12px;
    padding: 10px 14px;
    background: rgba(255,255,255,0.04);
    color: #f8f4ff;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    font-size: 15px;
    font-weight: 400;
    outline: none;
    transition: border-color 140ms ease, background 140ms ease;
  }
  .shelf-log-composer-tag-input::placeholder { color: rgba(216,208,233,0.48); }
  .shelf-log-composer-tag-input:focus {
    border-color: rgba(196,181,253,0.42);
    background: rgba(196,181,253,0.06);
  }

  /* ----- Bottom toggles row ----- */
  .shelf-log-composer-foot {
    flex: 0 0 auto;
    padding: 14px 14px max(18px, calc(env(safe-area-inset-bottom, 0px) + 12px));
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 4px;
    border-top: 1px solid rgba(255,255,255,0.08);
    background: #0f0f12;
  }
  .shelf-log-composer-toggle {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 6px 4px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    color: rgba(216,208,233,0.46);
    font-family: 'Sohne', 'DM Sans', sans-serif;
    font-size: 11px;
    font-weight: 500;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color 120ms ease;
  }
  .shelf-log-composer-toggle svg {
    width: 30px;
    height: 30px;
    stroke: currentColor;
  }
  .shelf-log-composer-toggle.is-on { color: #f8f4ff; }
  .shelf-log-composer-toggle:active { transform: scale(0.95); }

  @media (min-width: 720px) {
    .shelf-log-composer-shell {
      max-width: 720px;
      left: auto;
      right: 0;
      box-shadow: -24px 0 60px rgba(0,0,0,0.4);
    }
  }

  /* v10.233: Music Album Profile — slide-in-from-right overlay for albums
     surfaced by the universal-search Music chip. Shelfd palette: #0f0f12
     base, lavender accents, gold rating, rose for danger. Compositor-only
     transforms for ProMotion smoothness. */
  body.music-album-profile-open { overflow: hidden; }
  .music-album-profile-page {
    position: fixed;
    inset: 0;
    /* v10.249: bumped above the artist profile (7340) so a user tapping an
       album in the artist's discography sees the album profile slide in on
       TOP. Previously the album opened underneath, only revealing itself
       after the artist profile was dismissed. */
    z-index: 7400;
    pointer-events: auto;
    background: transparent;
  }
  .music-album-profile-shell {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: #0f0f12;
    color: #f8f4ff;
    transform: translate3d(100%, 0, 0);
    transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform;
    font-family: 'Sohne', 'DM Sans', sans-serif;
    overflow: hidden;
  }
  .music-album-profile-page.is-open .music-album-profile-shell {
    transform: translate3d(0, 0, 0);
  }
  .music-album-profile-topbar {
    flex: 0 0 auto;
    min-height: 56px;
    padding: max(12px, env(safe-area-inset-top, 0px)) 16px 10px;
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr) 40px;
    align-items: center;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    background: #0f0f12;
  }
  .music-album-profile-back {
    width: 38px;
    height: 38px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    background: rgba(255,255,255,0.05);
    color: #f8f4ff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
    cursor: pointer;
  }
  .music-album-profile-back svg { width: 24px; height: 24px; }
  .music-album-profile-back:active { transform: scale(0.94); }
  .music-album-profile-title {
    text-align: center;
    /* v11.067: bumped 14px -> 16px per spec. */
    font: 500 16px/1 'Sohne', 'DM Sans', sans-serif;
    color: #f8f4ff;
  }
  .music-album-profile-topbar-spacer { display: block; }
  .music-album-profile-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    padding: 24px 20px max(28px, calc(env(safe-area-inset-bottom, 0px) + 24px));
  }
  .music-album-profile-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    margin-bottom: 26px;
  }
  .music-album-profile-cover {
    width: min(72vw, 240px);
    aspect-ratio: 1 / 1;
    /* v10.234: 0px corners per spec — sharp/square album art. */
    border-radius: 0;
    background-size: cover;
    background-position: center;
    background-color: #1c1535;
    box-shadow: 0 24px 60px rgba(0,0,0,0.5);
    display: grid;
    place-items: center;
    font-size: 56px;
    color: rgba(196,181,253,0.6);
  }
  .music-album-profile-cover.no-img {
    background: linear-gradient(135deg, rgba(42,31,94,0.92), rgba(45,27,78,0.92));
  }
  .music-album-profile-meta {
    text-align: center;
    max-width: 100%;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .music-album-profile-album-title {
    margin: 0;
    color: #fff;
    font: 500 26px/1.15 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
    word-break: break-word;
  }
  .music-album-profile-artist {
    color: rgba(216,208,233,0.78);
    font: 500 16px/1.2 'Sohne', 'DM Sans', sans-serif;
  }
  .music-album-profile-year {
    color: rgba(216,208,233,0.55);
    font: 400 14px/1.1 'Sohne', 'DM Sans', sans-serif;
  }
  /* v10.734: status pill hoisted directly under the title on completed-status
     tabs (Movies ? Watched, TV/Anime ? Watched, Games ? Played, Music ?
     Listened, plus the existing Movies ? Watchlist hoist). Modifier class
     added by JS in 06-mylists-render-episodes-ratings.js when activeTab ===
     'watched' for the relevant sections.

     v10.736: CASCADE FIX.
     1. SPACING � per-section rules elsewhere in this file set margin-top
        to 0/6/8.4 at specificity (1,3,0)+!important, beating my v10.734
        (1,2,0) rule and producing the user-reported inconsistency
        (anime/music/shows had 0, games 6, movies 8.4). New selector below
        chains an attribute + extra class for specificity (1,5,0) so it
        wins on every section. Value bumped to 3px per Shelfd "0.5 line
        spacing" convention (1 line = 6px per v10.436 comment elsewhere).
     2. COLOR � `body.true-dark-mode #mylist-view .status-pill.watched-active`
        in 16-light-mode-contrast.css:4097-4104 has (1,4,0)+!important and
        was winning every status-pill text color. New selector below adds
        `body.true-dark-mode` prefix + chained classes for (1,5,0) so the
        white-60% color wins for any active-state variant. */
  #mylist-view .card[data-library-section] .status-pills.status-pills-selector-wrap.status-pills--under-title {
    margin-top: 3px !important;
  }
  /* v10.738: also override the border-color to white-60% so the outline
     matches the text (was the active-state's cyan/lavender/etc per the
     `.status-pill.watched-active`-style rules in 05-messages-early-polish.css
     and 01-mylists-cards-episodes.css). Our (1,5,0) specificity beats those
     (0,2,0) rules without needing to be split per active-state. Background
     intentionally unchanged � user spec was "outline" not fill. */
  body.true-dark-mode #mylist-view .status-pills.status-pills-selector-wrap.status-pills--under-title .status-pill,
  body.true-dark-mode #mylist-view .status-pills.status-pills-selector-wrap.status-pills--under-title .game-status-current-pill {
    color: rgba(255, 255, 255, 0.6) !important;
    border-color: rgba(255, 255, 255, 0.6) !important;
  }
  /* v10.234: facts list (release / genre / runtime).
     v10.701: force a single horizontal row of 3 explicit columns reading
     left?right Genre / Runtime / Release date. Previously was
     `repeat(auto-fit, minmax(120px, 1fr))` which collapsed to 2-then-1
     row on narrow meta blocks, making the facts look stacked vertically. */
  .music-album-profile-facts {
    margin: 12px 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px 12px;
    text-align: center;
  }
  .music-album-profile-fact dt {
    margin: 0 0 2px;
    color: rgba(216,208,233,0.55);
    font: 500 11px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .music-album-profile-fact dd {
    margin: 0;
    color: #f8f4ff;
    font: 500 14px/1.25 'Sohne', 'DM Sans', sans-serif;
    word-break: break-word;
  }
  /* v11.067: Apple Music / Spotify export links, sitting directly below the
     genre/runtime/release facts. Editorial-dark outline pills; the brand color
     lives only on the small leading logo so the row stays on-palette. */
  .music-album-profile-exports {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 16px 0 2px;
  }
  .music-album-profile-exports[hidden] { display: none; }
  .music-album-profile-export {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 15px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,0.14);
    background: rgba(255,255,255,0.05);
    color: #f4f1ff;
    font: 600 13px/1 'Sohne', 'DM Sans', sans-serif;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform 120ms ease, background 160ms ease, border-color 160ms ease;
  }
  .music-album-profile-export[hidden] { display: none; }
  .music-album-profile-export:active { transform: scale(0.96); }
  .music-album-profile-export svg { width: 16px; height: 16px; flex: 0 0 auto; }
  .music-album-profile-export-apple svg { color: #FA243C; }
  .music-album-profile-export-spotify svg { color: #1DB954; }
  /* v10.234: tracks block. */
  .music-album-profile-tracks {
    margin-top: 26px;
    padding-top: 22px;
    border-top: 1px solid rgba(255,255,255,0.08);
  }
  .music-album-profile-tracks-heading {
    color: #ffffff;
    font: 500 16px/1.2 'Sohne', 'DM Sans', sans-serif;
    margin: 0 0 12px;
  }
  .music-album-profile-track-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
  }
  .music-album-profile-track {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    /* v11.119: match the My Lists album-details tracklist row spacing. */
    padding: 14.1px 0;
    border-bottom: 1px solid rgba(255,255,255,0.04);
  }
  .music-album-profile-track:last-child { border-bottom: 0; }
  .music-album-profile-track-num {
    color: rgba(216,208,233,0.45);
    font: 500 13px/1 'Sohne', 'DM Sans', sans-serif;
    text-align: right;
  }
  .music-album-profile-track-title {
    color: #f8f4ff;
    /* v11.119: match the My Lists album-details track title (400 16.2px/1.35). */
    font: 400 16.2px/1.35 'Sohne', 'DM Sans', sans-serif;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
  }
  .music-album-profile-track-length {
    color: rgba(216,208,233,0.62);
    font: 400 13px/1 'Sohne', 'DM Sans', sans-serif;
    font-variant-numeric: tabular-nums;
  }
  .music-album-profile-track-loading,
  .music-album-profile-track-empty {
    padding: 14px 0;
    color: rgba(216,208,233,0.55);
    font: 400 13px/1.3 'Sohne', 'DM Sans', sans-serif;
    text-align: center;
  }
  .music-album-profile-add-btn {
    width: 100%;
    min-height: 52px;
    margin: 16px 0 0;
    padding: 0 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border: 1px solid rgba(196,181,253,0.32);
    border-radius: 14px;
    background: rgba(196,181,253,0.12);
    color: #f8f4ff;
    font: 500 16px/1 'Sohne', 'DM Sans', sans-serif;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms ease, transform 140ms ease;
  }
  .music-album-profile-add-btn svg {
    width: 20px;
    height: 20px;
    color: #c4b5fd;
  }
  .music-album-profile-add-btn:active {
    background: rgba(196,181,253,0.2);
    transform: scale(0.98);
  }
  /* v10.258 / v10.262: progressive add zone.
     - Default: full-width "Add to Shelf" pill (`.music-album-profile-add-btn`).
     - Tap it → row of three small status buttons (Listened / Planned / In
       Rotation) fits the same row width.
     - When album is already in the library → "Already Added · {status}"
       check pill replaces both states. */
  .music-album-profile-add-zone {
    margin: 16px 0 0;
  }
  .music-album-profile-add-row {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 6px;
  }
  .music-album-profile-add-row[hidden] { display: none !important; }
  .music-album-profile-add-choice {
    appearance: none;
    -webkit-appearance: none;
    min-height: 44px;
    padding: 0 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(196,181,253,0.32);
    border-radius: 12px;
    background: rgba(196,181,253,0.12);
    color: #f8f4ff;
    font: 500 13px/1 'Sohne', 'DM Sans', sans-serif;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms ease, transform 140ms ease;
    white-space: nowrap;
    text-align: center;
  }
  .music-album-profile-add-choice:active {
    background: rgba(196,181,253,0.2);
    transform: scale(0.96);
  }
  .music-album-profile-add-btn[hidden] { display: none !important; }
  /* v10.262: "Already Added" state — green-tinted pill with check icon. */
  .music-album-profile-already-added {
    background: rgba(52,211,153,0.10) !important;
    border-color: rgba(52,211,153,0.32) !important;
  }
  .music-album-profile-already-added svg {
    color: #34d399 !important;
  }
  /* v10.251: swap which icon shows based on data-add-state. + (plus) shows
     when the album is not yet in the shelf; ✓ (check) shows when it's
     already saved. */
  .music-album-profile-add-icon-add,
  .music-album-profile-add-icon-check { display: none; }
  .music-album-profile-add-btn[data-add-state="add"] .music-album-profile-add-icon-add { display: inline; }
  .music-album-profile-add-btn[data-add-state="in-shelf"] .music-album-profile-add-icon-check { display: inline; }
  .music-album-profile-add-btn[data-add-state="in-shelf"] {
    background: rgba(52,211,153,0.10);
    border-color: rgba(52,211,153,0.32);
  }
  .music-album-profile-add-btn[data-add-state="in-shelf"] svg.music-album-profile-add-icon-check {
    color: #34d399;
  }
  .music-album-profile-add-btn[data-add-state="in-shelf"] [data-music-profile-add-label] {
    color: #f8f4ff;
  }
  @media (min-width: 720px) {
    .music-album-profile-shell {
      max-width: 720px;
      left: auto;
      right: 0;
      box-shadow: -24px 0 60px rgba(0,0,0,0.4);
    }
    .music-album-profile-cover { width: 280px; }
  }

  /* Episodes */
  .ep-toggle-bar {
    border-top: 1px solid #2a2248; width: 100%; padding: 14px 20px;
    background: none; border-left: none; border-right: none; border-bottom: none;
    color: #ffffff; font-size: 13px; cursor: pointer; display: flex;
    align-items: center; justify-content: space-between; font-family: 'Sohne', 'DM Sans', sans-serif;
    transition: background 0.28s ease, border-color 0.28s ease, color 0.28s ease;
  }
  .ep-toggle-bar:hover {
    background: rgba(255,255,255,0.04);
    border-top-color: #3d3466;
  }
  .ep-toggle-bar:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 1px rgba(167,139,250,0.45);
  }
  .ep-arrow {
    transition: transform 0.72s cubic-bezier(0.16, 1, 0.3, 1), color 0.42s ease;
    display: inline-block;
    color: #bdb4d8;
  }
  .ep-arrow.open { transform: rotate(180deg); color: #c4b5fd; }
  .ep-list {
    /* v444: REMOVED the transform: translateY(-6px) ↔ translateY(0) animation.
       It was running on the SAME element being height-animated, which made the
       inner content visually slide UP at the same time the box was being
       CLIPPED by the shrinking/growing height. Those two effects compounded
       and produced the visible "shake/jitter" on collapse and on expand
       (especially obvious when the scroll-to-top did not fire to mask it).
       Now using ONLY a height transition for opening/closing — opacity also
       removed because it caused another sub-pixel render shift on close. */
    height: 0;
    overflow: hidden;
    transition: height 0.30s cubic-bezier(0.22, 1, 0.36, 1);
    overflow-anchor: none;
  }
  .ep-list.open {
    pointer-events: auto;
  }
  .ep-list-inner {
    padding: 4px 14px 14px;
  }
  .ep-actions { display: flex; gap: 8px; margin-bottom: 10px; justify-content: space-between; align-items: center; }
  /* v445/v446: episode scroll container — no visible scrollbar. */
  .ep-scroll {
    max-height: 340px;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 0;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
    overflow-anchor: none;
  }
  .ep-scroll::-webkit-scrollbar,
  .ep-scroll::-webkit-scrollbar-track,
  .ep-scroll::-webkit-scrollbar-thumb {
    display: none;
    width: 0;
    height: 0;
    background: transparent;
  }

  /* ── v446/v447/v448/v450: Focused-season mode (FLEX REBUILD) ───────────────
     Diagnosis from prior iterations:
       - When .ep-scroll had overflow: hidden, iOS Safari refused to pass touch
         to the inner .season-eps scroll. (v446 issue)
       - When .ep-scroll had overflow-y: auto BUT the active season content fit
         entirely within its max-height, iOS treated .ep-scroll as the
         touch-eligible scroll container, saw no overflow, and fell through to
         the page body. .season-eps was never tried as the scroll target.
         (v448 residual issue)
     Fix: in focused mode the .ep-list-inner becomes a fixed-height flex
     column. .ep-scroll inside it has flex:1 + overflow: visible, which means
     it is NO LONGER a scroll container at all — iOS skips straight past it
     and lands on .season-eps as the only scroll container in the chain.
     .season-eps is also a flex item with flex:1 and min-height:0 so it owns
     all remaining vertical space and scrolls episodes internally. */

  /* While focused, .ep-list-inner is a fixed-height flex column. */
  .ep-list.ep-list-focused-host > .ep-list-inner {
    display: flex !important;
    flex-direction: column !important;
    height: 460px !important;
    min-height: 0 !important;
  }
  .ep-list.ep-list-focused-host > .ep-list-inner > .ep-actions {
    flex: 0 0 auto !important;
  }
  /* .ep-scroll is no longer a scroll container in focused mode — it just
     stretches to fill the remaining height and lets .season-eps scroll. */
  .ep-list.ep-list-focused-host .ep-scroll.ep-season-focused {
    flex: 1 1 auto !important;
    max-height: none !important;
    overflow: visible !important;
    -webkit-overflow-scrolling: auto !important;
    min-height: 0 !important;
  }

  /* Inactive seasons are completely removed from layout. */
  .ep-scroll.ep-season-focused .season-block:not(.ep-season-active-block) {
    display: none !important;
  }

  /* Active season block fills the focused area as a flex column so the
     episode list (last child) can claim the leftover vertical space. */
  .ep-scroll.ep-season-focused .ep-season-active-block {
    display: flex !important;
    flex-direction: column !important;
    height: 100% !important;
    margin: 0 !important;
    min-height: 0 !important;
  }
  .ep-scroll.ep-season-focused .ep-season-active-block > .season-header {
    flex: 0 0 auto !important;
  }

  /* v770: .season-body wraps the rating bar + episode list. In focused mode
     it claims the remaining vertical space as an inner flex column so the
     rating bar stays fixed at the top and only .season-eps scrolls. */
  .ep-scroll.ep-season-focused .ep-season-active-block > .season-body {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
  }
  .ep-scroll.ep-season-focused .ep-season-active-block > .season-body > .season-rating-bar {
    flex: 0 0 auto !important;
  }

  /* Episode list = THE scroll container. flex:1 + min-height:0 is required
     for this to actually constrain height inside a flex parent. */
  .ep-scroll.ep-season-focused .ep-season-active-block .season-eps {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    height: auto !important;
    max-height: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch !important;
    overscroll-behavior: contain !important;
    touch-action: pan-y !important;
    scrollbar-width: none !important;
    -ms-overflow-style: none !important;
  }
  .ep-scroll.ep-season-focused .ep-season-active-block .season-eps::-webkit-scrollbar,
  .ep-scroll.ep-season-focused .ep-season-active-block .season-eps::-webkit-scrollbar-track,
  .ep-scroll.ep-season-focused .ep-season-active-block .season-eps::-webkit-scrollbar-thumb {
    display: none !important;
    width: 0 !important;
    height: 0 !important;
    background: transparent !important;
  }

  /* Belt-and-suspenders scrollbar hide for the broader .season-eps. */
  .season-eps {
    overflow-anchor: none;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .season-eps::-webkit-scrollbar { display: none; width: 0; height: 0; }

  /* Season rating bar — sits between the season header and episode list.
     In focused mode (above) it is held fixed by the .season-body flex layout. */
  .season-rating-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px 10px;
  }
  .season-rating-label {
    font-size: 12px;
    color: #7a6f99;
  }
  .season-block { margin-bottom: 6px; }
  .season-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 8px 10px; background: rgba(255,255,255,0.04); border-radius: 4px;
    cursor: pointer; user-select: none; margin-bottom: 4px;
    border: 1px solid #3d3466; transition: background 0.15s;
  }
  .season-header:hover { background: rgba(255,255,255,0.07); }
  .season-header-left { display: flex; align-items: center; gap: 8px; }
  .season-title { font-size: 13px; font-weight: 600; color: #e8e3f3; }
  .season-progress { font-size: 11px; color: #a99dc6; }
  .season-arrow { color: #a99dc6; font-size: 11px; transition: transform 0.2s; display: inline-block; }
  .season-arrow.open { transform: rotate(180deg); }
  .season-eps { padding-left: 8px; }
  .ep-row {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 8px 12px; border-radius: 4px; margin-bottom: 4px;
    background: rgba(255,255,255,0.02); border-left: 3px solid transparent;
    transition: border-left-color 0.36s ease, transform 0.2s ease; gap: 8px; position: relative;
    overflow: hidden; isolation: isolate;
  }
  .ep-row::before {
    content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
    background: rgba(34,211,238,0.09);
    clip-path: inset(0 100% 0 0 round 4px);
    opacity: 0;
  }
  .ep-row.watched-ep {
    border-left-color: #22d3ee;
    box-shadow: 0 0 0 1px rgba(34,211,238,0.08), 0 0 18px rgba(34,211,238,0.12);
  }
  .ep-row.watched-ep::before {
    clip-path: inset(0 0 0 0 round 4px);
    opacity: 1;
  }
  .ep-row.episode-watch-enter {
    border-left-color: transparent !important;
  }
  .ep-row.episode-watch-enter::before {
    opacity: 0;
    transform: scaleX(0);
  }
  .episode-fill-layer {
    position: absolute; inset: 0; pointer-events: none; z-index: 0;
    background: rgba(34,211,238,0.09);
    clip-path: inset(0 100% 0 0 round 4px);
    opacity: 1;
    will-change: clip-path, opacity;
  }
  .ep-row::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; z-index: 0;
    background:
      linear-gradient(90deg,
        rgba(255,255,255,0.00) 0%,
        rgba(255,255,255,0.92) 10%,
        rgba(103,232,249,0.82) 18%,
        rgba(34,211,238,0.48) 36%,
        rgba(34,211,238,0.16) 58%,
        rgba(34,211,238,0.04) 78%,
        rgba(34,211,238,0) 100%);
    transform-origin: left center;
    transform: translateX(-8%) scaleX(0.04);
    filter: blur(10px);
  }
  .ep-row > * { position: relative; z-index: 1; }
  .ep-row.episode-watch-sweep::after {
    animation: episodeWatchSweep 980ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  }
  .ep-row.episode-watch-impact .ep-check {
    animation: episodeCheckPop 540ms cubic-bezier(0.175, 0.885, 0.32, 1.25) forwards;
  }
  .ep-row.episode-watch-glow {
    animation: episodeRowGlow 1050ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  }
  .episode-burst {
    position: absolute; width: 84px; height: 84px; margin-left: -42px; margin-top: -42px;
    border-radius: 999px; pointer-events: none; z-index: 0;
    background:
      radial-gradient(circle,
        rgba(255,255,255,0.95) 0%,
        rgba(125,211,252,0.78) 14%,
        rgba(34,211,238,0.34) 34%,
        rgba(34,211,238,0.12) 52%,
        rgba(34,211,238,0) 72%);
    mix-blend-mode: screen;
  }
  @keyframes episodeWatchSweep {
    0% {
      opacity: 0;
      transform: translateX(-14%) scaleX(0.08);
      filter: blur(8px);
    }
    12% {
      opacity: 1;
      transform: translateX(-6%) scaleX(0.18);
      filter: blur(10px);
    }
    52% {
      opacity: 0.82;
      transform: translateX(0) scaleX(0.78);
      filter: blur(12px);
    }
    100% {
      opacity: 0;
      transform: translateX(2%) scaleX(1.08);
      filter: blur(18px);
    }
  }
  @keyframes episodeCheckPop {
    0% {
      transform: scale(1);
      box-shadow: 0 0 0 rgba(34,211,238,0);
      filter: brightness(1);
    }
    26% {
      transform: scale(1.22);
      box-shadow: 0 0 0 6px rgba(34,211,238,0.20);
      filter: brightness(1.18);
    }
    58% {
      transform: scale(1.08);
      box-shadow: 0 0 0 10px rgba(34,211,238,0.08);
      filter: brightness(1.08);
    }
    100% {
      transform: scale(1);
      box-shadow: 0 0 0 0 rgba(34,211,238,0);
      filter: brightness(1);
    }
  }
  @keyframes episodeRowGlow {
    0% {
      box-shadow: 0 0 0 0 rgba(34,211,238,0), 0 0 0 rgba(34,211,238,0);
    }
    20% {
      box-shadow: 0 0 0 1px rgba(103,232,249,0.24), 0 0 10px rgba(103,232,249,0.18);
    }
    55% {
      box-shadow: 0 0 0 1px rgba(34,211,238,0.18), 0 0 18px rgba(34,211,238,0.22);
    }
    100% {
      box-shadow: 0 0 0 1px rgba(34,211,238,0.08), 0 0 18px rgba(34,211,238,0.12);
    }
  }
  .ep-left { display: flex; align-items: flex-start; gap: 10px; flex: 1; min-width: 0; }
  .ep-check {
    width: 22px; height: 22px; border-radius: 3px; border: 2px solid #5c5278;
    background: transparent; cursor: pointer; display: flex; align-items: center;
    justify-content: center; color: #fff; font-size: 13px; font-weight: 700;
    transition: all 0.2s; flex-shrink: 0; margin-top: 1px;
  }
  .ep-check.checked { border-color: #22d3ee; background: #22d3ee; }
  .ep-row.future-locked-ep .ep-check,
  .ep-check:disabled {
    opacity: 0.36;
    cursor: default;
    border-color: rgba(92,82,120,0.55);
    background: rgba(255,255,255,0.03);
  }
  .ep-name { color: #e8e3f3; font-size: 14px; flex: 1; }
  .ep-rating-btn {
    background: none; border: none; cursor: pointer; padding: 2px 6px;
    font-size: 13px; color: #b8afd1; white-space: nowrap; flex-shrink: 0;
    border-radius: 4px; transition: background 0.15s;
  }
  .ep-rating-btn:hover { background: rgba(255,255,255,0.06); }
  /* v10.997: lit-state of the closed ep-rating button now uses the
     canonical champagne gold #E6C766 — was amber #f59e0b which was
     inconsistent with the title-card rating bubble, the full-page
     review stars, and the shelf-log composer stars. */
  .ep-rating-btn.has-rating { color: #E6C766; }
  .ep-rating-popup {
    position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
    background: #151025; border: 1px solid #3d3466; border-radius: 6px;
    padding: 8px 10px; display: flex; gap: 3px; align-items: center;
    box-shadow: 0 8px 24px rgba(0,0,0,0.5); z-index: 100;
  }
  /* v10.997: legacy `.ep-rating-popup .star-btn` rule kept dead-coded
     above just in case other paths still emit `.star-btn` markup —
     but the popup now ships slot-based markup (see below) that uses
     a separate selector family. */

  /* v10.999: per-episode review "+" button. Sits to the LEFT of the
     `.ep-rating-btn` on each episode row. Plain plus-icon when no
     review exists; swaps to the chat-bubble-with-lines glyph (same
     icon family as the title-card `.card-review-layers-btn`) once a
     review is saved. Icon color is muted lavender by default, becomes
     champagne gold when a review exists (matches the rating button's
     `.has-rating` color in v10.997). */
  .ep-review-btn {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: 0;
    padding: 4px;
    margin-right: 2px;
    color: rgba(245, 242, 255, 0.42);
    cursor: pointer;
    border-radius: 6px;
    line-height: 0;
    transition: background 0.15s, color 0.15s;
    -webkit-tap-highlight-color: transparent;
    flex-shrink: 0;
  }
  .ep-review-btn:hover,
  .ep-review-btn:focus-visible {
    background: rgba(255,255,255,0.06);
    color: rgba(245, 242, 255, 0.7);
    outline: none;
  }
  .ep-review-btn.has-comment {
    color: #E6C766;
  }
  .ep-review-btn.is-readonly { cursor: pointer; }
  .ep-review-btn svg {
    width: 18px;
    height: 18px;
    display: block;
  }

  /* v10.999: mini modal for writing an episode review. Centered card
     (not a bottom sheet) — fits the "mini" spec from the request.
     v11.002: z-index bumped 7200 → 12500. The full-page Show Details
     overlay (`.mylist-episode-page-overlay`) lives at z-index 12000;
     the previous 7200 was under it, so when the "+" button on an
     episode row opened the modal while the show-details page was up,
     the modal was painted underneath and invisible to the user. The
     symptom: "I hit the plus and nothing happened until I closed the
     full page show details". 12500 sits comfortably above the
     episode page (12000) but below the highest reserved layers
     (e.g. the v10.318 push-debug FAB at 2147483646). */
  .ep-review-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 12500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 18px;
    opacity: 0;
    transition: opacity 200ms ease;
    pointer-events: none;
  }
  .ep-review-modal-overlay.is-open {
    opacity: 1;
    pointer-events: auto;
  }
  .ep-review-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(5, 4, 13, 0.62);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
  }
  .ep-review-modal-sheet {
    position: relative;
    width: min(92vw, 460px);
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    background: #17171b;
    border-radius: 18px;
    padding: 18px 18px 14px;
    box-shadow: 0 24px 60px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.045);
    transform: translateY(8px) scale(0.98);
    opacity: 0;
    transition: transform 260ms cubic-bezier(0.18, 0.92, 0.18, 1), opacity 200ms ease;
  }
  .ep-review-modal-overlay.is-open .ep-review-modal-sheet {
    transform: translateY(0) scale(1);
    opacity: 1;
  }
  .ep-review-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 4px;
  }
  .ep-review-modal-header h2 {
    margin: 0;
    color: #f8f4ff;
    font: 500 16px/1.2 'Sohne', 'DM Sans', sans-serif;
    letter-spacing: 0;
  }
  .ep-review-modal-close {
    appearance: none;
    -webkit-appearance: none;
    background: rgba(255,255,255,0.05);
    border: 0;
    color: rgba(255,255,255,0.7);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .ep-review-modal-subtitle {
    color: rgba(196, 181, 253, 0.78);
    font: 300 12px/1.35 'Sohne', 'DM Sans', sans-serif;
    margin: 2px 0 12px;
  }
  .ep-review-modal-input {
    width: 100%;
    min-height: 120px;
    max-height: 40vh;
    box-sizing: border-box;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 12px;
    color: #f8f4ff;
    font: 400 14px/1.45 'Sohne', 'DM Sans', sans-serif;
    padding: 12px 14px;
    resize: vertical;
    outline: none;
  }
  .ep-review-modal-input:focus {
    border-color: rgba(196, 181, 253, 0.34);
    background: rgba(255,255,255,0.06);
  }
  .ep-review-modal-readonly-text {
    color: rgba(255,255,255,0.86);
    font: 400 14px/1.55 'Sohne', 'DM Sans', sans-serif;
    max-height: 50vh;
    overflow-y: auto;
    padding: 4px 2px 8px;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  .ep-review-modal-foot {
    margin-top: 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
  }
  .ep-review-modal-counter {
    color: rgba(196, 181, 253, 0.62);
    font: 300 11px/1 'Sohne', 'DM Sans', sans-serif;
    font-variant-numeric: tabular-nums;
  }
  .ep-review-modal-actions {
    display: flex;
    gap: 8px;
  }
  .ep-review-modal-cancel,
  .ep-review-modal-delete,
  .ep-review-modal-save {
    appearance: none;
    -webkit-appearance: none;
    border: 0;
    border-radius: 999px;
    padding: 8px 16px;
    font: 500 13px/1 'Sohne', 'DM Sans', sans-serif;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .ep-review-modal-cancel {
    background: rgba(255,255,255,0.06);
    color: rgba(255,255,255,0.78);
  }
  .ep-review-modal-delete {
    background: rgba(244, 63, 94, 0.14);
    color: #fda4af;
  }
  .ep-review-modal-save {
    background: #E6C766;
    color: #1a1404;
  }
  .ep-review-modal-cancel:hover { background: rgba(255,255,255,0.10); }
  .ep-review-modal-delete:hover { background: rgba(244, 63, 94, 0.22); }
  .ep-review-modal-save:hover { filter: brightness(1.04); }

  /* v10.997: SLOT-BASED episode rating widget. Mirrors the shelf-log
     composer's `.shelf-log-star-slot` pattern but scoped to the inline
     popup at 16px scale.
       - Empty star: outlined grey ★ via `.ep-rating-star-base`
       - Filled star: champagne-gold #E6C766 ★ via `.ep-rating-star-fill`,
         clipped to `--ep-star-fill` percent (0 / 50 / 100)
       - Two invisible hit zones per slot (left = half, right = full)
       - clip-path transitions for smooth half-step morphs during scrub
     Touch handler (epRatingStarsTouchMove) writes `--ep-star-fill`
     directly per slot → one property update per crossover → no style
     thrash, smooth 120Hz scrub on ProMotion. */
  .ep-rating-popup-stars {
    --ep-star-size: 16px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    touch-action: pan-y;
  }
  .ep-rating-star-slot {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--ep-star-size);
    height: calc(var(--ep-star-size) + 2px);
    flex-shrink: 0;
    line-height: 1;
  }
  .ep-rating-star-base,
  .ep-rating-star-fill {
    position: absolute;
    inset: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--ep-star-size);
    line-height: 1;
    pointer-events: none;
  }
  .ep-rating-star-base {
    color: rgba(245, 242, 255, 0.30); /* canonical empty-star grey */
    z-index: 1;
  }
  .ep-rating-star-fill {
    color: #E6C766; /* canonical champagne gold */
    z-index: 2;
    clip-path: inset(0 calc(100% - var(--ep-star-fill, 0%)) 0 0);
    -webkit-clip-path: inset(0 calc(100% - var(--ep-star-fill, 0%)) 0 0);
    transition: clip-path 140ms cubic-bezier(0.16, 1, 0.3, 1),
                -webkit-clip-path 140ms cubic-bezier(0.16, 1, 0.3, 1);
  }
  .ep-rating-star-hit {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50%;
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    z-index: 3;
    -webkit-tap-highlight-color: transparent;
  }
  .ep-rating-star-hit-left  { left: 0; }
  .ep-rating-star-hit-right { right: 0; }
  .ep-rating-star-hit-full  { left: 0; width: 100%; } /* 10-star scale: full-width hit */
  .ep-rating-popup-label {
    margin-left: 6px;
    color: #E6C766;
    font: 500 12px/1 'Sohne', 'DM Sans', sans-serif;
    font-variant-numeric: tabular-nums;
  }

  /* v11.013: overall show-rating widget on the full-page show-details
     hero. Reuses the v10.997 `.ep-rating-star-slot/-base/-fill/-hit`
     class family — this wrapper only bumps the star size (22px vs the
     popup's 16px) and the label font-size (16px vs 12px) per spec
     ("slightly bigger"). Same champagne gold, same slot-based
     half-step fill, same smooth scrub via myListOverallRatingTouch*. */
  .mylist-overall-rating-stars {
    --ep-star-size: 22px;
    gap: 3px;
  }
  .mylist-overall-rating-stars .ep-rating-popup-label {
    margin-left: 8px;
    font-size: 16px;
  }

  /* v11.013: rating + review buttons disabled for unreleased episodes.
     Faded look matches the existing `.ep-check:disabled` /
     `.ep-row.future-locked-ep .ep-check` pattern (v10.951). The button
     itself has `disabled` on the element so the click is also
     blocked at the browser level — pointer-events ensures even ghost
     synthetic clicks can't reach the handler. */
  .ep-review-btn.is-future-locked,
  .ep-review-btn:disabled,
  .ep-rating-btn.is-future-locked,
  .ep-rating-btn:disabled {
    opacity: 0.32;
    cursor: not-allowed;
    pointer-events: none;
    filter: grayscale(0.45);
  }

  /* v11.025: locked season-rating chip on the full-page show details —
     shown when the season hasn't released yet. Dimmed + non-interactive,
     matching the episode-level future-lock treatment. `pointer-events:
     none` guarantees no tap can reach a (non-existent) handler. */
  .mylist-episode-page-season-rating-chip.is-future-locked {
    opacity: 0.32;
    cursor: not-allowed;
    pointer-events: none;
    filter: grayscale(0.45);
  }


/* V266: Games card platform / hours / Tracker Stats details — clean mobile-first lines, no heavy capsules. */
.game-library-card {
  position: relative;
  padding-bottom: 8px;
}
.games-wishlist-card .games-wishlist-card-info {
  display: flex;
  flex-direction: column;
  /* v10.434: `min-height: 100%` removed — paired with the priority
     row's `margin-top: auto` (also removed below), the old layout
     forced the card-info column to stretch to match the cover and
     pushed the priority bubble to the very bottom. That made
     wishlist cards visibly taller than the playing-card variants
     even when they had less content. Now the column sizes to its
     natural content height like the playing cards do. */
}
.games-wishlist-card .games-wishlist-card-genre,
.games-wishlist-card .games-wishlist-card-platforms {
  font-size: 12px;
  font-weight: 500;
}
.games-wishlist-card .games-wishlist-card-priority {
  /* v10.434: `margin-top: auto` dropped so the priority bubble flows
     directly after the meta lines instead of being pinned to the
     card-info column's bottom edge. With this + the parent
     `min-height: 100%` removal above, wishlist cards now match the
     vertical size of playing cards. Padding-top reduced 10 -> 4 to
     give the bubble a tight single-line gap from the meta above
     (still uses default flex flow, no auto stretching). */
  padding-top: 4px;
  display: flex;
  justify-content: flex-start;
  align-items: flex-end;
}
.games-wishlist-card .games-wishlist-card-priority .watchlist-priority-slot {
  min-height: 22px;
}
.game-library-card .card-action-row {
  padding-right: 0;
}
.game-library-card .card-footer-actions {
  justify-content: center;
  width: 100%;
}
.game-card-edit-btn {
  position: absolute;
  right: 12px;
  bottom: 12px;
  width: 25px;
  height: 25px;
  padding: 0;
  border: 0;
  background: transparent;
  color: #ffffff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0.82;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 160ms ease, transform 180ms cubic-bezier(0.16, 1, 0.3, 1), color 160ms ease;
}
.game-card-edit-btn svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.game-card-edit-btn:active {
  transform: scale(0.92);
  opacity: 1;
}
.game-card-edit-btn:hover { color: #ffffff; opacity: 1; }
/* v10.231: competitive title-card "More" button — REBUILT from scratch
   under a fresh class (`.competitive-more-btn`) so it carries none of the
   old `.game-card-more-btn` baggage (the shared 6px/450 compact-text
   override in 17-auth-flow-setup.css used to shrink its label). No
   `!important` needed — this class appears in no other selector group, so
   plain declarations win cleanly.
   Position: anchored to the COVER's bottom edge so it lines up with the
   rating bubble. Pin TOP at the cover-bottom Y (142 desktop / 167 ≤700px)
   then translateY(-100%) raises the button by its own height so its BOTTOM
   lands exactly on that line — robust to the button's own height. */
.competitive-more-btn {
  position: absolute;
  right: 10px;
  top: 142px;
  bottom: auto;
  transform: translateY(-100%);
  min-width: 54px;
  height: 30px;
  padding: 0 13px;
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 999px;
  background: rgba(255,255,255,0.075);
  color: #ffffff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 10px;
  font-weight: 300;
  line-height: 1;
  letter-spacing: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 10px 22px rgba(0,0,0,0.24);
  transition: background 160ms ease, border-color 160ms ease, transform 160ms cubic-bezier(0.16, 1, 0.3, 1);
}
.competitive-more-btn:active {
  /* keep the translateY(-100%) lift while applying the press scale */
  transform: translateY(-100%) scale(0.94);
  background: rgba(255,255,255,0.13);
  border-color: rgba(255,255,255,0.18);
}
.competitive-more-btn:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.18);
}
/* ≤700px the game cover grows so its bottom edge moves to Y=167 (matching
   the .card-action-row mobile rule) — follow it so the button stays level
   with the rating bubble. */
@media (max-width: 700px) {
  .competitive-more-btn { top: 167px; bottom: auto; }
}
/* v314: expandable single-pill pop-out status selector (all card types) */
.game-status-pills-wrap, .status-pills-selector-wrap { margin-top: 6px; }
.game-status-selector {
  display: inline-flex;
  align-items: center;
}
.game-status-current-pill {
  flex-shrink: 0;
  position: relative;
}
.game-status-options {
  display: flex;
  align-items: center;
  gap: 4px;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  padding-left: 0;
  /* v11.203: open animation now rides opacity + a small translateX, NOT
     max-width. Animating max-width kept the box mid-resize for 340ms, during
     which overflow-x:auto wasn't reliably scrollable — so early touches after
     opening did nothing ("have to fidget before it scrolls"). max-width now
     switches INSTANTLY (no transition on it), so the tray is fully sized and
     natively scrollable the moment it opens; the eye still reads a smooth
     reveal from the opacity + slide. */
  transform: translateX(-6px);
  transition:
    opacity 220ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 220ms cubic-bezier(0.16, 1, 0.3, 1),
    padding-left 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
.game-status-selector.expanded .game-status-options {
  max-width: 380px;
  opacity: 1;
  padding-left: 5px;
  transform: translateX(0);
}
.game-status-options .status-pill {
  border-color: rgba(255, 252, 241, 0.6);
}

/* v312: inline game stats rows on the card */
.game-card-stats-inline {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 4px 0 5px;
}
.game-card-stat-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  line-height: 1.4;
}
.game-card-stat-label {
  color: rgba(255,255,255,0.5);
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
  min-width: 82px;
}
.game-card-stat-val {
  color: #ede8fc;
  font-weight: 650;
}
.game-card-tracker-icon-link {
  display: inline-flex;
  align-items: center;
  color: #06b6d4;
  text-decoration: none;
}
.game-card-tracker-icon-link svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.game-card-tracker-icon-link:hover { color: #ffffff; }
body.light-mode .game-card-stat-label { color: rgba(36,22,64,0.5); }
body.light-mode .game-card-stat-val { color: #241640; }
body.light-mode .game-card-tracker-icon-link { color: #6d28d9; }
body.light-mode .game-card-tracker-icon-link:hover { color: #241640; }

/* v945: Tracker.gg competitive API-only stats/profile connection framework */
.tracker-import-logo {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: linear-gradient(135deg, rgba(6,182,212,0.28), rgba(167,139,250,0.26));
  color: #eaf8ff;
  font-size: 13px;
  font-weight: 800;
}
.tracker-card-strip {
  width: 100%;
  margin: 6px 0 5px;
  padding: 13px 16px 12px;
  border: 0;
  border-radius: 9px;
  background: rgba(52,48,64,0.92);
  color: #ede8fc;
  text-align: left;
  cursor: pointer;
  contain: paint;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.025);
  transition: transform 180ms ease, background 180ms ease;
}
.tracker-card-strip:active { transform: scale(0.985); }
.tracker-card-strip-head { display: flex; align-items: center; justify-content: flex-start; gap: 8px; margin-bottom: 16px; }
.tracker-card-provider { color: #c4b5fd; font-size: 10px; font-weight: 750; text-transform: uppercase; letter-spacing: 0.4px; }
.tracker-card-account { min-width: 0; color: rgba(255,255,255,0.68); font-size: 14px; line-height: 1; font-weight: 760; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tracker-card-stat-grid,
.tracker-stats-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.tracker-card-strip .tracker-card-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; align-items: start; }
.tracker-card-stat-cell { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.tracker-card-stat-kicker { min-width: 0; display: flex; align-items: baseline; gap: 6px; max-width: 100%; }
.tracker-card-stat-label { color: #ffffff; font-size: 11px; line-height: 1; font-weight: 850; text-transform: uppercase; letter-spacing: 1px; }
.tracker-card-stat-value { min-width: 0; color: rgba(255,255,255,0.78); font-size: 10px; line-height: 1; font-weight: 500; letter-spacing: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tracker-card-rank-art {
  width: 31px;
  height: 31px;
  display: inline-grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 45% 40%, rgba(255,255,255,0.25), rgba(167,139,250,0.12) 42%, rgba(0,0,0,0.2) 72%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.16), 0 2px 6px rgba(0,0,0,0.28);
}
.tracker-card-rank-diamond {
  width: 16px;
  height: 16px;
  transform: rotate(45deg);
  border-radius: 4px;
  background: linear-gradient(135deg, #c4b5fd, #34d399);
  box-shadow: inset 0 0 0 2px rgba(255,255,255,0.32), 0 0 0 2px rgba(0,0,0,0.18);
}
.tracker-card-rank-sprite {
  width: 31px;
  height: 25px;
  display: inline-block;
  background-image: url('/assets/valorant-rank-badges.png?v=951_real_badges');
  background-repeat: no-repeat;
  background-size: 186px 100px;
  background-position: calc(var(--tracker-rank-col) * 31px * -1) calc(var(--tracker-rank-row) * 25px * -1);
  filter: drop-shadow(0 2px 5px rgba(0,0,0,0.38));
}
.tracker-stat-cell { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tracker-stat-cell span { color: rgba(255,255,255,0.46); font-size: 9px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.35px; }
.tracker-stat-cell strong { min-width: 0; color: #ffffff; font-size: 11px; font-weight: 750; line-height: 1.15; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tracker-rank-badge {
  --tracker-rank-sprite-w: 22px;
  --tracker-rank-sprite-h: 18px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 22px;
  padding: 2px 7px 2px 4px;
  border-radius: 999px;
  background: rgba(255,255,255,0.055);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08);
  white-space: nowrap;
}
.tracker-rank-sprite {
  width: var(--tracker-rank-sprite-w);
  height: var(--tracker-rank-sprite-h);
  flex: 0 0 auto;
  display: inline-block;
  background-image: url('/assets/valorant-rank-badges.png?v=951_real_badges');
  background-repeat: no-repeat;
  background-size: calc(var(--tracker-rank-sprite-w) * 6) calc(var(--tracker-rank-sprite-h) * 4);
  background-position: calc(var(--tracker-rank-col) * var(--tracker-rank-sprite-w) * -1) calc(var(--tracker-rank-row) * var(--tracker-rank-sprite-h) * -1);
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.35));
}
.tracker-rank-code { color: #ffffff; font-size: 10px; font-weight: 820; letter-spacing: 0.18px; }
.tracker-rank-badge-radiant .tracker-rank-code { letter-spacing: 0.08px; }
.tracker-link-overlay,
.tracker-stats-page { position: fixed; inset: 0; opacity: 0; pointer-events: none; transition: opacity 220ms ease; }
.tracker-stats-page { z-index: 3600; }
.tracker-link-overlay { z-index: 9800; }
.tracker-link-overlay.is-open,
.tracker-stats-page.is-open { opacity: 1; pointer-events: auto; }
.tracker-link-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.62); }
.tracker-link-sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: calc(100dvh - env(safe-area-inset-top, 0px) - 18px);
  padding: 10px 16px calc(18px + env(safe-area-inset-bottom, 0px));
  border-radius: 18px 18px 0 0;
  background: #0b0b0f;
  color: #f5f2ff;
  box-shadow: 0 -22px 70px rgba(0,0,0,0.42);
  overflow: auto;
  transform: translate3d(0, 18px, 0);
  transition: transform 260ms cubic-bezier(0.16, 1, 0.3, 1);
}
.tracker-link-overlay.is-open .tracker-link-sheet { transform: translate3d(0, 0, 0); }
.tracker-link-handle { width: 42px; height: 4px; border-radius: 999px; background: rgba(255,255,255,0.2); margin: 0 auto 14px; }
.tracker-link-top,
.tracker-stats-topbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tracker-link-kicker,
.tracker-stats-kicker,
.tracker-stats-provider { color: #c4b5fd; font-size: 11px; font-weight: 750; text-transform: uppercase; letter-spacing: 0.5px; }
.tracker-link-top h2,
.tracker-stats-topbar h2 { margin: 2px 0 0; color: #ffffff; font-size: 24px; line-height: 1.05; font-weight: 760; letter-spacing: 0; }
.tracker-link-close,
.tracker-stats-back,
.tracker-stats-edit { border: 0; background: rgba(255,255,255,0.08); color: #ffffff; border-radius: 999px; min-width: 38px; height: 38px; font-size: 14px; font-weight: 750; }
.tracker-stats-back svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; }
.tracker-link-copy,
.tracker-stats-note,
.tracker-stats-updated { margin-top: 10px; color: rgba(255,255,255,0.58); font-size: 13px; line-height: 1.35; }
.tracker-connection-card { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 12px; padding: 10px 11px; border-radius: 10px; background: rgba(196,181,253,0.08); }
.tracker-connection-card span { color: rgba(255,255,255,0.52); font-size: 11px; font-weight: 720; text-transform: uppercase; letter-spacing: 0.35px; }
.tracker-connection-card strong { min-width: 0; color: #f6f1ff; font-size: 13px; font-weight: 760; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tracker-auto-stats { margin-top: 12px; padding: 11px; border-radius: 12px; background: rgba(255,255,255,0.055); }
.tracker-auto-stats-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.tracker-auto-stats-head span { color: #c4b5fd; font-size: 11px; font-weight: 760; text-transform: uppercase; letter-spacing: 0.42px; }
.tracker-auto-stats-head small { max-width: 66%; color: rgba(255,255,255,0.5); font-size: 11px; line-height: 1.25; text-align: right; }
.tracker-link-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 16px; }
.tracker-manual-form { margin-top: 0; }
.tracker-link-field { display: flex; flex-direction: column; gap: 6px; }
.tracker-link-field-wide { grid-column: 1 / -1; }
.tracker-link-field span { color: rgba(255,255,255,0.54); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.35px; }
.tracker-link-field input,
.tracker-link-field select { min-height: 42px; border: 0; border-radius: 8px; background: rgba(255,255,255,0.08); color: #ffffff; padding: 0 11px; font-size: 15px; font-weight: 560; outline: none; }
.tracker-link-field input[type="file"] {
  min-height: auto;
  padding: 11px;
  font-size: 12px;
}
.tracker-highlight-upload-field small {
  color: rgba(255,255,255,0.45);
  font-size: 11px;
  line-height: 1.25;
}
.tracker-link-field input:focus,
.tracker-link-field select:focus { box-shadow: 0 0 0 1px rgba(196,181,253,0.42); }
.tracker-link-status { min-height: 18px; margin-top: 10px; color: rgba(255,255,255,0.58); font-size: 12px; }
.tracker-link-status-error { color: #fb7185; }
.tracker-link-actions { display: flex; gap: 10px; margin-top: 12px; }
.tracker-link-secondary,
.tracker-link-primary { flex: 1; min-height: 44px; border: 0; border-radius: 999px; font-size: 14px; font-weight: 760; }
.tracker-link-secondary { background: rgba(255,255,255,0.08); color: #efeaff; }
.tracker-link-primary { background: linear-gradient(135deg, #8b5cf6, #06b6d4); color: #ffffff; }
.tracker-stats-page { background: #050507; overflow: auto; }
.tracker-stats-shell { min-height: 100dvh; padding: calc(14px + env(safe-area-inset-top, 0px)) 16px calc(32px + env(safe-area-inset-bottom, 0px)); transform: translate3d(0, 12px, 0); transition: transform 240ms cubic-bezier(0.16, 1, 0.3, 1); }
.tracker-stats-page.is-open .tracker-stats-shell { transform: translate3d(0, 0, 0); }
.tracker-stats-edit { min-width: 58px; color: #c4b5fd; }
.tracker-stats-hero { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 14px; align-items: end; margin-top: 22px; }
.tracker-stats-poster { width: 96px; aspect-ratio: 3 / 4; border-radius: 10px; background: linear-gradient(135deg, rgba(124,58,237,0.3), rgba(6,182,212,0.18)); background-size: cover; background-position: top center; display: grid; place-items: center; color: #c4b5fd; font-size: 42px; font-weight: 760; box-shadow: 0 16px 34px rgba(0,0,0,0.36); }
.tracker-stats-summary { min-width: 0; padding-bottom: 2px; }
.tracker-stats-account { margin-top: 5px; color: #ffffff; font-size: 24px; line-height: 1.05; font-weight: 760; overflow-wrap: anywhere; }
.tracker-stats-open { display: inline-flex; margin-top: 10px; color: #c4b5fd; text-decoration: none; font-size: 13px; font-weight: 760; }
.tracker-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 24px; }
.tracker-stats-grid .tracker-stat-cell { padding: 13px; border-radius: 10px; background: rgba(255,255,255,0.06); }
.tracker-stats-grid .tracker-stat-cell span { font-size: 10px; }
.tracker-stats-grid .tracker-stat-cell strong { font-size: 22px; line-height: 1.05; }
.tracker-stats-grid .tracker-rank-badge { --tracker-rank-sprite-w: 34px; --tracker-rank-sprite-h: 28px; gap: 7px; min-height: 34px; padding: 4px 10px 4px 6px; }
.tracker-stats-grid .tracker-rank-code { font-size: 15px; }
body.light-mode .tracker-card-strip,
body.light-mode .tracker-link-sheet,
body.light-mode .tracker-stats-page { background: #f7f5fe; color: #171717; }
body.light-mode .tracker-card-account,
body.light-mode .tracker-link-copy,
body.light-mode .tracker-stats-note,
body.light-mode .tracker-stats-updated,
body.light-mode .tracker-stat-cell span,
body.light-mode .tracker-link-field span { color: rgba(20,20,20,0.58); }
body.light-mode .tracker-stat-cell strong,
body.light-mode .tracker-link-top h2,
body.light-mode .tracker-stats-topbar h2,
body.light-mode .tracker-stats-account { color: #171717; }
body.light-mode .tracker-link-field input,
body.light-mode .tracker-link-field select,
body.light-mode .tracker-stats-grid .tracker-stat-cell,
body.light-mode .tracker-connection-card,
body.light-mode .tracker-auto-stats { background: rgba(20,20,20,0.07); color: #171717; }
body.light-mode .tracker-connection-card span { color: rgba(20,20,20,0.58); }
body.light-mode .tracker-connection-card strong { color: #171717; }
body.light-mode .tracker-auto-stats-head small { color: rgba(20,20,20,0.58); }
@media (min-width: 720px) {
  .tracker-link-sheet { left: 50%; right: auto; bottom: 22px; width: min(520px, calc(100vw - 36px)); border-radius: 18px; transform: translate3d(-50%, 16px, 0); }
  .tracker-link-overlay.is-open .tracker-link-sheet { transform: translate3d(-50%, 0, 0); }
  .tracker-stats-shell { width: min(580px, 100%); margin: 0 auto; }
}
@media (max-width: 430px) {
  .tracker-link-actions { flex-direction: column; }
  .tracker-card-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* v311: hide pencil edit btn when the details panel is in edit mode — it overlaps the Save button */
.game-details-panel.editing ~ .game-card-edit-btn {
  display: none;
  pointer-events: none;
}
.game-library-card .comments-btn {
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: #cfc6e8 !important;
  min-height: 28px;
  padding: 0 11px 0 0 !important;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 11px !important;
  font-weight: 600 !important;
  letter-spacing: 0.01em;
  box-shadow: none !important;
}
.game-library-card .comments-btn:hover,
.game-library-card .comments-btn:active {
  background: transparent !important;
  border-color: transparent !important;
  color: #ffffff !important;
}
.game-library-card .comments-btn-label {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

/* v318: game card inline comment dropdown */
.game-card-comment-drop {
  display: none;
  flex-direction: column;
  gap: 8px;
  background: rgba(15, 12, 28, 0.97);
  border-top: 1px solid rgba(139, 92, 246, 0.18);
  padding: 10px 14px 12px;
}
.game-card-comment-drop.open {
  display: flex;
}
.game-card-comment-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 200px;
  overflow-y: auto;
}
.game-card-comment-item {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}
.game-card-comment-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.game-card-comment-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.game-card-comment-name {
  font-size: 11px;
  font-weight: 700;
  color: rgba(255,255,255,0.6);
  font-family: 'Sohne', 'DM Sans', sans-serif;
}
.game-card-comment-text {
  font-size: 13px;
  color: #ede8fc;
  line-height: 1.45;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  word-break: break-word;
}
.game-card-comment-empty {
  font-size: 12px;
  color: rgba(255,255,255,0.38);
  text-align: center;
  padding: 8px 0 4px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
}
.game-card-comment-input-row {
  display: flex;
  gap: 7px;
  align-items: flex-end;
  margin-top: 2px;
}
.game-card-comment-textarea {
  flex: 1;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(139,92,246,0.25);
  border-radius: 8px;
  padding: 7px 10px;
  font-size: 12px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  color: #ffffff;
  resize: none;
  min-height: 36px;
  max-height: 80px;
  outline: none;
  transition: border-color 140ms ease;
}
.game-card-comment-textarea:focus {
  border-color: rgba(139,92,246,0.55);
}
.game-card-comment-textarea::placeholder { color: rgba(255,255,255,0.32); }
.game-card-comment-post-btn {
  background: rgba(124,58,237,0.7);
  border: none;
  border-radius: 8px;
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  padding: 7px 13px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 140ms ease;
  flex-shrink: 0;
}
.game-card-comment-post-btn:hover { background: rgba(124,58,237,0.9); }
.game-card-comment-post-btn:disabled { opacity: 0.45; cursor: default; }
body.light-mode .game-card-comment-drop {
  background: rgba(244,240,255,0.97);
  border-top-color: rgba(124,58,237,0.2);
}
body.light-mode .game-card-comment-name { color: rgba(36,22,64,0.6); }
body.light-mode .game-card-comment-text { color: #241640; }
body.light-mode .game-card-comment-empty { color: rgba(36,22,64,0.4); }
body.light-mode .game-card-comment-textarea {
  background: rgba(255,255,255,0.7);
  border-color: rgba(124,58,237,0.3);
  color: #241640;
}

.game-details-expand-btn {
  border: 0;
  border-left: 1px solid rgba(196,181,253,0.18);
  background: transparent;
  color: #ffffff;
  min-height: 28px;
  padding: 0 0 0 11px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 180ms ease, opacity 180ms ease;
}
.game-details-expand-btn svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 360ms cubic-bezier(0.16, 1, 0.3, 1);
}
.game-details-expand-btn.open svg { transform: rotate(180deg); }
.game-details-panel {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transform: translate3d(0, -6px, 0);
  transition:
    max-height 520ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity 300ms ease,
    transform 520ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: max-height, opacity, transform;
  contain: layout paint;
}
.game-details-panel.open {
  max-height: 420px;
  opacity: 1;
  transform: translate3d(0, 0, 0);
}
.game-details-panel.open.editing { max-height: 620px; }
.game-details-inner {
  margin: 0 14px 10px;
  padding: 10px 0 2px;
  border-top: 1px solid rgba(196,181,253,0.16);
}
.game-details-read-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 34px;
  border-bottom: 1px solid rgba(196,181,253,0.10);
  color: #ece7f7;
}
.game-details-read-row:last-child { border-bottom: 0; }
.game-details-label,
.game-details-field > span,
.game-details-field-head > span:first-child {
  color: #ffffff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.game-details-field-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.game-details-steam-link {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 5px;
  color: #ffffff;
  font-size: 10px;
  font-weight: 650;
  letter-spacing: 0.01em;
  text-decoration: none;
  text-transform: none;
  white-space: nowrap;
  opacity: 0.9;
  -webkit-tap-highlight-color: transparent;
  transition: color 160ms ease, opacity 160ms ease, transform 180ms cubic-bezier(0.16, 1, 0.3, 1);
}
.game-details-steam-link svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.game-details-steam-link:active { transform: scale(0.96); opacity: 1; }
.game-details-steam-link:hover { color: #ffffff; opacity: 1; }
.game-details-read-row strong {
  color: #f7f3ff;
  font-size: 13px;
  font-weight: 650;
  text-align: right;
}
.game-details-muted {
  color: rgba(255,255,255,0.78);
  font-size: 13px;
  font-weight: 500;
  text-align: right;
}
.game-details-tracker-link {
  color: #f7f3ff;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
}
.game-details-tracker-icon-only svg {
  width: 20px;
  height: 20px;
}
.game-details-tracker-link svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.game-details-edit-grid {
  display: grid;
  grid-template-columns: 1fr 0.72fr;
  gap: 11px;
}
.game-details-field {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.game-details-field-wide { grid-column: 1 / -1; }
.game-details-field input,
.game-platform-select-btn {
  width: 100%;
  min-height: 38px;
  border: 0;
  border-bottom: 1px solid rgba(196,181,253,0.28);
  border-radius: 0;
  background: #100b22;
  color: #ffffff;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 14px;
  font-weight: 500;
  outline: none;
  padding: 0 4px;
  -webkit-appearance: none;
  appearance: none;
}
.game-details-field input:focus,
.game-platform-select-btn:focus {
  border-bottom-color: #a78bfa;
}
.game-platform-select {
  position: relative;
  width: 100%;
}
.game-platform-select-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.game-platform-select-btn .placeholder { color: rgba(255,255,255,0.72); }
.game-platform-select-btn svg {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 260ms cubic-bezier(0.16, 1, 0.3, 1);
}
.game-platform-select-btn[aria-expanded="true"] svg { transform: rotate(180deg); }
.game-platform-options {
  max-height: 0;
  overflow: hidden;
  background: #100b22;
  border-bottom: 1px solid rgba(196,181,253,0.18);
  opacity: 0;
  transform: translate3d(0, -4px, 0);
  transition:
    max-height 320ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity 220ms ease,
    transform 320ms cubic-bezier(0.16, 1, 0.3, 1);
}
.game-platform-options.open {
  max-height: 290px;
  opacity: 1;
  transform: translate3d(0, 0, 0);
}
.game-platform-option {
  width: 100%;
  min-height: 34px;
  border: 0;
  border-bottom: 1px solid rgba(196,181,253,0.08);
  background: transparent;
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 0 4px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.game-platform-option:last-child { border-bottom: 0; }
.game-platform-option.selected,
.game-platform-option:active {
  color: #ffffff;
  background: rgba(255,255,255,0.045);
}
.game-details-edit-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding-top: 13px;
}
.game-details-cancel-btn,
.game-details-save-btn {
  border: 0;
  background: transparent;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 13px;
  font-weight: 750;
  cursor: pointer;
  padding: 4px 0;
}
.game-details-cancel-btn { color: #ffffff; }
.game-details-save-btn { color: #ffffff; }
.game-library-card .game-details-panel,
.game-library-card .game-details-panel button,
.game-library-card .game-details-panel input,
.game-library-card .game-details-panel span,
.game-library-card .game-details-panel strong,
.game-library-card .game-details-panel a {
  color: #ffffff;
}
.game-library-card .game-details-panel input::placeholder { color: rgba(255,255,255,0.58); }

body.light-mode .game-card-edit-btn,
body.light-mode .game-library-card .comments-btn,
body.light-mode .game-details-expand-btn,
body.light-mode .game-details-read-row strong,
body.light-mode .game-details-tracker-link,
body.light-mode .game-details-save-btn { color: #241640; }
body.light-mode .game-details-inner { border-top-color: rgba(124,58,237,0.16); }
body.light-mode .game-details-read-row { border-bottom-color: rgba(124,58,237,0.10); }
body.light-mode .game-details-label,
body.light-mode .game-details-field > span,
body.light-mode .game-details-field-head > span:first-child,
body.light-mode .game-details-muted,
body.light-mode .game-details-cancel-btn { color: #756995; }
body.light-mode .game-details-steam-link { color: #5f4f84; }
body.light-mode .game-details-steam-link:hover { color: #241640; }
body.light-mode .game-details-field input,
body.light-mode .game-platform-select-btn,
body.light-mode .game-platform-options {
  background: #faf8ff;
  color: #12082e;
  border-bottom-color: rgba(124,58,237,0.24);
}
body.light-mode .game-platform-select-btn .placeholder { color: #756995; }
body.light-mode .game-platform-option {
  color: #4b3d67;
  border-bottom-color: rgba(124,58,237,0.10);
}
body.light-mode .game-platform-option.selected,
body.light-mode .game-platform-option:active {
  color: #12082e;
  background: rgba(124,58,237,0.06);
}
@media (max-width: 600px) {
  .game-library-card .card-action-row { padding-right: 0; }
  .game-details-inner { margin: 0 12px 10px; }
  .game-details-edit-grid { grid-template-columns: 1fr; }
  .game-card-edit-btn { right: 10px; bottom: 11px; }
  .competitive-more-btn { right: 9px; top: 167px; bottom: auto; min-width: 50px; height: 29px; padding: 0 12px; }
}

/* V296: ShelfLine action borders for My Lists card actions + edge-only status swipe support. */
#mylist-view .card-action-row .card-footer-actions {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 0;
  flex-wrap: nowrap;
}
#mylist-view .card-action-row .card-upcoming-release-label {
  font-size: 13px;
  font-weight: 550;
  color: #22d3ee;
  white-space: nowrap;
  letter-spacing: 0.01em;
  line-height: 1;
  flex-shrink: 0;
}

#mylist-view .watchlist-priority-slot {
  /* v10.434: bubble shrunk now that the "Priority" word is gone
     from the markup. Min-width dropped 68 -> 24 so the slot hugs
     the input. Min-height 28 -> 22 for a more compact pill.
     Padding 0 8px -> 0 6px. Gap removed since there's no longer a
     label adjacent to the input. */
  min-height: 22px;
  min-width: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(5,5,10,0.72);
  border: 1px solid rgba(255,255,255,0.16);
  color: rgba(232,227,243,0.76);
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 9.5px;
  font-weight: 650;
  line-height: 1;
  letter-spacing: 0.02em;
  flex: 0 0 auto;
  white-space: nowrap;
}
#mylist-view .watchlist-priority-slot span {
  pointer-events: none;
}
#mylist-view .watchlist-priority-input {
  width: 18px;
  min-width: 18px;
  border: 0;
  outline: 0;
  padding: 0;
  background: transparent;
  color: #fbbf24;
  /* v10.434: per spec — number is 11px @ weight 400 (was 800).
     Lighter weight reads as a softer affordance now that the
     "Priority" label is gone and the bubble shrunk around the
     number.
     v10.436: each property now carries `!important` because the
     17-auth-flow-setup.css cover-picker rule was previously
     bundling this selector with `font-size: 6px !important` /
     `font-weight: 550 !important`. The conflicting selector has
     been removed from that bundle in v10.436, but the !important
     here doubles as defense against any future rule that tries
     to re-bundle it. */
  font-size: 11px !important;
  font-weight: 400 !important;
  font-family: 'Sohne', 'DM Sans', sans-serif !important;
  line-height: 1 !important;
  text-align: center;
  appearance: textfield;
  -moz-appearance: textfield;
}
#mylist-view .watchlist-priority-input::-webkit-outer-spin-button,
#mylist-view .watchlist-priority-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
#mylist-view .watchlist-priority-input::placeholder {
  color: rgba(232,227,243,0.42);
}

/* v10.720: Episodes / comments-btn / game-details-expand-btn footer-bar
   buttons shrunk from min-height: 32px to 27px so the Episodes pill matches
   the share-watch + review buttons' vertical height. Text + chevron scaled
   in proportion (11px ? 10px) � the SVG-equivalent chevron `�` inherits
   from font-size so it shrinks automatically. Mobile @media override
   further below ALSO bumped to 27 + 10 to keep the iPhone cascade aligned. */
#mylist-view .card-action-row .comments-btn,
#mylist-view .card-action-row .ep-toggle-bar.card-footer-btn,
#mylist-view .game-library-card .comments-btn,
#mylist-view .game-details-expand-btn {
  min-height: 27px !important;
  width: auto !important;
  max-width: none !important;
  padding: 0 12px !important;
  border: 1px solid rgba(255,255,255,0.30) !important;
  border-radius: 999px !important;
  background: rgba(5,5,10,0.94) !important;
  color: #f7f3ff !important;
  box-shadow: none !important;
  font-family: 'Sohne', 'DM Sans', sans-serif !important;
  font-size: 10px !important;
  font-weight: 650 !important;
  line-height: 1 !important;
  letter-spacing: 0.01em !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 6px !important;
  flex: 0 0 auto !important;
  white-space: nowrap !important;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, transform 0.18s cubic-bezier(0.22, 1, 0.36, 1) !important;
}

#mylist-view .card-action-row .comments-btn:hover,
#mylist-view .card-action-row .comments-btn:active,
#mylist-view .card-action-row .ep-toggle-bar.card-footer-btn:hover,
#mylist-view .card-action-row .ep-toggle-bar.card-footer-btn:active,
#mylist-view .game-details-expand-btn:hover,
#mylist-view .game-details-expand-btn:active {
  background: rgba(12,12,18,0.98) !important;
  border-color: rgba(255,255,255,0.34) !important;
  color: #ffffff !important;
}

#mylist-view .card-action-row .comments-btn-label,
#mylist-view .card-action-row .ep-toggle-bar.card-footer-btn span:first-child {
  display: inline-flex !important;
  align-items: center !important;
  min-width: 0 !important;
  white-space: nowrap !important;
  /* v10.720: paired with the parent button shrink � 11px -> 10px so the
     "Episodes" label scales with the 27px button. */
  font-size: 10px !important;
  font-weight: 650 !important;
  line-height: 1 !important;
}

#mylist-view .card-action-row .ep-toggle-bar.card-footer-btn .ep-arrow {
  margin-left: 2px;
  flex: 0 0 auto;
}

body.light-mode #mylist-view .card-action-row .comments-btn,
body.light-mode #mylist-view .card-action-row .ep-toggle-bar.card-footer-btn,
body.light-mode #mylist-view .game-library-card .comments-btn,
body.light-mode #mylist-view .game-details-expand-btn {
  background: rgba(124,58,237,0.08) !important;
  border-color: rgba(124,58,237,0.22) !important;
  color: #4c1d95 !important;
}
body.light-mode #mylist-view .watchlist-priority-slot {
  background: rgba(124,58,237,0.06);
  border-color: rgba(124,58,237,0.18);
  color: rgba(55,43,86,0.76);
}
body.light-mode #mylist-view .watchlist-priority-input {
  color: #b45309;
}
body.light-mode #mylist-view .watchlist-priority-input::placeholder {
  color: rgba(55,43,86,0.36);
}

@media (max-width: 700px) {
  #mylist-view .card-action-row .card-footer-actions {
    gap: 6px;
  }
  /* v10.720: mobile override aligned with base 27/10 spec so iPhone viewports
     get the same Episodes pill geometry as desktop. Padding tightened to
     0 10px so the smaller text doesn't float in a too-wide pill. */
  #mylist-view .card-action-row .comments-btn,
  #mylist-view .card-action-row .ep-toggle-bar.card-footer-btn,
  #mylist-view .game-details-expand-btn {
    min-height: 27px !important;
    padding: 0 10px !important;
    font-size: 10px !important;
  }
  #mylist-view .card-action-row .comments-btn-label,
  #mylist-view .card-action-row .ep-toggle-bar.card-footer-btn span:first-child {
    font-size: 10px !important;
  }
}


/* V297: edge-only My Lists status swipe rails so card taps/buttons are never intercepted. */
.mylist-edge-swipe-rail {
  position: fixed;
  top: 0;
  bottom: 0;
  width: 24px;
  z-index: 260;
  display: none;
  background: transparent;
  touch-action: pan-y;
  pointer-events: auto;
}
.mylist-edge-swipe-rail-left { left: 0; }
.mylist-edge-swipe-rail-right { right: 0; }
body.main-tab-mylist .mylist-edge-swipe-rail { display: block; }
body.modal-open .mylist-edge-swipe-rail,
body.profile-active .mylist-edge-swipe-rail,
body.main-nav-switching .mylist-edge-swipe-rail,
body:not(.main-tab-mylist) .mylist-edge-swipe-rail { display: none !important; }
@media (min-width: 761px) {
  .mylist-edge-swipe-rail { display: none !important; }
}


/* V298: rails are retired; JS-only edge detection prevents invisible overlays from blocking card controls. */
.mylist-edge-swipe-rail {
  display: none !important;
  pointer-events: none !important;
}

/* V298: restore reliable star tap animation feedback on mobile/PWA. */
#mylist-view .stars .star-btn {
  position: relative;
  z-index: 1;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
#mylist-view .status-pill,
#mylist-view .ep-check,
#mylist-view .ep-toggle-bar,
#mylist-view .comments-btn {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}


/* V300: My Lists status swiping fully removed. No invisible overlay/rail may sit above cards. */
.mylist-edge-swipe-rail,
#_swipe_out {
  display: none !important;
  pointer-events: none !important;
  visibility: hidden !important;
}
#mylist-view,
#mylist-view .card,
#mylist-view .card * {
  -webkit-tap-highlight-color: transparent;
}
#mylist-view .status-pill,
#mylist-view .ep-check,
#mylist-view .ep-toggle-bar,
#mylist-view .comments-btn,
#mylist-view .star-btn {
  pointer-events: auto !important;
  touch-action: manipulation;
}

/* v374: app version footer cushion + Games Wishlist status */
.screenlist-bottom-link-wrap {
  flex-direction: column;
  gap: 7px;
  padding-top: 37px !important;
}
.screenlist-version-footer {
  color: rgba(216,207,243,0.62);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1;
  user-select: none;
}
body.light-mode .screenlist-version-footer {
  color: rgba(91,33,182,0.58);
}
.tab-btn.active[data-tab="wishlist"] { color: #f472b6; }
.status-pill.wishlist-active { border-color: #be185d; background: #3b1128; color: #f472b6; }
#mylist-view #mylist-toolbar .tab-btn[data-tab="watching"] { order: 0 !important; }
#mylist-view #mylist-toolbar .tab-btn[data-tab="planned"] { order: 1 !important; }
#mylist-view #mylist-toolbar .tab-btn[data-tab="watched"] { order: 2 !important; }
#mylist-view #mylist-toolbar .tab-btn[data-tab="wishlist"] { order: 3 !important; }
#mylist-view #mylist-toolbar .tab-btn[data-tab="live"] { display: none !important; }

.login-legal-links .screenlist-version-footer {
  flex-basis: 100%;
  text-align: center;
  margin-top: 54px;
}
body #mylist-view #mylist-toolbar .tabs .tab-btn[data-tab="watching"] { order: 0 !important; }
body #mylist-view #mylist-toolbar .tabs .tab-btn[data-tab="planned"] { order: 1 !important; }
body #mylist-view #mylist-toolbar .tabs .tab-btn[data-tab="watched"] { order: 2 !important; }
body #mylist-view #mylist-toolbar .tabs .tab-btn[data-tab="wishlist"] { order: 3 !important; }
body #mylist-view #mylist-toolbar .tabs .tab-btn[data-tab="live"] { display: none !important; }


/* v399: game card status selector horizontal scroll + darker Playing sub-toggle */
#mylist-view .status-pills-selector-wrap {
  max-width: 100%;
  overflow: visible;
}
#mylist-view .game-status-selector {
  max-width: 100%;
  min-width: 0;
}
#mylist-view .game-status-selector.expanded .game-status-options {
  max-width: min(68vw, 480px);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  overscroll-behavior-y: contain;
  scrollbar-width: none;
  padding-left: 8px;
  padding-right: 4px;
  /* v11.203: removed `scroll-snap-type: x proximity` (yanked the tray to snap
     points and resisted free 1:1 finger scrubbing) and `scroll-behavior:
     smooth` (animated every scroll, so the finger lagged the content). Native
     momentum scroll now scrubs cleanly 1:1. */
  touch-action: pan-x !important;
}
#mylist-view .game-status-selector.expanded .game-status-options::-webkit-scrollbar {
  display: none;
}
#mylist-view .game-status-options .status-pill {
  flex: 0 0 auto;
  white-space: nowrap;
  /* v11.203: removed `scroll-snap-align: start` (paired with the snap-type
     that was removed above) so scrubbing is free, not snap-resisted. */
}
#mylist-view .game-status-selector.expanded .game-status-options .status-pill {
  touch-action: pan-x !important;
}
#mylist-view .game-status-selector.expanded .game-status-options.is-drag-scrolling,
#mylist-view .game-status-selector.expanded .game-status-options.is-drag-scrolling .status-pill {
  cursor: grabbing;
}
#mylist-view .game-library-card .game-status-selector.expanded .game-status-options {
  max-width: min(70vw, 520px);
}
@media (max-width: 600px) {
  #mylist-view .game-library-card .game-status-selector.expanded .game-status-options {
    max-width: calc(100vw - 176px);
  }
}
/* v10.232: the `#mylist-view .games-playing-*` override block that lived
   here (re-imposing the old opaque dark-gradient card + gradient active
   pill) was DELETED. Its declarations only duplicated the base
   `.games-playing-*` rules above, so the base block is now the single
   source of truth for the glassy 6% finish — no override layer needed. */

/* v401: My Lists media card badge/release-date cleanup. */
#mylist-view .card-action-row.has-bottom-export {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  gap: 10px !important;
  padding-left: 14px !important;
  padding-right: 14px !important;
}

#mylist-view .card-action-row.has-bottom-export .mylist-card-bottom-export {
  flex: 0 0 100px !important;
  width: 100px !important;
  min-width: 100px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: flex-start !important;
}

#mylist-view .card-action-row.has-bottom-export .card-footer-actions {
  flex: 1 1 auto !important;
  justify-content: flex-start !important;
  min-width: 0 !important;
}

#mylist-view .mylist-bottom-export-badge {
  min-height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 9px;
  border-radius: 999px;
  text-decoration: none;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.02em;
  white-space: nowrap;
  background: rgba(251, 191, 36, 0.13);
  color: rgba(251, 225, 148, 0.94);
  border: 1px solid rgba(251, 191, 36, 0.22);
}

#mylist-view .mylist-bottom-export-badge.mal-export-badge {
  background: rgba(46, 117, 182, 0.14);
  color: rgba(191, 219, 254, 0.96);
  border-color: rgba(96, 165, 250, 0.28);
}

#mylist-view .mylist-upcoming-release-date {
  color: #67e8f9;
  font-weight: 800;
  text-transform: none;
  letter-spacing: 0.01em;
}

/* v434: Watch List availability line — release date / In theaters / Where to watch.
   Year sits between title and genre, then the availability line sits between genre
   and the status pill. Mobile/PWA-first sizing. */
#mylist-view .card-year.mylist-watchlist-year {
  font-size: 12px;
  color: rgba(232, 222, 255, 0.78);
  font-weight: 700;
  letter-spacing: 0.02em;
  margin-top: 3px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
}
body.light-mode #mylist-view .card-year.mylist-watchlist-year {
  color: rgba(60, 40, 110, 0.78);
}
/* v10.231 / v10.403 / v10.408: artist line under album title for music
   cards. v10.408 bumps opacity 60% -> 75% so the artist name reads
   slightly more present against the dark card. Cascade-winning override
   at 17-auth-flow-setup.css mirrors this value. */
#mylist-view .card-artist {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.75);
  font-weight: 500;
  letter-spacing: 0;
  margin-top: 3px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
}
body.light-mode #mylist-view .card-artist {
  color: rgba(60, 40, 110, 0.82);
}
#mylist-view .card-availability-line {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.02em;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  line-height: 1.2;
}
#mylist-view .watchlist-card-metadata {
  display: flex;
  flex-direction: column;
}
#mylist-view .mylist-availability-release-date {
  color: #67e8f9;
}
#mylist-view .mylist-availability-in-theaters {
  color: #fbbf24;
  text-transform: none;
}
#mylist-view .mylist-availability-where-to-watch {
  color: rgba(232, 222, 255, 0.86);
}
#mylist-view .mylist-availability-where-text {
  white-space: nowrap;
}
#mylist-view .mylist-availability-providers {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
}
#mylist-view .mylist-availability-provider {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* v11.227: radius reduced by 1px (22px → 20px diameter = 11px → 10px radius). */
  width: 20px;
  height: 20px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  flex: 0 0 auto;
}
#mylist-view .mylist-availability-provider img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* v11.227: keep the high-res source crisp when downscaled into the circle. */
  image-rendering: -webkit-optimize-contrast;
  image-rendering: auto;
}
#mylist-view .mylist-availability-provider-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: 10px;
  font-weight: 900;
  color: rgba(232, 222, 255, 0.84);
  background: rgba(124, 58, 237, 0.18);
}
body.light-mode #mylist-view .mylist-availability-where-to-watch {
  color: rgba(60, 40, 110, 0.84);
}
body.light-mode #mylist-view .mylist-availability-in-theaters { color: #b45309; }
body.light-mode #mylist-view .mylist-availability-release-date { color: #0891b2; }
body.light-mode #mylist-view .mylist-availability-provider {
  background: rgba(124, 58, 237, 0.06);
  border-color: rgba(124, 58, 237, 0.18);
}

body.light-mode #mylist-view .mylist-bottom-export-badge {
  color: #92400e;
  background: rgba(251, 191, 36, 0.16);
  border-color: rgba(180, 83, 9, 0.24);
}

body.light-mode #mylist-view .mylist-bottom-export-badge.mal-export-badge {
  color: #1d4ed8;
  background: rgba(59, 130, 246, 0.12);
  border-color: rgba(37, 99, 235, 0.22);
}

body.light-mode #mylist-view .mylist-upcoming-release-date { color: #0891b2; }

@media (max-width: 600px) {
  #mylist-view .card-action-row.has-bottom-export {
    padding-left: 14px !important;
    padding-right: 14px !important;
    gap: 8px !important;
  }

  #mylist-view .card-action-row.has-bottom-export .mylist-card-bottom-export {
    flex-basis: 100px !important;
    width: 100px !important;
  }

  #mylist-view .mylist-bottom-export-badge {
    min-height: 25px;
    padding: 0 8px;
    font-size: 9.5px;
  }
}

/* v413: game covers keep visible fallback art; placeholder only appears when no image exists */
#mylist-view .card-cover.screenlist-game-cover-pending,
#mylist-view .card-cover.no-img.screenlist-game-cover-pending,
.discover-media-poster.game-media-poster.screenlist-game-cover-pending {
  background-image: none !important;
  background: linear-gradient(145deg, rgba(19, 20, 27, 0.92), rgba(42, 43, 51, 0.82)) !important;
  color: rgba(255,255,255,0.84) !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  text-align: center !important;
}
#mylist-view .card-cover.screenlist-game-cover-pending span,
.discover-media-poster.game-media-poster.screenlist-game-cover-pending span {
  padding: 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: rgba(255,255,255,0.82);
}

/* v411: user-selected IGDB/Twitch game cover picker */
.game-card-cover-btn {
  position: static;
  min-height: 27px;
  padding: 0 10px;
  border: 1px solid rgba(196,181,253,0.30);
  border-radius: 999px;
  background: rgba(5, 4, 16, 0.72);
  color: #ffffff;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.01em;
  cursor: pointer;
  z-index: 3;
  flex: 0 0 auto;
  -webkit-tap-highlight-color: transparent;
}
.game-card-cover-btn:active { transform: scale(0.96); }
#mylist-view .game-library-card .card-footer-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.screenlist-game-profile-cover-btn {
  background: rgba(6, 182, 212, 0.22) !important;
  border-color: rgba(103, 232, 249, 0.42) !important;
  color: #ffffff !important;
}
.screenlist-game-cover-picker {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: none;
  align-items: flex-end;
  background: rgba(0,0,0,0.58);
  opacity: 0;
  transition: opacity 220ms ease;
}
.screenlist-game-cover-picker.open {
  display: flex;
  opacity: 1;
}
body.screenlist-game-cover-picker-open { overflow: hidden !important; }
.screenlist-game-cover-picker-sheet {
  width: 100%;
  height: min(88vh, 780px);
  border-radius: 28px 28px 0 0;
  border: 1px solid rgba(255,255,255,0.22);
  background: #05040d;
  color: #ffffff;
  transform: translate3d(0, 18px, 0);
  transition: transform 260ms cubic-bezier(0.16, 1, 0.3, 1);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  font-family: 'Sohne', 'DM Sans', sans-serif;
}
.screenlist-game-cover-picker.open .screenlist-game-cover-picker-sheet { transform: translate3d(0, 0, 0); }
.screenlist-game-cover-picker-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: max(16px, env(safe-area-inset-top, 0px)) 16px 10px;
  border-bottom: 1px solid rgba(255,255,255,0.13);
}
.screenlist-game-cover-picker-back,
.screenlist-game-cover-picker-search button {
  border: 1px solid rgba(255,255,255,0.20);
  background: rgba(255,255,255,0.08);
  color: #ffffff;
  border-radius: 999px;
  min-height: 38px;
  padding: 0 14px;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-weight: 850;
  cursor: pointer;
}
.screenlist-game-cover-picker-title-wrap {
  min-width: 0;
  display: grid;
  gap: 2px;
}
.screenlist-game-cover-picker-title-wrap strong {
  font-size: 18px;
  font-weight: 900;
}
.screenlist-game-cover-picker-title-wrap span {
  color: rgba(255,255,255,0.68);
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.screenlist-game-cover-picker-search {
  display: flex;
  gap: 10px;
  padding: 12px 16px 8px;
}
.screenlist-game-cover-picker-search input {
  flex: 1;
  min-width: 0;
  min-height: 42px;
  border-radius: 14px;
  border: 1px solid rgba(196,181,253,0.22);
  background: rgba(255,255,255,0.08);
  color: #ffffff;
  padding: 0 13px;
  font: 800 16px 'Sohne', 'DM Sans', sans-serif;
  outline: none;
}
.screenlist-game-cover-picker-status {
  min-height: 28px;
  padding: 0 16px 10px;
  color: rgba(255,255,255,0.70);
  font-size: 12px;
  font-weight: 750;
}
.screenlist-game-cover-picker-grid {
  flex: 1;
  overflow-y: auto;
  padding: 0 14px calc(24px + env(safe-area-inset-bottom, 0px));
  display: grid;
  gap: 16px;
}
.screenlist-game-cover-group {
  display: grid;
  gap: 9px;
}
.screenlist-game-cover-group-head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 22px;
  text-align: center;
}
.screenlist-game-cover-group-head::before,
.screenlist-game-cover-group-head::after {
  content: "";
  flex: 1;
  max-width: 72px;
  height: 1px;
  background: linear-gradient(90deg, rgba(255,255,255,0.08), rgba(255,255,255,0.32), rgba(255,255,255,0.08));
}
.screenlist-game-cover-group-head span {
  padding: 0 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.70);
}
.screenlist-game-cover-group-copy {
  margin: 0;
  padding: 0 10px;
  text-align: center;
  color: rgba(255,255,255,0.52);
  font-size: 11px;
  line-height: 1.45;
}
.screenlist-game-cover-choice-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 13px 10px;
}
.screenlist-game-cover-empty {
  grid-column: 1 / -1;
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 12px;
  padding: 13px 14px;
  color: rgba(255,255,255,0.62);
  background: rgba(255,255,255,0.045);
  font-size: 12px;
  line-height: 1.45;
  font-weight: 750;
  text-align: center;
}
.screenlist-game-cover-choice {
  appearance: none;
  border: 0;
  background: transparent;
  color: #ffffff;
  padding: 0;
  text-align: center;
  cursor: pointer;
  font-family: 'Sohne', 'DM Sans', sans-serif;
}
.screenlist-game-cover-choice img {
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  border-radius: 12px;
  border: 1px solid rgba(255,255,255,0.18);
  box-shadow: 0 12px 28px rgba(0,0,0,0.32);
  display: block;
}
.screenlist-game-cover-choice span {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  line-height: 1.18;
  font-weight: 800;
  color: rgba(255,255,255,0.88);
}
.screenlist-game-cover-choice small {
  display: block;
  margin-top: 4px;
  font-size: 10px;
  line-height: 1.2;
  font-weight: 700;
  color: rgba(255,255,255,0.52);
}
@media (min-width: 760px) {
  .screenlist-game-cover-picker { align-items: center; justify-content: center; }
  .screenlist-game-cover-picker-sheet {
    width: min(760px, 92vw);
    height: min(84vh, 760px);
    border-radius: 28px;
  }
  .screenlist-game-cover-choice-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* v414: automated cover search query is display-only. */
.screenlist-game-cover-picker-search input[readonly] {
  opacity: 0.82;
  cursor: default;
}

/* v427: My Lists category pager — click-driven horizontal slide between sections.
   Touch swipe is intentionally disabled. The pager is composited (transform + opacity)
   for ProMotion 120Hz smoothness. */
.mylist-stage {
  position: relative;
  isolation: isolate;
}
.mylist-pager-overlay {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 10;
  pointer-events: none;
  touch-action: pan-y;
  background: transparent;
}
.mylist-pager-track {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  width: 100%;
  height: 100%;
  transform: translate3d(0, 0, 0);
  will-change: transform;
}
.mylist-pager-panel {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}
/* v11.062: pager panels are transparent so cloned page content shows over the
   app background. The old purple "section name" placeholder is gone. */
.mylist-pager-panel-prev,
.mylist-pager-panel-mid,
.mylist-pager-panel-next {
  background: transparent;
}
/* v11.064: pass-through pages (sections the swipe only crosses, never lands on)
   are NOT rendered — they carry a blurred, dimmed clone of the current page so
   the fast 300ms slide still has "pages" whooshing past without the cost of
   rendering each section's real content. The slight scale-up hides the soft
   blurred edges within the overflow-clipped panel. */
.mylist-pager-panel-mid {
  filter: blur(14px);
  opacity: 0.55;
  transform: scale(1.06);
  transform-origin: center center;
}
@media (prefers-reduced-motion: reduce) {
  .mylist-pager-track {
    transition: none !important;
    transform: translate3d(0, 0, 0) !important;
  }
}

/* ==========================================================================
   v800/v803: Title-card comment feature — composer modal + card body display.
   + button sits far-right in card-right-controls. Posted text floats on card
   above the action row as flat white text; tap to edit (owner only).
   ========================================================================== */

/* + button shown when there's no comment yet (owner only) */
/* v10.713: comment-add (+) button resized 32x32 -> 27x27. Paired with the
   review-layers-btn below at the same size so the slot doesn't visibly resize
   when the user transitions from "no review" (shows +) to "has review"
   (shows layered chat bubble).
   v10.717: tightened to 24x24.
   v10.719: bumped back UP to 27x27. The mobile-breakpoint @media rule
   further below ALSO needs to match � see line ~7610. */
#mylist-view .card-action-row .card-comment-add-btn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 27px;
  height: 27px;
  min-width: 27px;
  min-height: 27px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.30);
  background: rgba(5,5,10,0.94);
  color: rgba(255,255,255,0.72);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: color 160ms ease, background 160ms ease, border-color 160ms ease, transform 140ms ease;
}
#mylist-view .card-action-row .card-comment-add-btn svg {
  width: 16px;
  height: 16px;
  display: block;
}
#mylist-view .card-action-row .card-comment-add-btn:hover {
  color: #ffffff;
  background: rgba(12,12,18,0.98);
  border-color: rgba(255,255,255,0.40);
}
#mylist-view .card-action-row .card-comment-add-btn:active { transform: scale(0.94); }

/* v10.220: layers icon shown on title cards when ANOTHER user is viewing the
   list and the owner has written a review for that title. Same chip shape +
   palette as the legacy + button so the action-row stays visually balanced. */
/* v10.713: review-layers button resized 32x32 -> 27x27. Mirrors the
   comment-add (+) button above so the slot stays the same size across
   review states.
   v10.717: tightened to 24x24.
   v10.719: bumped back UP to 27x27. Mobile-breakpoint @media rule below
   also needs to match. */
#mylist-view .card-action-row .card-review-layers-btn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 27px;
  height: 27px;
  min-width: 27px;
  min-height: 27px;
  border-radius: 50%;
  border: 1px solid rgba(196,181,253,0.32);
  background: rgba(28,21,53,0.86);
  color: #c4b5fd;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  transition: color 160ms ease, background 160ms ease, border-color 160ms ease, transform 140ms ease;
}
#mylist-view .card-action-row .card-review-layers-btn svg {
  width: 18px;
  height: 18px;
  display: block;
}
#mylist-view .card-action-row .card-review-layers-btn:hover {
  background: rgba(34,24,68,0.96);
  border-color: rgba(196,181,253,0.48);
  color: #f8f4ff;
}
#mylist-view .card-action-row .card-review-layers-btn:active { transform: scale(0.94); }
@media (max-width: 720px) {
  /* v10.718/v10.719: must match the base rule above. iPhone viewports always
     trigger this breakpoint. Current spec: 27x27. */
  #mylist-view .card-action-row .card-review-layers-btn { width: 27px; height: 27px; min-width: 27px; min-height: 27px; }
}

/* v10.220: media-review activity card body stack — username on top (handled
   by the existing meta row), then "wrote a review", then the title, then the
   star rating. Poster still floats on the right via the existing .sl-activity-poster
   absolute positioning. */
.shelfd-social-card.shelfd-media-review-card .sl-media-review-action {
  margin-top: 4px;
  /* v10.670: "Wrote a Review" is the review-card equivalent of the
     prefix action verb on standard activity cards. Switched from the
     old saturated #ffd84c to the canonical champagne gold #E6C766 �
     matches the new standard-card prefix color (also v10.670) and the
     rating stars. Weight also dropped 600 ? 400 to match the standard
     prefix weight; "Wrote a Review" now reads as a true peer of "Rated",
     "Added", "Watched" etc. across all card variants. */
  color: #E6C766;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  /* v10.653: dropped "Wrote a Review" header 16px -> 15px to match the
     unified 15px size now used by the action verb on standard activity
     cards (.sl-activity-composed-headline parent shorthand in
     04-activity-feed.css). Baseline: iPhone 14 Pro Max. */
  font-size: 15px;
  /* v10.670: weight 600 ? 400 to match standard-card prefix.
     Historical: 700 ? 600 in v10.649. */
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.2;
}
.shelfd-social-card.shelfd-media-review-card .sl-media-review-title {
  display: block;
  margin-top: 6px;
  padding: 0;
  background: transparent;
  border: 0;
  color: #ffffff;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  /* v10.653: dropped review-card media title 17px -> 15px to match the
     unified 15px size now used on standard activity cards
     (.sl-activity-composed-title inherits from parent headline shorthand
     in 04-activity-feed.css). Baseline: iPhone 14 Pro Max. */
  font-size: 15px;
  /* v10.651: dropped review-card media title 100 weight steps (500 -> 400)
     to match the same -100 pass applied to .sl-activity-composed-title on
     standard activity cards. NOTE: 400 is Sohne-Buch (Regular). If this
     reads too thin for a title element in practice, revert to 500. */
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: 0;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  word-break: break-word;
}
.shelfd-social-card.shelfd-media-review-card .sl-media-review-title:active { opacity: 0.78; }
.shelfd-social-card.shelfd-media-review-card .sl-media-review-rating {
  margin-top: 8px;
  display: flex;
  align-items: center;
}

/* v803/v817: Comment body — flat white text floated on the card, above the
   action row. Tap to edit for owner; read-only for others.

   v817: owner-edit element is now a native <button type="button">, not a
   div + role="button" + tabindex="0" (the old version was being treated
   as a focusable region by iOS Safari and the inner span often became
   event.target, so taps fell through and scrolled the page to the bottom
   instead of opening the edit modal). Native button = reliable clicks
   on iOS Safari + PWA. Below resets all native button styling so it
   still renders as flat text in line with the rest of the card. */
/* v851: posted comment now lives in the card body above the action row.
   This keeps it out of the footer flex row so buttons/overlays cannot cover
   or squeeze it out of view. */
/* v10.77: collapse the comment slot when there's no comment so it doesn't
   reserve awkward empty space below the rating area on Watched cards. The
   slot is always rendered (so partial-update helpers can find it by id),
   but an empty slot is `:empty` because `buildCardCommentBodyHtml` returns
   `''` when no comment exists. */
#mylist-view .card-comment-slot:empty {
  display: none;
}

#mylist-view .card-comment-body {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  padding: 0;
  margin: 9px 0 0;
  width: 100%;
  min-width: 100%;
  max-width: 100%;
  color: #ffffff;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#mylist-view .card-comment-body.card-comment-body--watched-media {
  font-size: 13px;
}
#mylist-view .rating-area + .card-comment-body.card-comment-body--watched-media {
  margin-top: 23px;
}
/* v850: inner span must inherit the parent's truncation contract,
   not its legacy block + break-word rules. */
#mylist-view .card-comment-body .card-comment-body-text {
  display: block;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  overflow-wrap: normal;
}
/* When the owner-edit element is rendered as a <button>, kill the
   native UA button look so it visually matches the read-only <div>.
   The posted comment is no longer inside the action row. */
button.card-comment-body,
#mylist-view button.card-comment-body {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  margin: 9px 0 0;
  text-align: left;
  font: inherit;
  color: inherit;
  letter-spacing: normal;
  cursor: pointer;
}
#mylist-view .card-comment-body-text {
  display: block;
  word-break: break-word;
  overflow-wrap: break-word;
  transition: opacity 140ms ease;
  /* v817: ensure clicks always land on the parent button — not the span —
     so the inline onclick fires reliably even when the user taps a
     specific character of the comment text. */
  pointer-events: none;
}
#mylist-view .card-comment-body.card-comment-body--owner {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#mylist-view .card-comment-body.card-comment-body--owner:hover .card-comment-body-text,
#mylist-view .card-comment-body.card-comment-body--owner:focus .card-comment-body-text,
#mylist-view .card-comment-body.card-comment-body--owner:focus-visible .card-comment-body-text {
  opacity: 0.72;
}
#mylist-view .card-comment-body.card-comment-body--owner:active .card-comment-body-text {
  opacity: 0.50;
}
/* Remove the default focus outline that browsers paint on <button>; the
   opacity dim above provides the visual focus cue. */
#mylist-view button.card-comment-body:focus {
  outline: none;
}
#mylist-view button.card-comment-body:focus-visible {
  outline: 2px solid rgba(167,139,250,0.55);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (max-width: 600px) {
  /* v846: mobile comment body — 12px, 90% opacity, weight 300. No
     block padding (it now lives inline at the far left of the action
     row; padding pushed it onto its own line in older versions). */
  #mylist-view .card-comment-body {
    font-size: 12px;
    font-weight: 300;
    opacity: 0.9;
    padding: 0;
    margin-top: 8px;
  }
  /* v10.718/v10.719: must match the base rule above. iPhone viewports always
     trigger this breakpoint. Current spec: 27x27. */
  #mylist-view .card-action-row .card-comment-add-btn { width: 27px; height: 27px; min-width: 27px; min-height: 27px; }
  #mylist-view .card-action-row .card-comment-add-btn svg { width: 14px; height: 14px; }
}

/* Composer modal — bottom-sheet style on mobile, centered card on desktop. */
/* Card-comment composer modal — centered floating card matching Add to Shelf style.
   visualViewport JS keeps it visible above keyboard on mobile. */
.card-comment-composer-overlay {
  position: fixed;
  inset: 0;
  z-index: 2147483646;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(20px, env(safe-area-inset-top, 0px)) 16px max(20px, env(safe-area-inset-bottom, 20px));
  pointer-events: none;
  opacity: 0;
  transition: opacity 180ms ease;
}
.card-comment-composer-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}
.card-comment-composer-backdrop {
  position: absolute;
  inset: 0;
  /* v842: removed `backdrop-filter: blur(4px)` and its -webkit prefix.
     `backdrop-filter` forces the backdrop element into its own
     compositor layer in iOS PWA WKWebView. With the sheet rendered as
     a non-promoted sibling, iOS's compositor hit-tester then routes
     taps that visually hit the sheet's child buttons (specifically the
     primary action button at the far right of the actions row — Save /
     Post) BACK to the promoted backdrop layer, where they hit nothing
     actionable. Result: Cancel button works (left side of actions),
     Save button does NOT — clicks register on the backdrop layer's
     "empty" area underneath. Solid darker background gives the same
     "dimmed underlying screen" effect without GPU-promoting the
     backdrop into a separate layer. */
  background: rgba(0,0,0,0.78);
}
/* v844 — modern charcoal/lavender redesign.
   Matches the auth-flow visual language (shelfd-auth-page in
   17-auth-flow-setup.css): charcoal surface, soft lavender accents,
   rounded 18px corners, pill-shape primary action, 16px inputs (also
   the iOS auto-zoom-skip threshold), no GPU-layer-promoting properties. */
.card-comment-composer-sheet {
  position: relative;
  width: min(92vw, 460px);
  max-height: min(88vh, 600px);
  overflow-y: auto;
  overflow-x: hidden;
  padding: 22px 22px 20px;
  background: #181c20;
  border: 1px solid rgba(196,181,253,0.22);
  border-radius: 20px;
  box-shadow: 0 24px 64px rgba(0,0,0,0.55), 0 0 0 0.5px rgba(255,255,255,0.04);
  display: flex;
  flex-direction: column;
  gap: 14px;
  font-family: 'Sohne', 'DM Sans', system-ui, -apple-system, sans-serif;
  color: #ffffff;
  /* v838 — opacity-only entry animation (transform causes iOS PWA
     WKWebView to promote the sheet into its own compositor layer,
     which breaks button hit-testing). */
  opacity: 0;
  transition: opacity 200ms ease;
}
.card-comment-composer-overlay.is-open .card-comment-composer-sheet {
  opacity: 1;
}
/* Drag handle hidden on centered modal */
.card-comment-composer-handle { display: none; }
.card-comment-composer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 0;
}
.card-comment-composer-header h2 {
  font-size: 17px;
  font-weight: 600;
  color: #ffffff;
  margin: 0;
  letter-spacing: 0.01em;
}
.card-comment-composer-close {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid rgba(255,255,255,0.08);
  background: rgba(255,255,255,0.05);
  color: #ffffff;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  -webkit-tap-highlight-color: transparent;
  transition: background 140ms ease, border-color 140ms ease, transform 140ms ease;
}
.card-comment-composer-close:hover { background: rgba(255,255,255,0.09); }
.card-comment-composer-close:active { transform: scale(0.92); }
.card-comment-composer-subtitle {
  color: rgba(196,181,253,0.78);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  margin-top: -4px;
}
.card-comment-composer-input {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  min-height: 120px;
  padding: 13px 14px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(196,181,253,0.16);
  border-radius: 12px;
  color: #ffffff;
  font-family: inherit;
  /* 16px — skips iOS focus auto-zoom which can fight `user-scalable=no`. */
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  resize: none;
  outline: none;
  -webkit-user-select: text;
  user-select: text;
  touch-action: auto;
  transition: border-color 160ms ease, background 160ms ease, box-shadow 200ms ease;
}
.card-comment-composer-input::placeholder { color: rgba(232,227,243,0.32); }
.card-comment-composer-input:focus {
  background: rgba(255,255,255,0.09);
  border-color: rgba(196,181,253,0.42);
  box-shadow: 0 0 0 3px rgba(139,92,246,0.16);
}
.card-comment-composer-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 2px;
}
.card-comment-composer-counter {
  color: rgba(232,227,243,0.45);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.2px;
}
.card-comment-composer-actions {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.card-comment-composer-actions .btn-secondary,
.card-comment-composer-actions .btn-primary {
  appearance: none;
  -webkit-appearance: none;
  min-height: 40px;
  border-radius: 999px;
  font-family: inherit;
  font-size: 13.5px;
  letter-spacing: 0.01em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 140ms cubic-bezier(0.22, 1, 0.36, 1), background 160ms ease, border-color 160ms ease, box-shadow 200ms ease;
}
.card-comment-composer-actions .btn-secondary {
  padding: 0 18px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(196,181,253,0.22);
  color: rgba(232,227,243,0.85);
  font-weight: 500;
}
.card-comment-composer-actions .btn-secondary:hover {
  background: rgba(167,139,250,0.10);
  border-color: rgba(196,181,253,0.42);
  color: #ffffff;
}
.card-comment-composer-actions .btn-secondary:active { transform: scale(0.985); }
.card-comment-composer-actions .btn-primary {
  padding: 0 22px;
  background: linear-gradient(135deg, #8b5cf6, #7c3aed);
  border: 0;
  color: #ffffff;
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(139,92,246,0.25);
}
.card-comment-composer-actions .btn-primary:hover {
  box-shadow: 0 12px 32px rgba(139,92,246,0.35);
}
.card-comment-composer-actions .btn-primary:active { transform: scale(0.985); }
.card-comment-composer-actions .btn-primary:disabled {
  opacity: 0.55;
  cursor: progress;
  box-shadow: none;
}

/* =============================================================================
   v11.042 — GAME PROFILE PAGE: full UI rebuild (Editorial Dark, flat + minimal)
   -----------------------------------------------------------------------------
   Single source of truth. Replaces the stacked v10.353 / v10.357 / v11.037
   reskins (all removed). No button functions changed — every class / id /
   data-attribute the JS depends on is preserved:
     #mylist-game-profile-page, .mylist-game-profile-scroll,
     .mylist-game-profile-edit, .mylist-rank-picker-*,
     [data-game-profile-edit-field], .rank-picker-open, .is-open, etc.
   Flat #0E0E0E surface, hairline dividers, lavender (#a78bfa) interactive
   accent, subtle inset cards for figures. Söhne throughout.
   ============================================================================= */
body.mylist-game-profile-open { overflow: hidden; }

.mylist-game-profile-page {
  position: fixed;
  inset: 0;
  z-index: 7600;
  display: flex;
  flex-direction: column;
  background: #0E0E0E;
  color: #f5f2ff;
  font-family: 'Sohne', 'DM Sans', sans-serif;
  transform: translate3d(100%, 0, 0);
  transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
  overflow: hidden;
  -webkit-text-size-adjust: 100%;
  touch-action: manipulation;
}
.mylist-game-profile-page.is-open { transform: translate3d(0, 0, 0); }
.mylist-game-profile-page * { font-family: 'Sohne', 'DM Sans', sans-serif; }

.mylist-game-profile-shell {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  height: 100dvh;
}

/* ---- Topbar -------------------------------------------------------------- */
.mylist-game-profile-topbar {
  flex: 0 0 auto;
  position: sticky;
  top: 0;
  z-index: 5;
  display: grid;
  /* v11.077: equal side columns so the centered "Game Profile" title sits at
     true screen center regardless of the back button vs action-button widths. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  padding: calc(env(safe-area-inset-top, 0px) + 10px) 16px 12px;
  background: #0E0E0E;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.mylist-game-profile-topbar > span {
  justify-self: center;
  min-width: 0;
  color: #ffffff;
  font-size: 18px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mylist-game-profile-back {
  appearance: none;
  -webkit-appearance: none;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.04);
  color: #ffffff;
  border-radius: 50%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-back svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.mylist-game-profile-back:active { transform: scale(0.94); opacity: 0.8; }
.mylist-game-profile-actions {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.mylist-game-profile-share {
  appearance: none;
  -webkit-appearance: none;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.04);
  color: #ffffff;
  border-radius: 50%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-share svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.mylist-game-profile-share:active { transform: scale(0.94); opacity: 0.8; }
.mylist-game-profile-edit {
  appearance: none;
  -webkit-appearance: none;
  min-width: 56px;
  height: 32px;
  padding: 0 15px;
  border: 1px solid rgba(167, 139, 250, 0.34);
  background: rgba(167, 139, 250, 0.12);
  color: #c4b5fd;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-edit:active { transform: scale(0.96); opacity: 0.8; }
.mylist-game-profile-edit:disabled { opacity: 0.55; }

/* ---- Scroll body --------------------------------------------------------- */
.mylist-game-profile-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 18px 18px calc(env(safe-area-inset-bottom, 0px) + 36px);
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.mylist-game-profile-scroll::-webkit-scrollbar { display: none; }
.mylist-game-profile-page.rank-picker-open .mylist-game-profile-scroll {
  overflow: hidden;
  touch-action: none;
}

/* ---- Hero ---------------------------------------------------------------- */
.mylist-game-profile-hero {
  position: relative;
  display: block;
  padding: 2px 0 22px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
/* Flat, minimal — the old ambient blur layers are intentionally hidden. */
.mylist-game-profile-hero-bg,
.mylist-game-profile-hero-glow { display: none !important; }
.mylist-game-profile-hero-card {
  display: grid;
  grid-template-columns: 104px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}
.mylist-game-profile-cover {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  padding: 0;
  width: 104px;
  aspect-ratio: 5 / 6.38;
  height: auto;
  border-radius: 12px;
  background-color: #1a1a1a;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.5);
  cursor: pointer;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-cover:active { transform: scale(0.985); }
.mylist-game-profile-cover.no-img {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.42);
  font-size: 40px;
  font-weight: 600;
  background: linear-gradient(135deg, rgba(167, 139, 250, 0.28), rgba(255, 255, 255, 0.05));
}
.mylist-game-profile-identity {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.mylist-game-profile-eyebrow-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.mylist-game-profile-kicker {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 11px;
  border-radius: 999px;
  border: 1px solid rgba(167, 139, 250, 0.4);
  background: rgba(167, 139, 250, 0.14);
  color: #c4b5fd;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.mylist-game-profile-tracker-shortcut {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.05);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-tracker-shortcut:active { transform: scale(0.92); opacity: 0.75; }
.mylist-game-profile-tracker-mark {
  color: #c4b5fd;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  transform: translateX(2px);
}
.mylist-game-profile-tracker-shortcut svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: #c4b5fd;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: translate(-1px, -2px);
}
.mylist-game-profile-identity h1 {
  margin: 0;
  color: #ffffff;
  font-size: 24px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}
.mylist-game-profile-meta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
}
.mylist-game-profile-meta-row span {
  color: rgba(255, 255, 255, 0.55);
  font-size: 13px;
  font-weight: 400;
  line-height: 1;
}
.mylist-game-profile-subcopy {
  margin: 2px 0 0;
  max-width: 38ch;
  color: rgba(255, 255, 255, 0.5);
  font-size: 13px;
  font-weight: 300;
  line-height: 1.5;
}

/* v11.079: interactive rating in the hero (replaces the old subcopy). Same
   half-step star visual as the Write-a-Review composer, sized to fit. */
.mylist-game-profile-rating {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 8px 0 0;
}
.mylist-game-profile-rating-stars {
  display: inline-flex;
  gap: 3px;
}
.mylist-game-profile-rating-slot {
  position: relative;
  display: inline-block;
  width: 26px;
  height: 26px;
  font-size: 26px;
  line-height: 26px;
}
.mylist-game-profile-rating-base { color: rgba(255, 255, 255, 0.22); }
.mylist-game-profile-rating-fill {
  position: absolute;
  inset: 0;
  color: #E6C36A;
  overflow: hidden;
  clip-path: inset(0 calc(100% - var(--star-fill, 0%)) 0 0);
}
.mylist-game-profile-rating-hit {
  position: absolute;
  top: 0;
  width: 50%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-rating-hit-left { left: 0; }
.mylist-game-profile-rating-hit-right { right: 0; }
.mylist-game-profile-rating.is-readonly .mylist-game-profile-rating-hit { display: none; }
.mylist-game-profile-rating-value {
  color: rgba(255, 255, 255, 0.6);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
}

/* ---- Facts strip --------------------------------------------------------- */
.mylist-game-profile-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 1px;
  margin: 18px 0 0;
  border-radius: 14px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.07);
}
.mylist-game-profile-facts div {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 13px 14px;
  background: #0E0E0E;
  min-width: 0;
}
.mylist-game-profile-facts span {
  color: rgba(255, 255, 255, 0.45);
  font-size: 11px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.mylist-game-profile-facts strong {
  color: rgba(255, 255, 255, 0.92);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

/* ---- Section panels ------------------------------------------------------ */
.mylist-game-profile-panel {
  padding: 22px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.mylist-game-profile-panel:last-child { border-bottom: 0; }
.mylist-game-profile-panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 16px;
}
.mylist-game-profile-panel-head span {
  color: #ffffff;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
}
.mylist-game-profile-panel-head small {
  flex: 0 0 auto;
  max-width: 55%;
  color: rgba(255, 255, 255, 0.42);
  font-size: 12px;
  font-weight: 300;
  line-height: 1.3;
  text-align: right;
}

/* ---- Stat grid (read + edit share the card; label on top, value below) --- */
.mylist-game-profile-stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.mylist-game-profile-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  min-width: 0;
  padding: 14px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.03);
}
.mylist-game-profile-stat > span {
  color: rgba(255, 255, 255, 0.45);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.mylist-game-profile-stat > strong {
  max-width: 100%;
  color: #ffffff;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Rank read-stat: centered icon + name + label */
.mylist-game-profile-rank-stat {
  align-items: center;
  text-align: center;
  gap: 8px;
}
.mylist-game-profile-rank-logo,
.mylist-game-profile-rank-logo-placeholder {
  width: 46px;
  height: 46px;
  flex: 0 0 46px;
  object-fit: contain;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.4));
}
.mylist-game-profile-rank-logo-placeholder {
  border-radius: 12px;
  border: 1px dashed rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.04);
  filter: none;
}
.mylist-game-profile-rank-stat > strong {
  width: 100%;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.2;
}
.mylist-game-profile-rank-stat > span {
  width: 100%;
}

/* ---- Edit: profile setup grid + fields ----------------------------------- */
.mylist-game-profile-edit-meta-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.mylist-game-profile-edit-meta label {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.mylist-game-profile-edit-meta label > span,
.mylist-game-profile-editable-link-label,
.mylist-game-profile-highlight-input span {
  color: rgba(255, 255, 255, 0.5);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
/* v11.044: editable-link label row holds the field label + an optional
   "Open ↗" quick-link to the source site (Tracker.gg). */
.mylist-game-profile-editable-link-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}
.mylist-game-profile-field-open {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  color: #c4b5fd;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.01em;
  text-transform: none;
  text-decoration: none;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-field-open:active { opacity: 0.7; }
/* Read-mode "Not linked" tracker row: keep "Not linked" pinned right so
   the Open link sits next to the label (the circled spot). */
.mylist-game-profile-link-row.has-quick-open > strong { margin-left: auto; }
.mylist-game-profile-edit-meta input,
.mylist-game-profile-edit-meta select,
.mylist-game-profile-editable-stat input,
.mylist-game-profile-editable-link input {
  width: 100%;
  height: 44px;
  padding: 0 12px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.25);
  color: #ffffff;
  font-size: 16px;
  font-weight: 400;
  line-height: 1;
  outline: none;
  box-sizing: border-box;
  -webkit-text-size-adjust: 100%;
  /* v11.044: guarantee text selection + the iOS Paste callout work in
     these fields regardless of any app-level user-select:none. */
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}
.mylist-game-profile-edit-meta select {
  appearance: none;
  -webkit-appearance: none;
}
.mylist-game-profile-edit-meta input:focus,
.mylist-game-profile-edit-meta select:focus,
.mylist-game-profile-editable-stat input:focus,
.mylist-game-profile-editable-link input:focus {
  border-color: rgba(167, 139, 250, 0.6);
  box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.15);
}

/* ---- Rank icon picker ---------------------------------------------------- */
.mylist-rank-picker-field { position: relative; }
.mylist-rank-picker-field.is-open { z-index: 30; }
.mylist-rank-picker-trigger {
  width: 100%;
  height: 48px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 12px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.25);
  color: #ffffff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mylist-rank-picker-trigger img {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  object-fit: contain;
}
.mylist-rank-picker-empty {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: 8px;
  border: 1px dashed rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.04);
}
.mylist-rank-picker-trigger strong {
  min-width: 0;
  color: #ffffff;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mylist-rank-picker-menu {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 8px);
  z-index: 40;
  max-height: min(360px, 50vh);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: #161616;
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.5);
  display: none;
}
.mylist-rank-picker-field.is-open .mylist-rank-picker-menu {
  display: grid;
  gap: 6px;
}
.mylist-rank-picker-option {
  width: 100%;
  min-height: 46px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  border-radius: 12px;
  border: 1px solid transparent;
  background: transparent;
  color: rgba(255, 255, 255, 0.88);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mylist-rank-picker-option.active {
  border-color: rgba(167, 139, 250, 0.4);
  background: rgba(167, 139, 250, 0.16);
}
.mylist-rank-picker-option img {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  object-fit: contain;
}
.mylist-rank-picker-option span {
  color: #ffffff;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.2;
}

/* ---- Links --------------------------------------------------------------- */
.mylist-game-profile-links .mylist-game-profile-panel-head { margin-bottom: 6px; }
.mylist-game-profile-link-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 52px;
  margin-top: 10px;
  padding: 0 14px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  color: #ffffff;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.mylist-game-profile-link-row:active { transform: scale(0.99); }
.mylist-game-profile-link-row > span {
  color: rgba(255, 255, 255, 0.86);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.2;
}
.mylist-game-profile-link-row > strong {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  color: #c4b5fd;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}
a.mylist-game-profile-link-row > strong::after {
  content: '\203A';
  margin-left: 7px;
  color: #a78bfa;
  font-size: 17px;
  font-weight: 400;
  line-height: 1;
}
.mylist-game-profile-link-row.is-disabled { opacity: 0.55; }
.mylist-game-profile-link-row.is-disabled > strong { color: rgba(255, 255, 255, 0.4); }
/* v11.044: a not-linked row that offers a quick-open link stays full
   opacity (the Open ↗ must read as tappable) — only the "Not linked"
   status text is muted. */
.mylist-game-profile-link-row.is-disabled.has-quick-open { opacity: 1; }
.mylist-game-profile-link-row.is-disabled.has-quick-open > span { color: rgba(255, 255, 255, 0.86); }
.mylist-game-profile-editable-link {
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 8px;
  min-height: 0;
  padding: 12px 14px;
}
.mylist-game-profile-highlight-button { cursor: pointer; }
.mylist-game-profile-edit-status {
  min-height: 18px;
  margin-top: 12px;
  color: rgba(255, 255, 255, 0.54);
  font-size: 13px;
  font-weight: 300;
  line-height: 1.4;
  text-align: center;
}
.mylist-game-profile-edit-status.is-error { color: #ff7a7a; }

/* ---- Highlight reel embed ------------------------------------------------ */
.mylist-game-profile-highlight-preview {
  padding: 22px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.mylist-game-profile-highlight-head {
  margin: 0 0 12px;
  color: #ffffff;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.mylist-game-profile-highlight-head span {
  color: rgba(255, 255, 255, 0.48);
  font-size: 13px;
  font-weight: 400;
}
.mylist-game-profile-highlight-track {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  margin: 0 -2px;
  padding: 0 2px 2px;
}
.mylist-game-profile-highlight-track::-webkit-scrollbar { display: none; }
.mylist-game-profile-highlight-slide {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: start;
}
.mylist-game-profile-highlight-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: #000;
}
.mylist-game-profile-highlight-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.mylist-game-profile-highlight-caption {
  margin: 10px 2px 0;
  color: rgba(255, 255, 255, 0.86);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.35;
}

/* ---- Highlight link bottom-sheet modal ----------------------------------- */
.mylist-game-profile-highlight-modal {
  position: fixed;
  inset: 0;
  z-index: 2147483300;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* JS (visualViewport) feeds the live keyboard height into this var so the
     bottom sheet lifts above the iOS keyboard instead of hiding behind it. */
  padding-bottom: var(--game-profile-highlight-keyboard-offset, 0px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease, padding-bottom 180ms ease;
}
.mylist-game-profile-highlight-modal.is-open {
  opacity: 1;
  pointer-events: auto;
}
.mylist-game-profile-highlight-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.mylist-game-profile-highlight-sheet {
  position: relative;
  width: min(100%, 520px);
  max-height: min(82vh, 680px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 12px 18px calc(env(safe-area-inset-bottom, 0px) + 20px);
  border-radius: 24px 24px 0 0;
  background: #161616;
  border: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow: 0 -20px 60px rgba(0, 0, 0, 0.5);
  transform: translateY(22px);
  transition: transform 180ms ease;
}
.mylist-game-profile-highlight-modal.is-open .mylist-game-profile-highlight-sheet {
  transform: translateY(0);
}
.mylist-game-profile-highlight-grabber {
  width: 42px;
  height: 4px;
  margin: 0 auto 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
}
.mylist-game-profile-highlight-sheet h2 {
  margin: 0 0 8px;
  color: #ffffff;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.2;
}
.mylist-game-profile-highlight-sheet p {
  margin: 0 0 16px;
  color: rgba(255, 255, 255, 0.55);
  font-size: 14px;
  font-weight: 300;
  line-height: 1.5;
}
.mylist-game-profile-highlight-input {
  display: grid;
  gap: 8px;
  margin-bottom: 10px;
}
.mylist-game-profile-highlight-input input {
  width: 100%;
  height: 46px;
  padding: 0 13px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: rgba(0, 0, 0, 0.25);
  color: #ffffff;
  font-size: 16px;
  outline: none;
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}
.mylist-game-profile-highlight-input input:focus {
  border-color: rgba(167, 139, 250, 0.6);
  box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.15);
}
.mylist-game-profile-highlight-list {
  display: grid;
  gap: 12px;
  margin-bottom: 12px;
}
.mylist-game-profile-highlight-editor-row {
  display: grid;
  gap: 2px;
  padding: 12px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.mylist-game-profile-highlight-remove,
.mylist-game-profile-highlight-add {
  width: fit-content;
  min-height: 34px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.82);
  font-size: 13px;
  font-weight: 400;
}
.mylist-game-profile-highlight-remove[hidden] { display: none; }
.mylist-game-profile-highlight-add {
  margin: 0 0 14px;
  color: #c4b5fd;
}
.mylist-game-profile-highlight-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.mylist-game-profile-highlight-secondary,
.mylist-game-profile-highlight-primary {
  min-height: 46px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 500;
  border: 1px solid rgba(255, 255, 255, 0.10);
  cursor: pointer;
}
.mylist-game-profile-highlight-secondary {
  background: rgba(255, 255, 255, 0.06);
  color: #ffffff;
}
.mylist-game-profile-highlight-primary {
  background: #a78bfa;
  border-color: transparent;
  color: #0E0E0E;
  font-weight: 600;
}

/* ---- Desktop scale-up (app is iPhone-first; this just relaxes spacing) --- */
@media (min-width: 720px) {
  .mylist-game-profile-hero-card { grid-template-columns: 132px minmax(0, 1fr); }
  .mylist-game-profile-cover { width: 132px; }
  .mylist-game-profile-identity h1 { font-size: 28px; }
}

@media (prefers-reduced-motion: reduce) {
  .mylist-game-profile-page,
  .mylist-game-profile-highlight-modal,
  .mylist-game-profile-highlight-sheet { transition: none !important; }
}

/* =============================================================================
   v11.224 — Title-card text line-height = 18px (My Lists)
   Every text element on a My Lists title card (`#mylist-view .card`) renders
   with a fixed 18px line-height. Scoped to the card root + all descendants so
   titles, status pills, episode counts, ratings, metadata, and footer button
   labels all share an 18px leading. `!important` wins over any per-element
   line-height (incl. existing !important rules). Episode/season detail pages
   and full-page profiles are NOT affected (outside `#mylist-view .card`).
   ============================================================================= */
#mylist-view .card,
#mylist-view .card * {
  line-height: 18px !important;
}

/* =============================================================================
   v11.226 — Uniform 6px vertical gap between EVERY stacked element on a card
   Every stacked child inside `.card-info` (title row, status pill, year,
   artist, genre, progress area, next-episode line, inline rating, comment slot,
   metadata, etc.) is separated by exactly 6px. The first stacked child has no
   top margin so the stack starts flush with the cover top.
   This is a rebuild-over-override: it replaces the prior per-section margins
   (anime 0, shows 0, games 6, movies 8.4, under-title 3) with ONE uniform 6px,
   matching the Games card spacing across every category. Highest-specificity
   `#mylist-view .card .card-info > *` + later declaration + !important wins
   the cascade cleanly. Episode/season pages + profiles are untouched.
   ============================================================================= */
#mylist-view .card .card-info > * {
  margin-top: 6px !important;
}
#mylist-view .card .card-info > *:first-child {
  margin-top: 0 !important;
}

/* v11.229 — collapse stacked internal margins between the episode count and
   the "Where to watch" line. The big gap was three margins stacking:
   .progress-meta margin-bottom (only needed to separate the count from a
   progress BAR) + the 6px card-info gap + .card-availability-line margin-top.
   Planned cards have no progress bar, so the progress-meta margin is wasted
   space. Drop it ONLY when progress-meta is the last child (no bar present),
   and zero the availability line's own top margin so the uniform 6px between
   card-info children is the single source of the gap. Watching cards (which
   DO have a bar) keep progress-meta's margin because it is not :last-child. */
#mylist-view .card .progress-area > .progress-meta:last-child {
  margin-bottom: 0 !important;
}
#mylist-view .card .watchlist-card-metadata > *:first-child {
  margin-top: 0 !important;
}
#mylist-view .card .card-availability-line {
  margin-top: 0 !important;
}

/* =============================================================================
   v11.230 — HD poster: real <img> cover (My Lists, non-game)
   The non-game card cover now renders a real <img> (`.card-cover-img`) instead
   of a CSS background-image. WKWebView applies proper retina downscaling to
   <img>, so the poster reads crisp at 2x/3x; backgrounds looked soft. The img
   fills the existing `.card-cover` box (which is flex + overflow:hidden) via
   absolute positioning so it doesn't fight the flex centering used for the
   emoji/placeholder fallback. Portrait posters use top-center crop (matches the
   old background-position); music covers are square and center-cropped.
   ============================================================================= */
#mylist-view .card .card-cover { position: relative; }
#mylist-view .card .card-cover-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
  border-radius: inherit;
  /* keep the high-res source sharp when scaled into the small box */
  image-rendering: -webkit-optimize-contrast;
}
#mylist-view .card .card-cover-img.card-cover-img-music {
  object-position: center center;
}

/* =============================================================================
   v11.232 — Smoother My Lists scrolling
   Long libraries repaint every card on each scroll frame (each card has a
   border + gradient + box-shadow). `content-visibility: auto` lets the browser
   SKIP layout/paint for cards currently off-screen, so only the ~handful of
   visible cards are rendered per frame — big win on long lists. The paired
   `contain-intrinsic-size` reserves an estimated height for off-screen cards
   so the scrollbar/position stays stable (no jump) before they paint.
   ~420px is a typical TV/movie card height; the browser refines it after a
   card has been rendered once. Music cards are shorter, so they get a smaller
   estimate. Safe to revert (single block).
   ============================================================================= */
#mylist-view #cards-grid > .card {
  content-visibility: auto;
  contain-intrinsic-size: auto 420px;
}
#mylist-view #cards-grid > .card[data-library-section="music"] {
  contain-intrinsic-size: auto 150px;
}

/* =============================================================================
   v11.233 — Glassy status button (My Lists title cards)
   Rebuild of the visible per-card status button (`.game-status-current-pill`)
   into a modern frosted-glass pill: translucent gradient fill, backdrop blur,
   soft 1px light border, inset top highlight + subtle drop shadow, and a crisp
   press state. Replaces the flat outline-only look. Scoped to
   `body.true-dark-mode #mylist-view` + chained classes so it beats the v10.738
   white-60% outline rule (1,5,0 + !important) without touching the pop-out
   OPTION pills (`.game-status-options .status-pill`) — the selector mechanics
   and per-status active colors are unchanged. Only the resting button skin.
   ============================================================================= */
/* v11.234: selectors now carry TWO ids (#mylist-view + #cards-grid) = (2,x,0)
   so they beat the v10.738 rule (1,5,0 + !important) that pinned the button's
   border + text to white-60% and was suppressing the glass border/tint. */
/* v11.238: ALL status buttons use the French Lilac (#e1b7e5) identity,
   regardless of status — whisper-glass chip in one unified color. The
   per-status tint blocks were removed; this single base rule colors every
   state (watching/watched/paused/etc) the same lilac. */
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.watching-active,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.competitive-active,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.planned-active,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.wishlist-active,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.watched-active,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.paused-active,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.dropped-active,
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill.live-active {
  color: #e1b7e5 !important;
  border: 1px solid rgba(225, 183, 229, 0.45) !important;
  background: rgba(225, 183, 229, 0.10) !important;
  background-image: none !important;
  -webkit-backdrop-filter: blur(10px) saturate(125%);
  backdrop-filter: blur(10px) saturate(125%);
  box-shadow: none !important;
  border-radius: 7px !important;
  padding: 3.5px 10px !important;
  font-weight: 400 !important;
  letter-spacing: 0.02em;
  transition: transform 140ms ease, background 180ms ease, border-color 180ms ease;
  -webkit-tap-highlight-color: transparent;
}
body.true-dark-mode #mylist-view #cards-grid .status-pills .game-status-current-pill:active {
  transform: scale(0.97);
  background: rgba(225, 183, 229, 0.16) !important;
}

/* =============================================================================
   v11.251 — My Lists CATEGORY tabs + STATUS tabs: type normalization
   Category tabs (.section-btn: Games / Anime / Music / Movies / TV) and the
   status tabs (.tab-btn: Watching / Watchlist / Watched / Paused):
     - ALL CAPS (text-transform: uppercase)
     - letter-spacing: 0
     - Söhne (app default) font, forced past any contrast/override file
     - status tabs also get line-height: 1 (tightest safe — a literal 0 clips
       the glyphs). Scoped high + !important so 16-light-mode-contrast.css and
       12-pwa-header-continuity.css can't override the family/spacing.
   Two IDs (#mylist-view #mylist-toolbar / #mylist-header) keep specificity
   above the existing rules in 12 + 16. Dark-mode is the only production theme.
   ============================================================================= */
/* Categories (.section-btn) — ALL CAPS, Söhne, 0 tracking. */
#mylist-view #mylist-header .section-btn,
body.true-dark-mode #mylist-view #mylist-header .section-btn {
  font-family: 'Sohne', 'DM Sans', sans-serif !important;
  text-transform: uppercase !important;
  letter-spacing: 0 !important;
}
/* Status tabs (.tab-btn) — v11.253/254: NOT all-caps. Labels keep their
   authored casing (first letter only: "Watching", "Watchlist", …). Söhne,
   0 tracking, tight line-height, 12px (overrides the 13px !important in file 12). */
#mylist-view #mylist-toolbar .tab-btn,
body.true-dark-mode #mylist-view #mylist-toolbar .tab-btn {
  font-family: 'Sohne', 'DM Sans', sans-serif !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  line-height: 1 !important;
  font-size: 12px !important;
}

/* =============================================================================
   v11.252 — Shelf loading animation (game full-page profile)
   Replaces the "Building this game page..." text with a small, clean loader: a
   row of books that pop up onto a shelf plank one after another, loop. Books
   are simple lavender bars of varied height; the plank is a thin underline.
   Transform/opacity only (GPU-composited, ProMotion-friendly).
   ============================================================================= */
.shelfd-shelf-loading {
  display: flex !important;
  align-items: center;
  justify-content: center;
  padding: 40px 0;
}
.shelfd-shelf-loader {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 5px;
  height: 34px;
  padding: 0 4px 6px;
}
.shelfd-shelf-book {
  width: 7px;
  border-radius: 2px 2px 0 0;
  background: linear-gradient(180deg, #c4b5fd, #8b5cf6);
  transform: translateY(10px) scaleY(0.4);
  transform-origin: bottom center;
  opacity: 0;
  animation: shelfdShelfBookPop 1.5s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}
.shelfd-shelf-book:nth-child(1) { height: 24px; animation-delay: 0s; }
.shelfd-shelf-book:nth-child(2) { height: 30px; animation-delay: 0.12s; background: linear-gradient(180deg, #ddd0ff, #a78bfa); }
.shelfd-shelf-book:nth-child(3) { height: 20px; animation-delay: 0.24s; }
.shelfd-shelf-book:nth-child(4) { height: 28px; animation-delay: 0.36s; background: linear-gradient(180deg, #ddd0ff, #a78bfa); }
.shelfd-shelf-book:nth-child(5) { height: 22px; animation-delay: 0.48s; }
.shelfd-shelf-plank {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.22);
}
@keyframes shelfdShelfBookPop {
  0%   { transform: translateY(10px) scaleY(0.4); opacity: 0; }
  18%  { transform: translateY(0) scaleY(1); opacity: 1; }
  72%  { transform: translateY(0) scaleY(1); opacity: 1; }
  90%  { transform: translateY(10px) scaleY(0.4); opacity: 0; }
  100% { transform: translateY(10px) scaleY(0.4); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .shelfd-shelf-book { animation-duration: 3s; }
}
