dev-02.00 to main #1

Merged
mokoconsulting-tech merged 6 commits from dev-02.00 into main 2025-08-30 23:50:41 +00:00
47 changed files with 2915 additions and 3124 deletions
Showing only changes of commit bee7796645 - Show all commits

85
CHANGELOG.md Normal file
View File

@@ -0,0 +1,85 @@
<!--
=========================================================================
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/ .
=========================================================================
FILE INFORMATION
DEFGROUP: Joomla
INGROUP: Moko-Cassiopeia
PATH: CHANGELOG.md
VERSION: 02.00
BRIEF: Changelog file documenting version history of Moko-Cassiopeia
=========================================================================
-->
Changelog — Moko-Cassiopeia
#Version 2.0 (2025-08-30)
**Major Release** — introduces the long-awaited **Dark Mode Toggle**, streamlining accessibility and usability enhancements.
##Added
* **Dark Mode Toggle**
* Frontend toggle switch included in template.
* JavaScript handles switching between light/dark modes.
* Dark mode CSS rules applied across template styles.
* Automatic persistence of user choice (via localStorage).
* **Header Parameters Update**
* Added **logo parameter support** in template settings.
* Updated metadata & copyright header.
* **Expanded TOC (Table of Contents)**
* Automatic TOC injection when enabled.
* User selects placement via article > options > layout (`toc-left` or `toc-right`).
##Improved
* Cleaned up `index.php` by removing **skip-to-content** duplicate calls.
* Consolidated JavaScript asset loading (ensuring dark-mode script is loaded correctly from external JS file).
* Streamlined CSS for **toggle switch**, ensuring it inherits Bootstrap/Cassiopeia defaults.
* General accessibility refinements in typography and color contrast.
##Fixed
* Fixed missing **logo param** in header output.
* Corrected stylesheet inconsistencies between Bootstrap 5 helpers and template overrides.
* Patched redundant calls in script includes.
---
#Previous Versions
##1.0
* **Initial Public Release** with:
* Font Awesome 6
* Bootstrap 5 helpers
* Automatic Table of Contents (TOC) utility
* Moko Expansions: Google Tag Manager / GA4 hooks
---
For the full development roadmap, visit:
[Moko-Cassiopeia Roadmap](https://mokoconsulting.tech/support/joomla-cms/moko-cassiopeia-roadmap)

View File

@@ -1,22 +1,31 @@
<!-- <!--
=========================================================================
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech> Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project. This file is part of a Moko Consulting project.
This documentation is free software: you can redistribute it and/or modify SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This documentation is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this documentation. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see https://www.gnu.org/licenses/ .
=========================================================================
SPDX-License-Identifier: GPL-3.0-or-later FILE INFORMATION
DEFGROUP: Joomla
INGROUP: Moko-Cassiopeia
PATH: CODE_OF_CONDUCT.md
VERSION: 02.00
BRIEF: Contributor Code of Conduct for Moko-Cassiopeia project
=========================================================================
--> -->
# Code of Conduct # Code of Conduct

View File

@@ -1,3 +1,33 @@
<!--
=========================================================================
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/ .
=========================================================================
FILE INFORMATION
DEFGROUP: Joomla
INGROUP: Moko-Cassiopeia
PATH: CONTRIBUTING.md
VERSION: 02.00
BRIEF: Contribution guidelines for the Moko-Cassiopeia project
=========================================================================
-->
# Contributing Guidelines # Contributing Guidelines
Thank you for considering contributing to this project! We welcome contributions from the community and are grateful for your support. Thank you for considering contributing to this project! We welcome contributions from the community and are grateful for your support.

View File

@@ -1,13 +1,30 @@
;--------------------------------------------------- # =========================================================================
; Template: moko-cassiopeia # Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
; File: en-GB.tpl_moko-cassiopeia.ini #
; Version: 02.00 # This file is part of a Moko Consulting project.
; Author: Jonathan Miller #
; Copyright: (C) 2025 Moko Consulting. All rights reserved. # SPDX-License-Identifier: GPL-3.0-or-later
; License: GNU General Public License v3 or later; see LICENSE.txt #
; Description: Language strings for the frontend template. # This program is free software; you can redistribute it and/or modify
; Note: All ini files must be saved as UTF-8 without BOM. # it under the terms of the GNU General Public License as published by
;--------------------------------------------------- # the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see https://www.gnu.org/licenses/ .
# =========================================================================
# FILE INFORMATION
# DEFGROUP: Joomla
# INGROUP: Moko-Cassiopeia
# PATH: language/en-GB/tpl_moko-cassiopeia.ini
# VERSION: 02.00
# BRIEF: English (GB) language strings for the Moko-Cassiopeia Joomla template
# =========================================================================
; ===== Template meta ===== ; ===== Template meta =====
MOKO-CASSIOPEIA="MOKO-CASSIOPEIA Site template" MOKO-CASSIOPEIA="MOKO-CASSIOPEIA Site template"

View File

@@ -1,13 +1,30 @@
;--------------------------------------------------- # =========================================================================
; Template: moko-cassiopeia # Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
; File: en-GB.tpl_moko-cassiopeia.sys.ini #
; Version: 02.00 # This file is part of a Moko Consulting project.
; Author: Jonathan Miller #
; Copyright: (C) 2025 Moko Consulting. All rights reserved. # SPDX-License-Identifier: GPL-3.0-or-later
; License: GNU General Public License v3 or later; see LICENSE.txt #
; Description: Language strings for the frontend template. # This program is free software; you can redistribute it and/or modify
; Note: All ini files must be saved as UTF-8 without BOM. # it under the terms of the GNU General Public License as published by
;--------------------------------------------------- # the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see https://www.gnu.org/licenses/ .
# =========================================================================
# FILE INFORMATION
# DEFGROUP: Joomla
# INGROUP: Moko-Cassiopeia
# PATH: language/en-GB/tpl_moko-cassiopeia.sys.ini
# VERSION: 02.00
# BRIEF: English (GB) system language strings for template metadata and installer
# =========================================================================
TPL_MOKO-CASSIOPEIA="Moko-Cassiopeia Site template" TPL_MOKO-CASSIOPEIA="Moko-Cassiopeia Site template"
TPL_MOKO-CASSIOPEIA_MOD_MENU_LAYOUT_COLLAPSE-METISMENU="Collapsible Dropdown" TPL_MOKO-CASSIOPEIA_MOD_MENU_LAYOUT_COLLAPSE-METISMENU="Collapsible Dropdown"
@@ -30,11 +47,12 @@ TPL_MOKO-CASSIOPEIA_POSITION_TOP-B="Top-b"
TPL_MOKO-CASSIOPEIA_POSITION_TOPBAR="Top Bar" TPL_MOKO-CASSIOPEIA_POSITION_TOPBAR="Top Bar"
TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-LEFT="Drawer-Left" TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-LEFT="Drawer-Left"
TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-RIGHT="Drawer-Right" TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-RIGHT="Drawer-Right"
TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION="<h3>MOKO-CASSIOPEIA Template Description</h3> TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION=
TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION="<h3>MOKO-CASSIOPEIA Template Description (v2.0)</h3>
<p> <p>
<strong>MOKO-CASSIOPEIA</strong> continues Joomlas tradition of space-themed default templates— <strong>MOKO-CASSIOPEIA 2.0</strong> continues Joomlas tradition of space-themed default templates—
building on the legacy of <em>Solarflare</em> from Joomla 1.0, <em>Milkyway</em> from Joomla 1.5, building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5),
and <em>Protostar</em> from Joomla 3.0. and <em>Protostar</em> (Joomla 3.0).
</p> </p>
<p> <p>
This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4,
@@ -42,41 +60,40 @@ TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION="<h3>MOKO-CASSIOPEIA Template Description</h
enhancements and structural refinements specifically tailored for use by Moko Consulting. enhancements and structural refinements specifically tailored for use by Moko Consulting.
</p> </p>
<p> <p>
<strong>MOKO-CASSIOPEIA</strong> is designed to serve as a versatile, production-ready base for <strong>Version 2.0</strong> introduces significant new functionality including a Dark Mode toggle,
contemporary Joomla websites, emphasizing speed, clarity, and open-source philosophy. Google Tag Manager (GTM) and Google Analytics 4 (GA4) hooks, and expanded template configuration
options — all while keeping overrides minimal and upgrade-friendly.
</p> </p>
<h4>Features</h4> <h4>Features</h4>
<ul> <ul>
<li>Fully responsive and mobile-first layout</li> <li>Fully responsive and mobile-first layout</li>
<li>Based on Joomla 4+ template architecture</li> <li>Based on Joomla 4+ template architecture</li>
<li>Enhanced SCSS and CSS overrides for custom styling</li> <li>Enhanced SCSS and CSS overrides for streamlined custom styling</li>
<li>Built-in support for Bootstrap 5</li> <li>Built-in support for <strong>Bootstrap 5</strong></li>
<li> <li>Font Awesome 6 integration for modern iconography</li>
Integrated dynamic Table of Contents via <li>Automatic Table of Contents (TOC) — selectable per article via <code>toc-left</code> or <code>toc-right</code> layouts</li>
<a href="https://afeld.github.io/bootstrap-toc/" target="_blank" rel="noopener">Bootstrap TOC</a> <li><strong>Dark Mode toggle (new in v2.0)</strong> with user switch and admin override</li>
</li> <li><strong>Optional GTM + GA4 hooks (new in v2.0)</strong> for analytics and marketing integration</li>
<li>Optimized template structure for performance and maintainability</li> <li>Optimized template structure for performance and maintainability</li>
<li>Custom module positions and layout presets</li> <li>Custom module positions and layout presets</li>
<li>Accessible, lightweight, and extensible</li> <li>Accessible, lightweight, and extensible for long-term use</li>
<li>Ideal for professional services, portfolios, and informational websites</li> <li>Ideal for professional services, portfolios, and informational websites</li>
</ul> </ul>
<h4>Code Attribution</h4> <h4>Code Attribution</h4>
<p> <p>
This template is based on the original <strong>Cassiopeia</strong> template developed by the This template is based on the original <strong>Cassiopeia</strong> template developed by the
<a href="https://www.joomla.org" target="_blank" rel="noopener">Joomla! Project</a> and released under the GNU General Public License. <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License.
</p> </p>
<p> <p>
Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.
</p>a </p>
<p> <p>
It includes integration with It includes integration with
<a href="https://afeld.github.io/bootstrap-toc/" target="_blank" rel="noopener">Bootstrap TOC</a>, <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>,
an open-source table of contents generator by A. Feld, licensed under the MIT License. an open-source table of contents generator by A. Feld, licensed under the MIT License.
</p> </p>
<p> <p>
All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.
</p>" </p>"
JGLOBAL_OFFLINE="Offline"

View File

@@ -1,13 +1,30 @@
;--------------------------------------------------- # =========================================================================
; Template: moko-cassiopeia # Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
; File: en-GB.tpl_moko-cassiopeia.ini #
; Version: 02.00 # This file is part of a Moko Consulting project.
; Author: Jonathan Miller #
; Copyright: (C) 2025 Moko Consulting. All rights reserved. # SPDX-License-Identifier: GPL-3.0-or-later
; License: GNU General Public License v3 or later; see LICENSE.txt #
; Description: Language strings for the frontend template. # This program is free software; you can redistribute it and/or modify
; Note: All ini files must be saved as UTF-8 without BOM. # it under the terms of the GNU General Public License as published by
;--------------------------------------------------- # the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see https://www.gnu.org/licenses/ .
# =========================================================================
# FILE INFORMATION
# DEFGROUP: Joomla
# INGROUP: Moko-Cassiopeia
# PATH: language/en-US/tpl_moko-cassiopeia.ini
# VERSION: 02.00
# BRIEF: English (US) language strings for the Moko-Cassiopeia Joomla template
# =========================================================================
; ===== Template meta ===== ; ===== Template meta =====
MOKO-CASSIOPEIA="MOKO-CASSIOPEIA Site template" MOKO-CASSIOPEIA="MOKO-CASSIOPEIA Site template"

View File

@@ -1,13 +1,30 @@
;--------------------------------------------------- # =========================================================================
; Template: moko-cassiopeia # Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
; File: en-US.tpl_moko-cassiopeia.sys.ini #
; Version: 02.00 # This file is part of a Moko Consulting project.
; Author: Jonathan Miller #
; Copyright: (C) 2025 Moko Consulting. All rights reserved. # SPDX-License-Identifier: GPL-3.0-or-later
; License: GNU General Public License v3 or later; see LICENSE.txt #
; Description: Language strings for the frontend template. # This program is free software; you can redistribute it and/or modify
; Note: All ini files must be saved as UTF-8 without BOM. # it under the terms of the GNU General Public License as published by
;--------------------------------------------------- # the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see https://www.gnu.org/licenses/ .
# =========================================================================
# FILE INFORMATION
# DEFGROUP: Joomla
# INGROUP: Moko-Cassiopeia
# PATH: language/en-US/tpl_moko-cassiopeia.sys.ini
# VERSION: 02.00
# BRIEF: English (US) system language strings for template metadata and installer
# =========================================================================
TPL_MOKO-CASSIOPEIA="Moko-Cassiopeia Site template" TPL_MOKO-CASSIOPEIA="Moko-Cassiopeia Site template"
TPL_MOKO-CASSIOPEIA_MOD_MENU_LAYOUT_COLLAPSE-METISMENU="Collapsible Dropdown" TPL_MOKO-CASSIOPEIA_MOD_MENU_LAYOUT_COLLAPSE-METISMENU="Collapsible Dropdown"
@@ -31,11 +48,11 @@ TPL_MOKO-CASSIOPEIA_POSITION_TOPBAR="Top Bar"
TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-LEFT="Drawer-Left" TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-LEFT="Drawer-Left"
TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-RIGHT="Drawer-Right" TPL_MOKO-CASSIOPEIA_POSITION_DRAWER-RIGHT="Drawer-Right"
TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION= TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION=
TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION="<h3>MOKO-CASSIOPEIA Template Description</h3> TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION="<h3>MOKO-CASSIOPEIA Template Description (v2.0)</h3>
<p> <p>
<strong>MOKO-CASSIOPEIA</strong> continues Joomlas tradition of space-themed default templates— <strong>MOKO-CASSIOPEIA 2.0</strong> continues Joomlas tradition of space-themed default templates—
building on the legacy of <em>Solarflare</em> from Joomla 1.0, <em>Milkyway</em> from Joomla 1.5, building on the legacy of <em>Solarflare</em> (Joomla 1.0), <em>Milkyway</em> (Joomla 1.5),
and <em>Protostar</em> from Joomla 3.0. and <em>Protostar</em> (Joomla 3.0).
</p> </p>
<p> <p>
This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4, This template is a customized fork of the <strong>Cassiopeia</strong> template introduced in Joomla 4,
@@ -43,41 +60,40 @@ TPL_MOKO-CASSIOPEIA_XML_DESCRIPTION="<h3>MOKO-CASSIOPEIA Template Description</h
enhancements and structural refinements specifically tailored for use by Moko Consulting. enhancements and structural refinements specifically tailored for use by Moko Consulting.
</p> </p>
<p> <p>
<strong>MOKO-CASSIOPEIA</strong> is designed to serve as a versatile, production-ready base for <strong>Version 2.0</strong> introduces significant new functionality including a Dark Mode toggle,
contemporary Joomla websites, emphasizing speed, clarity, and open-source philosophy. Google Tag Manager (GTM) and Google Analytics 4 (GA4) hooks, and expanded template configuration
options — all while keeping overrides minimal and upgrade-friendly.
</p> </p>
<h4>Features</h4> <h4>Features</h4>
<ul> <ul>
<li>Fully responsive and mobile-first layout</li> <li>Fully responsive and mobile-first layout</li>
<li>Based on Joomla 4+ template architecture</li> <li>Based on Joomla 4+ template architecture</li>
<li>Enhanced SCSS and CSS overrides for custom styling</li> <li>Enhanced SCSS and CSS overrides for streamlined custom styling</li>
<li>Built-in support for Bootstrap 5</li> <li>Built-in support for <strong>Bootstrap 5</strong></li>
<li> <li>Font Awesome 6 integration for modern iconography</li>
Integrated dynamic Table of Contents via <li>Automatic Table of Contents (TOC) — selectable per article via <code>toc-left</code> or <code>toc-right</code> layouts</li>
<a href="https://afeld.github.io/bootstrap-toc/" target="_blank" rel="noopener">Bootstrap TOC</a> <li><strong>Dark Mode toggle (new in v2.0)</strong> with user switch and admin override</li>
</li> <li><strong>Optional GTM + GA4 hooks (new in v2.0)</strong> for analytics and marketing integration</li>
<li>Optimized template structure for performance and maintainability</li> <li>Optimized template structure for performance and maintainability</li>
<li>Custom module positions and layout presets</li> <li>Custom module positions and layout presets</li>
<li>Accessible, lightweight, and extensible</li> <li>Accessible, lightweight, and extensible for long-term use</li>
<li>Ideal for professional services, portfolios, and informational websites</li> <li>Ideal for professional services, portfolios, and informational websites</li>
</ul> </ul>
<h4>Code Attribution</h4> <h4>Code Attribution</h4>
<p> <p>
This template is based on the original <strong>Cassiopeia</strong> template developed by the This template is based on the original <strong>Cassiopeia</strong> template developed by the
<a href="https://www.joomla.org" target="_blank" rel="noopener">Joomla! Project</a> and released under the GNU General Public License. <a href=\"https://www.joomla.org\" target=\"_blank\" rel=\"noopener\">Joomla! Project</a> and released under the GNU General Public License.
</p> </p>
<p> <p>
Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards. Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.
</p>a </p>
<p> <p>
It includes integration with It includes integration with
<a href="https://afeld.github.io/bootstrap-toc/" target="_blank" rel="noopener">Bootstrap TOC</a>, <a href=\"https://afeld.github.io/bootstrap-toc/\" target=\"_blank\" rel=\"noopener\">Bootstrap TOC</a>,
an open-source table of contents generator by A. Feld, licensed under the MIT License. an open-source table of contents generator by A. Feld, licensed under the MIT License.
</p> </p>
<p> <p>
All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable. All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.
</p>" </p>"
JGLOBAL_OFFLINE="Offline"

View File

@@ -1,3 +1,33 @@
@charset "UTF-8";
/* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/editor.css
* VERSION: 02.00
* BRIEF: Stylesheet for Joomla editor content within Moko-Cassiopeia template
* =========================================================================
*/
/* STYLES FOR JOOMLA! EDITOR */ /* STYLES FOR JOOMLA! EDITOR */
body { body {
font-size: 1rem; font-size: 1rem;

View File

@@ -1,3 +1,33 @@
@charset "UTF-8";
/* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/gable.css
* VERSION: 02.00
* BRIEF: Stylesheet providing gable-specific layout and design rules for Moko-Cassiopeia
* =========================================================================
*/
:root { :root {
--gab-blue: transparent; --gab-blue: transparent;
--gab-green: #7ac143; --gab-green: #7ac143;

View File

@@ -1,551 +0,0 @@
/*!
* @package Joomla.Site
* @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/global/light/colors_alternative.css
*
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*
* Website: https://mokoconsulting.tech
* Email: hello@mokoconsulting.tech
* Phone: +1 (931) 279-6313
*/
/* -----------------------------------------------
* LIGHT THEME
* --------------------------------------------- */
:root[data-bs-theme="light"] {
color-scheme: light;
--color-primary: #112855;
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #3f8ff0;
--mainmenu-nav-link-color: white;
--color-link: #224FAA;
--color-hover: var(--accent-color-primary);
--header-background-image: url('../../../../../../../media/templates/site/moko-cassiopeia/images/bg.svg');
--header-background-attachment: fixed;
--header-background-repeat: repeat;
--header-background-size: auto;
--container-below-topbar-bg-image: ;
--container-below-topbar-bg-color ;
--container-below-topbar-bg-position: auto;
--container-below-topbar-bg-attachment: fixed;
--container-below-topbar-bg-repeat: repeat;
--container-below-topbar-bg-size: auto;
--container-below-topbar-border: ;
--container-below-topbar-border-radius: ;
--container-top-a-bg-image: ;
--container-top-a-bg-color: ;
--container-top-a-bg-position: auto;
--container-top-a-bg-attachment: fixed;
--container-top-a-bg-repeat: repeat;
--container-top-a-bg-size: auto;
--container-top-a-border: ;
--container-top-a-border-radius: ;
--container-top-b-bg-image: ;
--container-top-b-bg-color: ;
--container-top-b-bg-position: auto;
--container-top-b-bg-attachment: fixed;
--container-top-b-bg-repeat: repeat;
--container-top-b-bg-size: auto;
--container-top-b-border: ;
--container-top-b-border-radius: ;
--container-toc-bg: var(--mainmenu-nav-link-color);
--container-toc-color: var(--color-primary);
--container-sidebar-bg-image: ;
--container-sidebar-bg-color: ;
--container-sidebar-bg-position: auto;
--container-sidebar-bg-attachment: scroll;
--container-sidebar-bg-repeat: repeat;
--container-sidebar-bg-size: auto;
--container-sidebar-border: ;
--container-sidebar-border-radius: ;
--container-bottom-a-bg-image: ;
--container-bottom-a-bg-color: ;
--container-bottom-a-bg-position: auto;
--container-bottom-a-bg-attachment: fixed;
--container-bottom-a-bg-repeat: repeat;
--container-bottom-a-bg-size: auto;
--container-bottom-a-border: ;
--container-bottom-a-border-radius: ;
--container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: ;
--container-bottom-b-bg-position: auto;
--container-bottom-b-bg-attachment: fixed;
--container-bottom-b-bg-repeat: repeat;
--container-bottom-b-bg-size: auto;
--container-bottom-b-border: ;
--container-bottom-b-border-radius: ;
--nav-text-color: var(--mainmenu-nav-link-color);
--nav-bg-color: var(--color-link);
--border: 5px;
--muted-color: #6d757e;
--hr-color: var(--border-color, #dfe3e7);
--link-active-color: var(--link-color);
--code-color-ink: var(--code-color, #e93f8e);
--border-color-soft: var(--border-color, #dfe3e7);
--kbd-bg: var(--secondary-bg, #eaedf0);
--kbd-ink: var(--body-bg, #fff);
--toc-bg: var(--secondary-bg, #eaedf0);
--toc-ink: var(--color-primary, #112855);
--selection-bg: var(--highlight-bg, #fbeea8);
--selection-ink: var(--body-color, #22262a);
--blue: #010156;
--black: #000;
--indigo: #6812f3;
--purple: #6f42c2;
--pink: #e93f8e;
--red: #a51f18;
--orange: #fd7e17;
--yellow: #ad6200;
--green: #448344;
--teal: #5abfdd;
--cyan: #30638d;
--white: #fff;
--gray-100: #f9fafb;
--gray-200: #eaedf0;
--gray-300: #dfe3e7;
--gray-400: #ced4da;
--gray-500: #adb5bd;
--gray-600: #6d757e;
--gray-700: #484f56;
--gray-800: #353b41;
--gray-900: #22262a;
--primary: #010156;
--secondary: #6d757e;
--success: #448344;
--info: #30638d;
--warning: #ad6200;
--danger: #a51f18;
--light: #f9fafb;
--dark: #353b41;
--primary-rgb: 1, 1, 86;
--secondary-rgb: 109, 117, 126;
--success-rgb: 68, 131, 68;
--info-rgb: 48, 99, 141;
--warning-rgb: 173, 98, 0;
--danger-rgb: 165, 31, 24;
--light-rgb: 249, 250, 251;
--dark-rgb: 53, 59, 65;
--primary-text-emphasis: #002;
--secondary-text-emphasis: #2c2f32;
--success-text-emphasis: #1b351b;
--info-text-emphasis: #132838;
--warning-text-emphasis: #452700;
--danger-text-emphasis: #420c09;
--light-text-emphasis: #484f56;
--dark-text-emphasis: #484f56;
--primary-bg-subtle: #ccd;
--secondary-bg-subtle: #e2e3e5;
--success-bg-subtle: #dae6da;
--info-bg-subtle: #d6e0e8;
--warning-bg-subtle: #efe0cc;
--danger-bg-subtle: #edd2d1;
--light-bg-subtle: #fcfcfd;
--dark-bg-subtle: #ced4da;
--primary-border-subtle: #99b;
--secondary-border-subtle: #c5c8cb;
--success-border-subtle: #b4ceb4;
--info-border-subtle: #acc1d1;
--warning-border-subtle: #dec099;
--danger-border-subtle: #dba5a2;
--light-border-subtle: #eaedf0;
--dark-border-subtle: #adb5bd;
--white-rgb: 255, 255, 255;
--black-rgb: 0, 0, 0;
--font-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--gradient: linear-gradient(180deg, #ffffff26, #fff0);
--body-font-family: var(--optain-cassiopeia-font-family-body, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
--body-font-size: 1rem;
--body-font-weight: 400;
--body-line-height: 1.5;
--body-color: #22262a;
--body-color-rgb: 34, 38, 42;
--body-bg: #fff;
--body-bg-rgb: 255, 255, 255;
--emphasis-color: #000;
--emphasis-color-rgb: 0, 0, 0;
--secondary-color: #22262abf;
--secondary-color-rgb: 34, 38, 42;
--secondary-bg: #eaedf0;
--secondary-bg-rgb: 234, 237, 240;
--tertiary-color: #22262a80;
--tertiary-color-rgb: 34, 38, 42;
--tertiary-bg: #f9fafb;
--tertiary-bg-rgb: 249, 250, 251;
--heading-color: inherit;
--link-color: #224faa;
--link-color-rgb: 34, 79, 170;
--link-decoration: underline;
--link-hover-color: #424077;
--link-hover-color-rgb: 66, 64, 119;
--code-color: #e93f8e;
--highlight-color: #22262a;
--highlight-bg: #fbeea8;
--border-width: 1px;
--border-style: solid;
--border-color: #dfe3e7;
--border-color-translucent: #0000002d;
--border-radius: .25rem;
--border-radius-sm: .2rem;
--border-radius-lg: .3rem;
--border-radius-xl: .3rem;
--border-radius-xxl: 2rem;
--border-radius-2xl: var(--border-radius-xxl)*2;
--border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000026;
--box-shadow-sm: 0 .125rem .25rem #00000013;
--box-shadow-lg: 0 1rem 3rem #0000002d;
--box-shadow-inset: inset 0 1px 2px #00000013;
--focus-ring-width: .25rem;
--focus-ring-opacity: .25;
--focus-ring-color: #01015640;
--form-valid-color: #448344;
--form-valid-border-color: #448344;
--form-invalid-color: #a51f18;
--form-invalid-border-color: #a51f18;
}
.btn {
--btn-padding-x: 1rem;
--btn-padding-y: 0.6rem;
--btn-font-family: ;
--btn-font-size: 1rem;
--btn-font-weight: 400;
--btn-line-height: 1.5;
--btn-color: hsl(210, 11%, 15%);
--btn-bg: transparent;
--btn-border-width: 1px;
--btn-border-color: transparent;
--btn-border-radius: 0.25rem;
--btn-active-border-color: transparent;
--btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
--btn-disabled-opacity: 0.65;
--btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--btn-focus-shadow-rgb), .5);
display: inline-block;
padding: var(--btn-padding-y) var(--btn-padding-x);
font-family: var(--btn-font-family);
font-size: var(--btn-font-size);
font-weight: var(--btn-font-weight);
line-height: var(--btn-line-height);
color: var(--btn-color);
text-align: center;
text-decoration: none;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: var(--btn-border-width) solid var(--btn-border-color);
border-radius: var(--btn-border-radius);
background-color: var(--btn-bg);
-webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
-o-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
}
.btn-primary {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(240, 98%, 17%);
--btn-border-color: hsl(240, 98%, 17%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #010149;
--btn-hover-border-color: #010145;
--btn-focus-shadow-rgb: 39, 39, 111;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #010145;
--btn-active-border-color: #010141;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(240, 98%, 17%);
--btn-disabled-border-color: hsl(240, 98%, 17%);
}
.btn-secondary {
--btn-color: --nav-text-color;
--btn-bg: --nav-bg-color;
--btn-border-color: hsl(210, 7%, 46%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #5d636b;
--btn-hover-border-color: #575e65;
--btn-focus-shadow-rgb: gray;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #575e65;
--btn-active-border-color: #52585f;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(210, 7%, 46%);
--btn-disabled-border-color: hsl(210, 7%, 46%);
}
.btn-success {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(120, 32%, 39%);
--btn-border-color: hsl(120, 32%, 39%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #3a6f3a;
--btn-hover-border-color: #366936;
--btn-focus-shadow-rgb: 96, 150, 96;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #366936;
--btn-active-border-color: #336233;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(120, 32%, 39%);
--btn-disabled-border-color: hsl(120, 32%, 39%);
}
.btn-info {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(207, 49%, 37%);
--btn-border-color: hsl(207, 49%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #295478;
--btn-hover-border-color: #264f71;
--btn-focus-shadow-rgb: 79, 122, 158;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #264f71;
--btn-active-border-color: #244a6a;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(207, 49%, 37%);
--btn-disabled-border-color: hsl(207, 49%, 37%);
}
.btn-warning {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(34, 100%, 34%);
--btn-border-color: hsl(34, 100%, 34%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #935300;
--btn-hover-border-color: #8a4e00;
--btn-focus-shadow-rgb: 185, 122, 38;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #8a4e00;
--btn-active-border-color: #824a00;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(34, 100%, 34%);
--btn-disabled-border-color: hsl(34, 100%, 34%);
}
.btn-danger {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(3, 75%, 37%);
--btn-border-color: hsl(3, 75%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #8c1a14;
--btn-hover-border-color: #841913;
--btn-focus-shadow-rgb: 179, 65, 59;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #841913;
--btn-active-border-color: #7c1712;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(3, 75%, 37%);
--btn-disabled-border-color: hsl(3, 75%, 37%);
}
.btn-light {
--btn-color: hsl(0, 0%, 0%);
--btn-bg: hsl(210, 17%, 98%);
--btn-border-color: hsl(210, 17%, 98%);
--btn-hover-color: hsl(0, 0%, 0%);
--btn-hover-bg: #d4d5d5;
--btn-hover-border-color: #c7c8c9;
--btn-focus-shadow-rgb: 212, 213, 213;
--btn-active-color: hsl(0, 0%, 0%);
--btn-active-bg: #c7c8c9;
--btn-active-border-color: #bbbcbc;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 0%);
--btn-disabled-bg: hsl(210, 17%, 98%);
--btn-disabled-border-color: hsl(210, 17%, 98%);
}
.btn-dark {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(210, 10%, 23%);
--btn-border-color: hsl(210, 10%, 23%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #53585e;
--btn-hover-border-color: #494f54;
--btn-focus-shadow-rgb: 83, 88, 94;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #5d6267;
--btn-active-border-color: #494f54;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(210, 10%, 23%);
--btn-disabled-border-color: hsl(210, 10%, 23%);
}
.btn-outline-primary {
--btn-color: hsl(240, 98%, 17%);
--btn-border-color: hsl(240, 98%, 17%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(240, 98%, 17%);
--btn-hover-border-color: hsl(240, 98%, 17%);
--btn-focus-shadow-rgb: 1, 1, 86;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(240, 98%, 17%);
--btn-active-border-color: hsl(240, 98%, 17%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(240, 98%, 17%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(240, 98%, 17%);
--gradient: none;
}
.btn-outline-secondary {
--btn-color: hsl(210, 7%, 46%);
--btn-border-color: hsl(210, 7%, 46%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(210, 7%, 46%);
--btn-hover-border-color: hsl(210, 7%, 46%);
--btn-focus-shadow-rgb: 109, 117, 126;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(210, 7%, 46%);
--btn-active-border-color: hsl(210, 7%, 46%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(210, 7%, 46%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(210, 7%, 46%);
--gradient: none;
}
.btn-outline-success {
--btn-color: hsl(120, 32%, 39%);
--btn-border-color: hsl(120, 32%, 39%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(120, 32%, 39%);
--btn-hover-border-color: hsl(120, 32%, 39%);
--btn-focus-shadow-rgb: 68, 131, 68;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(120, 32%, 39%);
--btn-active-border-color: hsl(120, 32%, 39%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(120, 32%, 39%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(120, 32%, 39%);
--gradient: none;
}
.btn-outline-info {
--btn-color: hsl(207, 49%, 37%);
--btn-border-color: hsl(207, 49%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(207, 49%, 37%);
--btn-hover-border-color: hsl(207, 49%, 37%);
--btn-focus-shadow-rgb: 48, 99, 141;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(207, 49%, 37%);
--btn-active-border-color: hsl(207, 49%, 37%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(207, 49%, 37%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(207, 49%, 37%);
--gradient: none;
}
.btn-outline-warning {
--btn-color: hsl(34, 100%, 34%);
--btn-border-color: hsl(34, 100%, 34%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(34, 100%, 34%);
--btn-hover-border-color: hsl(34, 100%, 34%);
--btn-focus-shadow-rgb: 173, 98, 0;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(34, 100%, 34%);
--btn-active-border-color: hsl(34, 100%, 34%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(34, 100%, 34%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(34, 100%, 34%);
--gradient: none;
}
.btn-outline-danger {
--btn-color: hsl(3, 75%, 37%);
--btn-border-color: hsl(3, 75%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(3, 75%, 37%);
--btn-hover-border-color: hsl(3, 75%, 37%);
--btn-focus-shadow-rgb: 165, 31, 24;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(3, 75%, 37%);
--btn-active-border-color: hsl(3, 75%, 37%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(3, 75%, 37%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(3, 75%, 37%);
--gradient: none;
}
.btn-outline-light {
--btn-color: hsl(210, 17%, 98%);
--btn-border-color: hsl(210, 17%, 98%);
--btn-hover-color: hsl(0, 0%, 0%);
--btn-hover-bg: hsl(210, 17%, 98%);
--btn-hover-border-color: hsl(210, 17%, 98%);
--btn-focus-shadow-rgb: 249, 250, 251;
--btn-active-color: hsl(0, 0%, 0%);
--btn-active-bg: hsl(210, 17%, 98%);
--btn-active-border-color: hsl(210, 17%, 98%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(210, 17%, 98%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(210, 17%, 98%);
--gradient: none;
}
.btn-outline-dark {
--btn-color: hsl(210, 10%, 23%);
--btn-border-color: hsl(210, 10%, 23%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(210, 10%, 23%);
--btn-hover-border-color: hsl(210, 10%, 23%);
--btn-focus-shadow-rgb: 53, 59, 65;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(210, 10%, 23%);
--btn-active-border-color: hsl(210, 10%, 23%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(210, 10%, 23%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(210, 10%, 23%);
--gradient: none;
}
.btn-link {
--btn-font-weight: 400;
--btn-color: var(--link-color);
--btn-bg: transparent;
--btn-border-color: transparent;
--btn-hover-color: var(--link-hover-color);
--btn-hover-border-color: transparent;
--btn-active-color: var(--link-hover-color);
--btn-active-border-color: transparent;
--btn-disabled-color: hsl(210, 7%, 46%);
--btn-disabled-border-color: transparent;
--btn-box-shadow: none;
--btn-focus-shadow-rgb: 39, 39, 111;
text-decoration: underline;
}

View File

@@ -1,551 +0,0 @@
/*!
* @package Joomla.Site
* @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/global/light/colors_standard.css
*
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*
* Website: https://mokoconsulting.tech
* Email: hello@mokoconsulting.tech
* Phone: +1 (931) 279-6313
*/
/* -----------------------------------------------
* LIGHT THEME
* --------------------------------------------- */
:root[data-bs-theme="light"] {
color-scheme: light;
--color-primary: #112855;
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #3f8ff0;
--mainmenu-nav-link-color: white;
--color-link: #224FAA;
--color-hover: var(--accent-color-primary);
--header-background-image: url('../../../../../../../media/templates/site/moko-cassiopeia/images/bg.svg');
--header-background-attachment: fixed;
--header-background-repeat: repeat;
--header-background-size: auto;
--container-below-topbar-bg-image: ;
--container-below-topbar-bg-color ;
--container-below-topbar-bg-position: auto;
--container-below-topbar-bg-attachment: fixed;
--container-below-topbar-bg-repeat: repeat;
--container-below-topbar-bg-size: auto;
--container-below-topbar-border: ;
--container-below-topbar-border-radius: ;
--container-top-a-bg-image: ;
--container-top-a-bg-color: ;
--container-top-a-bg-position: auto;
--container-top-a-bg-attachment: fixed;
--container-top-a-bg-repeat: repeat;
--container-top-a-bg-size: auto;
--container-top-a-border: ;
--container-top-a-border-radius: ;
--container-top-b-bg-image: ;
--container-top-b-bg-color: ;
--container-top-b-bg-position: auto;
--container-top-b-bg-attachment: fixed;
--container-top-b-bg-repeat: repeat;
--container-top-b-bg-size: auto;
--container-top-b-border: ;
--container-top-b-border-radius: ;
--container-toc-bg: var(--mainmenu-nav-link-color);
--container-toc-color: var(--color-primary);
--container-sidebar-bg-image: ;
--container-sidebar-bg-color: ;
--container-sidebar-bg-position: auto;
--container-sidebar-bg-attachment: scroll;
--container-sidebar-bg-repeat: repeat;
--container-sidebar-bg-size: auto;
--container-sidebar-border: ;
--container-sidebar-border-radius: ;
--container-bottom-a-bg-image: ;
--container-bottom-a-bg-color: ;
--container-bottom-a-bg-position: auto;
--container-bottom-a-bg-attachment: fixed;
--container-bottom-a-bg-repeat: repeat;
--container-bottom-a-bg-size: auto;
--container-bottom-a-border: ;
--container-bottom-a-border-radius: ;
--container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: ;
--container-bottom-b-bg-position: auto;
--container-bottom-b-bg-attachment: fixed;
--container-bottom-b-bg-repeat: repeat;
--container-bottom-b-bg-size: auto;
--container-bottom-b-border: ;
--container-bottom-b-border-radius: ;
--nav-text-color: var(--mainmenu-nav-link-color);
--nav-bg-color: var(--color-link);
--border: 5px;
--muted-color: #6d757e;
--hr-color: var(--border-color, #dfe3e7);
--link-active-color: var(--link-color);
--code-color-ink: var(--code-color, #e93f8e);
--border-color-soft: var(--border-color, #dfe3e7);
--kbd-bg: var(--secondary-bg, #eaedf0);
--kbd-ink: var(--body-bg, #fff);
--toc-bg: var(--secondary-bg, #eaedf0);
--toc-ink: var(--color-primary, #112855);
--selection-bg: var(--highlight-bg, #fbeea8);
--selection-ink: var(--body-color, #22262a);
--blue: #010156;
--black: #000;
--indigo: #6812f3;
--purple: #6f42c2;
--pink: #e93f8e;
--red: #a51f18;
--orange: #fd7e17;
--yellow: #ad6200;
--green: #448344;
--teal: #5abfdd;
--cyan: #30638d;
--white: #fff;
--gray-100: #f9fafb;
--gray-200: #eaedf0;
--gray-300: #dfe3e7;
--gray-400: #ced4da;
--gray-500: #adb5bd;
--gray-600: #6d757e;
--gray-700: #484f56;
--gray-800: #353b41;
--gray-900: #22262a;
--primary: #010156;
--secondary: #6d757e;
--success: #448344;
--info: #30638d;
--warning: #ad6200;
--danger: #a51f18;
--light: #f9fafb;
--dark: #353b41;
--primary-rgb: 1, 1, 86;
--secondary-rgb: 109, 117, 126;
--success-rgb: 68, 131, 68;
--info-rgb: 48, 99, 141;
--warning-rgb: 173, 98, 0;
--danger-rgb: 165, 31, 24;
--light-rgb: 249, 250, 251;
--dark-rgb: 53, 59, 65;
--primary-text-emphasis: #002;
--secondary-text-emphasis: #2c2f32;
--success-text-emphasis: #1b351b;
--info-text-emphasis: #132838;
--warning-text-emphasis: #452700;
--danger-text-emphasis: #420c09;
--light-text-emphasis: #484f56;
--dark-text-emphasis: #484f56;
--primary-bg-subtle: #ccd;
--secondary-bg-subtle: #e2e3e5;
--success-bg-subtle: #dae6da;
--info-bg-subtle: #d6e0e8;
--warning-bg-subtle: #efe0cc;
--danger-bg-subtle: #edd2d1;
--light-bg-subtle: #fcfcfd;
--dark-bg-subtle: #ced4da;
--primary-border-subtle: #99b;
--secondary-border-subtle: #c5c8cb;
--success-border-subtle: #b4ceb4;
--info-border-subtle: #acc1d1;
--warning-border-subtle: #dec099;
--danger-border-subtle: #dba5a2;
--light-border-subtle: #eaedf0;
--dark-border-subtle: #adb5bd;
--white-rgb: 255, 255, 255;
--black-rgb: 0, 0, 0;
--font-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--gradient: linear-gradient(180deg, #ffffff26, #fff0);
--body-font-family: var(--optain-cassiopeia-font-family-body, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
--body-font-size: 1rem;
--body-font-weight: 400;
--body-line-height: 1.5;
--body-color: #22262a;
--body-color-rgb: 34, 38, 42;
--body-bg: #fff;
--body-bg-rgb: 255, 255, 255;
--emphasis-color: #000;
--emphasis-color-rgb: 0, 0, 0;
--secondary-color: #22262abf;
--secondary-color-rgb: 34, 38, 42;
--secondary-bg: #eaedf0;
--secondary-bg-rgb: 234, 237, 240;
--tertiary-color: #22262a80;
--tertiary-color-rgb: 34, 38, 42;
--tertiary-bg: #f9fafb;
--tertiary-bg-rgb: 249, 250, 251;
--heading-color: inherit;
--link-color: #224faa;
--link-color-rgb: 34, 79, 170;
--link-decoration: underline;
--link-hover-color: #424077;
--link-hover-color-rgb: 66, 64, 119;
--code-color: #e93f8e;
--highlight-color: #22262a;
--highlight-bg: #fbeea8;
--border-width: 1px;
--border-style: solid;
--border-color: #dfe3e7;
--border-color-translucent: #0000002d;
--border-radius: .25rem;
--border-radius-sm: .2rem;
--border-radius-lg: .3rem;
--border-radius-xl: .3rem;
--border-radius-xxl: 2rem;
--border-radius-2xl: var(--border-radius-xxl)*2;
--border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000026;
--box-shadow-sm: 0 .125rem .25rem #00000013;
--box-shadow-lg: 0 1rem 3rem #0000002d;
--box-shadow-inset: inset 0 1px 2px #00000013;
--focus-ring-width: .25rem;
--focus-ring-opacity: .25;
--focus-ring-color: #01015640;
--form-valid-color: #448344;
--form-valid-border-color: #448344;
--form-invalid-color: #a51f18;
--form-invalid-border-color: #a51f18;
}
.btn {
--btn-padding-x: 1rem;
--btn-padding-y: 0.6rem;
--btn-font-family: ;
--btn-font-size: 1rem;
--btn-font-weight: 400;
--btn-line-height: 1.5;
--btn-color: hsl(210, 11%, 15%);
--btn-bg: transparent;
--btn-border-width: 1px;
--btn-border-color: transparent;
--btn-border-radius: 0.25rem;
--btn-active-border-color: transparent;
--btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
--btn-disabled-opacity: 0.65;
--btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--btn-focus-shadow-rgb), .5);
display: inline-block;
padding: var(--btn-padding-y) var(--btn-padding-x);
font-family: var(--btn-font-family);
font-size: var(--btn-font-size);
font-weight: var(--btn-font-weight);
line-height: var(--btn-line-height);
color: var(--btn-color);
text-align: center;
text-decoration: none;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: var(--btn-border-width) solid var(--btn-border-color);
border-radius: var(--btn-border-radius);
background-color: var(--btn-bg);
-webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
-o-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
}
.btn-primary {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(240, 98%, 17%);
--btn-border-color: hsl(240, 98%, 17%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #010149;
--btn-hover-border-color: #010145;
--btn-focus-shadow-rgb: 39, 39, 111;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #010145;
--btn-active-border-color: #010141;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(240, 98%, 17%);
--btn-disabled-border-color: hsl(240, 98%, 17%);
}
.btn-secondary {
--btn-color: --nav-text-color;
--btn-bg: --nav-bg-color;
--btn-border-color: hsl(210, 7%, 46%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #5d636b;
--btn-hover-border-color: #575e65;
--btn-focus-shadow-rgb: gray;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #575e65;
--btn-active-border-color: #52585f;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(210, 7%, 46%);
--btn-disabled-border-color: hsl(210, 7%, 46%);
}
.btn-success {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(120, 32%, 39%);
--btn-border-color: hsl(120, 32%, 39%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #3a6f3a;
--btn-hover-border-color: #366936;
--btn-focus-shadow-rgb: 96, 150, 96;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #366936;
--btn-active-border-color: #336233;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(120, 32%, 39%);
--btn-disabled-border-color: hsl(120, 32%, 39%);
}
.btn-info {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(207, 49%, 37%);
--btn-border-color: hsl(207, 49%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #295478;
--btn-hover-border-color: #264f71;
--btn-focus-shadow-rgb: 79, 122, 158;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #264f71;
--btn-active-border-color: #244a6a;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(207, 49%, 37%);
--btn-disabled-border-color: hsl(207, 49%, 37%);
}
.btn-warning {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(34, 100%, 34%);
--btn-border-color: hsl(34, 100%, 34%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #935300;
--btn-hover-border-color: #8a4e00;
--btn-focus-shadow-rgb: 185, 122, 38;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #8a4e00;
--btn-active-border-color: #824a00;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(34, 100%, 34%);
--btn-disabled-border-color: hsl(34, 100%, 34%);
}
.btn-danger {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(3, 75%, 37%);
--btn-border-color: hsl(3, 75%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #8c1a14;
--btn-hover-border-color: #841913;
--btn-focus-shadow-rgb: 179, 65, 59;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #841913;
--btn-active-border-color: #7c1712;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(3, 75%, 37%);
--btn-disabled-border-color: hsl(3, 75%, 37%);
}
.btn-light {
--btn-color: hsl(0, 0%, 0%);
--btn-bg: hsl(210, 17%, 98%);
--btn-border-color: hsl(210, 17%, 98%);
--btn-hover-color: hsl(0, 0%, 0%);
--btn-hover-bg: #d4d5d5;
--btn-hover-border-color: #c7c8c9;
--btn-focus-shadow-rgb: 212, 213, 213;
--btn-active-color: hsl(0, 0%, 0%);
--btn-active-bg: #c7c8c9;
--btn-active-border-color: #bbbcbc;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 0%);
--btn-disabled-bg: hsl(210, 17%, 98%);
--btn-disabled-border-color: hsl(210, 17%, 98%);
}
.btn-dark {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(210, 10%, 23%);
--btn-border-color: hsl(210, 10%, 23%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: #53585e;
--btn-hover-border-color: #494f54;
--btn-focus-shadow-rgb: 83, 88, 94;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #5d6267;
--btn-active-border-color: #494f54;
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(0, 0%, 100%);
--btn-disabled-bg: hsl(210, 10%, 23%);
--btn-disabled-border-color: hsl(210, 10%, 23%);
}
.btn-outline-primary {
--btn-color: hsl(240, 98%, 17%);
--btn-border-color: hsl(240, 98%, 17%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(240, 98%, 17%);
--btn-hover-border-color: hsl(240, 98%, 17%);
--btn-focus-shadow-rgb: 1, 1, 86;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(240, 98%, 17%);
--btn-active-border-color: hsl(240, 98%, 17%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(240, 98%, 17%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(240, 98%, 17%);
--gradient: none;
}
.btn-outline-secondary {
--btn-color: hsl(210, 7%, 46%);
--btn-border-color: hsl(210, 7%, 46%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(210, 7%, 46%);
--btn-hover-border-color: hsl(210, 7%, 46%);
--btn-focus-shadow-rgb: 109, 117, 126;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(210, 7%, 46%);
--btn-active-border-color: hsl(210, 7%, 46%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(210, 7%, 46%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(210, 7%, 46%);
--gradient: none;
}
.btn-outline-success {
--btn-color: hsl(120, 32%, 39%);
--btn-border-color: hsl(120, 32%, 39%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(120, 32%, 39%);
--btn-hover-border-color: hsl(120, 32%, 39%);
--btn-focus-shadow-rgb: 68, 131, 68;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(120, 32%, 39%);
--btn-active-border-color: hsl(120, 32%, 39%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(120, 32%, 39%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(120, 32%, 39%);
--gradient: none;
}
.btn-outline-info {
--btn-color: hsl(207, 49%, 37%);
--btn-border-color: hsl(207, 49%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(207, 49%, 37%);
--btn-hover-border-color: hsl(207, 49%, 37%);
--btn-focus-shadow-rgb: 48, 99, 141;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(207, 49%, 37%);
--btn-active-border-color: hsl(207, 49%, 37%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(207, 49%, 37%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(207, 49%, 37%);
--gradient: none;
}
.btn-outline-warning {
--btn-color: hsl(34, 100%, 34%);
--btn-border-color: hsl(34, 100%, 34%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(34, 100%, 34%);
--btn-hover-border-color: hsl(34, 100%, 34%);
--btn-focus-shadow-rgb: 173, 98, 0;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(34, 100%, 34%);
--btn-active-border-color: hsl(34, 100%, 34%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(34, 100%, 34%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(34, 100%, 34%);
--gradient: none;
}
.btn-outline-danger {
--btn-color: hsl(3, 75%, 37%);
--btn-border-color: hsl(3, 75%, 37%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(3, 75%, 37%);
--btn-hover-border-color: hsl(3, 75%, 37%);
--btn-focus-shadow-rgb: 165, 31, 24;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(3, 75%, 37%);
--btn-active-border-color: hsl(3, 75%, 37%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(3, 75%, 37%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(3, 75%, 37%);
--gradient: none;
}
.btn-outline-light {
--btn-color: hsl(210, 17%, 98%);
--btn-border-color: hsl(210, 17%, 98%);
--btn-hover-color: hsl(0, 0%, 0%);
--btn-hover-bg: hsl(210, 17%, 98%);
--btn-hover-border-color: hsl(210, 17%, 98%);
--btn-focus-shadow-rgb: 249, 250, 251;
--btn-active-color: hsl(0, 0%, 0%);
--btn-active-bg: hsl(210, 17%, 98%);
--btn-active-border-color: hsl(210, 17%, 98%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(210, 17%, 98%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(210, 17%, 98%);
--gradient: none;
}
.btn-outline-dark {
--btn-color: hsl(210, 10%, 23%);
--btn-border-color: hsl(210, 10%, 23%);
--btn-hover-color: hsl(0, 0%, 100%);
--btn-hover-bg: hsl(210, 10%, 23%);
--btn-hover-border-color: hsl(210, 10%, 23%);
--btn-focus-shadow-rgb: 53, 59, 65;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(210, 10%, 23%);
--btn-active-border-color: hsl(210, 10%, 23%);
--btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--btn-disabled-color: hsl(210, 10%, 23%);
--btn-disabled-bg: transparent;
--btn-disabled-border-color: hsl(210, 10%, 23%);
--gradient: none;
}
.btn-link {
--btn-font-weight: 400;
--btn-color: var(--link-color);
--btn-bg: transparent;
--btn-border-color: transparent;
--btn-hover-color: var(--link-hover-color);
--btn-hover-border-color: transparent;
--btn-active-color: var(--link-hover-color);
--btn-active-border-color: transparent;
--btn-disabled-color: hsl(210, 7%, 46%);
--btn-disabled-border-color: transparent;
--btn-box-shadow: none;
--btn-focus-shadow-rgb: 39, 39, 111;
text-decoration: underline;
}

View File

@@ -1,118 +0,0 @@
<!--
* Copyright (C) 2025 Moko Consulting <jmiller@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<!--FILE INFORMATION
* DEFGROUP: Joomla.Site
* INGROUP: Templates.Moko-Cassiopeia
* FILE: index.html
* BRIEF: Security redirect page to block folder access and forward to site root.
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
/**
* @defgroup Dolibarr
* @file index.html (embedded script)
* @version 1.0.0
* @brief Security redirect logic. Replaces the current history entry with the site root.
* @details This script computes the absolute root URL using `location.origin` and
* forwards the user immediately. It prevents leaving the protected folder
* in the browser history by default.
*
* @section VARIABLES
* @var {Object} opts Configuration options for the redirect behavior.
* @var {string} opts.fallbackPath Path used when `location.origin` cannot be determined.
* @var {number} opts.delayMs Optional delay in milliseconds before redirecting.
* @var {"replace"|"assign"} opts.behavior Navigation method used for the redirect.
*
* @section OPTIONS
* - opts.fallbackPath: default "/" (root path)
* - opts.delayMs: default 0 (immediate)
* - opts.behavior: one of
* * "replace" — calls `location.replace(url)`; does not keep the folder page in history.
* * "assign" — calls `location.assign(url)`; keeps an extra history entry.
*/
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -1,14 +1,31 @@
/*! @charset "UTF-8";
* @package Joomla.Site /* =========================================================================
* @subpackage Templates.moko-cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @file /media/templates/sote/moko-cassiopeia/css/global/dark/colors_alternative.css
* *
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/global/dark/colors_alternative.css
* VERSION: 02.00
* BRIEF: Alternative dark mode color definitions for Moko-Cassiopeia template
* =========================================================================
*/ */
/* ----------------------------------------------- /* -----------------------------------------------

View File

@@ -1,14 +1,31 @@
/*! @charset "UTF-8";
* @package Joomla.Site /* =========================================================================
* @subpackage Templates.moko-cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @file /media/templates/sote/moko-cassiopeia/css/global/dark/colors_standard.css
* *
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/global/dark/colors_standard.css
* VERSION: 02.00
* BRIEF: Standard dark mode color definitions for Moko-Cassiopeia template
* =========================================================================
*/ */
/* ----------------------------------------------- /* -----------------------------------------------

View File

@@ -1,3 +1,33 @@
@charset "UTF-8";
/* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/global/fonts-local_roboto.css
* VERSION: 02.00
* BRIEF: Local Roboto font-face definitions for the Moko-Cassiopeia template
* =========================================================================
*/
@font-face { @font-face {
font-family: "Roboto"; font-family: "Roboto";
src: url("../../../../../vendor/roboto-fontface/fonts/roboto/Roboto-Regular.woff2") format("woff2"), url("../../../../../vendor/roboto-fontface/fonts/roboto/Roboto-Regular.woff") format("woff"); src: url("../../../../../vendor/roboto-fontface/fonts/roboto/Roboto-Regular.woff2") format("woff2"), url("../../../../../vendor/roboto-fontface/fonts/roboto/Roboto-Regular.woff") format("woff");

View File

@@ -1,14 +1,31 @@
/*! @charset "UTF-8";
* @package Joomla.Site /* =========================================================================
* @subpackage Templates.moko-cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @file /media/templates/sote/moko-cassiopeia/css/global/light/colors_alternative.css
* *
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/global/light/colors_alternative.css
* VERSION: 02.00
* BRIEF: Alternative light mode color definitions for Moko-Cassiopeia template
* =========================================================================
*/ */
/* ----------------------------------------------- /* -----------------------------------------------

View File

@@ -1,14 +1,31 @@
/*! @charset "UTF-8";
* @package Joomla.Site /* =========================================================================
* @subpackage Templates.moko-cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @file /media/templates/sote/moko-cassiopeia/css/global/light/colors_standard.css
* *
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/global/light/colors_standard.css
* VERSION: 02.00
* BRIEF: Standard light mode color definitions for Moko-Cassiopeia template
* =========================================================================
*/ */
/* ----------------------------------------------- /* -----------------------------------------------

View File

@@ -1,16 +1,33 @@
/*! @charset "UTF-8";
* @package Joomla.Site /* =========================================================================
* @subpackage Templates.moko-cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @file /media/templates/sote/moko-cassiopeia/css/global/csocial-media-demos.css
* *
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/global/social-media-demo.css
* VERSION: 02.00
* BRIEF: Demo styles for showcasing social media elements in Moko-Cassiopeia template
* =========================================================================
*/ */
*
/* /*
====================================================================== ======================================================================
Social Media Demo — FULL CSS (Joomla-safe, fully scoped) Social Media Demo — FULL CSS (Joomla-safe, fully scoped)

View File

@@ -1,3 +1,33 @@
@charset "UTF-8";
/* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/system/searchtools/searchtools.css
* VERSION: 02.00
* BRIEF: Stylesheet for Joomla search tools integration in Moko-Cassiopeia template
* =========================================================================
*/
.js-stools-container-bar { .js-stools-container-bar {
padding: 10px 20px; padding: 10px 20px;
} }

View File

@@ -1,15 +1,31 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /* =========================================================================
* @package Joomla.Site * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/template-rtl.css
* *
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/template-rtl.css
* VERSION: 02.00
* BRIEF: Right-to-left (RTL) layout stylesheet for Moko-Cassiopeia template
* =========================================================================
*/ */
/*! /*!
@@ -20,7 +36,6 @@
* sensitive rules are mirrored here to keep file size reasonable. * sensitive rules are mirrored here to keep file size reasonable.
*/ */
[dir="rtl"] .table-of-contents-ck-wrap { [dir="rtl"] .table-of-contents-ck-wrap {
width: 30%; width: 30%;

View File

@@ -1,15 +1,31 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /* =========================================================================
* @package Joomla.Site * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/template.css
* *
* @copyright 2025 Moko Consulting <https://mokoconsulting.tech> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/template.css
* VERSION: 02.00
* BRIEF: Main stylesheet providing layout, typography, and component styles for Moko-Cassiopeia
* =========================================================================
*/ */
*, *,
@@ -17206,5 +17222,41 @@ body.site.error-page {
text-decoration: none; text-decoration: none;
} }
#mokoThemeFab .knob {
position: absolute;
top: 2px;
left: 2px;
width: 20px;
height: 20px;
border-radius: var(--border-radius-xxl);
background: var(--bs-body-bg, #fff);
box-shadow: var(--box-shadow);
transition: transform .2s ease;
}
#mokoThemeFab [role="switch"][aria-checked="true"] .knob {
transform: translateX(20px);
}
#mokoThemeFab [role="switch"][aria-checked="true"] .switch {
background: rgba(var(--secondary-color), .15);
}
button#mokoThemeSwitch {
border: unset;
background-color: unset;
}
#mokoThemeFab .label {
user-select: none;
font-size: .875rem;
}
#mokoThemeFab.debug-outline {
outline: 2px dashed var(--pink);
outline-offset: 2px;
}
/* SOCIAL MEDIA DEMOS */ /* SOCIAL MEDIA DEMOS */
@import url("global/social-media-demos.css"); @import url("global/social-media-demos.css");

View File

@@ -1,4 +1,33 @@
@charset "UTF-8"; @charset "UTF-8";
/* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/vendor/choicesjs/choices.css
* VERSION: 02.00
* BRIEF: Vendor stylesheet for Choices.js select and input enhancements in Moko-Cassiopeia
* =========================================================================
*/
/* =============================== /* ===============================
= Choices = = Choices =
=============================== */ =============================== */

View File

@@ -1,3 +1,33 @@
@charset "UTF-8";
/* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/vendor/choicesjs/choices.css
* VERSION: 02.00
* BRIEF: Vendor stylesheet for Choices.js select and input enhancements in Moko-Cassiopeia
* =========================================================================
*/
@import "../../../../../../vendor/joomla-custom-elements/css/joomla-alert.css"; @import "../../../../../../vendor/joomla-custom-elements/css/joomla-alert.css";
#system-message-container:empty { #system-message-container:empty {
display: none; display: none;

View File

@@ -1,3 +1,33 @@
@charset "UTF-8";
/* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/css/vendor/vmbasic.css
* VERSION: 02.00
* BRIEF: Vendor stylesheet providing base styles for VM Basic in Moko-Cassiopeia
* =========================================================================
*/
/* Bootstrap */ /* Bootstrap */
.dropdown-menu { .dropdown-menu {
border-radius: 0; border-radius: 0;

View File

@@ -1,9 +1,32 @@
/** /* =========================================================================
* darkmode-toggle.js — Floating theme switch (class-based, CSP-proof) * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @version 2.2.1 *
* Storage key: "theme" -> "light" | "dark" * This file is part of a Moko Consulting project.
* Corner from <body data-theme-fab-pos="br|bl|tr|tl"> (default br) *
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/js/darkmode-toggle.js
* VERSION: 02.00
* BRIEF: JavaScript logic for dark mode toggle functionality in Moko-Cassiopeia
* =========================================================================
*/ */
(function () { (function () {
'use strict'; 'use strict';

View File

@@ -0,0 +1,347 @@
/*
=========================================================================
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/ .
=========================================================================
FILE INFORMATION
DEFGROUP: Joomla Template
FILE: media/templates/site/moko-cassiopeia/js/gtm.js
HEADER VERSION: 1.0
VERSION: 2.0
BRIEF: Safe, configurable Google Tag Manager loader for Moko-Cassiopeia.
PATH: media/templates/site/moko-cassiopeia/js/gtm.js
NOTE: Place the <noscript> fallback iframe in your HTML template (index.php). A JS file
cannot provide a true no-JS fallback by definition.
VARIABLES:
- window.MOKO_GTM_ID (string) // Optional global GTM container ID (e.g., "GTM-XXXXXXX")
- window.MOKO_GTM_OPTIONS (object) // Optional global options (see JSDoc below)
- data- attributes on the script tag or <html>/<body>:
data-gtm-id, data-data-layer, data-debug, data-ignore-dnt,
data-env-auth, data-env-preview, data-block-on-dev
=========================================================================
*/
/* global window, document, navigator */
(() => {
"use strict";
/**
* @typedef {Object} MokoGtmOptions
* @property {string} [id] GTM container ID (e.g., "GTM-XXXXXXX")
* @property {string} [dataLayerName] Custom dataLayer name (default: "dataLayer")
* @property {boolean} [debug] Log debug messages to console (default: false)
* @property {boolean} [ignoreDNT] Ignore Do Not Track and always load (default: false)
* @property {boolean} [blockOnDev] Block loading on localhost/*.test/127.0.0.1 (default: true)
* @property {string} [envAuth] GTM Environment auth string (optional)
* @property {string} [envPreview] GTM Environment preview name (optional)
* @property {Record<string,'granted'|'denied'>} [consentDefault]
* Default Consent Mode v2 map. Keys like:
* analytics_storage, ad_storage, ad_user_data, ad_personalization, functionality_storage, security_storage
* (default: {analytics_storage:'granted', functionality_storage:'granted', security_storage:'granted'})
* @property {() => (Record<string, any>|void)} [pageVars]
* Function returning extra page variables to push on init (optional)
*/
const PKG = "moko-gtm";
const PREFIX = `[${PKG}]`;
const WIN = window;
// Public API placeholder (attached to window at the end)
/** @type {{
* init: (opts?: Partial<MokoGtmOptions>) => void,
* setConsent: (updates: Record<string,'granted'|'denied'>) => void,
* push: (...args:any[]) => void,
* isLoaded: () => boolean,
* config: () => Required<MokoGtmOptions>
* }} */
const API = {};
// ---- Utilities ---------------------------------------------------------
const isDevHost = () => {
const h = WIN.location && WIN.location.hostname || "";
return (
h === "localhost" ||
h === "127.0.0.1" ||
h.endsWith(".local") ||
h.endsWith(".test")
);
};
const dntEnabled = () => {
// Different browsers expose DNT differently; treat "1" or "yes" as enabled.
const n = navigator;
const v = (n.doNotTrack || n.msDoNotTrack || (n.navigator && n.navigator.doNotTrack) || "").toString().toLowerCase();
return v === "1" || v === "yes";
};
const getCurrentScript = () => {
// document.currentScript is best; fallback to last <script> whose src ends with /gtm.js
const cs = document.currentScript;
if (cs) return cs;
const scripts = Array.from(document.getElementsByTagName("script"));
return scripts.reverse().find(s => (s.getAttribute("src") || "").includes("/gtm.js")) || null;
};
const getAttr = (el, name) => el ? el.getAttribute(name) : null;
const readDatasetCascade = (name) => {
// Check <script>, <html>, <body>, then <meta name="moko:gtm-<name>">
const script = getCurrentScript();
const html = document.documentElement;
const body = document.body;
const meta = document.querySelector(`meta[name="moko:gtm-${name}"]`);
return (
(script && script.dataset && script.dataset[name]) ||
(html && html.dataset && html.dataset[name]) ||
(body && body.dataset && body.dataset[name]) ||
(meta && meta.getAttribute("content")) ||
null
);
};
const parseBool = (v, fallback = false) => {
if (v == null) return fallback;
const s = String(v).trim().toLowerCase();
if (["1","true","yes","y","on"].includes(s)) return true;
if (["0","false","no","n","off"].includes(s)) return false;
return fallback;
};
const debugLog = (...args) => {
if (STATE.debug) {
try { console.info(PREFIX, ...args); } catch (_) {}
}
};
// ---- Configuration & State --------------------------------------------
/** @type {Required<MokoGtmOptions>} */
const STATE = {
id: "",
dataLayerName: "dataLayer",
debug: false,
ignoreDNT: false,
blockOnDev: true,
envAuth: "",
envPreview: "",
consentDefault: {
analytics_storage: "granted",
functionality_storage: "granted",
security_storage: "granted",
// The following default to "denied" unless the site explicitly opts-in:
ad_storage: "denied",
ad_user_data: "denied",
ad_personalization: "denied",
},
pageVars: () => ({})
};
const mergeOptions = (base, extra = {}) => {
const out = {...base};
for (const k in extra) {
if (!Object.prototype.hasOwnProperty.call(extra, k)) continue;
const v = extra[k];
if (v && typeof v === "object" && !Array.isArray(v)) {
out[k] = {...(out[k] || {}), ...v};
} else if (v !== undefined) {
out[k] = v;
}
}
return out;
};
const detectOptions = () => {
// 1) Global window options
/** @type {Partial<MokoGtmOptions>} */
const globalOpts = (WIN.MOKO_GTM_OPTIONS && typeof WIN.MOKO_GTM_OPTIONS === "object") ? WIN.MOKO_GTM_OPTIONS : {};
// 2) Dataset / meta
const idFromData = readDatasetCascade("id") || WIN.MOKO_GTM_ID || "";
const dlFromData = readDatasetCascade("dataLayer") || "";
const dbgFromData = readDatasetCascade("debug");
const dntFromData = readDatasetCascade("ignoreDnt");
const devFromData = readDatasetCascade("blockOnDev");
const authFromData = readDatasetCascade("envAuth") || "";
const prevFromData = readDatasetCascade("envPreview") || "";
// 3) Combine
/** @type {Partial<MokoGtmOptions>} */
const detected = {
id: idFromData || globalOpts.id || "",
dataLayerName: dlFromData || globalOpts.dataLayerName || undefined,
debug: parseBool(dbgFromData, !!globalOpts.debug),
ignoreDNT: parseBool(dntFromData, !!globalOpts.ignoreDNT),
blockOnDev: parseBool(devFromData, (globalOpts.blockOnDev ?? true)),
envAuth: authFromData || globalOpts.envAuth || "",
envPreview: prevFromData || globalOpts.envPreview || "",
consentDefault: globalOpts.consentDefault || undefined,
pageVars: typeof globalOpts.pageVars === "function" ? globalOpts.pageVars : undefined
};
return detected;
};
// ---- dataLayer / gtag helpers -----------------------------------------
const ensureDataLayer = () => {
const l = STATE.dataLayerName;
WIN[l] = WIN[l] || [];
return WIN[l];
};
/** gtag wrapper backed by dataLayer. */
const gtag = (...args) => {
const dl = ensureDataLayer();
dl.push(arguments.length > 1 ? args : args[0]);
debugLog("gtag push:", args);
};
API.push = (...args) => gtag(...args);
API.setConsent = (updates) => {
gtag("consent", "update", updates || {});
};
API.isLoaded = () => {
const hasScript = !!document.querySelector('script[src*="googletagmanager.com/gtm.js"]');
return hasScript;
};
API.config = () => ({...STATE});
// ---- Loader ------------------------------------------------------------
const buildEnvQuery = () => {
const qp = [];
if (STATE.envAuth) qp.push(`gtm_auth=${encodeURIComponent(STATE.envAuth)}`);
if (STATE.envPreview) qp.push(`gtm_preview=${encodeURIComponent(STATE.envPreview)}`, "gtm_cookies_win=x");
return qp.length ? `&${qp.join("&")}` : "";
};
const injectScript = () => {
if (!STATE.id) {
debugLog("GTM ID missing; aborting load.");
return;
}
if (API.isLoaded()) {
debugLog("GTM already loaded; skipping duplicate injection.");
return;
}
// Standard GTM bootstrap timing event
const dl = ensureDataLayer();
dl.push({ "gtm.start": new Date().getTime(), event: "gtm.js" });
const f = document.getElementsByTagName("script")[0];
const j = document.createElement("script");
j.async = true;
j.src = `https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(STATE.id)}${STATE.dataLayerName !== "dataLayer" ? `&l=${encodeURIComponent(STATE.dataLayerName)}` : ""}${buildEnvQuery()}`;
if (f && f.parentNode) {
f.parentNode.insertBefore(j, f);
} else {
(document.head || document.documentElement).appendChild(j);
}
debugLog("Injected GTM script:", j.src);
};
const applyDefaultConsent = () => {
// Consent Mode v2 default
gtag("consent", "default", STATE.consentDefault);
debugLog("Applied default consent:", STATE.consentDefault);
};
const pushInitialVars = () => {
// Minimal page vars; allow site to add more via pageVars()
const vars = {
event: "moko.page_init",
page_title: document.title || "",
page_language: (document.documentElement && document.documentElement.lang) || "",
...(typeof STATE.pageVars === "function" ? (STATE.pageVars() || {}) : {})
};
gtag(vars);
};
const shouldLoad = () => {
if (!STATE.ignoreDNT && dntEnabled()) {
debugLog("DNT is enabled; blocking GTM load (set ignoreDNT=true to override).");
return false;
}
if (STATE.blockOnDev && isDevHost()) {
debugLog("Development host detected; blocking GTM load (set blockOnDev=false to override).");
return false;
}
return true;
};
// ---- Public init -------------------------------------------------------
API.init = (opts = {}) => {
// Merge: defaults <- detected <- passed opts
const detected = detectOptions();
const merged = mergeOptions(STATE, mergeOptions(detected, opts));
// Commit back to STATE
Object.assign(STATE, merged);
debugLog("Config:", STATE);
// Prepare dataLayer/gtag and consent
ensureDataLayer();
applyDefaultConsent();
pushInitialVars();
// Load GTM if allowed
if (shouldLoad()) {
injectScript();
} else {
debugLog("GTM load prevented by configuration or environment.");
}
};
// ---- Auto-init on DOMContentLoaded (safe even if deferred) -------------
const autoInit = () => {
// Only auto-init if we have some ID from globals/datasets.
const detected = detectOptions();
const hasId = !!(detected.id || WIN.MOKO_GTM_ID);
if (hasId) {
API.init(); // use detected/global defaults
} else {
debugLog("No GTM ID detected; awaiting manual init via window.mokoGTM.init({ id: 'GTM-XXXXXXX' }).");
}
};
if (document.readyState === "complete" || document.readyState === "interactive") {
// Defer to ensure <body> exists for any late consumers.
setTimeout(autoInit, 0);
} else {
document.addEventListener("DOMContentLoaded", autoInit, { once: true });
}
// Expose API
WIN.mokoGTM = API;
// Helpful console hint (only if debug true after detection)
try {
const detected = detectOptions();
if (parseBool(detected.debug, false)) {
STATE.debug = true;
debugLog("Ready. You can call window.mokoGTM.init({ id: 'GTM-XXXXXXX' }).");
}
} catch (_) {}
})();

View File

@@ -1,11 +0,0 @@
/**
* @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia
* @file /media/templates/site/moko-cassiopeia/js/mod_gabble.js
* @copyright (C) 2025 Jonathan Miler || Moko Consulting <https://mokoconsulting.tech>
* @website: https://mokoconsulting.tech
* @email: hello@mokoconsulting.tech
* @phone: +1 (931) 279-6313
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @note This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/

View File

@@ -1,118 +0,0 @@
<!--
* Copyright (C) 2025 Moko Consulting <jmiller@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<!--FILE INFORMATION
* DEFGROUP: Joomla.Site
* INGROUP: Templates.Moko-Cassiopeia
* FILE: index.html
* BRIEF: Security redirect page to block folder access and forward to site root.
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Redirecting…</title>
<!-- Search engines: do not index this placeholder redirect page -->
<meta name="robots" content="noindex, nofollow, noarchive" />
<!-- Instant redirect fallback even if JavaScript is disabled -->
<meta http-equiv="refresh" content="0; url=/" />
<!-- Canonical root reference -->
<link rel="canonical" href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
/**
* @defgroup Dolibarr
* @file index.html (embedded script)
* @version 1.0.0
* @brief Security redirect logic. Replaces the current history entry with the site root.
* @details This script computes the absolute root URL using `location.origin` and
* forwards the user immediately. It prevents leaving the protected folder
* in the browser history by default.
*
* @section VARIABLES
* @var {Object} opts Configuration options for the redirect behavior.
* @var {string} opts.fallbackPath Path used when `location.origin` cannot be determined.
* @var {number} opts.delayMs Optional delay in milliseconds before redirecting.
* @var {"replace"|"assign"} opts.behavior Navigation method used for the redirect.
*
* @section OPTIONS
* - opts.fallbackPath: default "/" (root path)
* - opts.delayMs: default 0 (immediate)
* - opts.behavior: one of
* * "replace" — calls `location.replace(url)`; does not keep the folder page in history.
* * "assign" — calls `location.assign(url)`; keeps an extra history entry.
*/
(function redirectToRoot() {
// Configuration object with safe defaults.
var opts = {
fallbackPath: "/", // string: fallback destination if origin is unavailable
delayMs: 0, // number: delay before redirect in ms (0 = immediate)
behavior: "replace" // enum: "replace" | "assign"
};
// Determine absolute origin in all mainstream browsers.
var origin = (typeof location.origin === "string" && location.origin)
|| (location.protocol + "//" + location.host);
// Final destination: absolute root of the current site, or fallback path.
var destination = origin ? origin + "/" : opts.fallbackPath;
function go() {
if (opts.behavior === "assign") {
location.assign(destination);
} else {
location.replace(destination);
}
}
// Execute redirect, optionally after a short delay.
if (opts.delayMs > 0) {
setTimeout(go, opts.delayMs);
} else {
go();
}
})();
</script>
<!--
Secondary meta-refresh for no-JS environments is already set above.
Some very old crawlers may ignore JS; the meta refresh ensures coverage.
-->
<noscript>
<!-- Extra defense-in-depth: if JS is disabled, meta refresh (above) handles redirect. -->
<style>
html, body { height:100%; }
body { display:flex; align-items:center; justify-content:center; margin:0; font: 16px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.msg { opacity: .75; text-align: center; }
</style>
</noscript>
</head>
<body>
<div class="msg">Redirecting to the site root… If you are not redirected, <a href="/">click here</a>.</div>
</body>
</html>

View File

@@ -1,13 +1,30 @@
/** /* =========================================================================
* @package Joomla.Site * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @subpackage Templates.Moko-Cassiopeia *
* @file /media/templates/site/moko-cassiopeia/js/mod_menu/menu-metismenu-es5.js * This file is part of a Moko Consulting project.
* @copyright (C) 2025 Jonathan Miler || Moko Consulting <https://mokoconsulting.tech> *
* @website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* @email: hello@mokoconsulting.tech *
* @phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* @license GNU General Public License version 2 or later; see LICENSE.txt * it under the terms of the GNU General Public License as published by
* @note This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/js/mod_menu/menu-metismenu-es5.js
* VERSION: 02.00
* BRIEF: ES5-compatible MetisMenu script for Joomla mod_menu in Moko-Cassiopeia
* =========================================================================
*/ */
(function () { (function () {

View File

@@ -1,13 +1,30 @@
/** /* =========================================================================
* @package Joomla.Site * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @subpackage Templates.Moko-Cassiopeia *
* @file /media/templates/site/moko-cassiopeia/js/mod_menu/menu-metismenu.js * This file is part of a Moko Consulting project.
* @copyright (C) 2025 Jonathan Miler || Moko Consulting <https://mokoconsulting.tech> *
* @website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* @email: hello@mokoconsulting.tech *
* @phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* @license GNU General Public License version 2 or later; see LICENSE.txt * it under the terms of the GNU General Public License as published by
* @note This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/js/mod_menu/menu-metismenu.js
* VERSION: 02.00
* BRIEF: Modern MetisMenu script for Joomla mod_menu in Moko-Cassiopeia
* =========================================================================
*/ */
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {

View File

@@ -1,25 +1,14 @@
/** /* =========================================================================
* template.js — Custom JavaScript for the Moko Cassiopeia Joomla template * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia
* @file /media/templates/site/moko-cassiopeia/js/template.js
* @version 2.0
*
* @copyright (C) 2025 Moko Consulting
* @author Jonathan Miller
* @website https://mokoconsulting.tech
* @email hello@mokoconsulting.tech
* @phone +1 (931) 279-6313
*
* SPDX-License-Identifier: GPL-3.0-or-later
* *
* This file is part of a Moko Consulting project. * This file is part of a Moko Consulting project.
* *
* This program is free software: you can redistribute it and/or modify it * SPDX-License-Identifier: GPL-3.0-or-later
* under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or (at * This program is free software; you can redistribute it and/or modify
* your option) any later version. * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,7 +16,15 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/js/template.js
* VERSION: 02.00
* BRIEF: Core JavaScript utilities and behaviors for Moko-Cassiopeia template
* =========================================================================
*/ */
(function (win, doc) { (function (win, doc) {

View File

@@ -1,25 +1,14 @@
/** /* =========================================================================
* theme-init.js — Light/Dark mode initialization for Moko Cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia
* @file /media/templates/site/moko-cassiopeia/js/theme-init.js
* @version 2.0
*
* @copyright (C) 2025 Moko Consulting
* @author Jonathan Miller
* @website https://mokoconsulting.tech
* @email hello@mokoconsulting.tech
* @phone +1 (931) 279-6313
*
* SPDX-License-Identifier: GPL-3.0-or-later
* *
* This file is part of a Moko Consulting project. * This file is part of a Moko Consulting project.
* *
* This program is free software: you can redistribute it and/or modify it * SPDX-License-Identifier: GPL-3.0-or-later
* under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or (at * This program is free software; you can redistribute it and/or modify
* your option) any later version. * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,7 +16,15 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/js/theme-init.js
* VERSION: 02.00
* BRIEF: Initialization script for Moko-Cassiopeia theme features and behaviors
* =========================================================================
*/ */
(function (win, doc) { (function (win, doc) {

View File

@@ -1,25 +1,14 @@
/** /* =========================================================================
* user.js — User Custom JS File for Moko Cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia
* @file /media/templates/site/moko-cassiopeia/js/user.js
* @version 2.0
*
* @copyright (C) 2025 Moko Consulting
* @author Jonathan Miller
* @website https://mokoconsulting.tech
* @email hello@mokoconsulting.tech
* @phone +1 (931) 279-6313
*
* SPDX-License-Identifier: GPL-3.0-or-later
* *
* This file is part of a Moko Consulting project. * This file is part of a Moko Consulting project.
* *
* This program is free software: you can redistribute it and/or modify it * SPDX-License-Identifier: GPL-3.0-or-later
* under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or (at * This program is free software; you can redistribute it and/or modify
* your option) any later version. * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,5 +16,13 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: media/templates/site/moko-cassiopeia/js/user.js
* VERSION: 02.00
* BRIEF: JavaScript for handling user-specific interactions in Moko-Cassiopeia template
* =========================================================================
*/ */

Binary file not shown.

444
readme.md
View File

@@ -1,254 +1,304 @@
# Moko-Cassiopeia <!--
=========================================================================
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
A modern, lightweight enhancement layer for Joomlas Cassiopeia template. Moko-Cassiopeia adds **Font Awesome 6**, **Bootstrap 5** helpers, an automatic **Table of Contents (TOC)** utility, and optional **Moko Expansions** including **Google Tag Manager** and **Google Analytics (GA4)** hooks—all while keeping core template overrides minimal and upgradefriendly. This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/ .
=========================================================================
FILE INFORMATION
DEFGROUP: Joomla
INGROUP: Moko-Cassiopeia
PATH: README.md
VERSION: 02.00
BRIEF: Project readme for Moko-Cassiopeia, including features, setup, and usage
=========================================================================
-->
# Moko-Cassiopeia v02.00 — README
> Joomla! site template by **Moko Consulting**
> License: **GPL-3.0-or-later**
> Compatibility: **Joomla 4.4+ / 5.x** (PHP 8.1+)
--- ---
## Table of Contents ## Overview
- [Features](#features) Moko-Cassiopeia is a streamlined, Bootstrap-friendly Joomla template with a tokenized color system, Google Tag Manager / Analytics hooks, and performance-minded assets.
- [Requirements](#requirements)
- [Quick Start](#quick-start) * **v02.00 (2025-08-30)** introduces **Dark Mode** with OS auto-detection **and** an optional **Dark Mode Toggle** (ID **25**) so users can manually switch themes; their preference persists.
- [Installation](#installation) * **v01.00** was the initial public release (FA6, BS5, TOC, GTM/GA hooks).
- [Configuration](#configuration)
- [Global Params](#global-params) Public roadmap: **[https://mokoconsulting.tech/support/joomla-cms/moko-cassiopeia-roadmap](https://mokoconsulting.tech/support/joomla-cms/moko-cassiopeia-roadmap)**
- [Font Awesome 6](#font-awesome-6)
- [Bootstrap 5 Helpers](#bootstrap-5-helpers) ---
- [TOC Function](#toc-function)
- [Moko Expansions](#moko-expansions) ## Whats New in v02.00
- [Google Tag Manager](#google-tag-manager)
- [Google Analytics (GA4)](#google-analytics-ga4) * **Dark Mode** with `prefers-color-scheme` auto-detect.
- [CSS Variables](#css-variables) * **Dark Mode Toggle** (Template param **ID 25**) with positions **Header / Navbar / Footer**.
- [Usage Examples](#usage-examples)
- [Best Practices](#best-practices) * Persists choice to `localStorage` (key: `moko.theme`).
- [Development](#development) * Keyboard- and screen-reader-friendly; focus ring uses theme tokens.
- [Changelog](#changelog) * Admin option **“Show Theme Toggle”** (`On/Off`).
- [License](#license) * CSS refactor to **variables**: light tokens in `:root`, dark overrides in `[data-theme="dark"]`.
* Lowered CSS specificity, `rem` units for scalable typography/spacing.
* Stabilized WebAsset registrations (LTR/RTL presets).
--- ---
## Features ## Features
- **Font Awesome 6**: Solid, Regular, Brands (locally enqueued or CDN with Subresource Integrity). * **Dark Mode + Toggle**
- **Bootstrap 5**: Utility classes, grid, and components available to your layouts and modules. Auto-detect plus manual switch; persistent per user.
- **Auto TOC**: Generate an inpage Table of Contents from headings with a single data attribute.
- **Moko Expansions**: * **Bootstrap-friendly CSS**
- **GTM**: Dropin dataLayer and container injection with a template param. Low specificity, variable-driven utilities for buttons, alerts, typography, spacing.
- **GA4**: Native GA4 Measurement ID support (with or without GTM).
- **Productionsafe**: Assets loaded conditionally; no duplicate library loads if another extension already enqueues them. * **GTM / GA Hooks**
- **Accessible by default**: TOC anchors and focus styles follow a11y guidelines. Clean injection points for Google Tag Manager and optional direct GA4 tag.
* **LTR / RTL Presets**
Stable asset registration pattern for palette and template styles.
* **A11y & Performance**
Clear focus styling and balanced contrast; minified bundles in production.
---
## Requirements ## Requirements
- Joomla 4.4+ or Joomla 5+ * Joomla **4.4+** / **5.x**
- PHP 8.1+ * PHP **8.1+**
- Cassiopeia as the active base template (Moko-Cassiopeia may be installed as a child/override set) * Modern evergreen browsers (graceful fallback if `prefers-color-scheme` isnt available)
## Quick Start ---
1. Install the template package via Joomla Extension Manager.
2. In the Template Style settings, enable the features you want (FA6, BS5, TOC, GTM/GA).
3. (Optional) Add a TOC container to any article or module using the data attribute shown below.
## Installation ## Installation
1. Go to 'System''Install' → 'Extensions'. 1. **Install** via *Extensions → Manage → Install* (upload the template `.zip`).
2. Upload 'Moko-Cassiopeia.zip'. 2. **Set as default** in *System → Templates → Site Templates*.
3. After installation, go to 'System''Site Templates' → 'Styles' and open 'Moko-Cassiopeia'. 3. **Clear caches**: *System → Clear Cache* and hard-reload your browser.
4. Choose 'Default' to make it your active style (or assign per menu item).
## Configuration ---
Configuration lives in the Template Style parameters. Common params are listed below. Names may vary slightly depending on release. ## Template Options (high-level)
### Global Params **Theme**
- 'load\_bootstrap5' (bool): Enqueue Bootstrap 5 core CSS/JS if not provided by Joomla context. * **Force Theme**: `Auto` (default) | `Light` | `Dark`
- 'load\_fontawesome6' (bool): Enqueue Font Awesome 6 (solid, regular, brands). * **Show Theme Toggle** (ID **25**): `On` | `Off`
- 'use\_cdn' (bool): Use CDN with SRI instead of local assets. * **Toggle Position**: `Header` | `Navbar` | `Footer`
- 'minified' (bool): Prefer '.min' assets. * **Default Theme** (when not using Auto): `Light`
- 'defer\_js' (bool): Add 'defer' to templateinjected scripts where safe.
### Font Awesome 6 **GTM / Analytics**
When enabled, the template registers FA6 and exposes the standard icon syntax: * **GTM Container ID** (e.g., `GTM-XXXXXXX`)
* **Analytics Tag ID** (optional GA4 if not using GTM)
```html **Performance**
<i class='fa-solid fa-circle-check' aria-hidden='true'></i>
<span class='visually-hidden'>Success</span>
```
**Notes** * **Development Mode**
- Icons are decorative unless paired with text or 'aria-label'. * `Off``.min.css` / `.min.js` bundles
- Prefer the 'fa-solid', 'fa-regular', or 'fa-brands' families explicitly. * `On` → unminified sources for debugging
### Bootstrap 5 Helpers ---
If 'load\_bootstrap5' is enabled, grid and utilities are available: ## Dark Mode — Tokens & Toggle
```html **Color tokens**
<div class='container'>
<div class='row g-3'>
<div class='col-12 col-md-6'>Left</div>
<div class='col-12 col-md-6'>Right</div>
</div>
</div>
```
You can also use helpers like 'ratio', 'visually-hidden', 'd-flex', and spacing utilities (e.g., 'mt-3', 'px-4').
### TOC Function
Moko-Cassiopeia ships a tiny script that scans within a container for headings (h2h6) and builds a nested TOC with anchor links.
**Enable**: Turn on 'auto\_toc' in Template Style.
**Place a TOC container**:
```html
<nav class='toc' data-moko-toc='true' data-moko-toc-target='#article-body' aria-label='Table of contents'></nav>
```
**Mark your content region**:
```html
<article id='article-body'>
<h2>Section A</h2>
<p>...</p>
<h3>Subsection A.1</h3>
<p>...</p>
</article>
```
**Options via data attributes**
- 'data-moko-toc-target': CSS selector for the content area (default: 'main').
- 'data-moko-toc-levels': CSV or range string like '2-4' (default: '2-4').
- 'data-moko-toc-collapsible': 'true'|'false' to make nested lists collapsible.
**Styling**
A minimal stylesheet is included. Customize using the CSS variables below or add your own overrides.
### Moko Expansions
#### Google Tag Manager
Enable GTM by entering your container ID (e.g., 'GTM-XXXXXXX') in Template Style under 'Moko Expansions'. The template will inject the standard script and 'noscript' iframe per Google guidance.
**Data Layer**
You can push events from modules or overrides like so:
```html
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'moko_event',
'moko_category': 'ui',
'moko_action': 'toc_opened',
'moko_label': 'sidebar'
});
</script>
```
#### Google Analytics (GA4)
Two options:
1. **Direct GA4**: Provide 'G-' Measurement ID (e.g., 'G-ABC123XYZ'). The template injects the GA4 base script.
2. **Via GTM**: Leave GA4 field empty and configure GA4 inside your GTM container.
```html
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ 'event': 'page_view' });
</script>
```
> Tip: When both GTM and direct GA4 are set, the template prefers GTM to avoid duplicate pageviews.
## CSS Variables
Moko-Cassiopeia exposes custom properties for theme tuning. Example set:
```css ```css
:root { :root {
--moko-cassiopeia-color-primary: #0b4008; --color-bg: #ffffff;
--moko-cassiopeia-color-link: #0b4008; --color-surface: #f8f9fa;
--moko-cassiopeia-color-hover: #000000; --color-text: #1d2125;
--color-text-muted: #6c757d;
--color-border: #dee2e6;
--moko-cassiopeia-header-background-image: linear-gradient(30deg, #fefcf9, var(--accent-color-primary)); --color-primary: #0d6efd;
--moko-cassiopeia-header-background-position: auto; --color-primary-contrast: #ffffff;
--moko-cassiopeia-header-background-attachment: fixed;
--moko-cassiopeia-header-background-repeat: repeat; --color-link: var(--color-primary);
--moko-cassiopeia-header-background-size: auto; --color-link-hover: #0b5ed7;
--focus-ring: 0 0 0 .2rem rgba(13,110,253,.25);
}
[data-theme="dark"] {
--color-bg: #0e1116;
--color-surface: #151922;
--color-text: #e7eaf0;
--color-text-muted: #a4acb9;
--color-border: #2a3240;
--color-primary: #66b2ff;
--color-primary-contrast: #0d1117;
--color-link: var(--color-primary);
--color-link-hover: #99ccff;
--focus-ring: 0 0 0 .2rem rgba(102,178,255,.35);
} }
``` ```
> Apply these in a custom stylesheet or template options if provided. Use semantic variables where possible to maintain consistency. **Programmatic switch (optional)**
## Usage Examples ```js
// Apply and persist a choice
### 1) FA6 Icon Buttons document.documentElement.dataset.theme = 'dark'; // or 'light'
localStorage.setItem('moko.theme', 'dark'); // namespaced key
```html
<a class='btn btn-primary d-inline-flex align-items-center' href='#'>
<i class='fa-solid fa-bolt me-2' aria-hidden='true'></i>
<span>Action</span>
</a>
``` ```
### 2) Sticky Sidebar TOC ---
```html ## CSS Architecture
<aside class='position-sticky top-0 pt-3'>
<nav class='toc' data-moko-toc='true' data-moko-toc-target='#content'></nav> * **`template.css`** = structure/layout and component scaffolding
</aside> * **No hard-coded hex** in core selectors; all colors reference tokens
* **Units**: `rem` (replacing `em`) for scalable typography/spacing
* **Low specificity** to play nicely with Bootstrap and content plugins
---
## GTM / Analytics Integration
* Enter **GTM Container ID** in Template Options to inject the GTM snippet.
* Optionally add a **GA4 Measurement ID** if not routing GA via GTM.
* Output uses Joomla rendering events to avoid duplication.
> Verify tags with DevTools / Tag Assistant.
---
## RTL / LTR Assets (WebAsset JSON)
Minimal pattern:
```json
{
"$schema": "https://developer.joomla.org/schemas/json/schema_web_assets.json",
"name": "template.moko-cassiopeia",
"assets": [
{ "name": "template.moko-cassiopeia.styles", "type": "style", "uri": "templates/moko-cassiopeia/css/template.min.css" },
{ "name": "template.moko-cassiopeia.palette", "type": "style", "uri": "templates/moko-cassiopeia/css/colors_standard.min.css" },
{ "name": "template.moko-cassiopeia", "type": "preset", "dependencies": ["template.moko-cassiopeia.styles","template.moko-cassiopeia.palette"] }
]
}
``` ```
### 3) Moduledriven GA Event In `index.php`:
```php ```php
<?php /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
// In a custom module layout $wa = $this->getWebAssetManager();
$label = 'cta_hero'; $wa->usePreset('template.moko-cassiopeia');
?>
<button class='btn btn-outline-primary' onclick='window.dataLayer && window.dataLayer.push({"event": "cta_click", "label": "<?php echo $label; ?>"})'>
Click me
</button>
``` ```
> Note: We use single quotes in HTML where possible to keep consistency with PHP string style preferences. ---
## Best Practices ## Upgrade Notes
- **One source of truth** for analytics injection (prefer GTM, or direct GA4—not both). **1.0 → 2.0**
- **Defer noncritical JS** using the 'defer\_js' param when feasible.
- **Avoid duplicate libraries** if another extension already loads FA6/BS5.
- **Respect a11y**: Provide visible focus, 'visually-hidden' labels, and heading order for the TOC.
- **Cache smartly**: After enabling new features, clear Joomla cache and any CDN cache to propagate assets.
## Development * Clear Joomla + browser caches.
* Convert any hard-coded colors in overrides to **tokens** (e.g., `var(--color-text-muted)`).
* Review spacing/typography where `rem` replaces `em`.
* Verify asset names if you referenced WebAsset handles directly.
* If you previously added a custom dark-mode toggle, remove it and enable **Show Theme Toggle** (ID **25**).
- Source structure follows Joomla template conventions: ---
- '/css', '/js', '/images', '/html' (overrides), 'templateDetails.xml'
- Scripts are enqueued via the template's 'index.php' with conditional params.
- Build/compile steps (if using bundlers) are noted in 'package.json' (when applicable).
**Local overrides** ## Accessibility
- Place sitespecific CSS in '/css/custom.css'. * Improved contrast targets across light/dark.
- Use '/html' for component/module layout overrides as needed. * Visible, consistent focus indicators.
* Toggle is keyboard-navigable and labeled for assistive tech.
## Changelog ---
- 1.15: Added CSS theme seletor (dark/light) ## Troubleshooting
- 1.00: Initial public release with FA6, BS5, TOC, GTM/GA hooks.
## License * **Toggle not visible** → Ensure “Show Theme Toggle” is on and placed in a visible position.
* **Preference not persisting** → Check `localStorage` availability and console for JS errors.
* **Asset dependency warnings** → Confirm preset/asset names match your `joomla.asset.json`.
Distributed under the GNU General Public License v3. See 'LICENSE' for details. ---
## Feature Rundown & Comparison
### Moko-Cassiopeia v01.00 — Initial public release
* **Font Awesome 6** integrated; **Bootstrap 5** helpers.
* **TOC utility** hooks for article table of contents.
* **GTM/GA hooks** with safe injection points.
* Minimal, upgrade-friendly overrides; variable-ready CSS.
### Moko-Cassiopeia v02.00 — Dark Mode + Toggle (ID 25)
* **Dark Mode** with OS auto-detect.
* **Optional Dark Mode Toggle** (ID 25) in Header / Navbar / Footer; persisted per user.
* **Tokenized palette** (`:root` + `[data-theme="dark"]`).
* **CSS refactor**: low specificity; `rem` units; Bootstrap-friendly utilities.
* Stabilized **Web Asset** registrations (LTR/RTL presets).
### Baseline: Cassiopeia (Joomla 4.4 / 5.x)
* Responsive, accessible core site template with Bootstrap-friendly markup.
* Template options for color preset, layout width, sticky header, and module menu layouts.
* Web Asset Manager integration (`joomla.asset.json`, `$this->getWebAssetManager()`).
---
## Roadmap
Public roadmap: **[https://mokoconsulting.tech/support/joomla-cms/moko-cassiopeia-roadmap](https://mokoconsulting.tech/support/joomla-cms/moko-cassiopeia-roadmap)**
---
## Changelog (1.0 → 2.0)
### 02.00 — 2025-08-30 — “Dark Mode”
**Added**
* Dark Mode with OS auto-detection (`prefers-color-scheme`).
* **Dark Mode Toggle** (param **ID 25**) with positions Header / Navbar / Footer; persists choice via `localStorage` (`moko.theme`); accessible markup and focus styling.
* Tokenized CSS palette with `[data-theme="dark"]` overrides.
* Admin override to force Light/Dark/Auto.
* Bootstrap-friendly utility hooks mapped to tokens.
**Changed**
* `template.css` now structure/layout only; colors via tokens.
* `em``rem`; reduced specificity; standardized focus indicators.
**Fixed**
* WebAsset registrations (LTR/RTL/preset deps) and dark-theme link/muted contrast.
**Removed / Deprecated**
* Hard-coded color declarations and legacy hex-based helper classes.
---
### 01.00 — Initial public release
* **FA6**, **BS5**, **TOC**, **GTM/GA** hooks.

View File

@@ -1,11 +1,31 @@
<?php <?php
/* =========================================================================
/** * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia
* *
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt *
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: templates/moko-cassiopeia/component.php
* VERSION: 02.00
* BRIEF: Minimal component-only template file for Moko-Cassiopeia
* =========================================================================
*/ */
defined('_JEXEC') or die; defined('_JEXEC') or die;

View File

@@ -1,23 +1,33 @@
<?php <?php
/** /* =========================================================================
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* *
* @package Joomla.Site * This file is part of a Moko Consulting project.
* @subpackage Templates.Moko-Cassiopeia
* @file /templates/moko-cassiopeia/custom.php
* @version 02.00
* @copyright © 2025 Moko Consulting
* @author Jonathan Miller
* @website https://mokoconsulting.tech
* @email hello@mokoconsulting.tech
* @phone +1 (931) 279-6313
* *
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
* *
* This file is part of a Moko Consulting project released under the * This program is free software; you can redistribute it and/or modify
* GNU General Public License v3 or (at your option) any later version. * it under the terms of the GNU General Public License as published by
* It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * the Free Software Foundation; either version 3 of the License, or
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: templates/moko-cassiopeia/custom.php
* VERSION: 02.00
* BRIEF: Custom entry template file for Moko-Cassiopeia with user-defined overrides
* =========================================================================
*/ */
function console_log($output, $with_script_tags = true) { function console_log($output, $with_script_tags = true) {
$js_code = 'console.log(' . json_encode($output, JSON_HEX_TAG) . $js_code = 'console.log(' . json_encode($output, JSON_HEX_TAG) .
');'; ');';
@@ -27,4 +37,6 @@
echo $js_code; echo $js_code;
} }
?> ?>
<!--
Custom code included here Custom code included here
-->

View File

@@ -1,21 +1,31 @@
<?php <?php
/** /* =========================================================================
* error.php — Error page template for Moko Cassiopeia * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* *
* @package Joomla.Site * This file is part of a Moko Consulting project.
* @subpackage Templates.Moko-Cassiopeia *
* @file /templates/moko-cassiopeia/error.php * SPDX-License-Identifier: GPL-3.0-or-later
* @version 2.1 *
* @copyright (C) 2025 Moko Consulting * This program is free software; you can redistribute it and/or modify
* @author Jonathan Miller * it under the terms of the GNU General Public License as published by
* @website https://mokoconsulting.tech * the Free Software Foundation; either version 3 of the License, or
* @email hello@mokoconsulting.tech * (at your option) any later version.
* @phone +1 (931) 279-6313 *
* @license GNU General Public License version 3 or later; see LICENSE.txt * This program is distributed in the hope that it will be useful,
* @disclaimer This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: templates/moko-cassiopeia/error.php
* VERSION: 02.00
* BRIEF: Error page template file for Moko-Cassiopeia
* =========================================================================
*/ */
defined('_JEXEC') or die; defined('_JEXEC') or die;

View File

@@ -1,16 +1,31 @@
<?php <?php
/* =========================================================================
/** * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @package Joomla.Site
* @subpackage Templates.moko-cassiopeia
* @file \templates\moko-cassiopeia\html\com_content\article\toc-left.php
* *
* © 2025 Moko Consulting — All Rights Reserved * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: templates/moko-cassiopeia/html/com_content/article/toc-left.php
* VERSION: 02.00
* BRIEF: Template override for Joomla articles with Table of Contents aligned left
* =========================================================================
*/ */
defined('_JEXEC') or die; defined('_JEXEC') or die;

View File

@@ -1,16 +1,31 @@
<?php <?php
/* =========================================================================
/** * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @package Joomla.Site
* @subpackage Templates.moko-cassiopeia
* @file \templates\moko-cassiopeia\html\com_content\article\toc-right.php
* *
* © 2025 Moko Consulting — All Rights Reserved * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * SPDX-License-Identifier: GPL-3.0-or-later
* Email: hello@mokoconsulting.tech *
* Phone: +1 (931) 279-6313 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: templates/moko-cassiopeia/html/com_content/article/toc-right.php
* VERSION: 02.00
* BRIEF: Template override for Joomla articles with Table of Contents aligned right
* =========================================================================
*/ */
defined('_JEXEC') or die; defined('_JEXEC') or die;

View File

@@ -1,13 +1,34 @@
<?php <?php
/* =========================================================================
/** * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia
* *
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * This file is part of a Moko Consulting project.
* @license GNU General Public License version 2 or later; see LICENSE.txt *
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: templates/moko-cassiopeia/index.php
* VERSION: 02.00
* BRIEF: Main template index file for Moko-Cassiopeia rendering site layout
* =========================================================================
*/ */
defined('_JEXEC') or die; defined('_JEXEC') or die;
use Joomla\CMS\Factory; use Joomla\CMS\Factory;
@@ -20,23 +41,19 @@ use Joomla\CMS\Uri\Uri;
$app = Factory::getApplication(); $app = Factory::getApplication();
$input = $app->getInput(); $input = $app->getInput();
$wa = $this->getWebAssetManager(); $wa = $this->getWebAssetManager();
$params_ColorName = $this->params->get('colorName', 'colors_standard');
// Template params
$params_ColorName = (string) $this->params->get('colorName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom
$params_googletagmanager = $this->params->get('googletagmanager', false); $params_googletagmanager = $this->params->get('googletagmanager', false);
$params_googletagmanagerid = $this->params->get('googletagmanagerid', null); $params_googletagmanagerid = $this->params->get('googletagmanagerid', null);
$params_googleanalytics = $this->params->get('googleanalytics', false); $params_googleanalytics = $this->params->get('googleanalytics', false);
$params_googleanalyticsid = $this->params->get('googleanalyticsid', null); $params_googleanalyticsid = $this->params->get('googleanalyticsid', null);
$params_custom_head_start = $this->params->get('custom_head_start', null); $params_custom_head_start = $this->params->get('custom_head_start', null);
$params_custom_head_end = $this->params->get('custom_head_end', null); $params_custom_head_end = $this->params->get('custom_head_end', null);
$params_leftIcon = htmlspecialchars( $params_leftIcon = htmlspecialchars($this->params->get('drawerLeftIcon', 'fa-solid fa-chevron-left'), ENT_COMPAT, 'UTF-8');
$this->params->get('drawerLeftIcon', 'fa-solid fa-chevron-left'), $params_rightIcon = htmlspecialchars($this->params->get('drawerRightIcon', 'fa-solid fa-chevron-right'), ENT_COMPAT, 'UTF-8');
ENT_COMPAT, 'UTF-8'
);
$params_rightIcon = htmlspecialchars(
$this->params->get('drawerRightIcon', 'fa-solid fa-chevron-right'),
ENT_COMPAT, 'UTF-8'
);
// Add Bootstrap 5 Support // Bootstrap behaviors (assets handled via WAM)
HTMLHelper::_('bootstrap.framework'); HTMLHelper::_('bootstrap.framework');
HTMLHelper::_('bootstrap.loadCss', true); HTMLHelper::_('bootstrap.loadCss', true);
HTMLHelper::_('bootstrap.alert'); HTMLHelper::_('bootstrap.alert');
@@ -58,18 +75,59 @@ $view = $input->getCmd('view', '');
$layout = $input->getCmd('layout', ''); $layout = $input->getCmd('layout', '');
$task = $input->getCmd('task', ''); $task = $input->getCmd('task', '');
$itemid = $input->getCmd('Itemid', ''); $itemid = $input->getCmd('Itemid', '');
$sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8'); $sitenameR = $app->get('sitename'); // raw for title composition
$sitename = htmlspecialchars($sitenameR, ENT_QUOTES, 'UTF-8');
$menu = $app->getMenu()->getActive(); $menu = $app->getMenu()->getActive();
$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : ''; $pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';
// Template path // Respect “Site Name in Page Titles” (0:none, 1:before, 2:after)
$mode = (int) $app->get('sitename_pagetitles', 0);
$pageTitle = trim($this->getTitle());
$final = $pageTitle !== ''
? ($mode === 1 ? $sitenameR . ' - ' . $pageTitle
: ($mode === 2 ? $pageTitle . ' - ' . $sitenameR : $pageTitle))
: $sitenameR;
$this->setTitle($final);
// Template/Media path
$templatePath = 'media/templates/site/moko-cassiopeia'; $templatePath = 'media/templates/site/moko-cassiopeia';
// Color Theme // ===========================
$assetColorName = 'theme.' . $params_ColorName; // Web Asset Manager (WAM) — matches your joomla.asset.json
$wa->registerAndUseStyle($assetColorName, $templatePath . '/css/global/' . $params_ColorName . '.css'); // ===========================
// Use a font scheme if set in the template style options // Core template CSS
$wa->useStyle('template.base'); // css/template.css
$wa->useStyle('template.user'); // css/user.css
// Optional vendor CSS
$wa->useStyle('vendor.vmbasic');
$wa->useStyle('vendor.gable');
$wa->useStyle('vendor.bootstrap-toc');
// Color theme (light + optional dark)
$colorKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_ColorName));
$lightKey = 'template.light.' . $colorKey;
$darkKey = 'template.dark.' . $colorKey;
try {
$wa->useStyle($lightKey);
} catch (\Throwable $e) {
$wa->registerAndUseStyle('template.light.dynamic', $templatePath . '/css/global/colors/light/' . $params_ColorName . '.css');
}
try {
$wa->useStyle($darkKey);
} catch (\Throwable $e) {
// optional; omit if not present
}
// Scripts
$wa->useScript('template.js');
$wa->useScript('theme-init.js');
$wa->useScript('darkmode-toggle.js');
$wa->useScript('vendor.bootstrap-toc.js');
// Font scheme (external or local) + CSS custom properties
$params_FontScheme = $this->params->get('useFontScheme', false); $params_FontScheme = $this->params->get('useFontScheme', false);
$fontStyles = ''; $fontStyles = '';
@@ -78,65 +136,78 @@ if ($params_FontScheme) {
$this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']); $this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']);
$this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']); $this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']);
$this->getPreloadManager()->preload($params_FontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']); $this->getPreloadManager()->preload($params_FontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']);
$wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, [], ['media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'', 'crossorigin' => 'anonymous']); $wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, [], [
'media' => 'print',
'rel' => 'lazy-stylesheet',
'onload' => 'this.media=\'all\'',
'crossorigin' => 'anonymous'
]);
if (preg_match_all('/family=([^?:]*):/i', $params_FontScheme, $matches) > 0) { if (preg_match_all('/family=([^?:]*):/i', $params_FontScheme, $matches) > 0) {
$fontStyles = '--font-family-body: "' . str_replace('+', ' ', $matches[1][0]) . '", sans-serif;\n'; $fontStyles = '--font-family-body: "' . str_replace('+', ' ', $matches[1][0]) . '", sans-serif;' . "\n";
$fontStyles .= '--font-family-headings: "' . str_replace('+', ' ', isset($matches[1][1]) ? $matches[1][1] : $matches[1][0]) . '", sans-serif;\n'; $fontStyles .= '--font-family-headings: "' . str_replace('+', ' ', isset($matches[1][1]) ? $matches[1][1] : $matches[1][0]) . '", sans-serif;' . "\n";
$fontStyles .= '--font-weight-normal: 400;\n'; $fontStyles .= '--font-weight-normal: 400;' . "\n";
$fontStyles .= '--font-weight-headings: 700;'; $fontStyles .= '--font-weight-headings: 700;';
} }
} else { } else {
$wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, ['version' => 'auto'], ['media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'']); $wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, ['version' => 'auto'], [
$this->getPreloadManager()->preload($wa->getAsset('style', 'fontscheme.current')->getUri() . '?' . $this->getMediaVersion(), ['as' => 'style']); 'media' => 'print',
'rel' => 'lazy-stylesheet',
'onload' => 'this.media=\'all\''
]);
$this->getPreloadManager()->preload(
$wa->getAsset('style', 'fontscheme.current')->getUri() . '?' . $this->getMediaVersion(),
['as' => 'style']
);
} }
} }
// Enable assets // Expose CSS variables (and any computed font variables)
$wa->usePreset('template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')) $wa->addInlineStyle(":root {\n --hue: 214;\n --template-bg-light: #f0f4fb;\n --template-text-dark: #495057;\n --template-text-light: #ffffff;\n --template-link-color: #2a69b8;\n --template-special-color: #001B4C;\n $fontStyles\n}");
->useStyle('template.active.language')
->useStyle('template.user')
->useScript('template.user')
->addInlineStyle(":root {\n --hue: 214;\n --template-bg-light: #f0f4fb;\n --template-text-dark: #495057;\n --template-text-light: #ffffff;\n --template-link-color: #2a69b8;\n --template-special-color: #001B4C;\n $fontStyles\n }");
// Override 'template.active' asset for correct dependency // -------------------------------------
$wa->registerStyle('template.active', '', [], [], ['template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')]); // Brand: logo from params OR siteTitle
// -------------------------------------
$brandHtml = '';
$logoFile = (string) $this->params->get('logoFile');
// Logo file or site title if ($logoFile !== '') {
if ($this->params->get('logoFile')) { $brandHtml = HTMLHelper::_(
$logo = HTMLHelper::_('image', Uri::root(false) . htmlspecialchars($this->params->get('logoFile'), ENT_QUOTES), $sitename, ['loading' => 'eager', 'decoding' => 'async'], false, 0); 'image',
Uri::root(false) . htmlspecialchars($logoFile, ENT_QUOTES, 'UTF-8'),
$sitename,
['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'],
false,
0
);
} elseif ($this->params->get('siteTitle')) { } elseif ($this->params->get('siteTitle')) {
$logo = '<span title="' . $sitename . '">' . htmlspecialchars($this->params->get('siteTitle'), ENT_COMPAT, 'UTF-8') . '</span>'; $brandHtml = '<span class="site-title" title="' . $sitename . '">'
. htmlspecialchars($this->params->get('siteTitle'), ENT_COMPAT, 'UTF-8')
. '</span>';
} else { } else {
$logo = HTMLHelper::_('image', 'full_logo.png', $sitename, ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], true, 0); // Fallback to a bundled image (relative to media paths)
$brandHtml = HTMLHelper::_('image', 'full_logo.png', $sitename, ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], true, 0);
} }
// Layout flags
$hasClass = ''; $hasClass = '';
if ($this->countModules('sidebar-left', true)) { $hasClass .= ' has-sidebar-left'; } if ($this->countModules('sidebar-left', true)) { $hasClass .= ' has-sidebar-left'; }
if ($this->countModules('sidebar-right', true)) { $hasClass .= ' has-sidebar-right'; } if ($this->countModules('sidebar-right', true)) { $hasClass .= ' has-sidebar-right'; }
if ($this->countModules('drawer-left', true)) { $hasClass .= ' has-drawer-left'; } if ($this->countModules('drawer-left', true)) { $hasClass .= ' has-drawer-left'; }
if ($this->countModules('drawer-right', true)) { $hasClass .= ' has-drawer-right'; } if ($this->countModules('drawer-right', true)) { $hasClass .= ' has-drawer-right'; }
$params_DrawerIconLeft = $this->params->get('drawerIconLeft', 'fas fa-chevron-right');
$params_DrawerIconRight = $this->params->get('drawerIconRight', 'fas fa-chevron-left');
// Container // Container
$wrapper = $this->params->get('fluidContainer') ? 'wrapper-fluid' : 'wrapper-static'; $wrapper = $this->params->get('fluidContainer') ? 'wrapper-fluid' : 'wrapper-static';
$this->setMetaData('viewport', 'width=device-width, initial-scale=1');
$stickyHeader = $this->params->get('stickyHeader') ? 'position-sticky sticky-top' : ''; $stickyHeader = $this->params->get('stickyHeader') ? 'position-sticky sticky-top' : '';
// Meta
$this->setMetaData('viewport', 'width=device-width, initial-scale=1');
// Optional Font Awesome Kit (not defined in JSON)
if ($this->params->get('fA6KitCode')) { if ($this->params->get('fA6KitCode')) {
$fa6Kit = "https://kit.fontawesome.com/" . $this->params->get('fA6KitCode') . ".js"; $fa6Kit = "https://kit.fontawesome.com/" . $this->params->get('fA6KitCode') . ".js";
JHtml::_('script', $fa6Kit, ['crossorigin' => 'anonymous']); HTMLHelper::_('script', $fa6Kit, ['crossorigin' => 'anonymous']);
} else {
$wa->getAsset('style', 'fontawesome')->setAttribute('rel', 'lazy-stylesheet');
} }
// Add Bootstrap TOC CSS
$this->addStyleSheet($templatePath . '/css/vendor/afeld/bootstrap-toc.min.css');
// Add Bootstrap TOC JS (should be loaded after Bootstrap JS)
$this->addScript($templatePath . '/js/vendor/afeld/bootstrap-toc.min.js');
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@@ -144,32 +215,9 @@ $this->addScript($templatePath . '/js/vendor/afeld/bootstrap-toc.min.js');
<head> <head>
<?php if (trim($params_custom_head_start)) : ?><?php echo $params_custom_head_start; ?><?php endif; ?> <?php if (trim($params_custom_head_start)) : ?><?php echo $params_custom_head_start; ?><?php endif; ?>
<jdoc:include type="head" /> <jdoc:include type="head" />
<script>
window.addEventListener('DOMContentLoaded', function () {
var ua = navigator.userAgent || navigator.vendor || window.opera;
var isFacebookBrowser = ua.indexOf('FBAN') > -1 || ua.indexOf('FBAV') > -1;
if (isFacebookBrowser) {
var warning = document.createElement('div');
warning.textContent = '⚠️ KNOWN ISSUE: Images do not load in Facebook Web browser. Please open in external browser for full experience.';
warning.style.position = 'fixed';
warning.style.top = '0';
warning.style.left = '0';
warning.style.right = '0';
warning.style.zIndex = '10000';
warning.style.backgroundColor = '#007bff'; // Blue background
warning.style.color = '#fff';
warning.style.padding = '15px';
warning.style.textAlign = 'center';
warning.style.fontWeight = 'bold';
warning.style.fontSize = '16px';
warning.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
document.body.appendChild(warning);
}
});
</script>
<script> <script>
// Early theme application to avoid FOUC
(function () { (function () {
try { try {
var stored = localStorage.getItem('theme'); var stored = localStorage.getItem('theme');
@@ -180,13 +228,45 @@ $this->addScript($templatePath . '/js/vendor/afeld/bootstrap-toc.min.js');
})(); })();
</script> </script>
<script>
// Facebook in-app browser warning banner
window.addEventListener('DOMContentLoaded', function () {
var ua = navigator.userAgent || navigator.vendor || window.opera;
var isFacebookBrowser = ua.indexOf('FBAN') > -1 || ua.indexOf('FBAV') > -1;
if (isFacebookBrowser) {
var warning = document.createElement('div');
warning.textContent = '⚠️ KNOWN ISSUE: Images do not load in Facebook Web browser. Please open in external browser for full experience.';
warning.style.position = 'fixed';
warning.style.top = '0';
warning.style.left = '0';
warning.style.right = '0';
warning.style.zIndex = '10000';
warning.style.backgroundColor = '#007bff';
warning.style.color = '#fff';
warning.style.padding = '15px';
warning.style.textAlign = 'center';
warning.style.fontWeight = 'bold';
warning.style.fontSize = '16px';
warning.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
document.body.appendChild(warning);
}
});
</script>
<?php if (trim($params_custom_head_end)) : ?><?php echo $params_custom_head_end; ?><?php endif; ?> <?php if (trim($params_custom_head_end)) : ?><?php echo $params_custom_head_end; ?><?php endif; ?>
</head> </head>
<body data-bs-spy="scroll" data-bs-target="#toc" class="site <?php echo $option . ' ' . $wrapper . ' view-' . $view . ($layout ? ' layout-' . $layout : ' no-layout') . ($task ? ' task-' . $task : ' no-task') . ($itemid ? ' itemid-' . $itemid : '') . ($pageclass ? ' ' . $pageclass : '') . $hasClass . ($this->direction == 'rtl' ? ' rtl' : ''); ?>"> <body data-bs-spy="scroll" data-bs-target="#toc" class="site <?php
<?php echo $option . ' ' . $wrapper
if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) : . ' view-' . $view
$gtmID = htmlspecialchars($params_googletagmanagerid, ENT_QUOTES, 'UTF-8'); . ($layout ? ' layout-' . $layout : ' no-layout')
?> . ($task ? ' task-' . $task : ' no-task')
. ($itemid ? ' itemid-' . $itemid : '')
. ($pageclass ? ' ' . $pageclass : '')
. $hasClass
. ($this->direction == 'rtl' ? ' rtl' : '');
?>">
<?php if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) :
$gtmID = htmlspecialchars($params_googletagmanagerid, ENT_QUOTES, 'UTF-8'); ?>
<!-- Google Tag Manager --> <!-- Google Tag Manager -->
<script> <script>
(function(w,d,s,l,i){ (function(w,d,s,l,i){
@@ -208,39 +288,27 @@ if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) :
height="0" width="0" style="display:none;visibility:hidden"></iframe> height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript> </noscript>
<!-- End Google Tag Manager (noscript) --> <!-- End Google Tag Manager (noscript) -->
<?php <?php endif; ?>
endif;
if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) : <?php if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
$gaId = htmlspecialchars($params_googleanalyticsid, ENT_QUOTES, 'UTF-8'); $gaId = htmlspecialchars($params_googleanalyticsid, ENT_QUOTES, 'UTF-8'); ?>
?>
<!-- Google Analytics (gtag.js) --> <!-- Google Analytics (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<?php echo $gaId; ?>"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=<?php echo $gaId; ?>"></script>
<script> <script>
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);} function gtag(){dataLayer.push(arguments);}
gtag('js', new Date()); gtag('js', new Date());
// Optional: Consent Mode defaults (adjust to your needs or remove)
gtag('consent', 'default', { gtag('consent', 'default', {
'ad_storage': 'denied', 'ad_storage': 'denied',
'analytics_storage': 'granted', 'analytics_storage': 'granted',
'ad_user_data': 'denied', 'ad_user_data': 'denied',
'ad_personalization': 'denied' 'ad_personalization': 'denied'
}); });
// GA4 vs UA fallback
(function(id){ (function(id){
if (/^G-/.test(id)) { if (/^G-/.test(id)) {
// GA4 gtag('config', id, { 'anonymize_ip': true });
gtag('config', id, {
'anonymize_ip': true
});
} else if (/^UA-/.test(id)) { } else if (/^UA-/.test(id)) {
// Legacy Universal Analytics (sunset by Google, kept for backward compat) gtag('config', id, { 'anonymize_ip': true });
gtag('config', id, {
'anonymize_ip': true
});
console.warn('Using a UA- ID. Universal Analytics is sunset; consider migrating to GA4.'); console.warn('Using a UA- ID. Universal Analytics is sunset; consider migrating to GA4.');
} else { } else {
console.warn('Unrecognized Google Analytics ID format:', id); console.warn('Unrecognized Google Analytics ID format:', id);
@@ -250,7 +318,7 @@ if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
<!-- End Google Analytics --> <!-- End Google Analytics -->
<?php endif; ?> <?php endif; ?>
<header class="header container-header full-width<?php echo $stickyHeader ? ' ' . $stickyHeader : ''; ?>"> <header class="header container-header full-width<?php echo $stickyHeader ? ' ' . $stickyHeader : ''; ?>" role="banner">
<?php if ($this->countModules('topbar')) : ?> <?php if ($this->countModules('topbar')) : ?>
<div class="container-topbar"> <div class="container-topbar">
@@ -269,10 +337,12 @@ if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
<div class="grid-child"> <div class="grid-child">
<div class="navbar-brand"> <div class="navbar-brand">
<a class="brand-logo" href="<?php echo $this->baseurl; ?>/"> <a class="brand-logo" href="<?php echo $this->baseurl; ?>/">
<?php echo $logo; ?> <?php echo $brandHtml; ?>
</a> </a>
<?php if ($this->params->get('siteDescription')) : ?> <?php if ($this->params->get('siteDescription')) : ?>
<div class="site-description"><?php echo htmlspecialchars($this->params->get('siteDescription')); ?></div> <div class="site-description">
<?php echo htmlspecialchars($this->params->get('siteDescription'), ENT_QUOTES, 'UTF-8'); ?>
</div>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
@@ -309,7 +379,9 @@ if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
<?php if ($this->countModules('menu', true) || $this->countModules('search', true)) : ?> <?php if ($this->countModules('menu', true) || $this->countModules('search', true)) : ?>
<div class="grid-child container-nav"> <div class="grid-child container-nav">
<?php if ($this->countModules('menu', true)) : ?> <?php if ($this->countModules('menu', true)) : ?>
<nav role="navigation" aria-label="Primary">
<jdoc:include type="modules" name="menu" style="none" /> <jdoc:include type="modules" name="menu" style="none" />
</nav>
<?php endif; ?> <?php endif; ?>
<?php if ($this->countModules('search', true)) : ?> <?php if ($this->countModules('search', true)) : ?>
<div class="container-search"> <div class="container-search">
@@ -349,7 +421,7 @@ if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
<jdoc:include type="modules" name="breadcrumbs" style="none" /> <jdoc:include type="modules" name="breadcrumbs" style="none" />
<jdoc:include type="modules" name="main-top" style="card" /> <jdoc:include type="modules" name="main-top" style="card" />
<jdoc:include type="message" /> <jdoc:include type="message" />
<main> <main id="maincontent" role="main">
<jdoc:include type="component" /> <jdoc:include type="component" />
</main> </main>
<jdoc:include type="modules" name="main-bottom" style="card" /> <jdoc:include type="modules" name="main-bottom" style="card" />
@@ -397,7 +469,6 @@ if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
<!-- Left Offcanvas Drawer --> <!-- Left Offcanvas Drawer -->
<aside class="offcanvas offcanvas-start" tabindex="-1" id="drawer-left"> <aside class="offcanvas offcanvas-start" tabindex="-1" id="drawer-left">
<div class="offcanvas-header"> <div class="offcanvas-header">
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="<?php echo Text::_('JLIB_HTML_BEHAVIOR_CLOSE'); ?>"></button> <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="<?php echo Text::_('JLIB_HTML_BEHAVIOR_CLOSE'); ?>"></button>
</div> </div>
<div class="offcanvas-body"> <div class="offcanvas-body">
@@ -410,7 +481,6 @@ if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
<!-- Right Offcanvas Drawer --> <!-- Right Offcanvas Drawer -->
<aside class="offcanvas offcanvas-end" tabindex="-1" id="drawer-right"> <aside class="offcanvas offcanvas-end" tabindex="-1" id="drawer-right">
<div class="offcanvas-header"> <div class="offcanvas-header">
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="<?php echo Text::_('JLIB_HTML_BEHAVIOR_CLOSE'); ?>"></button> <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="<?php echo Text::_('JLIB_HTML_BEHAVIOR_CLOSE'); ?>"></button>
</div> </div>
<div class="offcanvas-body"> <div class="offcanvas-body">
@@ -420,65 +490,6 @@ if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
<?php endif; ?> <?php endif; ?>
<jdoc:include type="modules" name="debug" style="none" /> <jdoc:include type="modules" name="debug" style="none" />
<div class='position-fixed bottom-0 end-0 p-3' style='z-index:1080;'>
<div class='d-flex align-items-center gap-2 bg-body border rounded-pill shadow-sm px-3 py-2'>
<span class='small text-body'>Light</span>
<div class='form-check form-switch m-0'>
<input class='form-check-input' type='checkbox' role='switch' id='themeSwitch' aria-label='Toggle dark mode'>
</div>
<span class='small text-body'>Dark</span>
<button id='themeAuto' class='btn btn-sm btn-link text-decoration-none px-2' type='button' aria-label='Follow system theme'>Auto</button>
</div>
</div>
<script>
(function () {
var storageKey = 'theme';
var doc = document.documentElement;
var mql = window.matchMedia('(prefers-color-scheme: dark)');
var switchEl, autoBtn;
function getStored() { try { return localStorage.getItem(storageKey); } catch (e) { return null; } }
function setStored(v) { try { localStorage.setItem(storageKey, v); } catch (e) {} }
function clearStored() { try { localStorage.removeItem(storageKey); } catch (e) {} }
function systemTheme() { return mql.matches ? 'dark' : 'light'; }
function applyTheme(theme) {
doc.setAttribute('data-bs-theme', theme);
if (switchEl) switchEl.checked = (theme === 'dark');
}
function init() {
switchEl = document.getElementById('themeSwitch');
autoBtn = document.getElementById('themeAuto');
var stored = getStored();
applyTheme(stored ? stored : systemTheme());
if (switchEl) {
switchEl.addEventListener('change', function () {
var theme = switchEl.checked ? 'dark' : 'light';
applyTheme(theme);
setStored(theme);
});
}
if (autoBtn) {
autoBtn.addEventListener('click', function () {
clearStored();
applyTheme(systemTheme());
});
}
var onMqlChange = function () {
if (!getStored()) applyTheme(systemTheme());
};
if (typeof mql.addEventListener === 'function') mql.addEventListener('change', onMqlChange);
else if (typeof mql.addListener === 'function') mql.addListener(onMqlChange);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
else init();
})();
</script>
</body> </body>
</html> </html>

View File

@@ -1,3 +1,32 @@
/*
=========================================================================
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/ .
=========================================================================
FILE INFORMATION
DEFGROUP: Joomla
INGROUP: Moko-Cassiopeia
PATH: templates/moko-cassiopeia/joomla.asset.json
VERSION: 02.00
BRIEF: Joomla asset manifest defining scripts and styles for Moko-Cassiopeia template
=========================================================================
*/
{ {
"$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json",
"name": "tpl_moko-cassiopeia", "name": "tpl_moko-cassiopeia",
@@ -73,33 +102,33 @@
{ {
"name": "template.light.colors_standard", "name": "template.light.colors_standard",
"type": "style", "type": "style",
"uri": "media/templates/site/moko-cassiopeia/css/global/colors/light/colors_standard.css" "uri": "media/templates/site/moko-cassiopeia/css/global/light/colors_standard.css"
}, },
{ {
"name": "template.light.colors_alternative", "name": "template.light.colors_alternative",
"type": "style", "type": "style",
"uri": "media/templates/site/moko-cassiopeia/css/global/colors/light/colors_alternative.css" "uri": "media/templates/site/moko-cassiopeia/css/global/light/colors_alternative.css"
}, },
{ {
"name": "template.light.colors_custom", "name": "template.light.colors_custom",
"type": "style", "type": "style",
"uri": "media/templates/site/moko-cassiopeia/css/global/colors/light/colors_custom.css" "uri": "media/templates/site/moko-cassiopeia/css/global/light/colors_custom.css"
}, },
{ {
"name": "template.dark.colors_standard", "name": "template.dark.colors_standard",
"type": "style", "type": "style",
"uri": "media/templates/site/moko-cassiopeia/css/global/colors/dark/colors_standard.css" "uri": "media/templates/site/moko-cassiopeia/css/global/dark/colors_standard.css"
}, },
{ {
"name": "template.dark.colors_alternative", "name": "template.dark.colors_alternative",
"type": "style", "type": "style",
"uri": "media/templates/site/moko-cassiopeia/css/global/colors/dark/colors_alternative.css" "uri": "media/templates/site/moko-cassiopeia/css/global/dark/colors_alternative.css"
}, },
{ {
"name": "template.dark.colors_custom", "name": "template.dark.colors_custom",
"type": "style", "type": "style",
"uri": "media/templates/site/moko-cassiopeia/css/global/colors/dark/colors_custom.css" "uri": "media/templates/site/moko-cassiopeia/css/global/dark/colors_custom.css"
}, },
{ {

View File

@@ -1,11 +1,31 @@
<?php <?php
/** /* =========================================================================
* @package Joomla.Site * Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* @subpackage Templates.Moko-Cassiopeia
* *
* Offline template that explicitly loads css/template.css and css/colors_*.css. * This file is part of a Moko Consulting project.
* Includes: site-name-in-title rules, brand (logo OR title), theme switcher, *
* module positions (offline-header, offline), and login inside Bootstrap accordion. * SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
* =========================================================================
* FILE INFORMATION
* DEFGROUP: Joomla
* INGROUP: Moko-Cassiopeia
* PATH: templates/moko-cassiopeia/offline.php
* VERSION: 02.00
* BRIEF: Offline page template file for Moko-Cassiopeia
* =========================================================================
*/ */
declare(strict_types=1); declare(strict_types=1);

View File

@@ -1,20 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!-- =========================================================================
@copyright © 2025 Moko Consulting — All Rights Reserved Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
@license GNU General Public License version 2 or later; see LICENSE.txt
Website: https://mokoconsulting.tech This file is part of a Moko Consulting project.
Email: hello@mokoconsulting.tech
Phone: +1 (931) 279-6313
@package Joomla.Site SPDX-License-Identifier: GPL-3.0-or-later
@subpackage Templates.moko-cassiopeia
@file /templates/moko-cassiopeia/templateDetails.xml This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/ .
=========================================================================
FILE INFORMATION
DEFGROUP: Joomla
INGROUP: Moko-Cassiopeia
PATH: templates/moko-cassiopeia/templateDetails.xml
VERSION: 02.00
BRIEF: Template manifest XML file for Moko-Cassiopeia
=========================================================================
--> -->
<extension type="template" client="site" method="upgrade"> <extension type="template" client="site" method="upgrade">
<updateservers> <updateservers>