feat: add landing footer with donation support, change license to Unlicense
- Add extended landing footer with module links grouped by section - Integrate Liberapay donation widget with Umami tracking - Add support section to help dialog and goodbye lesson - Change license from MIT to Unlicense (public domain) - Disable Tailwind section (not yet activated) - Update German CTA copy - Update all 6 language translations for license text 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
24
LICENSE
Normal file
24
LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
||||
10
README.md
10
README.md
@@ -1,16 +1,16 @@
|
||||

|
||||
# Code Crispies
|
||||
|
||||
An interactive platform for learning CSS and Tailwind CSS through practical challenges.
|
||||
An interactive platform for learning HTML, CSS, and Tailwind CSS through practical challenges.
|
||||
|
||||
## 📚 Overview
|
||||
|
||||
Code Crispies is a web-based learning platform designed to help users master CSS and Tailwind CSS through hands-on exercises. The application presents a series of progressive challenges organized into themed modules, allowing learners to build their skills step by step while receiving immediate feedback.
|
||||
Code Crispies is a web-based learning platform designed to help users master HTML, CSS, and Tailwind CSS through hands-on exercises. The application presents a series of progressive challenges organized into themed modules, allowing learners to build their skills step by step while receiving immediate feedback.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Interactive Lessons**: Learn CSS and Tailwind concepts through practical, hands-on challenges
|
||||
- **Dual Mode Support**: Switch between CSS and Tailwind CSS learning modes
|
||||
- **Interactive Lessons**: Learn HTML, CSS, and Tailwind concepts through practical, hands-on challenges
|
||||
- **Multiple Learning Paths**: CSS fundamentals, HTML semantics, and Tailwind CSS utilities
|
||||
- **Progressive Difficulty**: Modules are structured to build skills gradually from basic to advanced
|
||||
- **Real-Time Feedback**: Get immediate validation on your code solutions with comprehensive feedback
|
||||
- **Progress Tracking**: Your learning progress is automatically saved in the browser
|
||||
@@ -256,4 +256,4 @@ When adding new lessons:
|
||||
|
||||
## 📄 License
|
||||
|
||||
Copyright (c) 2026 Michael Czechowski. Licensed under the [./LICENSE](WTFPL).
|
||||
This project is released into the public domain under the [Unlicense](./LICENSE). You are free to copy, modify, publish, use, compile, sell, or distribute this software for any purpose.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{
|
||||
"id": "next-steps",
|
||||
"title": "Keep Going!",
|
||||
"description": "<strong>Great progress!</strong> You're building real web development skills.<br><br><strong>Continue learning:</strong><br>• <a href=\"https://developer.mozilla.org\" target=\"_blank\">MDN Web Docs</a> - The definitive reference<br>• <a href=\"https://css-tricks.com\" target=\"_blank\">CSS-Tricks</a> - Practical techniques<br><br><strong>Practice ideas:</strong><br>• Build your portfolio site<br>• Recreate a website you like<br>• Try the <a href=\"#playground/0\">Playground</a> to experiment freely<br><br><strong>Contribute:</strong> Code Crispies is <a href=\"https://git.librete.ch/libretech/code-crispies\" target=\"_blank\">open source</a>. Add lessons, fix bugs, or translate!",
|
||||
"description": "<strong>Great progress!</strong> You're building real web development skills.<br><br><strong>Continue learning:</strong><br>• <a href=\"https://developer.mozilla.org\" target=\"_blank\">MDN Web Docs</a> - The definitive reference<br>• <a href=\"https://css-tricks.com\" target=\"_blank\">CSS-Tricks</a> - Practical techniques<br><br><strong>Practice ideas:</strong><br>• Build your portfolio site<br>• Recreate a website you like<br>• Try the <a href=\"#playground/0\">Playground</a> to experiment freely<br><br><strong>Contribute:</strong> Code Crispies is <a href=\"https://git.librete.ch/libretech/code-crispies\" target=\"_blank\">open source</a>. Add lessons, fix bugs, or translate!<br><br><strong>Support:</strong> Help keep it free and open source!<br><a href=\"https://liberapay.com/libretech/donate\" target=\"_blank\" onclick=\"typeof umami !== 'undefined' && umami.track('support_click', {location: 'goodbye'})\"><img alt=\"Donate using Liberapay\" src=\"https://liberapay.com/assets/widgets/donate.svg\" style=\"margin-top: 8px;\"></a>",
|
||||
"task": "Type <code>Thank you!</code>",
|
||||
"previewHTML": "",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 20px; text-align: center; font-size: 1.5rem; color: #6366f1; }",
|
||||
|
||||
37
src/app.js
37
src/app.js
@@ -155,6 +155,7 @@ const elements = {
|
||||
sidebarBackdrop: document.getElementById("sidebar-backdrop"),
|
||||
closeSidebar: document.getElementById("close-sidebar"),
|
||||
moduleList: document.getElementById("module-list"),
|
||||
footerLessonLinks: document.getElementById("footer-lesson-links"),
|
||||
progressFill: document.getElementById("progress-fill"),
|
||||
progressText: document.getElementById("progress-text"),
|
||||
resetBtn: document.getElementById("reset-btn"),
|
||||
@@ -1991,6 +1992,40 @@ function showLandingPage() {
|
||||
|
||||
// Update section progress on landing page
|
||||
updateLandingProgress();
|
||||
|
||||
// Render footer lesson links
|
||||
renderFooterLessonLinks();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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: [] };
|
||||
|
||||
modules.forEach((module) => {
|
||||
if (module.excludeFromProgress) return;
|
||||
const sectionId = getModuleSection(module);
|
||||
if (sectionId && sectionGroups[sectionId]) {
|
||||
sectionGroups[sectionId].push(module);
|
||||
}
|
||||
});
|
||||
|
||||
let html = "";
|
||||
Object.entries(sectionGroups).forEach(([sectionId, sectionModules]) => {
|
||||
if (sectionModules.length === 0) return;
|
||||
const sectionName = sectionId.toUpperCase();
|
||||
html += `<div class="footer-section-group"><strong><a href="#${sectionId}">${sectionName}</a></strong>`;
|
||||
sectionModules.forEach((module) => {
|
||||
html += `<a href="#${module.id}/0">${module.title}</a>`;
|
||||
});
|
||||
html += "</div>";
|
||||
});
|
||||
|
||||
elements.footerLessonLinks.innerHTML = html;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2387,6 +2422,8 @@ function init() {
|
||||
track("landing_cta", { href: target.getAttribute("href") });
|
||||
} else if (target.classList.contains("section-card")) {
|
||||
track("landing_section", { section: target.dataset.section });
|
||||
} else if (target.closest(".footer-support")) {
|
||||
track("support_click", { location: "landing" });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
90
src/i18n.js
90
src/i18n.js
@@ -134,7 +134,20 @@ const translations = {
|
||||
landingTailwindDesc: "Utility-first CSS framework",
|
||||
landingCtaTitle: "Start Learning Today",
|
||||
landingCtaSub: "Free and open source. No account required. Progress saved locally.",
|
||||
landingCtaButton: "Begin Your Journey"
|
||||
landingCtaButton: "Begin Your Journey",
|
||||
|
||||
// Footer
|
||||
footerModules: "Modules",
|
||||
footerResources: "Resources",
|
||||
footerPlayground: "Playground",
|
||||
footerAbout: "About",
|
||||
footerSupport: "Support",
|
||||
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."
|
||||
},
|
||||
|
||||
de: {
|
||||
@@ -271,7 +284,20 @@ const translations = {
|
||||
landingTailwindDesc: "Utility-first CSS-Framework",
|
||||
landingCtaTitle: "Heute noch anfangen",
|
||||
landingCtaSub: "Kostenlos und Open Source. Kein Konto erforderlich. Fortschritt wird lokal gespeichert.",
|
||||
landingCtaButton: "Starte deine Reise"
|
||||
landingCtaButton: "Jetzt erste Schritte machen",
|
||||
|
||||
// Footer
|
||||
footerModules: "Module",
|
||||
footerResources: "Ressourcen",
|
||||
footerPlayground: "Playground",
|
||||
footerAbout: "Über uns",
|
||||
footerSupport: "Unterstützen",
|
||||
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."
|
||||
},
|
||||
|
||||
// Polish
|
||||
@@ -408,7 +434,20 @@ const translations = {
|
||||
landingTailwindDesc: "Framework CSS oparty na klasach utility",
|
||||
landingCtaTitle: "Zacznij naukę już dziś",
|
||||
landingCtaSub: "Darmowe i open source. Bez konta. Postęp zapisywany lokalnie.",
|
||||
landingCtaButton: "Rozpocznij swoją podróż"
|
||||
landingCtaButton: "Rozpocznij swoją podróż",
|
||||
|
||||
// Footer
|
||||
footerModules: "Moduły",
|
||||
footerResources: "Zasoby",
|
||||
footerPlayground: "Plac zabaw",
|
||||
footerAbout: "O nas",
|
||||
footerSupport: "Wsparcie",
|
||||
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."
|
||||
},
|
||||
|
||||
// Spanish
|
||||
@@ -547,7 +586,20 @@ const translations = {
|
||||
landingTailwindDesc: "Framework CSS basado en utilidades",
|
||||
landingCtaTitle: "Empieza a aprender hoy",
|
||||
landingCtaSub: "Gratis y de código abierto. Sin cuenta requerida. Progreso guardado localmente.",
|
||||
landingCtaButton: "Comienza tu viaje"
|
||||
landingCtaButton: "Comienza tu viaje",
|
||||
|
||||
// Footer
|
||||
footerModules: "Módulos",
|
||||
footerResources: "Recursos",
|
||||
footerPlayground: "Zona de pruebas",
|
||||
footerAbout: "Acerca de",
|
||||
footerSupport: "Apoyar",
|
||||
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."
|
||||
},
|
||||
|
||||
// Arabic
|
||||
@@ -681,7 +733,20 @@ const translations = {
|
||||
landingTailwindDesc: "إطار CSS قائم على الأدوات",
|
||||
landingCtaTitle: "ابدأ التعلم اليوم",
|
||||
landingCtaSub: "مجاني ومفتوح المصدر. لا حاجة لحساب. يُحفظ التقدم محليًا.",
|
||||
landingCtaButton: "ابدأ رحلتك"
|
||||
landingCtaButton: "ابدأ رحلتك",
|
||||
|
||||
// Footer
|
||||
footerModules: "الوحدات",
|
||||
footerResources: "الموارد",
|
||||
footerPlayground: "ساحة التجربة",
|
||||
footerAbout: "حول",
|
||||
footerSupport: "الدعم",
|
||||
footerSupportText: "ساعد في إبقاء Code Crispies مجانيًا ومفتوح المصدر.",
|
||||
footerLicense: "مُطلق للملكية العامة.",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "ادعم المشروع",
|
||||
supportText: "ساعد في إبقاء Code Crispies مجانيًا ومفتوح المصدر."
|
||||
},
|
||||
|
||||
// Ukrainian
|
||||
@@ -817,7 +882,20 @@ const translations = {
|
||||
landingTailwindDesc: "CSS-фреймворк на основі утиліт",
|
||||
landingCtaTitle: "Почни вчитися сьогодні",
|
||||
landingCtaSub: "Безкоштовно та з відкритим кодом. Без реєстрації. Прогрес зберігається локально.",
|
||||
landingCtaButton: "Розпочни свою подорож"
|
||||
landingCtaButton: "Розпочни свою подорож",
|
||||
|
||||
// Footer
|
||||
footerModules: "Модулі",
|
||||
footerResources: "Ресурси",
|
||||
footerPlayground: "Пісочниця",
|
||||
footerAbout: "Про нас",
|
||||
footerSupport: "Підтримка",
|
||||
footerSupportText: "Допоможи зберегти Code Crispies безкоштовним та з відкритим кодом.",
|
||||
footerLicense: "Передано у суспільне надбання.",
|
||||
|
||||
// Help Dialog Support
|
||||
supportTitle: "Підтримати проєкт",
|
||||
supportText: "Допоможи зберегти Code Crispies безкоштовним та з відкритим кодом."
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
<nav class="main-nav" id="main-nav" aria-label="Main sections">
|
||||
<a href="#css" class="nav-link" data-section="css">CSS</a>
|
||||
<a href="#html" class="nav-link" data-section="html">HTML</a>
|
||||
<a href="#tailwind" class="nav-link" data-section="tailwind">Tailwind</a>
|
||||
<!-- Tailwind disabled until lessons are ready -->
|
||||
<!-- <a href="#tailwind" class="nav-link" data-section="tailwind">Tailwind</a> -->
|
||||
<a href="#reference/css" class="nav-link nav-link-ref" data-section="reference">Reference</a>
|
||||
</nav>
|
||||
<button id="help-btn" class="help-toggle" data-i18n-aria-label="help" aria-label="Help">?</button>
|
||||
@@ -150,12 +151,15 @@
|
||||
<p data-i18n="landingHtmlDesc">Semantic markup and native elements</p>
|
||||
<span class="section-card-progress" id="html-progress"></span>
|
||||
</a>
|
||||
<!-- Tailwind disabled until lessons are ready -->
|
||||
<!--
|
||||
<a href="#tailwind" class="section-card" data-section="tailwind">
|
||||
<div class="section-card-icon" style="background: #06b6d4">TW</div>
|
||||
<h3>Tailwind CSS</h3>
|
||||
<p data-i18n="landingTailwindDesc">Utility-first CSS framework</p>
|
||||
<span class="section-card-progress" id="tailwind-progress"></span>
|
||||
</a>
|
||||
-->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -164,6 +168,39 @@
|
||||
<a href="#welcome/0" class="cta-button" data-i18n="landingCtaButton">Begin Your Journey</a>
|
||||
<p class="cta-sub" data-i18n="landingCtaSub">Free and open source. No account required. Progress saved locally.</p>
|
||||
</section>
|
||||
|
||||
<footer class="landing-footer">
|
||||
<div class="footer-grid">
|
||||
<section class="footer-section footer-modules">
|
||||
<div id="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>
|
||||
</div>
|
||||
|
||||
@@ -356,7 +393,7 @@
|
||||
<li data-i18n-html="modeHtml"><strong>HTML</strong> - Practice semantic markup and native elements</li>
|
||||
</ul>
|
||||
<p class="help-nav-links">
|
||||
Jump to: <a href="#css">CSS</a> | <a href="#html">HTML</a> | <a href="#tailwind">Tailwind</a> |
|
||||
Jump to: <a href="#css">CSS</a> | <a href="#html">HTML</a> |
|
||||
<a href="#reference/css">Reference</a>
|
||||
</p>
|
||||
|
||||
@@ -415,6 +452,13 @@
|
||||
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a> – Public mirror</li>
|
||||
<li><a href="https://www.linkedin.com/in/michael-werner-czechowski" target="_blank">LinkedIn</a> – Michael Czechowski</li>
|
||||
</ul>
|
||||
|
||||
<h4 data-i18n="supportTitle">Support the Project</h4>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
|
||||
126
src/main.css
126
src/main.css
@@ -1865,6 +1865,132 @@ input:checked + .toggle-slider::before {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
/* ================= LANDING FOOTER ================= */
|
||||
.landing-footer {
|
||||
margin-top: 3rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.footer-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr 1fr 1fr;
|
||||
gap: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.footer-section h4 {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer-links li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.footer-links a {
|
||||
color: var(--light-text);
|
||||
text-decoration: none;
|
||||
font-size: 0.875rem;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
#footer-lesson-links {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.footer-section-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.footer-section-group strong {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.footer-section-group strong a {
|
||||
color: var(--text-color);
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.footer-section-group a {
|
||||
display: inline-block;
|
||||
color: #888;
|
||||
text-decoration: none;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
max-width: 140px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.footer-section-group a:hover {
|
||||
color: var(--primary-color);
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.footer-support p {
|
||||
color: var(--light-text);
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
text-align: center;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.footer-bottom p {
|
||||
color: var(--light-text);
|
||||
font-size: 0.8rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer-bottom a {
|
||||
color: var(--light-text);
|
||||
}
|
||||
|
||||
.footer-bottom a:hover {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.footer-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.footer-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================= SECTION PAGE ================= */
|
||||
.section-page {
|
||||
flex: 1;
|
||||
|
||||
Reference in New Issue
Block a user