:root {
  --mo-accent: #2c7a7b;                  /* teal — music/album semantic color */
  /* Charter palette + role accent — OPERATOR (dev) defaults: warm.
     spec-musicorgan-operator-player-organ-banner. .mo-player overrides below. */
  --charter-body: #ff905f;
  --charter-shade:#e76a39;               /* deeper skin tone for the blend */
  --charter-arm:  #ffaf8f;
  --charter-accent:#4aa3ff;              /* opposite-hue accent — blue weaves through the orange */
  --charter-eye:  #ffffff;
  --charter-pupil:#2b3b47;
  --mo-role-accent: #ff8c42;             /* warm — Operator */
  --mo-banner-bg: linear-gradient(#20283a, #1a202c);
}
/* PLAYER (Fly public read-only): cool/blue palette + accent. */
.mo-player {
  --charter-body: #5aa9ff;
  --charter-shade:#2f7fd6;               /* deeper skin tone for the blend */
  --charter-arm:  #9fccff;
  --charter-accent:#ff8a4c;              /* opposite-hue accent — orange weaves through the blue */
  --charter-eye:  #ffffff;
  --charter-pupil:#16263a;
  --mo-role-accent: #38bdf8;             /* cool — Player */
  --mo-banner-bg: linear-gradient(#142036, #0f1626);
}
.navbar-brand i { color: var(--mo-accent); }

/* ---- banner + role badge ---- */
.mo-banner { background: var(--mo-banner-bg); }
.mo-role-badge {
  display:inline-flex; align-items:center; gap:.3rem;
  font-size:.68rem; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  padding:.12rem .55rem; border-radius:1rem; margin-left:.55rem; color:#fff;
  background: var(--mo-role-accent); border:1px solid rgba(255,255,255,.28);
  white-space:nowrap;
}

/* ---- Charter mascot: palette via CSS vars + idle animation ---- */
.charter { width: 2.6rem; height: 2.6rem; display:block; overflow:visible; }
/* hero variant on the Charter home: large, centered, soft drop shadow */
.charter--hero { width: clamp(8rem, 22vw, 13rem); height: clamp(8rem, 22vw, 13rem);
  margin-inline:auto; filter: drop-shadow(0 10px 20px rgba(0,0,0,.18)); }
.mo-role-badge--hero { font-size:.8rem; padding:.3rem .85rem; margin-left:0; }
/* brand lockup tagline: "Music Organ" sitting under the Charter wordmark.
   Muted by default (light login card); brightened on the dark banner. */
.mo-tagline {
  font-size:.62rem; font-weight:600; line-height:1;
  text-transform:uppercase; letter-spacing:.08em;
  color:#718096;
}
.mo-banner .mo-tagline { color:rgba(255,255,255,.6); }
/* body wears the living-skin gradient (animated stop-colors below) + mottle filter */
.charter-body  { fill: url(#charter-skin-grad); }
.charter-arm   { fill: var(--charter-arm); }
/* chromatophore skin: 4 stops drift between the role's skin tones AND the
   opposite-hue accent, desynced — blues and oranges weave across the body.
   Stop 3 anchors the accent so the second hue is always visible. */
.charter-stop--1 { stop-color: var(--charter-shade);  animation: charter-skin-1 9s  ease-in-out infinite; }
.charter-stop--2 { stop-color: var(--charter-body);   animation: charter-skin-2 11s ease-in-out infinite; }
.charter-stop--3 { stop-color: var(--charter-accent); animation: charter-skin-3 8s  ease-in-out infinite; }
.charter-stop--4 { stop-color: var(--charter-arm);    animation: charter-skin-4 6.5s ease-in-out infinite; }
@keyframes charter-skin-1 { 0%,100% { stop-color: var(--charter-shade); }  50% { stop-color: var(--charter-accent); } }
@keyframes charter-skin-2 { 0%,100% { stop-color: var(--charter-body); }   50% { stop-color: var(--charter-arm); } }
@keyframes charter-skin-3 { 0%,100% { stop-color: var(--charter-accent); } 50% { stop-color: var(--charter-body); } }
@keyframes charter-skin-4 { 0%,100% { stop-color: var(--charter-arm); }    50% { stop-color: var(--charter-shade); } }
.charter-eye   { fill: var(--charter-eye); }
.charter-pupil-fill { fill: var(--charter-pupil); }
/* gentle whole-mascot sway — reads as arms drifting left/right + up/down */
.charter-arms { transform-box: fill-box; transform-origin: 50% 35%; animation: charter-sway 6s ease-in-out infinite; }
@keyframes charter-sway {
  0%   { transform: rotate(-2.6deg) translateY(0); }
  50%  { transform: rotate(2.6deg)  translateY(-12px); }
  100% { transform: rotate(-2.6deg) translateY(0); }
}
/* pupils dart on independent timings — the two eyes do NOT move together */
.charter-pupil { transform-box: fill-box; }
.charter-pupil--l { animation: charter-dart-l 5.3s ease-in-out infinite; }
.charter-pupil--r { animation: charter-dart-r 7.1s ease-in-out infinite; }
@keyframes charter-dart-l {
  0%,18%   { transform: translate(0,0); }
  26%,40%  { transform: translate(8px,-4px); }
  52%,66%  { transform: translate(-6px,5px); }
  78%,100% { transform: translate(5px,1px); }
}
@keyframes charter-dart-r {
  0%,12%   { transform: translate(-5px,3px); }
  30%,44%  { transform: translate(7px,4px); }
  58%,72%  { transform: translate(3px,-5px); }
  84%,100% { transform: translate(-4px,0); }
}
/* conductor's baton: the raised arm holds a baton; the conducting WAVE is the idle
   animation. The baton tapers to a point (its own taper = the tapered tip) and
   waves in free space beyond the arm, so no masking/blunting of the octopus arm.
   Pivots at the grip, desynced from the body sway / eye darts / skin.
   spec-musicorgan-charter-arm-wiggle */
/* plain uniform rod: a dark edge under a white core, rounded tip. NOT tapered —
   the octopus arm keeps its own natural smooth tip (that was what blunted earlier). */
.charter-baton-shaft-edge { fill: none; stroke: rgba(35,24,12,.55); stroke-width: 4.4; stroke-linecap: round; }
.charter-baton-shaft      { fill: none; stroke: #fbfaf5;          stroke-width: 3.0; stroke-linecap: round; }
/* classic dark cork handle (not themed — role is signalled elsewhere) */
.charter-baton-grip  { fill: #241d15; stroke: rgba(15,10,5,.55); stroke-width: 1; }
.charter-baton {
  transform-box: fill-box; transform-origin: 16% 90%;
  animation: charter-baton-wave 2.8s cubic-bezier(0.4,0,0.2,1) infinite;
}
@keyframes charter-baton-wave {
  0%   { transform: rotate(-13deg); }
  50%  { transform: rotate(13deg); }
  100% { transform: rotate(-13deg); }
}
@media (prefers-reduced-motion: reduce) {
  .charter-arms, .charter-pupil--l, .charter-pupil--r, .charter-baton,
  .charter-stop--1, .charter-stop--2, .charter-stop--3, .charter-stop--4 { animation: none !important; }
}
/* dev inspect aid — append ?inspect=armtip to the URL. Outlines the baton in cyan
   and slows the conducting wave (SAME ±13deg, longer 9s period) so the motion is
   easy to follow on the live page. Gated on <html class="inspect-armtip">; never
   affects the default render. spec-clodi-leaning-motion-tunicate. */
.inspect-armtip .charter-baton-shaft { stroke: #00e5ff; }
.inspect-armtip .charter-baton-grip  { stroke: #00e5ff; stroke-width: 2.5; }
.inspect-armtip .charter-baton { animation-duration: 9s; }
.inspect-armtip body::after {
  content: "INSPECT · cyan = .charter-baton (conductor's baton) · real ±13° conducting wave, slowed to 9s · drop ?inspect=armtip to restore";
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 2000;
  background: #00121a; color: #00e5ff; text-align: center;
  font: 600 .78rem/1.7 system-ui, sans-serif; letter-spacing: .02em; padding: .35rem;
}

/* ---- organ manual: large black & white keys, hover-depress ---- */
/* navbar-expand-lg forces flex-wrap:nowrap at >=992px, which squeezed the keys
   onto the content row. Make the sticky banner a plain BLOCK stack instead:
   the inner .container-fluid keeps Bootstrap's own display:flex (brand/search
   row), and .mo-keys + #mo-progress fall below it full-width. A block sticky
   element avoids the flex-direction:column + position:sticky resize glitch
   (banner drifting down, whitespace above). */
.mo-banner.navbar { display: block; }
.mo-keys { position: relative; width: 100%; height: 24px; user-select: none; border-top: 2px solid var(--mo-role-accent); }
.mo-keys-white { display: flex; height: 100%; }
.mo-key-w {
  flex: 1 1 0; background: linear-gradient(#fff, #ededed);
  border-right: 1px solid #b9b9b9; border-bottom: 2px solid rgba(0,0,0,.28);
  transform-origin: top; transition: transform .08s ease, background .08s ease;
}
.mo-key-w:last-child { border-right: 0; }
.mo-key-w:hover { background: linear-gradient(var(--mo-role-accent), #fff); transform: scaleY(.9); border-bottom-width: 1px; }
.mo-keys-black { position: absolute; inset: 0 0 auto 0; height: 62%; pointer-events: none; }
.mo-key-b {
  position: absolute; top: 0; width: 4.3%; height: 100%;
  background: linear-gradient(#3a3a3a, #050505); border-radius: 0 0 3px 3px;
  box-shadow: 0 2px 2px rgba(0,0,0,.5); pointer-events: auto;
  transform-origin: top; transition: transform .08s ease, background .08s ease;
}
.mo-key-b:hover { background: linear-gradient(var(--mo-role-accent), #1a1a1a); transform: scaleY(.88); }
.mo-key-b:nth-child(1) { left: 4.99%; }
.mo-key-b:nth-child(2) { left: 12.14%; }
.mo-key-b:nth-child(3) { left: 26.42%; }
.mo-key-b:nth-child(4) { left: 33.56%; }
.mo-key-b:nth-child(5) { left: 40.71%; }
.mo-key-b:nth-child(6) { left: 54.99%; }
.mo-key-b:nth-child(7) { left: 62.14%; }
.mo-key-b:nth-child(8) { left: 76.42%; }
.mo-key-b:nth-child(9) { left: 83.56%; }
.mo-key-b:nth-child(10){ left: 90.71%; }
.table-hover tbody tr:hover { background: #f0fbfb; }
.count-badge { font-variant-numeric: tabular-nums; }

/* htmx in-flight bar under the navbar */
.mo-progress { height: 2px; background: transparent; }
.mo-progress.htmx-request { background: linear-gradient(90deg, var(--mo-accent), #4fd1c5); animation: mo-pulse 1s ease-in-out infinite; }
@keyframes mo-pulse { 0%,100% { opacity:.4 } 50% { opacity:1 } }

/* ---- persistent player bar (now a static row inside the sticky top header) ---- */
.mo-topbar { z-index: 1030; }            /* banner + Now Playing pin together at top */
.mo-player {
  background: #1a202c; color: #e2e8f0;
  min-height: 20vh; display: flex; flex-direction: column; justify-content: center;
  gap: .35rem; padding-block: .6rem;
}
.mo-player-stage { width: 100%; }
/* big control satellites around the now-playing portlet */
.mo-pbtn { font-size: 1.5rem; line-height: 1; padding: .35rem .6rem; border-radius: .6rem; }
.mo-pbtn-lg { font-size: 2.4rem; padding: .2rem .75rem; border-radius: 50%; }
.mo-pbtn .badge { font-size: .6rem; }
/* now-playing portlet (centre): big art + big title */
.mo-portlet { min-width: 0; max-width: 42vw; cursor: pointer; }
.mo-portlet-art { height: clamp(72px, 13vh, 132px); width: clamp(72px, 13vh, 132px); object-fit: cover; background:#e6fffa; }
.mo-portlet-title { font-size: 1.4rem; font-weight: 600; line-height: 1.2; }
.mo-portlet-sub { font-size: 1.05rem; }
.mo-player .mo-audio { height: 42px; width: min(620px, 86vw); max-width: none; }
/* current-track ID reveal under the strip (own classes; not the canonical mo-id-chip) */
.mo-now-id { display: flex; }
.mo-nowid-text { color: #cbd5e0; }
.mo-nowid-copy.mo-nowid-copied { color: #34d399; border-color: #34d399; }
/* "show in list" locate flash on the target row */
.mo-row-flash { animation: mo-row-flash 1.3s ease-out; }
@keyframes mo-row-flash { 0%,25% { background: #ffe9a8 !important; } 100% { background: transparent; } }
@media (prefers-reduced-motion: reduce) { .mo-row-flash { animation: none !important; } }
.mo-now { min-width: 0; }
.mo-now-art { height: 38px; width: 38px; object-fit: cover; }
/* album-art thumbnails in cards/grids */
.mo-art { object-fit: cover; background: #e6fffa; }
.mo-art-card { width: 56px; height: 56px; flex: 0 0 56px; }
.mo-art-detail { width: 72px; height: 72px; }
.mo-player .btn-outline-light.active { background: var(--mo-accent); border-color: var(--mo-accent); color:#fff; }

/* up-next drawer */
.mo-queue-drawer { background:#222a38; max-height: 45vh; overflow-y:auto; }
.mo-queue-list li { display:flex; align-items:center; gap:.5rem; padding:.25rem .75rem; cursor:pointer; border-bottom:1px solid rgba(255,255,255,.05); }
.mo-queue-list li:hover { background:#2d3748; }
.mo-queue-list li.mo-current { background:#2c7a7b33; }
.mo-queue-list li.mo-current .mo-q-title { color:#4fd1c5; font-weight:600; }
.mo-queue-list .mo-q-title { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.mo-queue-list .mo-q-sub { color:#94a3b8; font-size:.8em; }
.mo-queue-list .mo-q-rm { color:#64748b; }
.mo-queue-list .mo-q-rm:hover { color:#f56565; }

/* play/now-playing affordances in lists */
tr.mo-row-playing { background:#e6fffa !important; }
tr.mo-row-playing td:first-child { box-shadow: inset 3px 0 0 var(--mo-accent); }

/* inline track-detail expansion row */
tr.mo-detail-row > td { background:#f8fafc; }
.mo-facts { display:grid; grid-template-columns: repeat(auto-fill, minmax(11rem,1fr)); gap:.35rem 1.25rem; }
.mo-facts dt { font-size:.7rem; text-transform:uppercase; letter-spacing:.04em; color:#718096; margin:0; }
.mo-facts dd { margin:0 0 .35rem 0; font-size:.9rem; }
.mo-mb { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size:.72rem; }

/* star rating widget */
.mo-stars { display:inline-flex; cursor:pointer; }
.mo-stars i { color:#cbd5e0; }
.mo-stars i.on { color:#ecc94b; }

/* row-ID affordance — tiny muted chip + inline copy popover (no layout shift) */
.mo-id-chip { display:inline-flex; align-items:center; gap:.2rem; vertical-align:baseline; }
.mo-id-text { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size:.68rem; color:#a0aec0; line-height:1; white-space:nowrap; }
.mo-id-info { font-size:.72rem; color:#a0aec0 !important; line-height:1; text-decoration:none; }
.mo-id-info:hover { color:var(--mo-accent) !important; }
.mo-id-pop { display:inline-flex; align-items:center; }
.mo-id-copy { font-size:.68rem; line-height:1.1; }
.mo-id-copy.mo-id-copied { color:#22863a; border-color:#22863a; }

/* alpha jump bar */
.mo-alpha { display:flex; flex-wrap:wrap; gap:.15rem; }
.mo-alpha a { width:1.7rem; text-align:center; }
.mo-alpha a.active { background:var(--mo-accent); color:#fff; border-color:var(--mo-accent); }

/* transcode status badge on the now-playing portlet
   (spec-musicorgan-transcode-web-rendition) — appended block, do not reorder */
.mo-transcode-badge {
  margin-top:.15rem; font-size:.72rem; line-height:1.2; font-weight:600;
  display:inline-flex; align-items:center; gap:.3rem;
  padding:.1rem .45rem; border-radius:.6rem;
}
.mo-transcode-wait { color:#0c2b34; background:#7fd1de; }
.mo-transcode-fail { color:#fff; background:#b23a48; }
.mo-transcode-wait::before { content:"\F130"; font-family:"bootstrap-icons"; animation:mo-tc-pulse 1.2s ease-in-out infinite; }
.mo-transcode-fail::before { content:"\F623"; font-family:"bootstrap-icons"; }
@keyframes mo-tc-pulse { 0%,100% { opacity:.4; } 50% { opacity:1; } }
