<div id=”rockstar-assignment-app”></div>

<style>
#rockstar-assignment-app {
–bg: #050505;
–bg2: #111111;
–panel: #171717;
–panel2: #f3f0e8;
–panel3: #ffffff;
–gold: #f5c542;
–gold2: #d4a514;
–text: #f5f5f5;
–muted: #b5b5b5;
–darktext: #111111;
–border: #333333;
–softborder: #d1d1d1;
–shadow: 0 10px 30px rgba(0,0,0,.25);
font-family: Arial, Helvetica, sans-serif;
color: var(–text);
}

#rockstar-assignment-app,
#rockstar-assignment-app * {
box-sizing: border-box;
color: inherit;
}

#rockstar-assignment-app .rsa-wrap {
min-height: 100vh;
background: linear-gradient(to bottom, #000000, #0f0f0f, #000000);
padding: 16px;
}

#rockstar-assignment-app .rsa-inner {
max-width: 1380px;
margin: 0 auto;
}

#rockstar-assignment-app .rsa-card {
background: rgba(17,17,17,.96);
border: 1px solid rgba(245,197,66,.22);
border-radius: 22px;
box-shadow: var(–shadow);
}

#rockstar-assignment-app .rsa-btn,
#rockstar-assignment-app button,
#rockstar-assignment-app a.rsa-btn {
cursor: pointer;
border: 1px solid transparent;
border-radius: 14px;
padding: 11px 16px;
font-size: 14px;
font-weight: 600;
transition: .18s ease;
text-decoration: none;
display: inline-block;
}

#rockstar-assignment-app .rsa-btn-gold {
background: var(–gold);
color: #000 !important;
}

#rockstar-assignment-app .rsa-btn-gold:hover {
background: #ffd85d;
}

#rockstar-assignment-app .rsa-btn-light {
background: #fff;
color: #111 !important;
border-color: #cfcfcf;
}

#rockstar-assignment-app .rsa-btn-light:hover {
background: #f0f0f0;
}

#rockstar-assignment-app .rsa-btn-complete {
background: #2e9b4b;
color: #fff !important;
border-color: #2e9b4b;
}

#rockstar-assignment-app .rsa-card-title {
color: var(–gold) !important;
font-size: 30px !important;
line-height: 1.15 !important;
font-weight: 700 !important;
margin: 0 0 8px !important;
}

#rockstar-assignment-app .rsa-card-sub {
color: var(–muted) !important;
font-size: 14px !important;
margin-bottom: 18px !important;
line-height: 1.5 !important;
}

#rockstar-assignment-app .rsa-page-card {
padding: 22px;
margin-bottom: 22px;
}

#rockstar-assignment-app .rsa-panel {
background: var(–panel2);
color: var(–darktext) !important;
border: 1px solid var(–softborder);
border-radius: 18px;
padding: 16px;
box-shadow: 0 2px 10px rgba(0,0,0,.06);
}

#rockstar-assignment-app .rsa-panel * {
color: inherit;
}

#rockstar-assignment-app .rsa-panel h3,
#rockstar-assignment-app .rsa-panel h4 {
margin: 0 0 8px;
color: #111 !important;
}

#rockstar-assignment-app .rsa-panel p {
margin: 0;
line-height: 1.5;
color: #111 !important;
}

#rockstar-assignment-app .rsa-student-content-grid {
display: grid;
grid-template-columns: 320px minmax(0, 1fr);
gap: 22px;
}

#rockstar-assignment-app .rsa-student-side-stack {
display: flex;
flex-direction: column;
gap: 14px;
}

#rockstar-assignment-app .rsa-top-lesson-details {
margin-bottom: 20px;
}

#rockstar-assignment-app .rsa-focus-image-wrap {
width: 100%;
border-radius: 14px;
overflow: hidden;
border: 1px solid #d3d3d3;
background: #111;
margin-bottom: 12px;
}

#rockstar-assignment-app .rsa-focus-image {
width: 100%;
height: auto;
display: block;
}

#rockstar-assignment-app .rsa-focus-placeholder {
min-height: 160px;
display: flex;
align-items: center;
justify-content: center;
color: #f5c542 !important;
background: #111;
font-weight: 700;
text-align: center;
padding: 20px;
}

#rockstar-assignment-app .rsa-album-box {
background: var(–panel2);
color: var(–darktext) !important;
border: 1px solid var(–softborder);
border-radius: 18px;
padding: 14px;
box-shadow: 0 2px 10px rgba(0,0,0,.06);
display: flex;
align-items: center;
justify-content: center;
}

#rockstar-assignment-app .rsa-album-btn {
width: 100%;
text-align: center;
background: #111;
color: #fff !important;
border: 1px solid #444;
border-radius: 14px;
padding: 14px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
min-height: 52px;
}

#rockstar-assignment-app .rsa-album-btn:hover {
background: #1d1d1d;
border-color: #666;
}

#rockstar-assignment-app .rsa-note-status {
font-size: 12px;
color: #666 !important;
margin-top: 8px;
text-align: center;
}

#rockstar-assignment-app .rsa-video-embed-wrap {
position: relative;
width: 100%;
padding-top: 56.25%;
border-radius: 16px;
overflow: hidden;
border: 1px solid #d3d3d3;
background: #000;
}

#rockstar-assignment-app .rsa-video-embed-wrap iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border: 0;
}

#rockstar-assignment-app .rsa-video-actions {
margin-top: 12px;
display: flex;
gap: 10px;
flex-wrap: wrap;
}

#rockstar-assignment-app .rsa-video-description {
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid #ddd4bf;
color: #444 !important;
font-size: 14px;
line-height: 1.55;
}

#rockstar-assignment-app .rsa-video-fallback {
background: #fff;
border: 1px solid #d3d3d3;
border-radius: 16px;
padding: 22px;
color: #111 !important;
}

#rockstar-assignment-app .rsa-video-fallback-url {
margin-top: 10px;
font-size: 13px;
color: #666 !important;
word-break: break-word;
}

#rockstar-assignment-app .rsa-pdf-wrap {
margin-top: 12px;
}

#rockstar-assignment-app .rsa-pdf-frame {
width: 100%;
height: 360px;
border: 1px solid #d3d3d3;
border-radius: 16px;
background: #fff;
overflow: hidden;
}

#rockstar-assignment-app .rsa-pdf-frame iframe {
width: 100%;
height: 100%;
border: 0;
display: block;
}

#rockstar-assignment-app .rsa-pdf-actions {
margin-top: 10px;
display: flex;
gap: 10px;
flex-wrap: wrap;
}

#rockstar-assignment-app .rsa-practice-player-wrap {
margin-top: 12px;
}

#rockstar-assignment-app .rsa-practice-player-box {
background: #fff;
border: 1px solid #d3d3d3;
border-radius: 16px;
padding: 16px;
}

#rockstar-assignment-app .rsa-practice-player-title {
font-weight: 700;
color: #111 !important;
margin-bottom: 8px;
}

#rockstar-assignment-app .rsa-practice-player-sub {
font-size: 13px;
color: #555 !important;
margin-bottom: 12px;
line-height: 1.45;
}

#rockstar-assignment-app .rsa-practice-player-frame {
position: relative;
width: 100%;
height: 230px;
border-radius: 16px;
overflow: hidden;
border: 1px solid #d3d3d3;
background: #000;
}

#rockstar-assignment-app .rsa-practice-player-frame iframe {
width: 100%;
height: 100%;
border: 0;
display: block;
}

#rockstar-assignment-app .rsa-practice-player-empty {
background: #fff;
border: 1px solid #d3d3d3;
border-radius: 16px;
padding: 16px;
color: #666 !important;
}

#rockstar-assignment-app .rsa-complete-wrap {
position: relative;
overflow: hidden;
}

#rockstar-assignment-app .rsa-complete-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 14px;
}

#rockstar-assignment-app .rsa-complete-note {
margin-top: 10px;
font-size: 13px;
color: #666 !important;
}

#rockstar-assignment-app .rsa-fireworks {
position: absolute;
inset: 0;
pointer-events: none;
overflow: hidden;
border-radius: 16px;
}

#rockstar-assignment-app .rsa-spark {
position: absolute;
width: 8px;
height: 8px;
border-radius: 999px;
background: var(–gold);
opacity: 0;
animation: rsaSpark .9s ease-out forwards;
}

@keyframes rsaSpark {
0% {
transform: translate(0, 0) scale(.2);
opacity: 1;
}
100% {
transform: translate(var(–tx), var(–ty)) scale(1.4);
opacity: 0;
}
}

#rockstar-assignment-app .rsa-modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0,0,0,.72);
z-index: 9998;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}

#rockstar-assignment-app .rsa-large-video-modal,
#rockstar-assignment-app .rsa-large-pdf-modal,
#rockstar-assignment-app .rsa-notes-modal {
width: min(1200px, 96vw);
background: #111;
border: 1px solid rgba(245,197,66,.25);
border-radius: 22px;
box-shadow: 0 20px 50px rgba(0,0,0,.45);
padding: 20px;
position: relative;
}

#rockstar-assignment-app .rsa-notes-modal {
width: min(780px, 96vw);
}

#rockstar-assignment-app .rsa-notes-box {
background: var(–panel2);
border: 1px solid var(–softborder);
border-radius: 18px;
padding: 16px;
color: #111 !important;
}

#rockstar-assignment-app .rsa-notes-box * {
color: inherit;
}

#rockstar-assignment-app .rsa-notes-textarea {
width: 100%;
min-height: 260px;
resize: vertical;
border-radius: 14px;
border: 1px solid #cfcfcf;
padding: 14px;
font-size: 15px;
line-height: 1.5;
color: #111 !important;
background: #fff;
font-family: Arial, Helvetica, sans-serif;
}

#rockstar-assignment-app .rsa-notes-textarea:focus {
outline: 2px solid var(–gold);
border-color: var(–gold);
}

#rockstar-assignment-app .rsa-notes-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 12px;
}

#rockstar-assignment-app .rsa-large-video-frame {
position: relative;
width: 100%;
padding-top: 56.25%;
border-radius: 16px;
overflow: hidden;
background: #000;
border: 1px solid #333;
}

#rockstar-assignment-app .rsa-large-video-frame iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border: 0;
}

#rockstar-assignment-app .rsa-large-pdf-modal {
height: min(88vh, 900px);
display: flex;
flex-direction: column;
}

#rockstar-assignment-app .rsa-large-pdf-frame {
flex: 1;
min-height: 0;
border-radius: 16px;
overflow: hidden;
background: #fff;
border: 1px solid #333;
}

#rockstar-assignment-app .rsa-large-pdf-frame iframe {
width: 100%;
height: 100%;
border: 0;
display: block;
}

#rockstar-assignment-app .rsa-large-video-close-x {
position: absolute;
top: 14px;
right: 14px;
width: 42px;
height: 42px;
border-radius: 999px;
background: var(–gold);
color: #000 !important;
border: none;
font-size: 22px;
line-height: 1;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
z-index: 3;
}

@media (max-width: 1100px) {
#rockstar-assignment-app .rsa-student-content-grid {
grid-template-columns: 1fr !important;
}
}
</style>

<script>
(function () {
const root = document.getElementById(“rockstar-assignment-app”);
if (!root) return;

const COMPLETION_STORAGE_KEY = “rockstar_single_lesson_complete_v1”;
const STUDENT_NOTES_STORAGE_KEY = “rockstar_student_practice_notes_v1”;

/******************************************************************
*
* EDIT AREA STARTS HERE
*
* This is the main area you will update for each lesson.
* Add your image URL, video URL, PDF URL, practice track URL,
* lesson notes, and buttons here.
*
******************************************************************/

const LESSON = {
// ===== MAIN PAGE TEXT =====
pageTitle: “RockStar Guitar Academy Lesson Page”,
pageSubtitle: “Current lesson, practice materials, and saved progress.”,

// ===== MAIN LESSON INFO =====
lessonTitle: “First Jam with E5”,
lessonDescription: “Start playing your first rock rhythm groove with E5 and a backing track.”,

// ===== TOP LESSON DETAILS BOX =====
lessonDetailsTitle: “Lesson Details”,
lessonNotes: “Work through the video first. Then play along with the practice track. Keep your hand relaxed and focus on steady timing.”,

// ===== LEFT SIDE FOCUS IMAGE BOX =====
focusBoxTitle: “This Week’s Focus”,

// Paste image URL here. Leave blank if you do not want an image.
focusImageUrl: “”,

// Text that appears under the image.
focusText: “Focus on steady downstrokes, clean timing, and locking in with the backing track.”,

// ===== STUDENT NOTES BUTTON =====
studentNotesButtonLabel: “My Practice Notes”,
studentNotesSubtext: “Saved on this device only.”,

// ===== LESSON VIDEO =====
// Paste regular YouTube video URL here.
// Examples:
// https://youtu.be/VIDEO_ID
// https://www.youtube.com/watch?v=VIDEO_ID
videoUrl: “https://youtube.com/watch?v=example1”,

// ===== PDF / LESSON SHEET =====
// IMPORTANT:
// If pdfUrl is blank, the PDF section will NOT show.
// If you paste in a PDF URL, the PDF section will appear under the video.
pdfSectionTitle: “PDF / Lesson Sheet”,
pdfName: “First Jam with E5.pdf”,
pdfUrl: “”,

// ===== YOUTUBE PRACTICE TRACK / BACKING TRACK =====
// Paste regular YouTube URL here.
practiceYoutubeUrl: “https://youtu.be/cjNGbn2f0-I”,

// ===== MYMUSICSTAFF BUTTON =====
mmsButtonLabel: “MMS Guitar JamZone”,
mmsButtonUrl: “https://app.mymusicstaff.com/”
};

/******************************************************************
*
* EDIT AREA ENDS HERE
*
* You usually should not need to edit below this line.
*
******************************************************************/

const state = {
largeVideoUrl: “”,
largeVideoTitle: “”,
pdfModalUrl: “”,
pdfModalTitle: “”,
notesModalOpen: false,
noteSaveMessage: “”,
fireworks: {
active: false,
nonce: 0
}
};

function esc(str) {
return String(str ?? “”)
.replace(/&/g, “&amp;”)
.replace(/</g, “&lt;”)
.replace(/>/g, “&gt;”)
.replace(/”/g, “&quot;”);
}

function toYouTubeEmbedUrl(url) {
if (!url) return “”;

try {
if (url.includes(“youtube.com/watch”)) {
const parsed = new URL(url);
const id = parsed.searchParams.get(“v”);
return id ? `https://www.youtube.com/embed/${id}` : “”;
}

if (url.includes(“youtu.be/”)) {
const parsed = new URL(url);
const id = parsed.pathname.replace(“/”, “”).split(“?”)[0];
return id ? `https://www.youtube.com/embed/${id}` : “”;
}

if (url.includes(“youtube.com/embed/”)) {
return url;
}

return “”;
} catch (e) {
return “”;
}
}

function toCompactPracticeEmbedUrl(url) {
const base = toYouTubeEmbedUrl(url);
if (!base) return “”;
return `${base}?controls=1&modestbranding=1&rel=0`;
}

function isProbablyRealVideoUrl(url) {
return !!url && !/example\d+/i.test(url);
}

function isLessonComplete() {
try {
return localStorage.getItem(COMPLETION_STORAGE_KEY) === “true”;
} catch (e) {
return false;
}
}

function setLessonComplete(value) {
try {
localStorage.setItem(COMPLETION_STORAGE_KEY, value ? “true” : “false”);
} catch (e) {}
}

function clearLessonComplete() {
try {
localStorage.removeItem(COMPLETION_STORAGE_KEY);
} catch (e) {}
}

function getStudentNotes() {
try {
return localStorage.getItem(STUDENT_NOTES_STORAGE_KEY) || “”;
} catch (e) {
return “”;
}
}

function saveStudentNotes(value) {
try {
localStorage.setItem(STUDENT_NOTES_STORAGE_KEY, value || “”);
return true;
} catch (e) {
return false;
}
}

function clearStudentNotes() {
try {
localStorage.removeItem(STUDENT_NOTES_STORAGE_KEY);
return true;
} catch (e) {
return false;
}
}

function studentHasNotes() {
return getStudentNotes().trim().length > 0;
}

function triggerFireworks() {
state.fireworks.active = true;
state.fireworks.nonce += 1;
renderApp();

setTimeout(() => {
state.fireworks.active = false;
renderApp();
}, 950);
}

function renderFireworks() {
if (!state.fireworks.active) return “”;

const sparks = [
{ left: “50%”, top: “55%”, tx: “-110px”, ty: “-80px” },
{ left: “50%”, top: “55%”, tx: “-70px”, ty: “-110px” },
{ left: “50%”, top: “55%”, tx: “0px”, ty: “-120px” },
{ left: “50%”, top: “55%”, tx: “70px”, ty: “-105px” },
{ left: “50%”, top: “55%”, tx: “110px”, ty: “-70px” },
{ left: “50%”, top: “55%”, tx: “120px”, ty: “0px” },
{ left: “50%”, top: “55%”, tx: “95px”, ty: “80px” },
{ left: “50%”, top: “55%”, tx: “20px”, ty: “115px” },
{ left: “50%”, top: “55%”, tx: “-55px”, ty: “105px” },
{ left: “50%”, top: “55%”, tx: “-115px”, ty: “35px” },
{ left: “50%”, top: “55%”, tx: “-100px”, ty: “-20px” },
{ left: “50%”, top: “55%”, tx: “35px”, ty: “95px” }
];

return `
<div class=”rsa-fireworks” data-fireworks=”${state.fireworks.nonce}”>
${sparks.map(s => `
<span class=”rsa-spark” style=”left:${s.left};top:${s.top};–tx:${s.tx};–ty:${s.ty};”></span>
`).join(“”)}
</div>
`;
}

function renderVideoBlock(videoUrl, title, description) {
const embedUrl = toYouTubeEmbedUrl(videoUrl);
const canEmbed = embedUrl && isProbablyRealVideoUrl(videoUrl);

if (canEmbed) {
return `
<div>
<div class=”rsa-video-embed-wrap”>
<iframe
src=”${esc(embedUrl)}”
title=”${esc(title || “Lesson Video”)}”
allow=”accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share”
allowfullscreen
referrerpolicy=”strict-origin-when-cross-origin”
></iframe>
</div>

<div class=”rsa-video-actions”>
<button
class=”rsa-btn rsa-btn-gold”
data-action=”open-large-video”
data-video-url=”${esc(videoUrl)}”
data-video-title=”${esc(title || “Lesson Video”)}”
>
Open Larger Player
</button>
</div>

${description ? `<div class=”rsa-video-description”>${esc(description)}</div>` : “”}
</div>
`;
}

return `
<div class=”rsa-video-fallback”>
<div style=”font-size:34px;margin-bottom:10px;”>▶</div>
<div style=”font-weight:700; margin-bottom:8px;”>Video not available inside the player</div>
<div class=”rsa-muted”>
Add a real YouTube URL in the lesson video URL area.
</div>
${videoUrl ? `<div class=”rsa-video-fallback-url”>${esc(videoUrl)}</div>` : “”}
${description ? `<div class=”rsa-video-description” style=”border-top:none;padding-top:0;margin-top:14px;”>${esc(description)}</div>` : “”}
</div>
`;
}

function renderPdfBlock(pdfUrl, pdfName) {
return `
<div class=”rsa-pdf-wrap”>
<div class=”rsa-pdf-frame”>
<iframe src=”${esc(pdfUrl)}” title=”${esc(pdfName || “Lesson PDF”)}”></iframe>
</div>

<div class=”rsa-pdf-actions”>
<button
class=”rsa-btn rsa-btn-gold”
data-action=”open-pdf-modal”
data-pdf-url=”${esc(pdfUrl)}”
data-pdf-title=”${esc(pdfName || “Lesson PDF”)}”
>
Open Larger PDF
</button>

<a class=”rsa-btn rsa-btn-light” href=”${esc(pdfUrl)}” target=”_blank” rel=”noopener noreferrer”>
Open in New Tab
</a>
</div>
</div>
`;
}

function renderPracticeYoutubePlayer() {
if (!LESSON.practiceYoutubeUrl) {
return `
<div class=”rsa-practice-player-empty”>
No practice track attached to this lesson yet.
</div>
`;
}

const embedUrl = toCompactPracticeEmbedUrl(LESSON.practiceYoutubeUrl);

if (!embedUrl) {
return `
<div class=”rsa-practice-player-empty”>
This YouTube practice track could not be loaded. Check the URL in the edit area.
</div>
`;
}

return `
<div class=”rsa-practice-player-wrap”>
<div class=”rsa-practice-player-box”>
<div class=”rsa-practice-player-title”>YouTube Practice Track</div>
<div class=”rsa-practice-player-sub”>
Use the YouTube controls below. Click the gear icon in the player to change playback speed.
</div>

<div class=”rsa-practice-player-frame”>
<iframe
src=”${esc(embedUrl)}”
title=”${esc(LESSON.lessonTitle || “Practice Track”)}”
allow=”accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share”
allowfullscreen
referrerpolicy=”strict-origin-when-cross-origin”
></iframe>
</div>
</div>
</div>
`;
}

function renderFocusImage() {
if (!LESSON.focusImageUrl) {
return `
<div class=”rsa-focus-image-wrap”>
<div class=”rsa-focus-placeholder”>
Focus Image Placeholder
</div>
</div>
`;
}

return `
<div class=”rsa-focus-image-wrap”>
<img class=”rsa-focus-image” src=”${esc(LESSON.focusImageUrl)}” alt=”${esc(LESSON.focusBoxTitle || “Lesson Focus”)}”>
</div>
`;
}

function renderNotesModal() {
if (!state.notesModalOpen) return “”;

const savedNotes = getStudentNotes();

return `
<div class=”rsa-modal-backdrop” data-action=”close-notes-backdrop”>
<div class=”rsa-notes-modal”>
<button class=”rsa-large-video-close-x” data-action=”close-notes” aria-label=”Close notes”>×</button>

<div style=”padding-right:52px;margin-bottom:16px;”>
<div class=”rsa-card-title” style=”font-size:24px !important;margin-bottom:4px;”>
My Practice Notes
</div>
<div class=”rsa-card-sub” style=”margin-bottom:0;”>
These notes are saved on this device/browser only.
</div>
</div>

<div class=”rsa-notes-box”>
<p style=”margin-bottom:10px;line-height:1.5;”>
Use this space for practice reminders, questions for your next lesson, tempos you reached, or anything you want to remember.
</p>

<textarea
class=”rsa-notes-textarea”
id=”rsaStudentNotesTextarea”
placeholder=”Example: Practice E5 downstrokes at 80 bpm. Ask about muting next lesson.”
>${esc(savedNotes)}</textarea>

<div class=”rsa-notes-actions”>
<button class=”rsa-btn rsa-btn-gold” data-action=”save-notes”>
Save Notes
</button>

<button class=”rsa-btn rsa-btn-light” data-action=”clear-notes”>
Clear Notes
</button>

<button class=”rsa-btn rsa-btn-light” data-action=”close-notes”>
Close
</button>
</div>

${state.noteSaveMessage ? `
<div style=”margin-top:10px;font-size:13px;color:#444 !important;”>
${esc(state.noteSaveMessage)}
</div>
` : “”}
</div>
</div>
</div>
`;
}

function renderLargeVideoModal() {
if (!state.largeVideoUrl) return “”;

const embedUrl = toYouTubeEmbedUrl(state.largeVideoUrl);
if (!embedUrl) return “”;

return `
<div class=”rsa-modal-backdrop” data-action=”close-large-video-backdrop”>
<div class=”rsa-large-video-modal”>
<button class=”rsa-large-video-close-x” data-action=”close-large-video” aria-label=”Close larger player”>×</button>

<div style=”display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px;padding-right:52px;”>
<div>
<div class=”rsa-card-title” style=”font-size:22px !important;margin-bottom:4px;”>
${esc(state.largeVideoTitle || “Lesson Video”)}
</div>

<div class=”rsa-card-sub” style=”margin-bottom:0;”>Larger video player</div>
</div>

<button class=”rsa-btn rsa-btn-gold” data-action=”close-large-video”>
Close
</button>
</div>

<div class=”rsa-large-video-frame”>
<iframe
src=”${esc(embedUrl)}”
title=”${esc(state.largeVideoTitle || “Lesson Video”)}”
allow=”accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share”
allowfullscreen
referrerpolicy=”strict-origin-when-cross-origin”
></iframe>
</div>
</div>
</div>
`;
}

function renderLargePdfModal() {
if (!state.pdfModalUrl) return “”;

return `
<div class=”rsa-modal-backdrop” data-action=”close-pdf-modal-backdrop”>
<div class=”rsa-large-pdf-modal”>
<button class=”rsa-large-video-close-x” data-action=”close-pdf-modal” aria-label=”Close PDF viewer”>×</button>

<div style=”display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px;padding-right:52px;”>
<div>
<div class=”rsa-card-title” style=”font-size:22px !important;margin-bottom:4px;”>
${esc(state.pdfModalTitle || “Lesson PDF”)}
</div>

<div class=”rsa-card-sub” style=”margin-bottom:0;”>Larger PDF viewer</div>
</div>

<div style=”display:flex;gap:10px;flex-wrap:wrap;”>
<a class=”rsa-btn rsa-btn-light” href=”${esc(state.pdfModalUrl)}” target=”_blank” rel=”noopener noreferrer”>
Open in New Tab
</a>

<button class=”rsa-btn rsa-btn-gold” data-action=”close-pdf-modal”>
Close
</button>
</div>
</div>

<div class=”rsa-large-pdf-frame”>
<iframe src=”${esc(state.pdfModalUrl)}” title=”${esc(state.pdfModalTitle || “Lesson PDF”)}”></iframe>
</div>
</div>
</div>
`;
}

function renderApp() {
const complete = isLessonComplete();
const hasNotes = studentHasNotes();

root.innerHTML = `
<div class=”rsa-wrap”>
<div class=”rsa-inner”>
<div class=”rsa-card rsa-page-card”>
<div class=”rsa-card-title”>${esc(LESSON.pageTitle)}</div>
<div class=”rsa-card-sub”>${esc(LESSON.pageSubtitle)}</div>

<div class=”rsa-panel rsa-top-lesson-details”>
<h4>${esc(LESSON.lessonDetailsTitle || “Lesson Details”)}</h4>
<p>${esc(LESSON.lessonNotes)}</p>
</div>

<div class=”rsa-student-content-grid”>
<div class=”rsa-student-side-stack”>
<div
class=”rsa-panel”
style=”
border:${complete ? ‘2px solid #2e9b4b’ : ‘1px solid var(–softborder)’};
background:${complete ? ‘#edf8f0’ : ‘var(–panel2)’};

>
<h4 style=”margin-bottom:12px;”>
${esc(LESSON.focusBoxTitle)}
</h4>

${renderFocusImage()}

<p>${esc(LESSON.focusText)}</p>
</div>

<div class=”rsa-album-box” style=”display:block;”>
<button class=”rsa-album-btn” data-action=”open-notes”>
${esc(LESSON.studentNotesButtonLabel || “My Practice Notes”)}
</button>
<div class=”rsa-note-status”>
${hasNotes ? “Notes saved on this device.” : esc(LESSON.studentNotesSubtext || “Saved on this device only.”)}
</div>
</div>

<div class=”rsa-album-box”>
<a class=”rsa-album-btn” href=”${esc(LESSON.mmsButtonUrl || “https://app.mymusicstaff.com/”)}” target=”_blank” rel=”noopener noreferrer”>
${esc(LESSON.mmsButtonLabel || “MMS Guitar JamZone”)}
</a>
</div>

<div class=”rsa-panel rsa-complete-wrap”>
<h4>Status</h4>

<p>
${complete ? “Nice. This lesson is marked complete on this device.” : “Mark this lesson complete when you’re done working through it.”}
</p>

<div class=”rsa-complete-buttons”>
<button
class=”rsa-btn ${complete ? “rsa-btn-complete” : “rsa-btn-gold”}”
data-action=”toggle-complete”
>
${complete ? “Completed — Click to Undo” : “Mark Complete”}
</button>

<button
class=”rsa-btn rsa-btn-light”
data-action=”clear-complete”
>
Clear
</button>
</div>

<div class=”rsa-complete-note”>
Saved on this device/browser only.
</div>

${renderFireworks()}
</div>
</div>

<div>
<div class=”rsa-card” style=”padding:22px;”>
<div class=”rsa-card-title” style=”font-size:24px !important;”>${esc(LESSON.lessonTitle)}</div>

<div class=”rsa-panel” style=”margin-bottom:16px;”>
${renderVideoBlock(LESSON.videoUrl, LESSON.lessonTitle, LESSON.lessonDescription)}
</div>

${LESSON.pdfUrl ? `
<div class=”rsa-panel” style=”margin-bottom:16px;”>
<h4 style=”margin-bottom:8px;”>${esc(LESSON.pdfSectionTitle || “PDF / Lesson Sheet”)}</h4>
${renderPdfBlock(LESSON.pdfUrl, LESSON.pdfName)}
</div>
` : “”}

<div class=”rsa-panel”>
<h4>Backing Track Player</h4>
${renderPracticeYoutubePlayer()}
</div>
</div>
</div>
</div>
</div>
</div>
</div>

${renderLargeVideoModal()}
${renderLargePdfModal()}
${renderNotesModal()}
`;

bindEvents();
}

function bindEvents() {
root.querySelectorAll(“[data-action=’toggle-complete’]”).forEach(el => {
el.addEventListener(“click”, () => {
const currentlyComplete = isLessonComplete();

if (currentlyComplete) {
setLessonComplete(false);
renderApp();
} else {
setLessonComplete(true);
triggerFireworks();
}
});
});

root.querySelectorAll(“[data-action=’clear-complete’]”).forEach(el => {
el.addEventListener(“click”, () => {
clearLessonComplete();
renderApp();
});
});

root.querySelectorAll(“[data-action=’open-notes’]”).forEach(el => {
el.addEventListener(“click”, () => {
state.notesModalOpen = true;
state.noteSaveMessage = “”;
renderApp();

setTimeout(() => {
const textarea = root.querySelector(“#rsaStudentNotesTextarea”);
if (textarea) textarea.focus();
}, 50);
});
});

root.querySelectorAll(“[data-action=’save-notes’]”).forEach(el => {
el.addEventListener(“click”, () => {
const textarea = root.querySelector(“#rsaStudentNotesTextarea”);
const value = textarea ? textarea.value : “”;
const saved = saveStudentNotes(value);

state.noteSaveMessage = saved
? “Saved. Your notes will stay on this device/browser.”
: “Could not save notes on this browser.”;

renderApp();
});
});

root.querySelectorAll(“[data-action=’clear-notes’]”).forEach(el => {
el.addEventListener(“click”, () => {
clearStudentNotes();
state.noteSaveMessage = “Notes cleared.”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’close-notes’]”).forEach(el => {
el.addEventListener(“click”, () => {
state.notesModalOpen = false;
state.noteSaveMessage = “”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’close-notes-backdrop’]”).forEach(el => {
el.addEventListener(“click”, (event) => {
if (event.target !== el) return;
state.notesModalOpen = false;
state.noteSaveMessage = “”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’open-large-video’]”).forEach(el => {
el.addEventListener(“click”, () => {
state.largeVideoUrl = el.getAttribute(“data-video-url”) || “”;
state.largeVideoTitle = el.getAttribute(“data-video-title”) || “Lesson Video”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’close-large-video’]”).forEach(el => {
el.addEventListener(“click”, () => {
state.largeVideoUrl = “”;
state.largeVideoTitle = “”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’close-large-video-backdrop’]”).forEach(el => {
el.addEventListener(“click”, (event) => {
if (event.target !== el) return;
state.largeVideoUrl = “”;
state.largeVideoTitle = “”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’open-pdf-modal’]”).forEach(el => {
el.addEventListener(“click”, () => {
state.pdfModalUrl = el.getAttribute(“data-pdf-url”) || “”;
state.pdfModalTitle = el.getAttribute(“data-pdf-title”) || “Lesson PDF”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’close-pdf-modal’]”).forEach(el => {
el.addEventListener(“click”, () => {
state.pdfModalUrl = “”;
state.pdfModalTitle = “”;
renderApp();
});
});

root.querySelectorAll(“[data-action=’close-pdf-modal-backdrop’]”).forEach(el => {
el.addEventListener(“click”, (event) => {
if (event.target !== el) return;
state.pdfModalUrl = “”;
state.pdfModalTitle = “”;
renderApp();
});
});
}

renderApp();
})();
</script>