body {
  margin: 0;
  background: var(--chloe-sage);
  color: var(--chloe-ink);
  font-family: "Cormorant Garamond", "Playfair Display", serif;
}

/* Issue #256 (Ticket 4 of #245): .chloe-sidebar and .chloe-switch rules
   moved out to sidebar/sidebar.css alongside the sidebar/sidebar.js
   component extraction. --chloe-sidebar-w/--chloe-sidebar-bar-h are
   declared in shared/tokens.css since .chloe-page below also reads them. */

/* --- Ticket A: header --- */
.chloe-page {
  padding-left: var(--chloe-sidebar-w);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.chloe-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding: 1.5rem 2rem;
}

/* Issue #254 (Ticket 2 of #245): .chloe-wordmark* rules moved to
   logo/logo.css alongside the logo/logo.js component extraction.
   Issue #255 (Ticket 3 of #245): .chloe-nav* rules moved to menu/menu.css
   alongside the menu/menu.js component extraction. */

.chloe-main {
  flex: 1 0 auto;
  padding: 0 2rem 2rem;
  min-height: 40vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* --- Ticket B: hero row (portrait + reserved player-card column) ---
   Columns centered against each other vertically so the shorter Now Playing
   column sits mid-height beside the tall square cover (per RadioCalicoLayout
   reference + 2026-07-27 request to vertically-center the block on screen). */
.chloe-hero {
  align-items: center;
}

.chloe-hero__portrait-col {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 2rem;
}

.chloe-hero__portrait {
  display: block;
  width: 100%;
  max-width: 528px;
  aspect-ratio: 1 / 1;
  height: auto;
  object-fit: cover;
  margin: 0 auto;
}

@media (max-width: 575.98px) {
  .chloe-hero__portrait {
    max-width: 240px;
  }
}

.chloe-hero__player-col {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 2rem;
}

/* Ticket E (issue #159, AC3): below `lg`, portrait/player columns stack full
   width — the desktop flex-end/flex-start alignment (meant to draw the two
   columns toward each other) would otherwise leave the portrait right-hung
   and the player card left-hung on a full-width column instead of centered.
   `width: 100%` is required here too: `.chloe-hero` is a Bootstrap `.row`
   (flex) and `col-lg-6` only applies at >=992px, so below that these columns
   have no Bootstrap-applied width and shrink-to-fit their content — leaving
   `justify-content: center` with no full-width box to center within. */
@media (max-width: 991.98px) {
  .chloe-hero__portrait-col,
  .chloe-hero__player-col {
    width: 100%;
    justify-content: center;
  }
}

/* --- Ticket C: Now Playing panel (issue #157) ---
   2026-07-27 review (RadioCalicoLayout.png): content floats directly on the
   page background (no white card wrapper — see the removed AC1 "white
   rounded card"); only the playback strip below is a themed surface, using
   --chloe-player-box-* tokens so it adapts across light/dark instead of a
   fixed literal-black box. */
.chloe-now-playing {
  width: 100%;
  max-width: 420px;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.chloe-now-playing__artist {
  margin: 0;
  font-family: var(--chloe-sans);
  font-weight: 700;
  font-size: 3rem;
  line-height: 1.1;
}

.chloe-now-playing__title-line {
  margin: 0;
  font-family: var(--chloe-sans);
  font-size: 1.6rem;
  font-weight: 700;
}

.chloe-now-playing__title {
  font-weight: 700;
}

.chloe-now-playing__year {
  font-weight: 700;
}

.chloe-now-playing__album {
  margin: 0;
  font-family: var(--chloe-sans);
  font-size: 1.05rem;
  font-weight: 700;
  opacity: 0.95;
}

.chloe-now-playing__quality {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.chloe-now-playing__quality-line {
  margin: 0;
  font-family: var(--chloe-sans);
  font-size: 0.9rem;
  font-style: italic;
  opacity: 0.6;
}

.chloe-now-playing__rating {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--chloe-sans);
  font-size: 0.95rem;
}

.chloe-now-playing__rating-btn {
  border: none;
  background: transparent;
  font-size: 1.1rem;
  line-height: 1;
  padding: 0.15rem;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.chloe-now-playing__rating-btn:hover {
  opacity: 0.85;
}

.chloe-now-playing__rating-btn.is-active {
  opacity: 1;
  transform: scale(1.15);
}

/* Issue #209: Recently Played modal trigger — flush-right within the
   existing .chloe-now-playing__rating flex row, above the audio controls. */
.chloe-now-playing__recently-played-trigger {
  margin-left: auto;
  border: 1px solid currentColor;
  background: transparent;
  color: var(--chloe-ink);
  font-family: var(--chloe-sans);
  font-size: 0.85rem;
  padding: 0.25rem 0.6rem;
  border-radius: 4px;
  cursor: pointer;
  opacity: 0.8;
}

.chloe-now-playing__recently-played-trigger:hover {
  opacity: 1;
}

/* --- Ticket D (issue #158, AC4): fetch-failure status line --- */
.chloe-now-playing__status {
  margin: 0;
  font-family: var(--chloe-sans);
  font-size: 0.85rem;
  font-style: italic;
  opacity: 0.75;
  color: var(--chloe-mint-deep);
}

.chloe-now-playing__player-box {
  background: var(--chloe-player-box-bg);
  color: var(--chloe-player-box-fg);
  border-radius: 16px;
  padding: 0.85rem 1.1rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-family: var(--chloe-sans);
}

.chloe-now-playing__progress-track {
  display: none;
  position: relative;
  height: 4px;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.2);
  overflow: hidden;
}

.chloe-now-playing__progress-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: var(--chloe-pink-deep);
}

/* --- Issue #209: Recently Played Modal ---
   The inline section (formerly here) was deleted outright per the human's
   step-3 review decision ("ลบ code เดิมออกเลย") — renderRecentlyPlayed()/
   parseRecentlyPlayed()/refreshNowPlaying() are unchanged and now target
   the modal's list element instead (see openRecentlyPlayedModal() in
   album-promo.js). Colors are drawn from the page's --chloe-* custom
   properties (defined near the top of this file, theme-aware via
   [data-chloe-theme="dark"]) so the modal tracks the light/dark toggle
   automatically, rather than a hardcoded palette (AC5). */
.chloe-recently-played-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgb(0 0 0 / 0.5);
  z-index: 1000;
}

.chloe-recently-played-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(90vw, 480px);
  max-height: 80vh;
  overflow-y: auto;
  background: var(--chloe-sage);
  color: var(--chloe-ink);
  border-radius: 16px;
  padding: 1.5rem;
  z-index: 1001;
  font-family: var(--chloe-sans);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.4);
}

.chloe-recently-played-modal__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
}

.chloe-recently-played-modal__title {
  font-family: var(--chloe-sans);
  font-size: 1.1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.8;
  margin: 0;
}

.chloe-recently-played-modal__close {
  border: 1px solid currentColor;
  background: transparent;
  color: var(--chloe-ink);
  font-family: var(--chloe-sans);
  border-radius: 4px;
  cursor: pointer;
  padding: 0.25rem 0.6rem;
  opacity: 0.8;
}

.chloe-recently-played-modal__close:hover {
  opacity: 1;
}

/* AC3: numbered "N. Artist : Title" rows — list-style: decimal gives the
   numbering for free; the colon is a ::after on the artist span so it stays
   out of the artist span's own textContent (recently-played-list.test.js
   asserts that text matches prev_artist_N exactly). */
.chloe-recently-played-modal__list {
  list-style: decimal;
  list-style-position: inside;
  margin: 0;
  padding: 0;
}

.chloe-recently-played__item {
  padding: 0.5rem 0;
  border-bottom: 1px solid rgb(0 0 0 / 0.08);
  font-family: var(--chloe-sans);
  font-size: 0.95rem;
}

.chloe-recently-played__item:last-child {
  border-bottom: none;
}

.chloe-recently-played__artist {
  font-weight: 700;
}

.chloe-recently-played__artist::after {
  content: " : ";
  font-weight: 400;
}

.chloe-recently-played__title {
  opacity: 0.75;
}

/* Ticket C (issue #157 review, 2026-07-24): playback controls DOM is
   rendered by the React island (mountPlayerControls() in album-promo.js) —
   these rules only style the classes/data-testids that component renders. */
.chloe-player-controls {
  position: relative; /* anchors the More Options dropdown (issue #446) */
  display: flex;
  align-items: center;
  flex-wrap: wrap; /* lets the Sleep Timer Countdown Panel (issue #447) wrap onto its own row below */
  gap: 1rem;
}

.chloe-player-controls__play {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 50%;
  border: none;
  background: var(--chloe-mint-deep);
  color: #ffffff;
  font-size: 1rem;
  cursor: pointer;
}

.chloe-player-controls__play:hover {
  opacity: 0.9;
}

.chloe-player-controls__timer {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  opacity: 0.85;
  white-space: nowrap;
}

.chloe-player-controls__live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--chloe-live-dot);
  animation: chloe-live-pulse 1.8s ease-in-out infinite;
}

@keyframes chloe-live-pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.4;
    transform: scale(0.75);
  }
}

/* Issue #465: speaker icon is its own button (keyboard/aria-pressed
   semantics, same pattern as .chloe-player-controls__more), separate from
   the slider's label. margin-left: auto moved here since this button is
   now the first element of the "push right" volume group. */
.chloe-player-controls__mute {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: inherit;
  font-size: 1.1rem;
  cursor: pointer;
  margin-left: auto;
}

.chloe-player-controls__mute:hover {
  background: rgb(255 255 255 / 0.12);
}

.chloe-player-controls__volume {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1;
  min-width: 0;
}

.chloe-player-controls__volume input[type="range"] {
  flex: 1;
  min-width: 48px;
  max-width: 100%;
  accent-color: var(--chloe-mint-deep);
}

/* --- Issue #446 (Ticket 0, parent #421): More Options button + sub-menu
   shell (Sleep Timer / Audio Quality / Share). The active-option highlight
   (AC3) uses a border + text-color accent rather than a full background —
   per the theme-token-background-audit skill, --chloe-pink-deep is the only
   accent token with a confirmed [data-chloe-theme="dark"] override, and a
   full-background swap risks contrast issues that a fixed-hue border avoids.
   No specific highlight color was locked in #421's review beyond "ไฮไลท์สี"
   (color highlight, replacing the earlier ✓ checkmark), so this keeps the
   border-left accent on --chloe-pink-deep even though issue #546's
   follow-ups moved the volume slider's accent-color and the play button's
   background to --chloe-mint-deep. */
.chloe-player-controls__more-wrap {
  position: relative;
  flex-shrink: 0;
}

.chloe-player-controls__more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: inherit;
  font-size: 1.1rem;
  cursor: pointer;
}

.chloe-player-controls__more:hover {
  background: rgb(255 255 255 / 0.12);
}

.chloe-player-controls__menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 200px;
  background: var(--chloe-sage);
  color: var(--chloe-ink);
  border-radius: 12px;
  padding: 0.5rem 0;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.25);
  z-index: 20;
  font-family: var(--chloe-sans);
}

.chloe-player-controls__menu-item {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  border-left: 3px solid transparent;
  background: transparent;
  color: inherit;
  font-size: 0.9rem;
  padding: 0.4rem 1rem 0.4rem calc(1rem - 3px);
  cursor: pointer;
}

.chloe-player-controls__menu-item:hover {
  background: rgb(0 0 0 / 0.05);
}

.chloe-player-controls__menu-item.is-active {
  border-left-color: var(--chloe-pink-deep);
  color: var(--chloe-mint-deep);
  font-weight: 700;
}

.chloe-player-controls__menu-item--share {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Top-level nav row (Sleep Timer / Audio Quality) that opens a nested
   sub-menu panel — 2026-08-24 review, #446: replaces the earlier layout
   where both option lists were always expanded inline in one flat panel. */
.chloe-player-controls__menu-item--nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.chloe-player-controls__menu-item-text {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.chloe-player-controls__menu-item-value {
  font-size: 0.75rem;
  opacity: 0.65;
}

/* Nested panel's back row — a real button (not a static heading) so it can
   navigate back to the top-level menu (click-to-expand/collapse, no
   hover-flyout — see #446 review). */
.chloe-player-controls__menu-back {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  border: none;
  background: transparent;
  color: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.75;
  padding: 0.3rem 1rem 0.5rem;
  cursor: pointer;
}

.chloe-player-controls__menu-back:hover {
  opacity: 1;
}

.chloe-player-controls__menu-divider {
  height: 1px;
  margin: 0.35rem 0;
  background: rgb(0 0 0 / 0.08);
}

/* --- Issue #447 (Ticket 1, parent #421): Sleep Timer Countdown Panel —
   docked below the main player bar (flex-basis: 100% on the flex-wrap
   container above), not inside the ⋮ dropdown. */
.chloe-player-controls__sleep-timer-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-basis: 100%;
  padding: 0.5rem 0.75rem;
  border-radius: 10px;
  background: var(--chloe-sage);
  color: var(--chloe-ink);
  font-size: 0.85rem;
}

.chloe-player-controls__sleep-timer-cancel {
  border: none;
  background: transparent;
  color: var(--chloe-mint-deep);
  font-weight: 700;
  font-size: 0.8rem;
  cursor: pointer;
  padding: 0.2rem 0.5rem;
}

.chloe-player-controls__sleep-timer-cancel:hover {
  text-decoration: underline;
}

/* --- Issue #449 (Ticket 3, parent #421): Share Modal — Copy Link only.
   Same fixed-backdrop/centered-panel pattern as the Recently Played Modal
   above (issue #209), reusing the --chloe-* theme-aware custom properties. */
.chloe-share-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgb(0 0 0 / 0.5);
  z-index: 1000;
}

.chloe-share-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(90vw, 420px);
  background: var(--chloe-sage);
  color: var(--chloe-ink);
  border-radius: 16px;
  padding: 1.5rem;
  z-index: 1001;
  font-family: var(--chloe-sans);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.4);
}

.chloe-share-modal__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
}

.chloe-share-modal__title {
  font-family: var(--chloe-sans);
  font-size: 1.1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.8;
}

.chloe-share-modal__close {
  border: 1px solid currentColor;
  background: transparent;
  color: var(--chloe-ink);
  font-family: var(--chloe-sans);
  border-radius: 4px;
  cursor: pointer;
  padding: 0.25rem 0.6rem;
  opacity: 0.8;
}

.chloe-share-modal__close:hover {
  opacity: 1;
}

.chloe-share-modal__url {
  font-family: var(--chloe-sans);
  font-size: 0.85rem;
  word-break: break-all;
  background: rgb(0 0 0 / 0.06);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  margin: 0 0 1rem;
}

.chloe-share-modal__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.6rem;
}

.chloe-share-modal__copied-status {
  font-family: var(--chloe-sans);
  font-size: 0.8rem;
  color: var(--chloe-ink);
  opacity: 0;
  animation-name: chloe-share-copied-fade;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-fill-mode: forwards;
}

@keyframes chloe-share-copied-fade {
  0% {
    opacity: 0;
  }
  15% {
    opacity: 1;
  }
  75% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.chloe-share-modal__copy {
  display: block;
  width: fit-content;
  border: none;
  border-radius: 8px;
  background: var(--chloe-pink-deep);
  color: #ffffff;
  font-family: var(--chloe-sans);
  font-weight: 700;
  font-size: 0.85rem;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
}

/* --- Ticket A: mobile — page-shell adjustments for the sidebar's bottom-bar
   collapse (sidebar's own rules moved to sidebar/sidebar.css, issue #256) --- */
@media (max-width: 767.98px) {
  .chloe-page {
    padding-left: 0;
    padding-bottom: var(--chloe-sidebar-bar-h);
  }

  .chloe-header {
    justify-content: center;
    text-align: center;
  }
}
