feat: complete section color coding with logo, hints, editor themes, and footers
- Add section-specific CodeMirror syntax highlighting (purple selectors for CSS) - Logo now uses section colors (CSS purple as default, changes per section) - Add section color coding for hints - Add full footer to section and reference pages - Fix nav highlight updates for sidebar and prev/next navigation - Change welcome module mode to CSS for purple theme on first lesson - Rebrand "Code Crispies" to "CODE CRISPIES" across all translations - Fix scroll to top on section page navigation - Change HTML section color to raspberry (#c75b7a)
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"id": "welcome",
|
||||
"title": "Welcome",
|
||||
"description": "Get started with Code Crispies",
|
||||
"mode": "html",
|
||||
"mode": "css",
|
||||
"difficulty": "beginner",
|
||||
"excludeFromProgress": true,
|
||||
"lessons": [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"id": "welcome",
|
||||
"title": "مرحباً",
|
||||
"description": "ابدأ مع Code Crispies",
|
||||
"mode": "html",
|
||||
"mode": "css",
|
||||
"difficulty": "beginner",
|
||||
"excludeFromProgress": true,
|
||||
"lessons": [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"id": "welcome",
|
||||
"title": "Willkommen",
|
||||
"description": "Erste Schritte mit Code Crispies",
|
||||
"mode": "html",
|
||||
"mode": "css",
|
||||
"difficulty": "beginner",
|
||||
"excludeFromProgress": true,
|
||||
"lessons": [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"id": "welcome",
|
||||
"title": "Bienvenido",
|
||||
"description": "Comienza con Code Crispies",
|
||||
"mode": "html",
|
||||
"mode": "css",
|
||||
"difficulty": "beginner",
|
||||
"excludeFromProgress": true,
|
||||
"lessons": [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"id": "welcome",
|
||||
"title": "Witaj",
|
||||
"description": "Rozpocznij przygodę z Code Crispies",
|
||||
"mode": "html",
|
||||
"mode": "css",
|
||||
"difficulty": "beginner",
|
||||
"excludeFromProgress": true,
|
||||
"lessons": [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"id": "welcome",
|
||||
"title": "Ласкаво просимо",
|
||||
"description": "Почніть з Code Crispies",
|
||||
"mode": "html",
|
||||
"mode": "css",
|
||||
"difficulty": "beginner",
|
||||
"excludeFromProgress": true,
|
||||
"lessons": [
|
||||
|
||||
59
src/app.js
59
src/app.js
@@ -156,6 +156,8 @@ const elements = {
|
||||
closeSidebar: document.getElementById("close-sidebar"),
|
||||
moduleList: document.getElementById("module-list"),
|
||||
footerLessonLinks: document.getElementById("footer-lesson-links"),
|
||||
refFooterLessonLinks: document.getElementById("ref-footer-lesson-links"),
|
||||
sectionFooterLessonLinks: document.getElementById("section-footer-lesson-links"),
|
||||
progressFill: document.getElementById("progress-fill"),
|
||||
progressText: document.getElementById("progress-text"),
|
||||
resetBtn: document.getElementById("reset-btn"),
|
||||
@@ -456,6 +458,13 @@ function selectLesson(moduleId, lessonIndex) {
|
||||
|
||||
loadCurrentLesson();
|
||||
|
||||
// Update section color coding (after loadCurrentLesson to ensure content is loaded first)
|
||||
const newState = lessonEngine.getCurrentState();
|
||||
updateSectionColor(getModuleSection(newState.module));
|
||||
|
||||
// Update nav highlight
|
||||
updateNavHighlight({ type: RouteType.LESSON, moduleId, lessonIndex });
|
||||
|
||||
// Close sidebar after selection on mobile
|
||||
if (window.innerWidth <= 768) {
|
||||
closeSidebar();
|
||||
@@ -694,11 +703,15 @@ function nextLesson() {
|
||||
// Update URL
|
||||
updateHash(newState.module.id, newState.lessonIndex);
|
||||
|
||||
if (newState.module.id !== prevModuleId) {
|
||||
const moduleChanged = newState.module.id !== prevModuleId;
|
||||
if (moduleChanged) {
|
||||
updateModuleHighlight(newState.module.id);
|
||||
updateSectionColor(getModuleSection(newState.module));
|
||||
}
|
||||
loadCurrentLesson();
|
||||
if (moduleChanged) {
|
||||
updateSectionColor(getModuleSection(newState.module));
|
||||
updateNavHighlight({ type: RouteType.LESSON, moduleId: newState.module.id, lessonIndex: newState.lessonIndex });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,11 +724,15 @@ function prevLesson() {
|
||||
// Update URL
|
||||
updateHash(newState.module.id, newState.lessonIndex);
|
||||
|
||||
if (newState.module.id !== prevModuleId) {
|
||||
const moduleChanged = newState.module.id !== prevModuleId;
|
||||
if (moduleChanged) {
|
||||
updateModuleHighlight(newState.module.id);
|
||||
updateSectionColor(getModuleSection(newState.module));
|
||||
}
|
||||
loadCurrentLesson();
|
||||
if (moduleChanged) {
|
||||
updateSectionColor(getModuleSection(newState.module));
|
||||
updateNavHighlight({ type: RouteType.LESSON, moduleId: newState.module.id, lessonIndex: newState.lessonIndex });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1852,7 +1869,7 @@ function stripHtml(html) {
|
||||
* Update page meta tags based on current route for SEO
|
||||
*/
|
||||
function updatePageMeta(route) {
|
||||
const defaultTitle = "Code Crispies - Learn HTML & CSS Interactively | Free Coding Practice";
|
||||
const defaultTitle = "CODE CRISPIES - Learn HTML & CSS Interactively | Free Coding Practice";
|
||||
const defaultDesc =
|
||||
"Master HTML, CSS, and Tailwind through hands-on coding exercises. Free, open-source learning platform with instant feedback. No account required.";
|
||||
|
||||
@@ -1872,7 +1889,7 @@ function updatePageMeta(route) {
|
||||
case RouteType.SECTION: {
|
||||
const sectionNames = { css: "CSS", html: "HTML", tailwind: "Tailwind CSS" };
|
||||
const sectionName = sectionNames[route.sectionId] || route.sectionId;
|
||||
title = `${sectionName} Lessons - Code Crispies | Learn ${sectionName}`;
|
||||
title = `${sectionName} Lessons - CODE CRISPIES | Learn ${sectionName}`;
|
||||
description = `Learn ${sectionName} through interactive coding exercises. Hands-on practice with instant feedback.`;
|
||||
break;
|
||||
}
|
||||
@@ -1881,7 +1898,7 @@ function updatePageMeta(route) {
|
||||
const module = lessonEngine.modules.find((m) => m.id === route.moduleId);
|
||||
const lesson = module?.lessons[route.lessonIndex];
|
||||
if (module && lesson) {
|
||||
title = `${lesson.title} - ${module.title} | Code Crispies`;
|
||||
title = `${lesson.title} - ${module.title} | CODE CRISPIES`;
|
||||
const lessonDesc = stripHtml(lesson.description || lesson.task);
|
||||
description = lessonDesc.length > 155 ? lessonDesc.slice(0, 152) + "..." : lessonDesc || defaultDesc;
|
||||
}
|
||||
@@ -1897,7 +1914,7 @@ function updatePageMeta(route) {
|
||||
html: "HTML Elements"
|
||||
};
|
||||
const refName = refNames[route.refId] || "Reference";
|
||||
title = `${refName} Reference - Code Crispies`;
|
||||
title = `${refName} Reference - CODE CRISPIES`;
|
||||
description = `Quick reference guide for ${refName}. Syntax, examples, and common patterns for web development.`;
|
||||
break;
|
||||
}
|
||||
@@ -1913,13 +1930,13 @@ function updatePageMeta(route) {
|
||||
// Update Open Graph tags
|
||||
const ogTitle = document.querySelector('meta[property="og:title"]');
|
||||
const ogDesc = document.querySelector('meta[property="og:description"]');
|
||||
if (ogTitle) ogTitle.setAttribute("content", title.replace(" | Code Crispies", "").replace(" - Code Crispies", ""));
|
||||
if (ogTitle) ogTitle.setAttribute("content", title.replace(" | CODE CRISPIES", "").replace(" - CODE CRISPIES", ""));
|
||||
if (ogDesc) ogDesc.setAttribute("content", description);
|
||||
|
||||
// Update Twitter tags
|
||||
const twitterTitle = document.querySelector('meta[name="twitter:title"]');
|
||||
const twitterDesc = document.querySelector('meta[name="twitter:description"]');
|
||||
if (twitterTitle) twitterTitle.setAttribute("content", title.replace(" | Code Crispies", "").replace(" - Code Crispies", ""));
|
||||
if (twitterTitle) twitterTitle.setAttribute("content", title.replace(" | CODE CRISPIES", "").replace(" - CODE CRISPIES", ""));
|
||||
if (twitterDesc) twitterDesc.setAttribute("content", description);
|
||||
}
|
||||
|
||||
@@ -1994,6 +2011,11 @@ function updateSectionColor(sectionId) {
|
||||
} else {
|
||||
document.body.removeAttribute("data-section");
|
||||
}
|
||||
|
||||
// Update code editor theme for section
|
||||
if (codeEditor) {
|
||||
codeEditor.setSection(sectionId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2018,8 +2040,6 @@ function showLandingPage() {
|
||||
* Render module links in the landing page footer, grouped by section
|
||||
*/
|
||||
function renderFooterLessonLinks() {
|
||||
if (!elements.footerLessonLinks) return;
|
||||
|
||||
const modules = lessonEngine.modules || [];
|
||||
const sectionGroups = { css: [], html: [] };
|
||||
|
||||
@@ -2042,7 +2062,16 @@ function renderFooterLessonLinks() {
|
||||
html += "</div>";
|
||||
});
|
||||
|
||||
elements.footerLessonLinks.innerHTML = html;
|
||||
// Update all footer lesson links
|
||||
if (elements.footerLessonLinks) {
|
||||
elements.footerLessonLinks.innerHTML = html;
|
||||
}
|
||||
if (elements.refFooterLessonLinks) {
|
||||
elements.refFooterLessonLinks.innerHTML = html;
|
||||
}
|
||||
if (elements.sectionFooterLessonLinks) {
|
||||
elements.sectionFooterLessonLinks.innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2077,7 +2106,6 @@ function updateLandingProgress() {
|
||||
function showSectionPage(sectionId) {
|
||||
hideAllPages();
|
||||
elements.sectionPage?.classList.remove("hidden");
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
// Update section color
|
||||
updateSectionColor(sectionId);
|
||||
@@ -2120,6 +2148,9 @@ function showSectionPage(sectionId) {
|
||||
const percent = total > 0 ? Math.round((completed / total) * 100) : 0;
|
||||
if (elements.sectionProgressFill) elements.sectionProgressFill.style.width = `${percent}%`;
|
||||
if (elements.sectionProgressText) elements.sectionProgressText.textContent = `${completed} of ${total} lessons complete`;
|
||||
|
||||
// Scroll to top after content is rendered
|
||||
requestAnimationFrame(() => window.scrollTo(0, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ export const sections = {
|
||||
id: "html",
|
||||
title: "HTML",
|
||||
description: "Semantic markup and native elements",
|
||||
color: "#d4637b",
|
||||
color: "#c75b7a",
|
||||
order: 2
|
||||
},
|
||||
tailwind: {
|
||||
|
||||
86
src/i18n.js
86
src/i18n.js
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Internationalization module for Code Crispies
|
||||
* Internationalization module for CODE CRISPIES
|
||||
*/
|
||||
|
||||
const translations = {
|
||||
en: {
|
||||
// Page
|
||||
pageTitle: "Code Crispies - Learn HTML & CSS Interactively",
|
||||
pageTitle: "CODE CRISPIES - Learn HTML & CSS Interactively",
|
||||
skipLink: "Skip to main content",
|
||||
|
||||
// Header
|
||||
@@ -48,9 +48,9 @@ const translations = {
|
||||
|
||||
// Help dialog
|
||||
helpTitle: "Help",
|
||||
aboutTitle: "About Code Crispies",
|
||||
aboutTitle: "About CODE CRISPIES",
|
||||
aboutText:
|
||||
"Code Crispies is a free, open-source platform for learning web development through hands-on exercises. No account required - just start coding!",
|
||||
"CODE CRISPIES is a free, open-source platform for learning web development through hands-on exercises. No account required - just start coding!",
|
||||
learningModesTitle: "Learning Modes",
|
||||
modeCss: "<strong>CSS</strong> - Write CSS rules to style elements",
|
||||
modeTailwind: "<strong>Tailwind</strong> - Apply utility classes directly in HTML",
|
||||
@@ -85,7 +85,7 @@ const translations = {
|
||||
|
||||
// Contact
|
||||
contactTitle: "Contact & Links",
|
||||
contactText: 'Code Crispies is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
contactText: 'CODE CRISPIES is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
|
||||
// Reset dialog
|
||||
resetDialogTitle: "Reset Progress",
|
||||
@@ -121,7 +121,7 @@ const translations = {
|
||||
landingHeroHighlight: "By Writing Real Code",
|
||||
landingHeroSubtitle: "Master HTML, CSS, and Tailwind through hands-on exercises with instant feedback. Free and open source.",
|
||||
landingCtaStart: "Start Learning NOW",
|
||||
landingWhyTitle: "Why Code Crispies Works",
|
||||
landingWhyTitle: "Why CODE CRISPIES Works",
|
||||
landingBenefit1Title: "Learn by Doing",
|
||||
landingBenefit1Text: "Write real code from lesson one. No videos to watch—just you, an editor, and instant feedback on every keystroke.",
|
||||
landingBenefit2Title: "Practice at Your Pace",
|
||||
@@ -145,17 +145,17 @@ const translations = {
|
||||
footerPlayground: "Playground",
|
||||
footerAbout: "About",
|
||||
footerSupport: "Support",
|
||||
footerSupportText: "Help keep Code Crispies free and open source.",
|
||||
footerSupportText: "Help keep CODE CRISPIES free and open source.",
|
||||
footerLicense: "Released into the public domain.",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "Support the Project",
|
||||
supportText: "Help keep Code Crispies free and open source."
|
||||
supportText: "Help keep CODE CRISPIES free and open source."
|
||||
},
|
||||
|
||||
de: {
|
||||
// Page
|
||||
pageTitle: "Code Crispies - HTML & CSS interaktiv lernen",
|
||||
pageTitle: "CODE CRISPIES - HTML & CSS interaktiv lernen",
|
||||
skipLink: "Zum Hauptinhalt springen",
|
||||
|
||||
// Header
|
||||
@@ -198,9 +198,9 @@ const translations = {
|
||||
|
||||
// Help dialog
|
||||
helpTitle: "Hilfe",
|
||||
aboutTitle: "Über Code Crispies",
|
||||
aboutTitle: "Über CODE CRISPIES",
|
||||
aboutText:
|
||||
"Code Crispies ist eine kostenlose Open-Source-Plattform zum Erlernen von Webentwicklung durch praktische Übungen. Kein Konto erforderlich - einfach loslegen!",
|
||||
"CODE CRISPIES ist eine kostenlose Open-Source-Plattform zum Erlernen von Webentwicklung durch praktische Übungen. Kein Konto erforderlich - einfach loslegen!",
|
||||
learningModesTitle: "Lernmodi",
|
||||
modeCss: "<strong>CSS</strong> - Schreibe CSS-Regeln zum Stylen von Elementen",
|
||||
modeTailwind: "<strong>Tailwind</strong> - Wende Utility-Klassen direkt im HTML an",
|
||||
@@ -236,7 +236,7 @@ const translations = {
|
||||
|
||||
// Contact
|
||||
contactTitle: "Kontakt & Links",
|
||||
contactText: 'Code Crispies wird von <a href="https://librete.ch" target="_blank">LibreTECH</a> entwickelt',
|
||||
contactText: 'CODE CRISPIES wird von <a href="https://librete.ch" target="_blank">LibreTECH</a> entwickelt',
|
||||
|
||||
// Reset dialog
|
||||
resetDialogTitle: "Fortschritt zurücksetzen",
|
||||
@@ -272,7 +272,7 @@ const translations = {
|
||||
landingHeroHighlight: "Selbstständig lernen",
|
||||
landingHeroSubtitle: "Meistere HTML, CSS und Tailwind durch praktische Übungen mit sofortigem Feedback. Kostenlos und Open Source.",
|
||||
landingCtaStart: "Jetzt starten",
|
||||
landingWhyTitle: "Warum Code Crispies funktioniert",
|
||||
landingWhyTitle: "Warum CODE CRISPIES funktioniert",
|
||||
landingBenefit1Title: "Lernen durch Praxis",
|
||||
landingBenefit1Text:
|
||||
"Schreibe echten Code ab der ersten Lektion. Keine Videos – nur du, ein Editor und sofortiges Feedback bei jedem Tastendruck.",
|
||||
@@ -298,18 +298,18 @@ const translations = {
|
||||
footerPlayground: "Playground",
|
||||
footerAbout: "Über uns",
|
||||
footerSupport: "Unterstützen",
|
||||
footerSupportText: "Hilf mit, Code Crispies kostenlos und Open Source zu halten.",
|
||||
footerSupportText: "Hilf mit, CODE CRISPIES kostenlos und Open Source zu halten.",
|
||||
footerLicense: "Gemeinfrei (Public Domain).",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "Projekt unterstützen",
|
||||
supportText: "Hilf mit, Code Crispies kostenlos und Open Source zu halten."
|
||||
supportText: "Hilf mit, CODE CRISPIES kostenlos und Open Source zu halten."
|
||||
},
|
||||
|
||||
// Polish
|
||||
pl: {
|
||||
// Page
|
||||
pageTitle: "Code Crispies - Nauka HTML i CSS interaktywnie",
|
||||
pageTitle: "CODE CRISPIES - Nauka HTML i CSS interaktywnie",
|
||||
skipLink: "Przejdź do głównej treści",
|
||||
|
||||
// Header
|
||||
@@ -352,9 +352,9 @@ const translations = {
|
||||
|
||||
// Help dialog
|
||||
helpTitle: "Pomoc",
|
||||
aboutTitle: "O Code Crispies",
|
||||
aboutTitle: "O CODE CRISPIES",
|
||||
aboutText:
|
||||
"Code Crispies to darmowa platforma open-source do nauki tworzenia stron internetowych poprzez praktyczne ćwiczenia. Nie wymaga konta - po prostu zacznij kodować!",
|
||||
"CODE CRISPIES to darmowa platforma open-source do nauki tworzenia stron internetowych poprzez praktyczne ćwiczenia. Nie wymaga konta - po prostu zacznij kodować!",
|
||||
learningModesTitle: "Tryby nauki",
|
||||
modeCss: "<strong>CSS</strong> - Pisz reguły CSS do stylizowania elementów",
|
||||
modeTailwind: "<strong>Tailwind</strong> - Stosuj klasy utility bezpośrednio w HTML",
|
||||
@@ -389,7 +389,7 @@ const translations = {
|
||||
|
||||
// Contact
|
||||
contactTitle: "Kontakt i linki",
|
||||
contactText: 'Code Crispies jest rozwijany przez <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
contactText: 'CODE CRISPIES jest rozwijany przez <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
|
||||
// Reset dialog
|
||||
resetDialogTitle: "Resetuj postęp",
|
||||
@@ -425,7 +425,7 @@ const translations = {
|
||||
landingHeroHighlight: "Pisząc prawdziwy kod",
|
||||
landingHeroSubtitle: "Opanuj HTML, CSS i Tailwind poprzez praktyczne ćwiczenia z natychmiastową informacją zwrotną. Darmowe i open source.",
|
||||
landingCtaStart: "Zacznij TERAZ",
|
||||
landingWhyTitle: "Dlaczego Code Crispies działa",
|
||||
landingWhyTitle: "Dlaczego CODE CRISPIES działa",
|
||||
landingBenefit1Title: "Ucz się przez praktykę",
|
||||
landingBenefit1Text:
|
||||
"Pisz prawdziwy kod od pierwszej lekcji. Żadnych filmów – tylko ty, edytor i natychmiastowa informacja zwrotna przy każdym naciśnięciu klawisza.",
|
||||
@@ -451,18 +451,18 @@ const translations = {
|
||||
footerPlayground: "Plac zabaw",
|
||||
footerAbout: "O nas",
|
||||
footerSupport: "Wsparcie",
|
||||
footerSupportText: "Pomóż utrzymać Code Crispies darmowym i open source.",
|
||||
footerSupportText: "Pomóż utrzymać CODE CRISPIES darmowym i open source.",
|
||||
footerLicense: "Udostępnione jako domena publiczna.",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "Wesprzyj projekt",
|
||||
supportText: "Pomóż utrzymać Code Crispies darmowym i open source."
|
||||
supportText: "Pomóż utrzymać CODE CRISPIES darmowym i open source."
|
||||
},
|
||||
|
||||
// Spanish
|
||||
es: {
|
||||
// Page
|
||||
pageTitle: "Code Crispies - Aprende HTML y CSS de forma interactiva",
|
||||
pageTitle: "CODE CRISPIES - Aprende HTML y CSS de forma interactiva",
|
||||
skipLink: "Saltar al contenido principal",
|
||||
|
||||
// Header
|
||||
@@ -505,9 +505,9 @@ const translations = {
|
||||
|
||||
// Help dialog
|
||||
helpTitle: "Ayuda",
|
||||
aboutTitle: "Acerca de Code Crispies",
|
||||
aboutTitle: "Acerca de CODE CRISPIES",
|
||||
aboutText:
|
||||
"Code Crispies es una plataforma gratuita de código abierto para aprender desarrollo web a través de ejercicios prácticos. No se requiere cuenta, ¡solo empieza a programar!",
|
||||
"CODE CRISPIES es una plataforma gratuita de código abierto para aprender desarrollo web a través de ejercicios prácticos. No se requiere cuenta, ¡solo empieza a programar!",
|
||||
learningModesTitle: "Modos de aprendizaje",
|
||||
modeCss: "<strong>CSS</strong> - Escribe reglas CSS para estilizar elementos",
|
||||
modeTailwind: "<strong>Tailwind</strong> - Aplica clases de utilidad directamente en HTML",
|
||||
@@ -543,7 +543,7 @@ const translations = {
|
||||
|
||||
// Contact
|
||||
contactTitle: "Contacto y enlaces",
|
||||
contactText: 'Code Crispies es desarrollado por <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
contactText: 'CODE CRISPIES es desarrollado por <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
|
||||
// Reset dialog
|
||||
resetDialogTitle: "Reiniciar progreso",
|
||||
@@ -580,7 +580,7 @@ const translations = {
|
||||
landingHeroSubtitle:
|
||||
"Domina HTML, CSS y Tailwind a través de ejercicios prácticos con retroalimentación instantánea. Gratis y de código abierto.",
|
||||
landingCtaStart: "Empieza AHORA",
|
||||
landingWhyTitle: "Por qué funciona Code Crispies",
|
||||
landingWhyTitle: "Por qué funciona CODE CRISPIES",
|
||||
landingBenefit1Title: "Aprende haciendo",
|
||||
landingBenefit1Text:
|
||||
"Escribe código real desde la primera lección. Sin videos que ver—solo tú, un editor y retroalimentación instantánea en cada tecla.",
|
||||
@@ -606,18 +606,18 @@ const translations = {
|
||||
footerPlayground: "Zona de pruebas",
|
||||
footerAbout: "Acerca de",
|
||||
footerSupport: "Apoyar",
|
||||
footerSupportText: "Ayuda a mantener Code Crispies gratis y de código abierto.",
|
||||
footerSupportText: "Ayuda a mantener CODE CRISPIES gratis y de código abierto.",
|
||||
footerLicense: "Liberado al dominio público.",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "Apoyar el proyecto",
|
||||
supportText: "Ayuda a mantener Code Crispies gratis y de código abierto."
|
||||
supportText: "Ayuda a mantener CODE CRISPIES gratis y de código abierto."
|
||||
},
|
||||
|
||||
// Arabic
|
||||
ar: {
|
||||
// Page
|
||||
pageTitle: "Code Crispies - تعلم HTML و CSS بشكل تفاعلي",
|
||||
pageTitle: "CODE CRISPIES - تعلم HTML و CSS بشكل تفاعلي",
|
||||
skipLink: "انتقل إلى المحتوى الرئيسي",
|
||||
|
||||
// Header
|
||||
@@ -660,8 +660,8 @@ const translations = {
|
||||
|
||||
// Help dialog
|
||||
helpTitle: "مساعدة",
|
||||
aboutTitle: "عن Code Crispies",
|
||||
aboutText: "Code Crispies هي منصة مجانية مفتوحة المصدر لتعلم تطوير الويب من خلال تمارين عملية. لا يلزم حساب - فقط ابدأ البرمجة!",
|
||||
aboutTitle: "عن CODE CRISPIES",
|
||||
aboutText: "CODE CRISPIES هي منصة مجانية مفتوحة المصدر لتعلم تطوير الويب من خلال تمارين عملية. لا يلزم حساب - فقط ابدأ البرمجة!",
|
||||
learningModesTitle: "أوضاع التعلم",
|
||||
modeCss: "<strong>CSS</strong> - اكتب قواعد CSS لتنسيق العناصر",
|
||||
modeTailwind: "<strong>Tailwind</strong> - طبق فئات الأدوات مباشرة في HTML",
|
||||
@@ -696,7 +696,7 @@ const translations = {
|
||||
|
||||
// Contact
|
||||
contactTitle: "التواصل والروابط",
|
||||
contactText: 'Code Crispies تم تطويره بواسطة <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
contactText: 'CODE CRISPIES تم تطويره بواسطة <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
|
||||
// Reset dialog
|
||||
resetDialogTitle: "إعادة تعيين التقدم",
|
||||
@@ -732,7 +732,7 @@ const translations = {
|
||||
landingHeroHighlight: "بكتابة كود حقيقي",
|
||||
landingHeroSubtitle: "أتقن HTML و CSS و Tailwind من خلال تمارين عملية مع ملاحظات فورية. مجاني ومفتوح المصدر.",
|
||||
landingCtaStart: "ابدأ الآن",
|
||||
landingWhyTitle: "لماذا Code Crispies فعال",
|
||||
landingWhyTitle: "لماذا CODE CRISPIES فعال",
|
||||
landingBenefit1Title: "تعلم بالممارسة",
|
||||
landingBenefit1Text: "اكتب كودًا حقيقيًا من الدرس الأول. لا فيديوهات للمشاهدة—فقط أنت ومحرر وملاحظات فورية مع كل ضغطة مفتاح.",
|
||||
landingBenefit2Title: "بسرعتك الخاصة",
|
||||
@@ -756,18 +756,18 @@ const translations = {
|
||||
footerPlayground: "ساحة التجربة",
|
||||
footerAbout: "حول",
|
||||
footerSupport: "الدعم",
|
||||
footerSupportText: "ساعد في إبقاء Code Crispies مجانيًا ومفتوح المصدر.",
|
||||
footerSupportText: "ساعد في إبقاء CODE CRISPIES مجانيًا ومفتوح المصدر.",
|
||||
footerLicense: "مُطلق للملكية العامة.",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "ادعم المشروع",
|
||||
supportText: "ساعد في إبقاء Code Crispies مجانيًا ومفتوح المصدر."
|
||||
supportText: "ساعد في إبقاء CODE CRISPIES مجانيًا ومفتوح المصدر."
|
||||
},
|
||||
|
||||
// Ukrainian
|
||||
uk: {
|
||||
// Page
|
||||
pageTitle: "Code Crispies - Вивчай HTML та CSS інтерактивно",
|
||||
pageTitle: "CODE CRISPIES - Вивчай HTML та CSS інтерактивно",
|
||||
skipLink: "Перейти до основного вмісту",
|
||||
|
||||
// Header
|
||||
@@ -810,9 +810,9 @@ const translations = {
|
||||
|
||||
// Help dialog
|
||||
helpTitle: "Допомога",
|
||||
aboutTitle: "Про Code Crispies",
|
||||
aboutTitle: "Про CODE CRISPIES",
|
||||
aboutText:
|
||||
"Code Crispies — це безкоштовна платформа з відкритим кодом для вивчення веб-розробки через практичні вправи. Обліковий запис не потрібен — просто починайте кодувати!",
|
||||
"CODE CRISPIES — це безкоштовна платформа з відкритим кодом для вивчення веб-розробки через практичні вправи. Обліковий запис не потрібен — просто починайте кодувати!",
|
||||
learningModesTitle: "Режими навчання",
|
||||
modeCss: "<strong>CSS</strong> - Пишіть правила CSS для стилізації елементів",
|
||||
modeTailwind: "<strong>Tailwind</strong> - Застосовуйте утилітарні класи безпосередньо в HTML",
|
||||
@@ -847,7 +847,7 @@ const translations = {
|
||||
|
||||
// Contact
|
||||
contactTitle: "Контакти та посилання",
|
||||
contactText: 'Code Crispies розроблено <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
contactText: 'CODE CRISPIES розроблено <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||
|
||||
// Reset dialog
|
||||
resetDialogTitle: "Скинути прогрес",
|
||||
@@ -883,7 +883,7 @@ const translations = {
|
||||
landingHeroHighlight: "Пишучи справжній код",
|
||||
landingHeroSubtitle: "Опануй HTML, CSS та Tailwind через практичні вправи з миттєвим зворотним зв'язком. Безкоштовно та з відкритим кодом.",
|
||||
landingCtaStart: "Почни ЗАРАЗ",
|
||||
landingWhyTitle: "Чому Code Crispies працює",
|
||||
landingWhyTitle: "Чому CODE CRISPIES працює",
|
||||
landingBenefit1Title: "Вчись на практиці",
|
||||
landingBenefit1Text:
|
||||
"Пиши справжній код з першого уроку. Жодних відео—тільки ти, редактор і миттєвий зворотний зв'язок при кожному натисканні клавіші.",
|
||||
@@ -908,12 +908,12 @@ const translations = {
|
||||
footerPlayground: "Пісочниця",
|
||||
footerAbout: "Про нас",
|
||||
footerSupport: "Підтримка",
|
||||
footerSupportText: "Допоможи зберегти Code Crispies безкоштовним та з відкритим кодом.",
|
||||
footerSupportText: "Допоможи зберегти CODE CRISPIES безкоштовним та з відкритим кодом.",
|
||||
footerLicense: "Передано у суспільне надбання.",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "Підтримати проєкт",
|
||||
supportText: "Допоможи зберегти Code Crispies безкоштовним та з відкритим кодом."
|
||||
supportText: "Допоможи зберегти CODE CRISPIES безкоштовним та з відкритим кодом."
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ const crispyTheme = EditorView.theme(
|
||||
{ dark: true }
|
||||
);
|
||||
|
||||
// Syntax highlighting with purple accent
|
||||
const crispyHighlight = HighlightStyle.define([
|
||||
// Default syntax highlighting (blue accent)
|
||||
const defaultHighlight = HighlightStyle.define([
|
||||
{ tag: tags.keyword, color: "#c9a6eb" },
|
||||
{ tag: tags.operator, color: "#cdd6f4" },
|
||||
{ tag: tags.variableName, color: "#89b4fa" },
|
||||
@@ -83,8 +83,42 @@ const crispyHighlight = HighlightStyle.define([
|
||||
{ tag: tags.color, color: "#f9e2af" }
|
||||
]);
|
||||
|
||||
// Combined theme export
|
||||
export const crispyEditorTheme = [crispyTheme, syntaxHighlighting(crispyHighlight)];
|
||||
// CSS section highlighting (purple selectors)
|
||||
const cssHighlight = HighlightStyle.define([
|
||||
{ tag: tags.keyword, color: "#c9a6eb" },
|
||||
{ tag: tags.operator, color: "#cdd6f4" },
|
||||
{ tag: tags.variableName, color: "#c9a6eb" },
|
||||
{ tag: tags.propertyName, color: "#89b4fa" },
|
||||
{ tag: tags.attributeName, color: "#89b4fa" },
|
||||
{ tag: tags.className, color: "#c9a6eb" },
|
||||
{ tag: tags.tagName, color: "#c9a6eb" },
|
||||
{ tag: tags.string, color: "#a6e3a1" },
|
||||
{ tag: tags.number, color: "#fab387" },
|
||||
{ tag: tags.bool, color: "#fab387" },
|
||||
{ tag: tags.null, color: "#fab387" },
|
||||
{ tag: tags.comment, color: "#6c7086", fontStyle: "italic" },
|
||||
{ tag: tags.bracket, color: "#cdd6f4" },
|
||||
{ tag: tags.punctuation, color: "#cdd6f4" },
|
||||
{ tag: tags.definition(tags.variableName), color: "#c9a6eb" },
|
||||
{ tag: tags.function(tags.variableName), color: "#89b4fa" },
|
||||
{ tag: tags.atom, color: "#c9a6eb" },
|
||||
{ tag: tags.unit, color: "#a6e3a1" },
|
||||
{ tag: tags.color, color: "#f9e2af" }
|
||||
]);
|
||||
|
||||
// Get highlight style based on section
|
||||
function getHighlightForSection(section) {
|
||||
if (section === "css") return cssHighlight;
|
||||
return defaultHighlight;
|
||||
}
|
||||
|
||||
// Get theme with section-specific highlighting
|
||||
export function getEditorTheme(section) {
|
||||
return [crispyTheme, syntaxHighlighting(getHighlightForSection(section))];
|
||||
}
|
||||
|
||||
// Default combined theme export (for backwards compatibility)
|
||||
export const crispyEditorTheme = [crispyTheme, syntaxHighlighting(defaultHighlight)];
|
||||
|
||||
// Custom overrides for editor styling
|
||||
const editorTheme = EditorView.theme(
|
||||
@@ -110,6 +144,7 @@ export class CodeEditor {
|
||||
this.options = options;
|
||||
this.view = null;
|
||||
this.mode = options.mode || "css";
|
||||
this.section = options.section || null;
|
||||
this.onChange = options.onChange || (() => {});
|
||||
}
|
||||
|
||||
@@ -126,7 +161,7 @@ export class CodeEditor {
|
||||
// Build extensions array
|
||||
const extensions = [
|
||||
langExtension,
|
||||
crispyEditorTheme,
|
||||
getEditorTheme(this.section),
|
||||
editorTheme,
|
||||
// History for undo/redo
|
||||
history(),
|
||||
@@ -215,6 +250,17 @@ export class CodeEditor {
|
||||
this.init(currentValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set section for theme (css, html, tailwind)
|
||||
*/
|
||||
setSection(section) {
|
||||
if (this.section === section) return;
|
||||
|
||||
this.section = section;
|
||||
const currentValue = this.getValue();
|
||||
this.init(currentValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the editor
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>Code Crispies - Learn HTML & CSS Interactively | Free Coding Practice</title>
|
||||
<title>CODE CRISPIES - Learn HTML & CSS Interactively | Free Coding Practice</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Master HTML, CSS, and Tailwind through hands-on coding exercises. Free, open-source learning platform with instant feedback. No account required."
|
||||
@@ -19,14 +19,14 @@
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://codecrispi.es/" />
|
||||
<meta property="og:title" content="Code Crispies - Learn HTML & CSS Interactively" />
|
||||
<meta property="og:title" content="CODE CRISPIES - Learn HTML & CSS Interactively" />
|
||||
<meta property="og:description" content="Master HTML, CSS, and Tailwind through hands-on coding exercises. Free and open source." />
|
||||
<meta property="og:image" content="https://codecrispi.es/og-image.png" />
|
||||
<meta property="og:site_name" content="Code Crispies" />
|
||||
<meta property="og:site_name" content="CODE CRISPIES" />
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="Code Crispies - Learn HTML & CSS Interactively" />
|
||||
<meta name="twitter:title" content="CODE CRISPIES - Learn HTML & CSS Interactively" />
|
||||
<meta name="twitter:description" content="Master HTML, CSS, and Tailwind through hands-on coding exercises." />
|
||||
<meta name="twitter:image" content="https://codecrispi.es/og-image.png" />
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebApplication",
|
||||
"name": "Code Crispies",
|
||||
"name": "CODE CRISPIES",
|
||||
"description": "Interactive platform for learning HTML, CSS, and Tailwind through hands-on coding exercises",
|
||||
"url": "https://codecrispi.es/",
|
||||
"applicationCategory": "EducationalApplication",
|
||||
@@ -100,7 +100,7 @@
|
||||
</section>
|
||||
|
||||
<section class="why-it-works">
|
||||
<h2 data-i18n="landingWhyTitle">Why Code Crispies Works</h2>
|
||||
<h2 data-i18n="landingWhyTitle">Why CODE CRISPIES Works</h2>
|
||||
<div class="benefits-grid">
|
||||
<article class="benefit-card">
|
||||
<svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@@ -198,7 +198,7 @@
|
||||
</section>
|
||||
<section class="footer-section footer-support">
|
||||
<h4 data-i18n="footerSupport">Support</h4>
|
||||
<p data-i18n="footerSupportText">Help keep Code Crispies free and open source.</p>
|
||||
<p data-i18n="footerSupportText">Help keep CODE CRISPIES free and open source.</p>
|
||||
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||
</section>
|
||||
@@ -227,6 +227,38 @@
|
||||
<!-- Educational content with integrated module links -->
|
||||
<div class="section-intro" id="section-intro"></div>
|
||||
</article>
|
||||
<footer class="section-footer landing-footer">
|
||||
<div class="footer-grid">
|
||||
<section class="footer-section footer-modules">
|
||||
<div id="section-footer-lesson-links" class="footer-links"></div>
|
||||
</section>
|
||||
<section class="footer-section">
|
||||
<h4 data-i18n="footerResources">Resources</h4>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#reference/css">CSS Reference</a></li>
|
||||
<li><a href="#reference/html">HTML Reference</a></li>
|
||||
<li><a href="#playground/0" data-i18n="footerPlayground">Playground</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="footer-section">
|
||||
<h4 data-i18n="footerAbout">About</h4>
|
||||
<ul class="footer-links">
|
||||
<li><a href="https://librete.ch" target="_blank">LibreTECH</a></li>
|
||||
<li><a href="https://git.librete.ch/libretech/code-crispies" target="_blank">Source Code</a></li>
|
||||
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="footer-section footer-support">
|
||||
<h4 data-i18n="footerSupport">Support</h4>
|
||||
<p data-i18n="footerSupportText">Help keep CODE CRISPIES free and open source.</p>
|
||||
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||
</section>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2025 <a href="https://librete.ch">LibreTECH</a>. <span data-i18n="footerLicense">Open source under MIT License.</span></p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Reference/Cheatsheet Pages -->
|
||||
@@ -243,8 +275,37 @@
|
||||
<!-- Reference content injected by JS -->
|
||||
</div>
|
||||
</article>
|
||||
<footer class="reference-footer">
|
||||
<p>© 2025 <a href="https://librete.ch">LibreTECH</a>. <span data-i18n="footerLicense">Released into public domain.</span></p>
|
||||
<footer class="reference-footer landing-footer">
|
||||
<div class="footer-grid">
|
||||
<section class="footer-section footer-modules">
|
||||
<div id="ref-footer-lesson-links" class="footer-links"></div>
|
||||
</section>
|
||||
<section class="footer-section">
|
||||
<h4 data-i18n="footerResources">Resources</h4>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#reference/css">CSS Reference</a></li>
|
||||
<li><a href="#reference/html">HTML Reference</a></li>
|
||||
<li><a href="#playground/0" data-i18n="footerPlayground">Playground</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="footer-section">
|
||||
<h4 data-i18n="footerAbout">About</h4>
|
||||
<ul class="footer-links">
|
||||
<li><a href="https://librete.ch" target="_blank">LibreTECH</a></li>
|
||||
<li><a href="https://git.librete.ch/libretech/code-crispies" target="_blank">Source Code</a></li>
|
||||
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="footer-section footer-support">
|
||||
<h4 data-i18n="footerSupport">Support</h4>
|
||||
<p data-i18n="footerSupportText">Help keep CODE CRISPIES free and open source.</p>
|
||||
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||
</section>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2025 <a href="https://librete.ch">LibreTECH</a>. <span data-i18n="footerLicense">Open source under MIT License.</span></p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
@@ -389,9 +450,9 @@
|
||||
<button id="help-dialog-close" class="dialog-close" aria-label="Close">×</button>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<h4 data-i18n="aboutTitle">About Code Crispies</h4>
|
||||
<h4 data-i18n="aboutTitle">About CODE CRISPIES</h4>
|
||||
<p data-i18n="aboutText">
|
||||
Code Crispies is a free, open-source platform for learning web development through hands-on exercises. No account required -
|
||||
CODE CRISPIES is a free, open-source platform for learning web development through hands-on exercises. No account required -
|
||||
just start coding!
|
||||
</p>
|
||||
|
||||
@@ -455,7 +516,7 @@
|
||||
</div>
|
||||
|
||||
<h4 data-i18n="contactTitle">Contact & Links</h4>
|
||||
<p data-i18n-html="contactText">Code Crispies is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a></p>
|
||||
<p data-i18n-html="contactText">CODE CRISPIES is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a></p>
|
||||
<ul>
|
||||
<li><a href="https://git.librete.ch/libretech/code-crispies" target="_blank">Gitea</a> – Self-hosted source repository</li>
|
||||
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a> – Public mirror</li>
|
||||
@@ -463,7 +524,7 @@
|
||||
</ul>
|
||||
|
||||
<h4 data-i18n="supportTitle">Support the Project</h4>
|
||||
<p data-i18n="supportText">Help keep Code Crispies free and open source.</p>
|
||||
<p data-i18n="supportText">Help keep CODE CRISPIES free and open source.</p>
|
||||
<div class="help-support" onclick="typeof umami !== 'undefined' && umami.track('support_click', {location: 'help'})">
|
||||
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||
|
||||
142
src/main.css
142
src/main.css
@@ -252,11 +252,11 @@ kbd {
|
||||
}
|
||||
|
||||
.logo h1 .code-text {
|
||||
color: var(--primary-color);
|
||||
color: #8b6bc4;
|
||||
}
|
||||
|
||||
.logo h1 .crispies-text {
|
||||
background: var(--primary-color);
|
||||
background: #8b6bc4;
|
||||
color: white;
|
||||
padding: 0.15rem 0.35rem;
|
||||
border-radius: 4px;
|
||||
@@ -264,6 +264,31 @@ kbd {
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Logo section color coding */
|
||||
[data-section="css"] .logo h1 .code-text {
|
||||
color: #8b6bc4;
|
||||
}
|
||||
|
||||
[data-section="css"] .logo h1 .crispies-text {
|
||||
background: #8b6bc4;
|
||||
}
|
||||
|
||||
[data-section="html"] .logo h1 .code-text {
|
||||
color: #c75b7a;
|
||||
}
|
||||
|
||||
[data-section="html"] .logo h1 .crispies-text {
|
||||
background: #c75b7a;
|
||||
}
|
||||
|
||||
[data-section="tailwind"] .logo h1 .code-text {
|
||||
color: #26a69a;
|
||||
}
|
||||
|
||||
[data-section="tailwind"] .logo h1 .crispies-text {
|
||||
background: #26a69a;
|
||||
}
|
||||
|
||||
.help-toggle {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
@@ -1954,7 +1979,9 @@ input:checked + .toggle-slider::before {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
#footer-lesson-links {
|
||||
#footer-lesson-links,
|
||||
#ref-footer-lesson-links,
|
||||
#section-footer-lesson-links {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
}
|
||||
@@ -2856,12 +2883,12 @@ input:checked + .toggle-slider::before {
|
||||
--section-color-rgb: 139, 107, 196;
|
||||
}
|
||||
|
||||
/* HTML Section - Balanced Rose */
|
||||
/* HTML Section - Raspberry */
|
||||
[data-section="html"] {
|
||||
--section-color: #d4637b;
|
||||
--section-color-light: #e08899;
|
||||
--section-color-dark: #b84d63;
|
||||
--section-color-rgb: 212, 99, 123;
|
||||
--section-color: #c75b7a;
|
||||
--section-color-light: #d97a94;
|
||||
--section-color-dark: #a84862;
|
||||
--section-color-rgb: 199, 91, 122;
|
||||
}
|
||||
|
||||
/* Tailwind Section - Balanced Teal */
|
||||
@@ -2878,7 +2905,7 @@ input:checked + .toggle-slider::before {
|
||||
}
|
||||
|
||||
.nav-link[data-section="html"] {
|
||||
color: #d4637b;
|
||||
color: #c75b7a;
|
||||
}
|
||||
|
||||
.nav-link[data-section="tailwind"] {
|
||||
@@ -2893,8 +2920,8 @@ input:checked + .toggle-slider::before {
|
||||
|
||||
.nav-link[data-section="html"]:hover,
|
||||
.nav-link[data-section="html"].active {
|
||||
background: rgba(212, 99, 123, 0.1);
|
||||
color: #b84d63;
|
||||
background: rgba(199, 91, 122, 0.1);
|
||||
color: #a84862;
|
||||
}
|
||||
|
||||
.nav-link[data-section="tailwind"]:hover,
|
||||
@@ -2903,17 +2930,45 @@ input:checked + .toggle-slider::before {
|
||||
color: #00897b;
|
||||
}
|
||||
|
||||
/* Logo color coding based on section */
|
||||
[data-section="css"] .code-text {
|
||||
color: #8b6bc4;
|
||||
/* Hint section colors */
|
||||
body[data-section="css"] .hint {
|
||||
background: rgba(139, 107, 196, 0.3);
|
||||
border-left-color: #a98cd6;
|
||||
}
|
||||
|
||||
[data-section="html"] .code-text {
|
||||
color: #d4637b;
|
||||
body[data-section="css"] .hint-progress {
|
||||
background: #8b6bc4;
|
||||
}
|
||||
|
||||
[data-section="tailwind"] .code-text {
|
||||
color: #26a69a;
|
||||
body[data-section="html"] .hint {
|
||||
background: rgba(199, 91, 122, 0.3);
|
||||
border-left-color: #d97a94;
|
||||
}
|
||||
|
||||
body[data-section="html"] .hint-progress {
|
||||
background: #c75b7a;
|
||||
}
|
||||
|
||||
body[data-section="tailwind"] .hint {
|
||||
background: rgba(38, 166, 154, 0.3);
|
||||
border-left-color: #4db6ac;
|
||||
}
|
||||
|
||||
body[data-section="tailwind"] .hint-progress {
|
||||
background: #26a69a;
|
||||
}
|
||||
|
||||
/* RTL hint border */
|
||||
[dir="rtl"] body[data-section="css"] .hint {
|
||||
border-right-color: #a98cd6;
|
||||
}
|
||||
|
||||
[dir="rtl"] body[data-section="html"] .hint {
|
||||
border-right-color: #d97a94;
|
||||
}
|
||||
|
||||
[dir="rtl"] body[data-section="tailwind"] .hint {
|
||||
border-right-color: #4db6ac;
|
||||
}
|
||||
|
||||
/* Reference nav link colors */
|
||||
@@ -2937,13 +2992,13 @@ input:checked + .toggle-slider::before {
|
||||
}
|
||||
|
||||
.ref-nav-link[data-ref="html"] {
|
||||
color: #d4637b;
|
||||
color: #c75b7a;
|
||||
}
|
||||
|
||||
.ref-nav-link[data-ref="html"]:hover,
|
||||
.ref-nav-link[data-ref="html"].active {
|
||||
background: rgba(212, 99, 123, 0.15);
|
||||
color: #b84d63;
|
||||
background: rgba(199, 91, 122, 0.15);
|
||||
color: #a84862;
|
||||
}
|
||||
|
||||
/* CodeMirror section color overrides */
|
||||
@@ -2966,21 +3021,21 @@ body[data-section="css"] .cm-editor .cm-activeLine {
|
||||
}
|
||||
|
||||
body[data-section="html"] .cm-editor .cm-content {
|
||||
caret-color: #d4637b !important;
|
||||
caret-color: #c75b7a !important;
|
||||
}
|
||||
|
||||
body[data-section="html"] .cm-editor .cm-cursor,
|
||||
body[data-section="html"] .cm-editor .cm-dropCursor {
|
||||
border-left-color: #d4637b !important;
|
||||
border-left-color: #c75b7a !important;
|
||||
}
|
||||
|
||||
body[data-section="html"] .cm-editor .cm-selectionBackground,
|
||||
body[data-section="html"] .cm-editor .cm-content ::selection {
|
||||
background-color: rgba(212, 99, 123, 0.25) !important;
|
||||
background-color: rgba(199, 91, 122, 0.25) !important;
|
||||
}
|
||||
|
||||
body[data-section="html"] .cm-editor .cm-activeLine {
|
||||
background-color: rgba(212, 99, 123, 0.08) !important;
|
||||
background-color: rgba(199, 91, 122, 0.08) !important;
|
||||
}
|
||||
|
||||
body[data-section="tailwind"] .cm-editor .cm-content {
|
||||
@@ -3012,12 +3067,12 @@ body[data-section="css"] .module-pill .level-indicator {
|
||||
}
|
||||
|
||||
body[data-section="html"] .module-pill {
|
||||
background: rgba(212, 99, 123, 0.1);
|
||||
color: #d4637b;
|
||||
background: rgba(199, 91, 122, 0.1);
|
||||
color: #c75b7a;
|
||||
}
|
||||
|
||||
body[data-section="html"] .module-pill .level-indicator {
|
||||
color: #b84d63;
|
||||
color: #a84862;
|
||||
}
|
||||
|
||||
body[data-section="tailwind"] .module-pill {
|
||||
@@ -3035,7 +3090,7 @@ body[data-section="css"] .code-block {
|
||||
}
|
||||
|
||||
body[data-section="html"] .code-block {
|
||||
border-color: rgba(212, 99, 123, 0.4);
|
||||
border-color: rgba(199, 91, 122, 0.4);
|
||||
}
|
||||
|
||||
body[data-section="tailwind"] .code-block {
|
||||
@@ -3061,7 +3116,7 @@ body[data-section="tailwind"] .code-block .cm-editor .cm-line {
|
||||
}
|
||||
|
||||
[data-section="html"] .task-instruction {
|
||||
background: rgba(212, 99, 123, 0.92);
|
||||
background: rgba(199, 91, 122, 0.92);
|
||||
}
|
||||
|
||||
[data-section="tailwind"] .task-instruction {
|
||||
@@ -3074,7 +3129,7 @@ body[data-section="css"] .section-progress-bar .progress-fill {
|
||||
}
|
||||
|
||||
body[data-section="html"] .section-progress-bar .progress-fill {
|
||||
background: #d4637b;
|
||||
background: #c75b7a;
|
||||
}
|
||||
|
||||
body[data-section="tailwind"] .section-progress-bar .progress-fill {
|
||||
@@ -3087,23 +3142,28 @@ body[data-section="tailwind"] .section-progress-bar .progress-fill {
|
||||
}
|
||||
|
||||
[data-section="html"] .section-hero h1 {
|
||||
color: #d4637b;
|
||||
color: #c75b7a;
|
||||
}
|
||||
|
||||
[data-section="tailwind"] .section-hero h1 {
|
||||
color: #26a69a;
|
||||
}
|
||||
|
||||
/* Reference footer */
|
||||
.reference-footer {
|
||||
text-align: center;
|
||||
padding: 2rem 1rem;
|
||||
margin-top: 3rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
color: var(--light-text);
|
||||
font-size: 0.9rem;
|
||||
/* Section and Reference footer - override landing-footer styles */
|
||||
.section-footer.landing-footer,
|
||||
.reference-footer.landing-footer {
|
||||
max-width: 900px;
|
||||
margin: 6rem auto 0;
|
||||
padding: 0 var(--spacing-lg) var(--spacing-lg);
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.reference-footer a {
|
||||
.section-footer .footer-links a,
|
||||
.reference-footer .footer-links a {
|
||||
color: var(--light-text);
|
||||
}
|
||||
|
||||
.section-footer .footer-links a:hover,
|
||||
.reference-footer .footer-links a:hover {
|
||||
color: var(--section-color, var(--primary-color));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user