/* === Digital Journal Editor Custom CSS === */
html, body {
  overflow-x: auto !important;
  overflow-y: auto !important;
  height: auto !important;
  min-height: 100% !important;
}

#dj-root {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  max-width: 100%;
  margin: 0 auto;
  padding: 0 20px 200px 20px !important;
  overflow: visible !important;
  height: auto !important;
  min-height: 1200px !important;
}

#dj-warning {
  background: #fef3c7;
  border: 2px solid #f59e0b;
  border-radius: 8px;
  padding: 15px;
  margin: 16px 0;
  font-size: 14px;
  color: #92400e;
  font-weight: 600;
  text-align: center;
}

#dj-toolbar-1 {
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: center !important;
  gap: 10px !important;
  overflow-x: scroll !important;
  overflow-y: hidden !important;
  scrollbar-gutter: stable both-edges !important;
  padding-bottom: 14px !important;
  box-sizing: border-box !important;
  touch-action: pan-x !important;
  -webkit-overflow-scrolling: touch !important;
  white-space: nowrap !important;
  background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
  border: 1px solid #6ee7b7;
  border-radius: 12px;
  padding-top: 12px;
  padding-left: 20px;
  padding-right: 20px;
  margin: 16px 0;
  min-height: 62px;
  box-shadow: 0 2px 8px rgba(16,185,129,.2);
  width: 100% !important;
  position: relative;
  z-index: 1000;
}

#dj-toolbar-1::-webkit-scrollbar {
  height: 12px !important;
  background-color: #d1fae5 !important;
}
#dj-toolbar-1::-webkit-scrollbar-thumb {
  background-color: #10b981 !important;
  border-radius: 4px !important;
  border: 2px solid #d1fae5 !important;
}

#dj-ruler-h, #dj-ruler-v { 
  pointer-events: none !important;
  display: block !important;
  z-index: 10 !important;
}

#dj-canvas { 
  pointer-events: auto !important; 
  max-width: none !important; 
}

.dj-btn {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  height: 38px !important;
  padding: 0 18px !important;
  border: 2px solid rgba(255,255,255,.8) !important;
  border-radius: 8px !important;
  font-size: 14px !important;
  font-weight: 600 !important;
  color: #fff !important;
  cursor: pointer !important;
  white-space: nowrap !important;
}

.dj-btn.active {
  background: #059669 !important;
  border: 2px solid #fbbf24 !important;
  box-shadow: 0 0 10px #fbbf24 !important;
}

#btn-upload-image { background: linear-gradient(135deg,#ef4444,#dc2626)!important; }
#btn-upload-bg    { background: linear-gradient(135deg,#f97316,#ea580c)!important; }
#dj-add-text      { background: linear-gradient(135deg,#f59e0b,#d97706)!important; }
#dj-flip-h { background: linear-gradient(135deg,#06b6d4,#0891b2)!important; }
#dj-flip-v { background: linear-gradient(135deg,#0ea5e9,#0284c7)!important; }
#dj-rotate-left { background: linear-gradient(135deg,#3b82f6,#2563eb)!important; }
#dj-rotate-right { background: linear-gradient(135deg,#2563eb,#1d4ed8)!important; }
#dj-crop { background: linear-gradient(135deg,#6366f1,#4f46e5)!important; }
#dj-apply-crop { background: linear-gradient(135deg,#10b981,#059669)!important; }
#dj-cancel-crop { background: linear-gradient(135deg,#dc2626,#b91c1c)!important; }
#dj-filter-gray { background: linear-gradient(135deg,#6b7280,#4b5563)!important; }
#dj-duplicate { background: linear-gradient(135deg,#8b5cf6,#7c3aed)!important; }
#dj-align-center { background: linear-gradient(135deg,#a855f7,#9333ea)!important; }
#dj-text-bold { background: linear-gradient(135deg,#d946ef,#c026d3)!important; }
#dj-text-italic { background: linear-gradient(135deg,#e879f9,#d946ef)!important; }
#dj-delete        { background: linear-gradient(135deg,#dc2626,#b91c1c)!important; }
#dj-undo          { background: linear-gradient(135deg,#14b8a6,#0d9488)!important; }
#dj-redo          { background: linear-gradient(135deg,#06b6d4,#0891b2)!important; }
#dj-download-png  { background: linear-gradient(135deg,#3b82f6,#2563eb)!important; }
#dj-download-pdf  { background: linear-gradient(135deg,#6366f1,#4f46e5)!important; }
#dj-download-jpeg { background: linear-gradient(135deg,#8b5cf6,#7c3aed)!important; }
#dj-download-svg  { background: linear-gradient(135deg,#a855f7,#9333ea)!important; }

.dj-input, #dj-root select {
  height: 38px !important;
  padding: 0 12px !important;
  border: 2px solid #fff !important;
  border-radius: 8px !important;
  background: #fff !important;
  font-size: 14px !important;
  color: #1a1a1a !important;
}
.dj-input.mini { 
  width: 65px !important; 
  text-align: center !important; 
}
.dj-input.slider {
  width: 120px !important;
  vertical-align: middle !important;
}
.dj-label {
  font-weight: bold !important;
  color: #065f46 !important;
  margin-right: 4px !important;
  white-space: nowrap !important;
}

#dj-stage { 
  position: relative !important; 
  margin: 20px 0 200px 0 !important; 
  line-height: 0 !important; 
  overflow: visible !important; 
  background: transparent !important;
  width: 100% !important;
  height: auto !important;
  min-height: 900px !important;
}

#dj-ruler-h { 
  top: 0 !important; 
  left: 30px !important; 
  height: 30px !important; 
  width: auto !important; 
  position: absolute !important; 
  background: #f3f4f6 !important; 
}

#dj-ruler-v { 
  top: 30px !important; 
  left: 0 !important; 
  width: 30px !important; 
  height: auto !important; 
  position: absolute !important; 
  background: #f3f4f6 !important; 
}

#dj-stage .canvas-wrap { 
  position: relative !important; 
  display: inline-block !important; 
  margin-left: 30px !important; 
  margin-top: 30px !important; 
  margin-bottom: 100px !important;
  line-height: 0 !important; 
}

#dj-canvas { 
  border: 2px solid #ccc !important;
  display: block !important;
  background: #fff !important;
  box-shadow: 0 2px 10px rgba(0,0,0,.1) !important;
  cursor: default !important;
  touch-action: none !important;
  width: 1320px !important;
  height: 700px !important;
}

#dj-upload-image, #dj-upload-bg { 
  position: absolute !important; 
  left: -9999px !important; 
  opacity: 0 !important;
}

#dj-status {
  display: none !important;
  visibility: hidden !important;
  opacity: 0 !important;
  height: 0 !important;
  overflow: hidden !important;
  position: absolute !important;
  left: -9999px !important;
}

#dj-root .status {
  display: none !important;
  visibility: hidden !important;
  opacity: 0 !important;
  height: 0 !important;
  overflow: hidden !important;
  position: absolute !important;
  left: -9999px !important;
}

.status {
  display: none !important;
}

#dj-root h2 {
  display: none !important;
}

#dj-root .dj-note {
  display: none !important;
}

.crop-controls {
  display: none;
}
.crop-controls.active {
  display: inline-block !important;
}

@media (max-width: 768px) {
  #dj-root {
    display: none !important;
  }
  #dj-root:before {
    content: "Please use a desktop computer to access the editor.";
    display: block !important;
    text-align: center;
    padding: 40px 20px;
    font-size: 18px;
    color: #666;
  }
}
<!-- START AI SHEET PERFORMER JS -->
alert('Custom JS is running!');
<script>
// ====== WHERE YOUR BACKEND WILL BE ======
const API = {
  OMR:   "http://localhost:8000/api/omr",
  PIANO: "http://localhost:8000/api/render-piano",
  VOCAL: "http://localhost:8000/api/render-vocal",
  MIX:   "http://localhost:8000/api/mix"
};

// if you don’t have vocal backend yet turn off vocals for now:
const VOCALS_ENABLED = false;

const $ = sel => document.querySelector(sel);

function setBusy(b) {
  $("#ai-sp-run").disabled = b;
  $("#ai-sp-status").textContent = b ? "Working…" : "";
}

async function postForm(url, formData) {
  const r = await fetch(url, { method: "POST", body: formData });
  if (!r.ok) throw new Error(await r.text());
  return r;
}

function blobToPlayer(elAudio, elLink, blob, filename) {
  const url = URL.createObjectURL(blob);
  elAudio.src = url;
  elLink.href = url;
  elLink.download = filename;
}

document.addEventListener("DOMContentLoaded", () => {
  const form = $("#ai-sp-form");
  const results = document.querySelector(".ai-sp__results");
  const st = $("#ai-sp-status");

  form.addEventListener("submit", async (e) => {
    e.preventDefault();
    results.hidden = true;
    st.textContent = "starting…";

    const file = $("#ai-sp-file").files[0];
    if (!file) { st.textContent = "choose a file first"; return; }
    const tempo = parseInt($("#ai-sp-tempo").value || "0", 10);
    const doOMR = $("#ai-sp-omr").checked;

    setBusy(true);

    try {
      let scoreBlob = file;

      // 1) send to piano
      st.textContent = "rendering piano…";
      const fdPiano = new FormData();
      fdPiano.append("score", scoreBlob);
      if (tempo > 0) fdPiano.append("tempo", String(tempo));
      const pianoResp = await postForm(API.PIANO, fdPiano);
      const pianoBlob = await pianoResp.blob();

      // 2) mix only piano for now
      st.textContent = "mixing…";
      const fdMix = new FormData();
      fdMix.append("piano", pianoBlob, "piano.wav");
      const mixResp = await postForm(API.MIX, fdMix);
      const mixBlob = await mixResp.blob();

      blobToPlayer($("#ai-sp-audio-piano"), $("#ai-sp-dl-piano"), pianoBlob, "piano.wav");
      blobToPlayer($("#ai-sp-audio-mix"), $("#ai-sp-dl-mix"), mixBlob, "mix.mp3");

      results.hidden = false;
      st.textContent = "done.";
    } catch (err) {
      st.textContent = "error: " + err.message;
      console.error(err);
    } finally {
      setBusy(false);
    }
  });
});
</script>
.ai-sp__results { display: block !important; }
.ai-sp__status { display: block !important; }

<!-- END AI SHEET PERFORMER JS -->
