Stylesheet Updats

This commit is contained in:
2025-08-24 23:47:15 -05:00
parent a215784424
commit f2e774f8ec
35 changed files with 6083 additions and 16022 deletions

View File

@@ -1,72 +1,71 @@
/* STYLES FOR JOOMLA! EDITOR */ /* STYLES FOR JOOMLA! EDITOR */
body { body {
margin: 1rem; font-size: 1rem;
font-size: 1rem; font-weight: 400;
font-weight: 400; line-height: 1.5;
line-height: 1.5; color: #22262a;
color: #22262a; background-color: #fff;
background-color: #fff;
} }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
margin-top: 0; margin-top: 0;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
font-weight: 700; font-weight: 700;
line-height: 1.2; line-height: 1.2;
} }
h1 { h1 {
font-size: calc(1.375rem + 1.5vw); font-size: calc(1.375rem + 1.5vw);
} }
h2 { h2 {
font-size: calc(1.325rem + 0.9vw); font-size: calc(1.325rem + 0.9vw);
} }
h3 { h3 {
font-size: calc(1.3rem + 0.6vw); font-size: calc(1.3rem + 0.6vw);
} }
h4 { h4 {
font-size: calc(1.275rem + 0.3vw); font-size: calc(1.275rem + 0.3vw);
} }
h5 { h5 {
font-size: 1.25rem; font-size: 1.25rem;
} }
h6 { h6 {
font-size: 1rem; font-size: 1rem;
} }
a { a {
text-decoration: none; text-decoration: none;
} }
a:link { a:link {
color: #224faa; color: #224faa;
} }
a:hover { a:hover {
color: #424077; color: #424077;
} }
p { p {
margin-top: 0; margin-top: 0;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
/* STYLES FOR JOOMLA! EDITOR */ /* STYLES FOR JOOMLA! EDITOR */
hr#system-readmore { hr#system-readmore {
color: #f00; color: #f00;
border: #f00 dashed 1px; border: #f00 dashed 1px;
} }
span[lang] { span[lang] {
padding: 2px; padding: 2px;
border: 1px dashed #bbb; border: 1px dashed #bbb;
} }
span[lang]:after { span[lang]:after {
font-size: smaller; font-size: smaller;
color: #f00; color: #f00;
vertical-align: super; vertical-align: super;
content: attr(lang); content: attr(lang);
} }

View File

@@ -0,0 +1,351 @@
/*!
* @package Joomla.Site
* @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/global/dark/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
*/
/* -----------------------------------------------
* DARK THEME
* --------------------------------------------- */
:root[data-bs-theme='dark']{
/* System hint for native widgets */
color-scheme: dark;
/* Brand & links */
--color-primary: #112855;
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #6fb3ff;
--mainmenu-nav-link-color: #fff;
--color-link: #224FAA;
--color-hover: #224FAA;
/* Header background (kept same image; works over dark bg) */
--header-background-image: url('../../../../../../media/templates/site/moko-cassiopeia/images/bg.svg'); --header-background-attachment: fixed;
--header-background-repeat: repeat;
--header-background-size: auto;
/* Section containers */
--container-below-topbar-bg-image: ;
--container-below-topbar-bg-color: ;
--container-below-topbar-bg-position: center;
--container-below-topbar-bg-attachment: fixed;
--container-below-topbar-bg-repeat: no-repeat;
--container-below-topbar-bg-size: cover;
--container-below-topbar-border: ;
--container-below-topbar-border-radius: ;
--container-top-a-bg-image: ;
--container-top-a-bg-color: ;
--container-top-a-bg-position: center;
--container-top-a-bg-attachment: fixed;
--container-top-a-bg-repeat: no-repeat;
--container-top-a-bg-size: cover;
--container-top-a-border: ;
--container-top-a-border-radius: ;
--container-top-b-bg-image: ;
--container-top-b-bg-color: ;
--container-top-b-bg-position: center;
--container-top-b-bg-attachment: fixed;
--container-top-b-bg-repeat: no-repeat;
--container-top-b-bg-size: cover;
--container-top-b-border: ;
--container-top-b-border-radius: ;
--container-toc-bg: ;
--container-toc-color: #dbe3ff;
--container-sidebar-bg-image: ;
--container-sidebar-bg-color: ;
--container-sidebar-bg-position: center;
--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: center;
--container-bottom-a-bg-attachment: fixed;
--container-bottom-a-bg-repeat: no-repeat;
--container-bottom-a-bg-size: cover;
--container-bottom-a-border: ;
--container-bottom-a-border-radius: 5px;
--container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: ;
--container-bottom-b-bg-position: center;
--container-bottom-b-bg-attachment: fixed;
--container-bottom-b-bg-repeat: no-repeat;
--container-bottom-b-bg-size: cover;
--container-bottom-b-border: ;
--container-bottom-b-border-radius: ;
/* Nav & accents */
--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);
/* Palette */
--blue: #91a4ff;
--black: #000;
--indigo: #b19cff;
--purple: #c0a5ff;
--pink: #ff8fc0;
--red: #ff7a73;
--orange: #ff9c4d;
--yellow: #ffd166;
--green: #78d694;
--teal: #76e3ff;
--cyan: #6fb7ff;
--white: #fff;
/* Grays tuned for dark */
--gray-100: #161a20;
--gray-200: #1b2027;
--gray-300: #222831;
--gray-400: #2b323b;
--gray-500: #36404a;
--gray-600: #48525d;
--gray-700: #5b6672;
--gray-800: #cfd6de;
--gray-900: #e6ebf1;
/* Contextuals (keep brand hues) */
--primary: #010156;
--secondary: #48525d;
--success: #4aa664;
--info: #4f7aa0;
--warning: #c77a00;
--danger: #c23a31;
--light: #1b2027;
--dark: #0f1318;
/* RGB helpers */
--primary-rgb: 1,1,86;
--secondary-rgb: 72,82,93;
--success-rgb: 74,166,100;
--info-rgb: 79,122,160;
--warning-rgb: 199,122,0;
--danger-rgb: 194,58,49;
--light-rgb: 27,32,39;
--dark-rgb: 15,19,24;
/* Emphasis & subtle variants */
--primary-text-emphasis: #c7ccff;
--secondary-text-emphasis: #cfd6de;
--success-text-emphasis: #bde8c9;
--info-text-emphasis: #bcd6ee;
--warning-text-emphasis: #ffd9a6;
--danger-text-emphasis: #ffb7b2;
--light-text-emphasis: #d2d8df;
--dark-text-emphasis: #d2d8df;
--primary-bg-subtle: #0b1030;
--secondary-bg-subtle: #1e2430;
--success-bg-subtle: #0f2a1b;
--info-bg-subtle: #0d2232;
--warning-bg-subtle: #2a1e06;
--danger-bg-subtle: #2d1110;
--light-bg-subtle: #12161d;
--dark-bg-subtle: #1e2430;
--primary-border-subtle: #2b3a7a;
--secondary-border-subtle: #2b323b;
--success-border-subtle: #2b5b40;
--info-border-subtle: #254861;
--warning-border-subtle: #5a3c0e;
--danger-border-subtle: #5c2723;
--light-border-subtle: #222831;
--dark-border-subtle: #2b323b;
/* Typography & layout */
--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: #e6ebf1;
--body-color-rgb: 230, 235, 241;
--body-bg: #0e1318;
--body-bg-rgb: 14, 19, 24;
--emphasis-color: #fff;
--emphasis-color-rgb: 255, 255, 255;
--secondary-color: #e6ebf1bf;
--secondary-color-rgb: 230, 235, 241;
--secondary-bg: #151b22;
--secondary-bg-rgb: 21, 27, 34;
--tertiary-color: #e6ebf180;
--tertiary-color-rgb: 230, 235, 241;
--tertiary-bg: #10151b;
--tertiary-bg-rgb: 16, 21, 27;
--heading-color: #f1f5f9;
--link-color: #8ab4f8;
--link-color-rgb: 138, 180, 248;
--link-decoration: underline;
--link-hover-color: #c3d6ff;
--link-hover-color-rgb: 195, 214, 255;
--code-color: #ff7abd;
--highlight-color: #111;
--highlight-bg: #ffe28a1a;
--border-width: 1px;
--border-style: solid;
--border-color: #2b323b;
--border-color-translucent: #ffffff26;
--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);
--border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000066;
--box-shadow-sm: 0 .125rem .25rem #00000040;
--box-shadow-lg: 0 1rem 3rem #00000080;
--box-shadow-inset: inset 0 1px 2px #00000040;
--focus-ring-width: .25rem;
--focus-ring-opacity: .6;
--focus-ring-color: #5472ff66;
--form-valid-color: #78d694;
--form-valid-border-color: #78d694;
--form-invalid-color: #ff8e86;
--form-invalid-border-color: #ff8e86;
}
.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: var(--white);
--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;
}
/* Buttons — inherit brand hues; ensure strong contrast on dark bg */
.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: 84, 114, 255;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #010145;
--btn-active-border-color: #010141;
}
.btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
--btn-border-color: #3a4250;
--btn-hover-color: #fff;
--btn-hover-bg: #1b2a55;
--btn-hover-border-color: #162448;
--btn-focus-shadow-rgb: 84, 114, 255;
--btn-active-color: #fff;
--btn-active-bg: #162448;
--btn-active-border-color: #12203f;
}
/* Outline buttons on dark: keep readable borders */
.btn-outline-light {
--btn-color: #e6ebf1;
--btn-border-color: #e6ebf1;
--btn-hover-color: #111;
--btn-hover-bg: #e6ebf1;
--btn-hover-border-color: #e6ebf1;
--btn-active-color: #111;
--btn-active-bg: #d7dce2;
--btn-active-border-color: #d7dce2;
--gradient: none;
}
/* Links as buttons */
.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: #6d7781;
--btn-disabled-border-color: transparent;
--btn-box-shadow: none;
--btn-focus-shadow-rgb: 84, 114, 255;
text-decoration: underline;
}
.btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
}

View File

@@ -0,0 +1,351 @@
/*!
* @package Joomla.Site
* @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/global/dark/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
*/
/* -----------------------------------------------
* DARK THEME
* --------------------------------------------- */
:root[data-bs-theme='dark']{
/* System hint for native widgets */
color-scheme: dark;
/* Brand & links */
--color-primary: #112855;
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #6fb3ff;
--mainmenu-nav-link-color: #fff;
--color-link: #224FAA;
--color-hover: #224FAA;
/* Header background (kept same image; works over dark bg) */
--header-background-image: url('../../../../../../media/templates/site/moko-cassiopeia/images/bg.svg'); --header-background-attachment: fixed;
--header-background-repeat: repeat;
--header-background-size: auto;
/* Section containers */
--container-below-topbar-bg-image: ;
--container-below-topbar-bg-color: ;
--container-below-topbar-bg-position: center;
--container-below-topbar-bg-attachment: fixed;
--container-below-topbar-bg-repeat: no-repeat;
--container-below-topbar-bg-size: cover;
--container-below-topbar-border: ;
--container-below-topbar-border-radius: ;
--container-top-a-bg-image: ;
--container-top-a-bg-color: ;
--container-top-a-bg-position: center;
--container-top-a-bg-attachment: fixed;
--container-top-a-bg-repeat: no-repeat;
--container-top-a-bg-size: cover;
--container-top-a-border: ;
--container-top-a-border-radius: ;
--container-top-b-bg-image: ;
--container-top-b-bg-color: ;
--container-top-b-bg-position: center;
--container-top-b-bg-attachment: fixed;
--container-top-b-bg-repeat: no-repeat;
--container-top-b-bg-size: cover;
--container-top-b-border: ;
--container-top-b-border-radius: ;
--container-toc-bg: ;
--container-toc-color: #dbe3ff;
--container-sidebar-bg-image: ;
--container-sidebar-bg-color: ;
--container-sidebar-bg-position: center;
--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: center;
--container-bottom-a-bg-attachment: fixed;
--container-bottom-a-bg-repeat: no-repeat;
--container-bottom-a-bg-size: cover;
--container-bottom-a-border: ;
--container-bottom-a-border-radius: 5px;
--container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: ;
--container-bottom-b-bg-position: center;
--container-bottom-b-bg-attachment: fixed;
--container-bottom-b-bg-repeat: no-repeat;
--container-bottom-b-bg-size: cover;
--container-bottom-b-border: ;
--container-bottom-b-border-radius: ;
/* Nav & accents */
--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);
/* Palette */
--blue: #91a4ff;
--black: #000;
--indigo: #b19cff;
--purple: #c0a5ff;
--pink: #ff8fc0;
--red: #ff7a73;
--orange: #ff9c4d;
--yellow: #ffd166;
--green: #78d694;
--teal: #76e3ff;
--cyan: #6fb7ff;
--white: #fff;
/* Grays tuned for dark */
--gray-100: #161a20;
--gray-200: #1b2027;
--gray-300: #222831;
--gray-400: #2b323b;
--gray-500: #36404a;
--gray-600: #48525d;
--gray-700: #5b6672;
--gray-800: #cfd6de;
--gray-900: #e6ebf1;
/* Contextuals (keep brand hues) */
--primary: #010156;
--secondary: #48525d;
--success: #4aa664;
--info: #4f7aa0;
--warning: #c77a00;
--danger: #c23a31;
--light: #1b2027;
--dark: #0f1318;
/* RGB helpers */
--primary-rgb: 1,1,86;
--secondary-rgb: 72,82,93;
--success-rgb: 74,166,100;
--info-rgb: 79,122,160;
--warning-rgb: 199,122,0;
--danger-rgb: 194,58,49;
--light-rgb: 27,32,39;
--dark-rgb: 15,19,24;
/* Emphasis & subtle variants */
--primary-text-emphasis: #c7ccff;
--secondary-text-emphasis: #cfd6de;
--success-text-emphasis: #bde8c9;
--info-text-emphasis: #bcd6ee;
--warning-text-emphasis: #ffd9a6;
--danger-text-emphasis: #ffb7b2;
--light-text-emphasis: #d2d8df;
--dark-text-emphasis: #d2d8df;
--primary-bg-subtle: #0b1030;
--secondary-bg-subtle: #1e2430;
--success-bg-subtle: #0f2a1b;
--info-bg-subtle: #0d2232;
--warning-bg-subtle: #2a1e06;
--danger-bg-subtle: #2d1110;
--light-bg-subtle: #12161d;
--dark-bg-subtle: #1e2430;
--primary-border-subtle: #2b3a7a;
--secondary-border-subtle: #2b323b;
--success-border-subtle: #2b5b40;
--info-border-subtle: #254861;
--warning-border-subtle: #5a3c0e;
--danger-border-subtle: #5c2723;
--light-border-subtle: #222831;
--dark-border-subtle: #2b323b;
/* Typography & layout */
--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: #e6ebf1;
--body-color-rgb: 230, 235, 241;
--body-bg: #0e1318;
--body-bg-rgb: 14, 19, 24;
--emphasis-color: #fff;
--emphasis-color-rgb: 255, 255, 255;
--secondary-color: #e6ebf1bf;
--secondary-color-rgb: 230, 235, 241;
--secondary-bg: #151b22;
--secondary-bg-rgb: 21, 27, 34;
--tertiary-color: #e6ebf180;
--tertiary-color-rgb: 230, 235, 241;
--tertiary-bg: #10151b;
--tertiary-bg-rgb: 16, 21, 27;
--heading-color: #f1f5f9;
--link-color: #8ab4f8;
--link-color-rgb: 138, 180, 248;
--link-decoration: underline;
--link-hover-color: #c3d6ff;
--link-hover-color-rgb: 195, 214, 255;
--code-color: #ff7abd;
--highlight-color: #111;
--highlight-bg: #ffe28a1a;
--border-width: 1px;
--border-style: solid;
--border-color: #2b323b;
--border-color-translucent: #ffffff26;
--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);
--border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000066;
--box-shadow-sm: 0 .125rem .25rem #00000040;
--box-shadow-lg: 0 1rem 3rem #00000080;
--box-shadow-inset: inset 0 1px 2px #00000040;
--focus-ring-width: .25rem;
--focus-ring-opacity: .6;
--focus-ring-color: #5472ff66;
--form-valid-color: #78d694;
--form-valid-border-color: #78d694;
--form-invalid-color: #ff8e86;
--form-invalid-border-color: #ff8e86;
}
.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: var(--white);
--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;
}
/* Buttons — inherit brand hues; ensure strong contrast on dark bg */
.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: 84, 114, 255;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #010145;
--btn-active-border-color: #010141;
}
.btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
--btn-border-color: #3a4250;
--btn-hover-color: #fff;
--btn-hover-bg: #1b2a55;
--btn-hover-border-color: #162448;
--btn-focus-shadow-rgb: 84, 114, 255;
--btn-active-color: #fff;
--btn-active-bg: #162448;
--btn-active-border-color: #12203f;
}
/* Outline buttons on dark: keep readable borders */
.btn-outline-light {
--btn-color: #e6ebf1;
--btn-border-color: #e6ebf1;
--btn-hover-color: #111;
--btn-hover-bg: #e6ebf1;
--btn-hover-border-color: #e6ebf1;
--btn-active-color: #111;
--btn-active-bg: #d7dce2;
--btn-active-border-color: #d7dce2;
--gradient: none;
}
/* Links as buttons */
.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: #6d7781;
--btn-disabled-border-color: transparent;
--btn-box-shadow: none;
--btn-focus-shadow-rgb: 84, 114, 255;
text-decoration: underline;
}
.btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
}

View File

@@ -1,10 +1,9 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller || Moko Consulting — https://mokoconsulting.tech */
/*! /*!
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.moko-cassiopeia * @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/global/colors_standard.css * @file /media/templates/sote/moko-cassiopeia/css/global/light/colors_alternative.css
* *
* © 2025 Moko Consulting All Rights Reserved * @copyright 2025 Moko Consulting <https://mokoconsulting.tech>
* @license GNU General Public License version 2 or later; see LICENSE.txt * @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * Website: https://mokoconsulting.tech
@@ -12,14 +11,22 @@
* Phone: +1 (931) 279-6313 * Phone: +1 (931) 279-6313
*/ */
:root, [data-bs-theme="light"] { /* -----------------------------------------------
* LIGHT THEME
* --------------------------------------------- */
:root[data-bs-theme="light"] {
color-scheme: light; color-scheme: light;
--color-primary: #112855; --color-primary: #112855;
--color-link: #224FAA; --accent-color-primary: #3f8ff0;
--color-hover: #224FAA; --accent-color-secondary: #3f8ff0;
--header-background-image: url('../../../../../media/templates/site/moko-cassiopeia/images/bg.svg'); --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-attachment: fixed;
--header-background-repeat: repeat; --header-background-repeat: repeat;
--header-background-size: auto; --header-background-size: auto;
@@ -51,7 +58,7 @@
--container-top-b-border: ; --container-top-b-border: ;
--container-top-b-border-radius: ; --container-top-b-border-radius: ;
--container-toc-bg: white; --container-toc-bg: var(--mainmenu-nav-link-color);
--container-toc-color: var(--color-primary); --container-toc-color: var(--color-primary);
--container-sidebar-bg-image: ; --container-sidebar-bg-image: ;
@@ -70,7 +77,7 @@
--container-bottom-a-bg-repeat: repeat; --container-bottom-a-bg-repeat: repeat;
--container-bottom-a-bg-size: auto; --container-bottom-a-bg-size: auto;
--container-bottom-a-border: ; --container-bottom-a-border: ;
--container-bottom-a-border-radius: 5px; --container-bottom-a-border-radius: ;
--container-bottom-b-bg-image: ; --container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: ; --container-bottom-b-bg-color: ;
@@ -81,12 +88,21 @@
--container-bottom-b-border: ; --container-bottom-b-border: ;
--container-bottom-b-border-radius: ; --container-bottom-b-border-radius: ;
--nav-text-color: white; --nav-text-color: var(--mainmenu-nav-link-color);
--nav-bg-color: #224FAA; --nav-bg-color: var(--color-link);
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #3f8ff0;
--border: 5px; --border: 5px;
--mainmenu-nav-link-color: white;
--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; --blue: #010156;
--black: #000; --black: #000;
@@ -190,7 +206,7 @@
--border-radius-lg: .3rem; --border-radius-lg: .3rem;
--border-radius-xl: .3rem; --border-radius-xl: .3rem;
--border-radius-xxl: 2rem; --border-radius-xxl: 2rem;
--border-radius-2xl: var(--border-radius-xxl); --border-radius-2xl: var(--border-radius-xxl)*2;
--border-radius-pill: 50rem; --border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000026; --box-shadow: 0 .5rem 1rem #00000026;
--box-shadow-sm: 0 .125rem .25rem #00000013; --box-shadow-sm: 0 .125rem .25rem #00000013;
@@ -205,6 +221,47 @@
--form-invalid-border-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-primary {
--btn-color: hsl(0, 0%, 100%); --btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(240, 98%, 17%); --btn-bg: hsl(240, 98%, 17%);
@@ -492,293 +549,3 @@
--btn-focus-shadow-rgb: 39, 39, 111; --btn-focus-shadow-rgb: 39, 39, 111;
text-decoration: underline; text-decoration: underline;
} }
/* -----------------------------------------------
* DARK THEME append below your light block
* --------------------------------------------- */
:root[data-bs-theme='dark'], [data-bs-theme='dark'] {
/* System hint for native widgets */
color-scheme: dark;
/* Brand & links */
--color-primary: #c7d2ff;
--color-link: #8ab4f8;
--color-hover: #bcd1ff;
/* Header background (kept same image; works over dark bg) */
--header-background-image: url('../../../../../media/templates/site/moko-cassiopeia/images/bg.svg');
--header-background-attachment: fixed;
--header-background-repeat: repeat;
--header-background-size: auto;
/* Section containers */
--container-below-topbar-bg-image: ;
--container-below-topbar-bg-color: #0f141b;
--container-below-topbar-bg-position: center;
--container-below-topbar-bg-attachment: fixed;
--container-below-topbar-bg-repeat: no-repeat;
--container-below-topbar-bg-size: cover;
--container-below-topbar-border: 1px solid #2b323b;
--container-below-topbar-border-radius: 8px;
--container-top-a-bg-image: ;
--container-top-a-bg-color: #0e1319;
--container-top-a-bg-position: center;
--container-top-a-bg-attachment: fixed;
--container-top-a-bg-repeat: no-repeat;
--container-top-a-bg-size: cover;
--container-top-a-border: 1px solid #2b323b;
--container-top-a-border-radius: 8px;
--container-top-b-bg-image: ;
--container-top-b-bg-color: #0e1319;
--container-top-b-bg-position: center;
--container-top-b-bg-attachment: fixed;
--container-top-b-bg-repeat: no-repeat;
--container-top-b-bg-size: cover;
--container-top-b-border: 1px solid #2b323b;
--container-top-b-border-radius: 8px;
--container-toc-bg: #0f141b;
--container-toc-color: #dbe3ff;
--container-sidebar-bg-image: ;
--container-sidebar-bg-color: #0c1016;
--container-sidebar-bg-position: center;
--container-sidebar-bg-attachment: scroll;
--container-sidebar-bg-repeat: repeat;
--container-sidebar-bg-size: auto;
--container-sidebar-border: 1px solid #28303a;
--container-sidebar-border-radius: 8px;
--container-bottom-a-bg-image: ;
--container-bottom-a-bg-color: #0e141b;
--container-bottom-a-bg-position: center;
--container-bottom-a-bg-attachment: fixed;
--container-bottom-a-bg-repeat: no-repeat;
--container-bottom-a-bg-size: cover;
--container-bottom-a-border: 1px solid #2b323b;
--container-bottom-a-border-radius: 5px;
--container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: #0e141b;
--container-bottom-b-bg-position: center;
--container-bottom-b-bg-attachment: fixed;
--container-bottom-b-bg-repeat: no-repeat;
--container-bottom-b-bg-size: cover;
--container-bottom-b-border: 1px solid #2b323b;
--container-bottom-b-border-radius: 8px;
/* Nav & accents */
--nav-text-color: #fff;
--nav-bg-color: #0e1a3c;
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #6fb3ff;
--border: 5px;
--mainmenu-nav-link-color: #fff;
/* Palette */
--blue: #91a4ff;
--black: #000;
--indigo: #b19cff;
--purple: #c0a5ff;
--pink: #ff8fc0;
--red: #ff7a73;
--orange: #ff9c4d;
--yellow: #ffd166;
--green: #78d694;
--teal: #76e3ff;
--cyan: #6fb7ff;
--white: #fff;
/* Grays tuned for dark */
--gray-100: #161a20;
--gray-200: #1b2027;
--gray-300: #222831;
--gray-400: #2b323b;
--gray-500: #36404a;
--gray-600: #48525d;
--gray-700: #5b6672;
--gray-800: #cfd6de;
--gray-900: #e6ebf1;
/* Contextuals (keep brand hues) */
--primary: #010156;
--secondary: #48525d;
--success: #4aa664;
--info: #4f7aa0;
--warning: #c77a00;
--danger: #c23a31;
--light: #1b2027;
--dark: #0f1318;
/* RGB helpers */
--primary-rgb: 1,1,86;
--secondary-rgb: 72,82,93;
--success-rgb: 74,166,100;
--info-rgb: 79,122,160;
--warning-rgb: 199,122,0;
--danger-rgb: 194,58,49;
--light-rgb: 27,32,39;
--dark-rgb: 15,19,24;
/* Emphasis & subtle variants */
--primary-text-emphasis: #c7ccff;
--secondary-text-emphasis: #cfd6de;
--success-text-emphasis: #bde8c9;
--info-text-emphasis: #bcd6ee;
--warning-text-emphasis: #ffd9a6;
--danger-text-emphasis: #ffb7b2;
--light-text-emphasis: #d2d8df;
--dark-text-emphasis: #d2d8df;
--primary-bg-subtle: #0b1030;
--secondary-bg-subtle: #1e2430;
--success-bg-subtle: #0f2a1b;
--info-bg-subtle: #0d2232;
--warning-bg-subtle: #2a1e06;
--danger-bg-subtle: #2d1110;
--light-bg-subtle: #12161d;
--dark-bg-subtle: #1e2430;
--primary-border-subtle: #2b3a7a;
--secondary-border-subtle: #2b323b;
--success-border-subtle: #2b5b40;
--info-border-subtle: #254861;
--warning-border-subtle: #5a3c0e;
--danger-border-subtle: #5c2723;
--light-border-subtle: #222831;
--dark-border-subtle: #2b323b;
/* Typography & layout */
--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: #e6ebf1;
--body-color-rgb: 230, 235, 241;
--body-bg: #0e1318;
--body-bg-rgb: 14, 19, 24;
--emphasis-color: #fff;
--emphasis-color-rgb: 255, 255, 255;
--secondary-color: #e6ebf1bf;
--secondary-color-rgb: 230, 235, 241;
--secondary-bg: #151b22;
--secondary-bg-rgb: 21, 27, 34;
--tertiary-color: #e6ebf180;
--tertiary-color-rgb: 230, 235, 241;
--tertiary-bg: #10151b;
--tertiary-bg-rgb: 16, 21, 27;
--heading-color: #f1f5f9;
--link-color: #8ab4f8;
--link-color-rgb: 138, 180, 248;
--link-decoration: underline;
--link-hover-color: #c3d6ff;
--link-hover-color-rgb: 195, 214, 255;
--code-color: #ff7abd;
--highlight-color: #111;
--highlight-bg: #ffe28a1a;
--border-width: 1px;
--border-style: solid;
--border-color: #2b323b;
--border-color-translucent: #ffffff26;
--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);
--border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000066;
--box-shadow-sm: 0 .125rem .25rem #00000040;
--box-shadow-lg: 0 1rem 3rem #00000080;
--box-shadow-inset: inset 0 1px 2px #00000040;
--focus-ring-width: .25rem;
--focus-ring-opacity: .6;
--focus-ring-color: #5472ff66;
--form-valid-color: #78d694;
--form-valid-border-color: #78d694;
--form-invalid-color: #ff8e86;
--form-invalid-border-color: #ff8e86;
}
/* Buttons — inherit brand hues; ensure strong contrast on dark bg */
[data-bs-theme='dark'] .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: 84, 114, 255;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #010145;
--btn-active-border-color: #010141;
}
[data-bs-theme='dark'] .btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
--btn-border-color: #3a4250;
--btn-hover-color: #fff;
--btn-hover-bg: #1b2a55;
--btn-hover-border-color: #162448;
--btn-focus-shadow-rgb: 84, 114, 255;
--btn-active-color: #fff;
--btn-active-bg: #162448;
--btn-active-border-color: #12203f;
}
/* Outline buttons on dark: keep readable borders */
[data-bs-theme='dark'] .btn-outline-light {
--btn-color: #e6ebf1;
--btn-border-color: #e6ebf1;
--btn-hover-color: #111;
--btn-hover-bg: #e6ebf1;
--btn-hover-border-color: #e6ebf1;
--btn-active-color: #111;
--btn-active-bg: #d7dce2;
--btn-active-border-color: #d7dce2;
--gradient: none;
}
/* Links as buttons */
[data-bs-theme='dark'] .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: #6d7781;
--btn-disabled-border-color: transparent;
--btn-box-shadow: none;
--btn-focus-shadow-rgb: 84, 114, 255;
text-decoration: underline;
}
/* -----------------------------------------------
* OPTIONAL: small fix for .btn-secondary in light
* (uses var() so it picks up your nav colors)
* --------------------------------------------- */
[data-bs-theme='light'] .btn-secondary,
:root .btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
}

View File

@@ -1,10 +1,9 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller || Moko Consulting — https://mokoconsulting.tech */
/*! /*!
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.moko-cassiopeia * @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/global/colors_standard.css * @file /media/templates/sote/moko-cassiopeia/css/global/light/colors_standard.css
* *
* © 2025 Moko Consulting All Rights Reserved * @copyright 2025 Moko Consulting <https://mokoconsulting.tech>
* @license GNU General Public License version 2 or later; see LICENSE.txt * @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * Website: https://mokoconsulting.tech
@@ -12,14 +11,22 @@
* Phone: +1 (931) 279-6313 * Phone: +1 (931) 279-6313
*/ */
:root, [data-bs-theme="light"] { /* -----------------------------------------------
* LIGHT THEME
* --------------------------------------------- */
:root[data-bs-theme="light"] {
color-scheme: light; color-scheme: light;
--color-primary: #112855; --color-primary: #112855;
--color-link: #224FAA; --accent-color-primary: #3f8ff0;
--color-hover: #224FAA; --accent-color-secondary: #3f8ff0;
--header-background-image: url('../../../../../media/templates/site/moko-cassiopeia/images/bg.svg'); --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-attachment: fixed;
--header-background-repeat: repeat; --header-background-repeat: repeat;
--header-background-size: auto; --header-background-size: auto;
@@ -51,7 +58,7 @@
--container-top-b-border: ; --container-top-b-border: ;
--container-top-b-border-radius: ; --container-top-b-border-radius: ;
--container-toc-bg: white; --container-toc-bg: var(--mainmenu-nav-link-color);
--container-toc-color: var(--color-primary); --container-toc-color: var(--color-primary);
--container-sidebar-bg-image: ; --container-sidebar-bg-image: ;
@@ -70,7 +77,7 @@
--container-bottom-a-bg-repeat: repeat; --container-bottom-a-bg-repeat: repeat;
--container-bottom-a-bg-size: auto; --container-bottom-a-bg-size: auto;
--container-bottom-a-border: ; --container-bottom-a-border: ;
--container-bottom-a-border-radius: 5px; --container-bottom-a-border-radius: ;
--container-bottom-b-bg-image: ; --container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: ; --container-bottom-b-bg-color: ;
@@ -81,12 +88,21 @@
--container-bottom-b-border: ; --container-bottom-b-border: ;
--container-bottom-b-border-radius: ; --container-bottom-b-border-radius: ;
--nav-text-color: white; --nav-text-color: var(--mainmenu-nav-link-color);
--nav-bg-color: #224FAA; --nav-bg-color: var(--color-link);
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #3f8ff0;
--border: 5px; --border: 5px;
--mainmenu-nav-link-color: white;
--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; --blue: #010156;
--black: #000; --black: #000;
@@ -190,7 +206,7 @@
--border-radius-lg: .3rem; --border-radius-lg: .3rem;
--border-radius-xl: .3rem; --border-radius-xl: .3rem;
--border-radius-xxl: 2rem; --border-radius-xxl: 2rem;
--border-radius-2xl: var(--border-radius-xxl); --border-radius-2xl: var(--border-radius-xxl)*2;
--border-radius-pill: 50rem; --border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000026; --box-shadow: 0 .5rem 1rem #00000026;
--box-shadow-sm: 0 .125rem .25rem #00000013; --box-shadow-sm: 0 .125rem .25rem #00000013;
@@ -205,6 +221,47 @@
--form-invalid-border-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-primary {
--btn-color: hsl(0, 0%, 100%); --btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(240, 98%, 17%); --btn-bg: hsl(240, 98%, 17%);
@@ -492,293 +549,3 @@
--btn-focus-shadow-rgb: 39, 39, 111; --btn-focus-shadow-rgb: 39, 39, 111;
text-decoration: underline; text-decoration: underline;
} }
/* -----------------------------------------------
* DARK THEME append below your light block
* --------------------------------------------- */
:root[data-bs-theme='dark'], [data-bs-theme='dark'] {
/* System hint for native widgets */
color-scheme: dark;
/* Brand & links */
--color-primary: #112855;
--color-link: #224FAA;
--color-hover: #224FAA;
/* Header background (kept same image; works over dark bg) */
--header-background-image: url('../../../../../media/templates/site/moko-cassiopeia/images/bg.svg');
--header-background-attachment: fixed;
--header-background-repeat: repeat;
--header-background-size: auto;
/* Section containers */
--container-below-topbar-bg-image: ;
--container-below-topbar-bg-color: #0f141b;
--container-below-topbar-bg-position: center;
--container-below-topbar-bg-attachment: fixed;
--container-below-topbar-bg-repeat: no-repeat;
--container-below-topbar-bg-size: cover;
--container-below-topbar-border: 1px solid #2b323b;
--container-below-topbar-border-radius: 8px;
--container-top-a-bg-image: ;
--container-top-a-bg-color: #0e1319;
--container-top-a-bg-position: center;
--container-top-a-bg-attachment: fixed;
--container-top-a-bg-repeat: no-repeat;
--container-top-a-bg-size: cover;
--container-top-a-border: 1px solid #2b323b;
--container-top-a-border-radius: 8px;
--container-top-b-bg-image: ;
--container-top-b-bg-color: #0e1319;
--container-top-b-bg-position: center;
--container-top-b-bg-attachment: fixed;
--container-top-b-bg-repeat: no-repeat;
--container-top-b-bg-size: cover;
--container-top-b-border: 1px solid #2b323b;
--container-top-b-border-radius: 8px;
--container-toc-bg: #0f141b;
--container-toc-color: #dbe3ff;
--container-sidebar-bg-image: ;
--container-sidebar-bg-color: #0c1016;
--container-sidebar-bg-position: center;
--container-sidebar-bg-attachment: scroll;
--container-sidebar-bg-repeat: repeat;
--container-sidebar-bg-size: auto;
--container-sidebar-border: 1px solid #28303a;
--container-sidebar-border-radius: 8px;
--container-bottom-a-bg-image: ;
--container-bottom-a-bg-color: #0e141b;
--container-bottom-a-bg-position: center;
--container-bottom-a-bg-attachment: fixed;
--container-bottom-a-bg-repeat: no-repeat;
--container-bottom-a-bg-size: cover;
--container-bottom-a-border: 1px solid #2b323b;
--container-bottom-a-border-radius: 5px;
--container-bottom-b-bg-image: ;
--container-bottom-b-bg-color: #0e141b;
--container-bottom-b-bg-position: center;
--container-bottom-b-bg-attachment: fixed;
--container-bottom-b-bg-repeat: no-repeat;
--container-bottom-b-bg-size: cover;
--container-bottom-b-border: 1px solid #2b323b;
--container-bottom-b-border-radius: 8px;
/* Nav & accents */
--nav-text-color: #fff;
--nav-bg-color: #0e1a3c;
--accent-color-primary: #3f8ff0;
--accent-color-secondary: #6fb3ff;
--border: 5px;
--mainmenu-nav-link-color: #fff;
/* Palette */
--blue: #91a4ff;
--black: #000;
--indigo: #b19cff;
--purple: #c0a5ff;
--pink: #ff8fc0;
--red: #ff7a73;
--orange: #ff9c4d;
--yellow: #ffd166;
--green: #78d694;
--teal: #76e3ff;
--cyan: #6fb7ff;
--white: #fff;
/* Grays tuned for dark */
--gray-100: #161a20;
--gray-200: #1b2027;
--gray-300: #222831;
--gray-400: #2b323b;
--gray-500: #36404a;
--gray-600: #48525d;
--gray-700: #5b6672;
--gray-800: #cfd6de;
--gray-900: #e6ebf1;
/* Contextuals (keep brand hues) */
--primary: #010156;
--secondary: #48525d;
--success: #4aa664;
--info: #4f7aa0;
--warning: #c77a00;
--danger: #c23a31;
--light: #1b2027;
--dark: #0f1318;
/* RGB helpers */
--primary-rgb: 1,1,86;
--secondary-rgb: 72,82,93;
--success-rgb: 74,166,100;
--info-rgb: 79,122,160;
--warning-rgb: 199,122,0;
--danger-rgb: 194,58,49;
--light-rgb: 27,32,39;
--dark-rgb: 15,19,24;
/* Emphasis & subtle variants */
--primary-text-emphasis: #c7ccff;
--secondary-text-emphasis: #cfd6de;
--success-text-emphasis: #bde8c9;
--info-text-emphasis: #bcd6ee;
--warning-text-emphasis: #ffd9a6;
--danger-text-emphasis: #ffb7b2;
--light-text-emphasis: #d2d8df;
--dark-text-emphasis: #d2d8df;
--primary-bg-subtle: #0b1030;
--secondary-bg-subtle: #1e2430;
--success-bg-subtle: #0f2a1b;
--info-bg-subtle: #0d2232;
--warning-bg-subtle: #2a1e06;
--danger-bg-subtle: #2d1110;
--light-bg-subtle: #12161d;
--dark-bg-subtle: #1e2430;
--primary-border-subtle: #2b3a7a;
--secondary-border-subtle: #2b323b;
--success-border-subtle: #2b5b40;
--info-border-subtle: #254861;
--warning-border-subtle: #5a3c0e;
--danger-border-subtle: #5c2723;
--light-border-subtle: #222831;
--dark-border-subtle: #2b323b;
/* Typography & layout */
--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: #e6ebf1;
--body-color-rgb: 230, 235, 241;
--body-bg: #0e1318;
--body-bg-rgb: 14, 19, 24;
--emphasis-color: #fff;
--emphasis-color-rgb: 255, 255, 255;
--secondary-color: #e6ebf1bf;
--secondary-color-rgb: 230, 235, 241;
--secondary-bg: #151b22;
--secondary-bg-rgb: 21, 27, 34;
--tertiary-color: #e6ebf180;
--tertiary-color-rgb: 230, 235, 241;
--tertiary-bg: #10151b;
--tertiary-bg-rgb: 16, 21, 27;
--heading-color: #f1f5f9;
--link-color: #8ab4f8;
--link-color-rgb: 138, 180, 248;
--link-decoration: underline;
--link-hover-color: #c3d6ff;
--link-hover-color-rgb: 195, 214, 255;
--code-color: #ff7abd;
--highlight-color: #111;
--highlight-bg: #ffe28a1a;
--border-width: 1px;
--border-style: solid;
--border-color: #2b323b;
--border-color-translucent: #ffffff26;
--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);
--border-radius-pill: 50rem;
--box-shadow: 0 .5rem 1rem #00000066;
--box-shadow-sm: 0 .125rem .25rem #00000040;
--box-shadow-lg: 0 1rem 3rem #00000080;
--box-shadow-inset: inset 0 1px 2px #00000040;
--focus-ring-width: .25rem;
--focus-ring-opacity: .6;
--focus-ring-color: #5472ff66;
--form-valid-color: #78d694;
--form-valid-border-color: #78d694;
--form-invalid-color: #ff8e86;
--form-invalid-border-color: #ff8e86;
}
/* Buttons — inherit brand hues; ensure strong contrast on dark bg */
[data-bs-theme='dark'] .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: 84, 114, 255;
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #010145;
--btn-active-border-color: #010141;
}
[data-bs-theme='dark'] .btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
--btn-border-color: #3a4250;
--btn-hover-color: #fff;
--btn-hover-bg: #1b2a55;
--btn-hover-border-color: #162448;
--btn-focus-shadow-rgb: 84, 114, 255;
--btn-active-color: #fff;
--btn-active-bg: #162448;
--btn-active-border-color: #12203f;
}
/* Outline buttons on dark: keep readable borders */
[data-bs-theme='dark'] .btn-outline-light {
--btn-color: #e6ebf1;
--btn-border-color: #e6ebf1;
--btn-hover-color: #111;
--btn-hover-bg: #e6ebf1;
--btn-hover-border-color: #e6ebf1;
--btn-active-color: #111;
--btn-active-bg: #d7dce2;
--btn-active-border-color: #d7dce2;
--gradient: none;
}
/* Links as buttons */
[data-bs-theme='dark'] .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: #6d7781;
--btn-disabled-border-color: transparent;
--btn-box-shadow: none;
--btn-focus-shadow-rgb: 84, 114, 255;
text-decoration: underline;
}
/* -----------------------------------------------
* OPTIONAL: small fix for .btn-secondary in light
* (uses var() so it picks up your nav colors)
* --------------------------------------------- */
[data-bs-theme='light'] .btn-secondary,
:root .btn-secondary {
--btn-color: var(--nav-text-color);
--btn-bg: var(--nav-bg-color);
}

View File

@@ -0,0 +1,220 @@
/*!
* @package Joomla.Site
* @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/global/csocial-media-demos.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
*/
*
/*
======================================================================
Social Media Demo — FULL CSS (Joomla-safe, fully scoped)
Scope: All selectors prefixed with .social-media-demo to avoid leakage
Usage: Wrap your article markup in <div class="social-media-demo"> ... </div>
Version: 2.0 (2025-08-23)
How its organized:
1) Container-level CSS variables (IMAGES ONLY). Colors are hard-coded per brand below.
2) Base/layout styles (sections, header shell, placeholders, buttons).
3) Platform brand colors (hard-coded) and cover height tweaks.
4) Image assignments (map classes like .fb-cover → variable --fb-cover-img).
INSTRUCTIONS:
- Save the images in their requried sizes into the [SITEROOT]/images/social/ folder with the exact names.
- For circle images, sue a square image t fille the entire space
- All images are center and miiddle aligned when loaded.
======================================================================
REQUIRED IMAGE SIZES — Social Media Demo Wireframes
Facebook
--fb-cover-img → Cover: 820×312 (desktop), 640×360 (mobile safe)
--fb-avatar-img → Profile: 176×176 (shown as circle, but use square image)
Twitter / X
--x-cover-img → Header: 1500×500
--x-avatar-img → Profile: up to 400×400 (shown as circle, but use square image)
LinkedIn Company
--li-cover-img → Banner: ~1128×191
--li-logo-img → Logo: up to 300×300 (rounded square)
Google Business Profile
--gmb-cover-img → Banner: ~960×200 (mobile ~960×140)
--gmb-logo-img → Logo: up to 300×300 (shown as circle, but use square image)
Instagram Business
--ig-cover-img → Not always visible, safe 1080×608 for highlight background
--ig-avatar-img → Profile: 320×320 (shown as circle, but use square image)
YouTube Channel
--yt-cover-img → Channel art: 2560×1440 (safe area ~1546×423 center)
--yt-avatar-img → Channel icon: 800×800 (shown as circle, but use square image)
TikTok Business
--tt-cover-img → Profile header: ~900×500 (safe area ~720×405)
--tt-avatar-img → Profile: 200×200 (shown as circle, but use square image)
Pinterest Business
--pin-cover-img → Board/brand banner: ~800×450
--pin-avatar-img → Profile: 165×165 (shown as circle, but use square image)
Snapchat Public Profile
--sc-cover-img → Banner: ~1080×1920 (stories/poster)
--sc-avatar-img → Bitmoji/Profile: 320×320 (shown as circle, but use square image)
Reddit Community
--rd-cover-img → Banner: 1920×384
--rd-avatar-img → Community icon: 256×256 (shown as circle, but use square image)
====================================================================== */
/* Container variables — IMAGES ONLY (safe-scoped) */
.social-media-demo {
--fb-cover-img: url('../../../../../image/social/fb-cover.jpg');
--fb-avatar-img: url('../../../../../image/social/fb-avatar.jpg');
--x-cover-img: url('../../../../../image/social/x-cover.jpg');
--x-avatar-img: url('../../../../../image/social/x-avatar.jpg');
--li-cover-img: url('../../../../../image/social/li-cover.jpg');
--li-logo-img: url('../../../../../image/social/li-logo.jpg');
--gmb-cover-img: url('../../../../../image/social/gmb-cover.jpg');
--gmb-logo-img: url('../../../../../image/social/gmb-logo.jpg');
--ig-cover-img: url('../../../../../image/social/ig-cover.jpg');
--ig-avatar-img: url('../../../../../image/social/ig-avatar.jpg');
--yt-cover-img: url('../../../../../image/social/yt-cover.jpg');
--yt-avatar-img: url('../../../../../image/social/yt-avatar.jpg');
--tt-cover-img: url('../../../../../image/social/tt-cover.jpg');
--tt-avatar-img: url('../../../../../image/social/tt-avatar.jpg');
--pin-cover-img: url('../../../../../image/social/pin-cover.jpg');
--pin-avatar-img: url('../../../../../image/social/pin-avatar.jpg');
--sc-cover-img: url('../../../../../image/social/sc-cover.jpg');
--sc-avatar-img: url('../../../../../image/social/sc-avatar.jpg');
--rd-cover-img: url('../../../../../image/social/rd-cover.jpg');
--rd-avatar-img: url('../../../../../image/social/rd-avatar.jpg');
}
/* DO NOT TOUCH */
.social-media-demo * { box-sizing: border-box; }
.social-media-demo section { margin: 24px auto; max-width: 1128px; background: #fff; border: 1px solid #d9dee3; border-radius: 12px; overflow: hidden; }
.social-media-demo section h2 { margin: 0; padding: 12px 16px; background: #f9fafb; border-bottom: 1px solid #d9dee3; font-size: 16px; font-weight: 800; color: #111; }
.social-media-demo .preview { padding: 16px; }
/* Header shell */
.social-media-demo .header { position: relative; border: 1px solid #d9dee3; border-radius: 12px; overflow: hidden; background: #fff; }
.social-media-demo .cover { position: relative; width: 100%; height: 200px; background-size: cover; background-position: center; background-color: #e8edf3; }
.social-media-demo .avatar-wrap { position: absolute; left: 16px; bottom: -48px; }
.social-media-demo .avatar,
.social-media-demo .logo { width: 160px; height: 160px; border: 4px solid #fff; background-size: cover; background-position: center; overflow: hidden; }
.social-media-demo .avatar.shown as circle, but use square image { border-radius: 999px; }
.social-media-demo .logo.rounded { border-radius: 16px; }
/* Meta */
.social-media-demo .meta { display: flex; justify-content: space-between; align-items: end; gap: 16px; padding: 16px; padding-top: 56px; }
.social-media-demo .name { font-size: 22px; font-weight: 800; color: #111; }
.social-media-demo .subline { font-size: 13px; color: #666; }
/* Buttons */
.social-media-demo .btn { display: inline-flex; align-items: center; height: 32px; padding: 0 12px; border-radius: 8px; border: 1px solid #d9dee3; background: #fff; font-weight: 700; color: #111; }
.social-media-demo .btn.primary { color: #fff; border-color: transparent; }
/* Placeholder visuals (used until you swap in real images) */
.social-media-demo .placeholder { position: relative; width: 100%; height: 100%; display: grid; place-items: center; text-align: center; font-weight: 600; color: #6b7280; background: repeating-linear-gradient(45deg,#f6f7f9 0 12px,#eef0f3 12px 24px); border: 1px dashed #cfd3d8; }
.social-media-demo .placeholder .dims { position: absolute; bottom: 8px; right: 8px; font-size: 12px; opacity: .85; }
/* 3) Platform brand colors & cover height tweaks (hard-coded colors on purpose) */
/* Facebook */
.social-media-demo #fb .btn.primary { background: #1877F2; }
.social-media-demo #fb .cover { height: 312px; }
@media (max-width: 480px) { .social-media-demo #fb .cover { height: 360px; } }
/* Twitter / X */
.social-media-demo #x .btn.primary { background: #1D9BF0; }
.social-media-demo #x .cover { height: 200px; background-color: #22303C; }
@media (max-width: 480px) { .social-media-demo #x .cover { height: 160px; } }
/* LinkedIn */
.social-media-demo #li .btn.primary { background: #0A66C2; }
.social-media-demo #li .cover { height: 220px; background-color: #e6edf5; }
@media (max-width: 480px) { .social-media-demo #li .cover { height: 160px; } }
/* Google Business Profile */
.social-media-demo #gmb .btn.primary { background: #4285F4; }
.social-media-demo #gmb .cover { height: 200px; }
@media (max-width: 480px) { .social-media-demo #gmb .cover { height: 140px; } }
/* Instagram Business */
.social-media-demo #ig .btn.primary { background: #E1306C; }
.social-media-demo #ig .cover { height: 200px; }
/* YouTube Channel */
.social-media-demo #yt .btn.primary { background: #FF0000; }
.social-media-demo #yt .cover { height: 180px; }
/* TikTok Business */
.social-media-demo #tt .btn.primary { background: #000000; color: #fff; }
.social-media-demo #tt .cover { height: 200px; }
/* Pinterest Business */
.social-media-demo #pin .btn.primary { background: #E60023; }
.social-media-demo #pin .cover { height: 200px; }
/* Snapchat Public Profile */
.social-media-demo #sc .btn.primary { background: #FFFC00; color: #000; }
.social-media-demo #sc .cover { height: 160px; }
/* Reddit Community */
.social-media-demo #rd .btn.primary { background: #FF4500; }
.social-media-demo #rd .cover { height: 180px; }
/* 4) Image assignments — map classes to variables (swap vars to change images) */
/* Facebook */
.social-media-demo .fb-cover { background-image: var(--fb-cover-img); }
.social-media-demo .fb-avatar { background-image: var(--fb-avatar-img); }
/* X */
.social-media-demo .x-cover { background-image: var(--x-cover-img); }
.social-media-demo .x-avatar { background-image: var(--x-avatar-img); }
/* LinkedIn */
.social-media-demo .li-cover { background-image: var(--li-cover-img); }
.social-media-demo .li-logo { background-image: var(--li-logo-img); }
/* Google Business */
.social-media-demo .gmb-cover { background-image: var(--gmb-cover-img); }
.social-media-demo .gmb-logo { background-image: var(--gmb-logo-img); }
/* Instagram */
.social-media-demo .ig-cover { background-image: var(--ig-cover-img); }
.social-media-demo .ig-avatar { background-image: var(--ig-avatar-img); }
/* YouTube */
.social-media-demo .yt-cover { background-image: var(--yt-cover-img); }
.social-media-demo .yt-avatar { background-image: var(--yt-avatar-img); }
/* TikTok */
.social-media-demo .tt-cover { background-image: var(--tt-cover-img); }
.social-media-demo .tt-avatar { background-image: var(--tt-avatar-img); }
/* Pinterest */
.social-media-demo .pin-cover { background-image: var(--pin-cover-img); }
.social-media-demo .pin-avatar { background-image: var(--pin-avatar-img); }
/* Snapchat */
.social-media-demo .sc-cover { background-image: var(--sc-cover-img); }
.social-media-demo .sc-avatar { background-image: var(--sc-avatar-img); }
/* Reddit */
.social-media-demo .rd-cover { background-image: var(--rd-cover-img); }
.social-media-demo .rd-avatar { background-image: var(--rd-avatar-img); }

View File

@@ -1,163 +0,0 @@
body {
background-image: url(../images/teaser_bg_sm.png);
background-repeat: repeat-x;
background-attachment: fixed;
}
.outer {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
width: 100%;
min-height: 100vh;
padding: 0;
overflow: hidden;
}
@media only screen and (min-width: 600px) {
.outer {
padding: 3em 0;
padding-bottom: 0;
padding-top:0;
}
}
.offline-card {
background-color:white;
padding:1em;
}
@media only screen and (min-width: 600px) {
.offline-card {
margin: 0 5em;
}
}
footer {
padding: 0 6em;
color: hsl(0, 0%, 100%);
background-color: var(--color-primary);
background-image: -o-linear-gradient(315deg, var(--color-primary) 0%, var(--color-hover) 100%);
background-image: linear-gradient(135deg, var(--color-primary) 0%, var(--color-hover) 100%);
border-radius: 5px 5px 0 0;
}
.footer{
margin-top: 0;
}
.footer .grid-child {
padding: 0 0.75em;
}
.offline-message-card {
width: 100%;
max-width: 30em;
margin: 60px auto;
background-color: hsl(0, 0%, 100%);
border: 1px solid hsla(0, 0%, 0%, 0.1);
border-radius: 5px;
-webkit-box-shadow: 0 0 10px hsla(0, 0%, 0%, 0.05);
box-shadow: 0 0 10px hsla(0, 0%, 0%, 0.05);
}
.header {
position: relative;
padding: 1em 2em;
margin: 0;
color: hsl(0, 0%, 100%);
text-align: center;
background-color: var(--color-primary);
background-image: -o-linear-gradient(315deg, var(--color-primary) 0%, var(--color-hover) 100%);
background-image: linear-gradient(135deg, var(--color-primary) 0%, var(--color-hover) 100%);
border-radius: 5px 5px 0 0;
}
[dir=rtl] .header {
background-image: -o-linear-gradient(315deg, var(--color-hover) 0%, var(--color-primary) 100%);
background-image: linear-gradient(135deg, var(--color-hover) 0%, var(--color-primary) 100%);
}
.login {
padding: 40px 20px 20px;
background-color: var(--nav-bg-color);
}
.form-control {
max-width: none;
}
img {
height: auto;
margin: 5px 0;
border: 0;
}
form,
fieldset {
padding: 0;
margin: 0;
}
label {
display: block;
margin: 0;
}
input[type=text],
input[type=password] {
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
height: auto;
}
input {
margin: 0.5em 0 1em;
}
.offline-card a {
}
.logo {
max-width: 300px;
max-height: 200px;
width: auto;
height: auto;
}
.offline-image {
max-height: 300px;
}
#offline-login-link{
background-image: linear-gradient(to top, rgba(255,0,0,0), rgba(255,255,255,1));
margin: 0 5em;
}
.logo-icon {
margin: 0 auto;
width: 37px;
height:37px;
z-index: 1;
padding: 12px;
margin-top: 2px;
background-color: hsl(0, 0%, 100%);
border: 1px solid hsla(0, 0%, 0%, 0.75);
border-radius: 50%;
-webkit-box-shadow: 0 0 5px hsla(0, 0%, 0%, 0.075);
box-shadow: 0 0 5px hsla(0, 0%, 0%, 0.075);
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.logo-icon svg {
display: block;
width: 38px;
}
a.social-icon {
ext-decoration:none;
border:0;width:36px;
height:36px;padding:2px;
margin:5px;
color:#000;
border-radius:50%;background-color:#ffffff;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,10 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller — | Moko Consulting|https://mokoconsulting.tech */
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.moko-cassiopeia * @subpackage Templates.moko-cassiopeia
* @file /media/templates/sote/moko-cassiopeia/css/template.css * @file /media/templates/sote/moko-cassiopeia/css/template.css
* *
* © 2025 Moko Consulting — All Rights Reserved * @copyright 2025 Moko Consulting <https://mokoconsulting.tech>
* @license GNU General Public License version 2 or later; see LICENSE.txt * @license GNU General Public License version 2 or later; see LICENSE.txt
* *
* Website: https://mokoconsulting.tech * Website: https://mokoconsulting.tech
@@ -3690,47 +3689,6 @@ textarea.form-control.is-invalid {
z-index: 4; z-index: 4;
} }
.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;
}
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.btn { .btn {
-webkit-transition: none; -webkit-transition: none;
@@ -3796,278 +3754,6 @@ fieldset:disabled .btn {
opacity: var(--btn-disabled-opacity); opacity: var(--btn-disabled-opacity);
} }
.btn-primary {
--btn-color: hsl(0, 0%, 100%);
--btn-bg: hsl(240, 98%, 17%);
--btn-border-color: hsl(240, 98%, 17%);
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #010149;
--btn-active-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: hsl(0, 0%, 100%);
--btn-bg: hsl(210, 7%, 46%);
--btn-border-color: hsl(210, 7%, 46%);
--btn-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #5d636b;
--btn-active-border-color: #575e65;
--btn-focus-shadow-rgb: 131, 138, 145;
--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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #3a6f3a;
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #295478;
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #935300;
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #8c1a14;
--btn-active-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-active-color: hsl(0, 0%, 0%);
--btn-active-bg: #d4d5d5;
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: #53585e;
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(240, 98%, 17%);
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(210, 7%, 46%);
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(120, 32%, 39%);
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(207, 49%, 37%);
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(34, 100%, 34%);
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(3, 75%, 37%);
--btn-active-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-active-color: hsl(0, 0%, 0%);
--btn-active-bg: hsl(210, 17%, 98%);
--btn-active-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-active-color: hsl(0, 0%, 100%);
--btn-active-bg: hsl(210, 10%, 23%);
--btn-active-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-link {
--btn-font-weight: 400; --btn-font-weight: 400;
--btn-color: var(--link-color); --btn-color: var(--link-color);
@@ -8792,7 +8478,7 @@ fieldset:disabled .btn {
} }
.sticky-top { .sticky-top {
position: sticky; position: sticky !important;
top: 0; top: 0;
z-index: 1020; z-index: 1020;
} }
@@ -14257,7 +13943,7 @@ th dd {
.com-contact__thumbnail { .com-contact__thumbnail {
text-align: left; text-align: left;
margin: 2em; margin: 2em;
padding:1rem; padding: 1rem;
} }
[data-bs-theme='dark'] .com-contact__thumbnail { [data-bs-theme='dark'] .com-contact__thumbnail {
@@ -14873,7 +14559,7 @@ li.current a {
.container-header .mod-menu>li>a, .container-header .mod-menu>li>a,
.container-header .mod-menu>li>span { .container-header .mod-menu>li>span {
position: relative; position: relative;
color: currentColor; color: var(--nav-text-color);
text-decoration: none; text-decoration: none;
} }
@@ -15179,6 +14865,12 @@ iframe {
margin-bottom: 0; margin-bottom: 0;
} }
.container-component,
.sidebar-left,
.sidebar-right {
height: 100%;
}
.container-component>*:first-child, .container-component>*:first-child,
.container-sidebar-left>*:first-child, .container-sidebar-left>*:first-child,
.container-sidebar-right>*:first-child { .container-sidebar-right>*:first-child {
@@ -15930,6 +15622,10 @@ body.wrapper-fluid .site-grid {
background-repeat: repeat-x; background-repeat: repeat-x;
} }
[data-bs-theme="dark"] body .site-grid {
background-image: none;
}
body.wrapper-fluid .grid-child { body.wrapper-fluid .grid-child {
//max-width: none; //max-width: none;
} }
@@ -17308,3 +17004,207 @@ form .form-select {
border: var(--container-bottom-b-border); border: var(--container-bottom-b-border);
} }
/* Moko Theme FAB */
#mokoThemeFab {
position: fixed;
z-index: 1200;
display: flex;
align-items: center;
gap: .5rem;
padding: .5rem .75rem;
border-radius: 999px;
border: none;
background: var(--muted-color);
box-shadow: var(--box-shadow);
font: inherit;
color: var(--white);
}
#mokoThemeFab.pos-br {
right: 2.5rem;
bottom: 1rem;
}
#mokoThemeFab.pos-bl {
left: 2.5rem;
bottom: 1rem;
}
#mokoThemeFab.pos-tr {
right: 2.5rem;
top: 1rem;
}
#mokoThemeFab.pos-tl {
left: 2.5rem;
top: 1rem;
}
#mokoThemeFab .switch {
display: inline-flex;
align-items: center;
position: relative;
width: 44px;
height: 24px;
background: var(--secondary-color);
transition: background .2s, border-color .2s;
border-radius: var(--border-radius-xxl);
}
#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;
}
body.site.error-page {
margin: 0;
padding: 0;
}
.error-wrap {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
.error-card {
max-width: 820px;
width: 100%;
border: 1px solid color-mix(in srgb, currentColor 15%, transparent);
border-radius: 14px;
padding: 2rem;
background: var(--template-bg-light, #fff);
.error-brand {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.error-brand .brand-logo {
background-color: invert(var(--body-bg));
padding: var(--border-radius-sxl);
border-radius: var(--border-radius-2xl);
}
.error-brand .logo {
max-height: 48px;
width: auto;
display: block;
}
.error-title {
margin: 0.5rem 0 0;
font-size: clamp(1.5rem, 2vw + 1rem, 2.25rem);
font-weight: 700;
}
.error-code {
opacity: .75;
font-weight: 600;
}
.error-actions {
display: flex;
flex-wrap: wrap;
gap: .75rem;
margin-top: 1.25rem;
}
.moko-offline-wrap {
min-height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto;
}
.moko-offline-main {
display: grid;
place-items: center;
padding: 2rem 1rem;
}
.moko-card {
max-width: 720px;
width: 100%;
}
.moko-brand {
display: flex;
align-items: center;
gap: .75rem;
text-decoration: none;
}
.moko-brand .brand-tagline {
display: block;
opacity: .75;
font-size: .875rem;
line-height: 1.2;
}
.theme-switcher .dropdown-item.active {
font-weight: 600;
}
.skip-link {
position: absolute;
left: -9999px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
.skip-l ink:focus {
position: static;
width: auto;
height: auto;
padding: .5rem 1rem;
}
.btn {
display: inline-flex;
align-items: center;
gap: .5rem;
border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
border-radius: 8px;
padding: .5rem .9rem;
text-decoration: none;
}
/* SOCIAL MEDIA DEMOS */
@import url("global/social-media-demos.css");

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1854.54 295" preserveAspectRatio="xMinYMid" width="1854.54" height="295"><path d="m14.47 145.7 6.898 6.899c0.102 0.101 0.199 0.101 0.3 0.101 0.102 0 0.2 0 0.302-0.101l6.898-6.899c0.102-0.1 0.102-0.2 0.102-0.3s0-0.2-0.102-0.3l-0.7-0.7c-0.101-0.1-0.198-0.1-0.3-0.1-0.101 0-0.2 0-0.301 0.1l-5.8 5.8-5.801-5.8c-0.101-0.1-0.199-0.1-0.301-0.1-0.101 0-0.199 0-0.301 0.1l-0.699 0.7c-0.101 0.1-0.101 0.2-0.101 0.3-0.294 0.1-0.194 0.2-0.094 0.3z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 510 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1854.54 295" preserveAspectRatio="xMinYMid" width="1854.54" height="295"><path d="M1825.1,145.7l6.9,6.9c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.3-0.1l6.9-6.9c0.1-0.1,0.1-0.2,0.1-0.3c0-0.1,0-0.2-0.1-0.3l-0.7-0.7c-0.1-0.1-0.2-0.1-0.3-0.1s-0.2,0-0.3,0.1l-5.8,5.8l-5.8-5.8c-0.1-0.1-0.2-0.1-0.3-0.1c-0.1,0-0.2,0-0.3,0.1l-0.7,0.7c-0.1,0.1-0.1,0.2-0.1,0.3C1824.9,145.5,1825,145.6,1825.1,145.7z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 459 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1854.539" height="295" preserveAspectRatio="xMinYMin meet"><path d="M13.573 145.7l6.9 6.9c.1.1.2.1.3.1s.2 0 .3-.1l6.9-6.9c.1-.1.1-.2.1-.3s0-.2-.1-.3l-.7-.7c-.1-.1-.2-.1-.3-.1s-.2 0-.3.1l-5.8 5.8-5.8-5.8c-.1-.1-.2-.1-.3-.1s-.2 0-.3.1l-.7.7c-.1.1-.1.2-.1.3-.296.1-.195.2-.096.3h-.002z"/><path fill="#fff" d="M44.54 0h1810v295h-1810z"/></svg>

Before

Width:  |  Height:  |  Size: 387 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1854.54 295" preserveAspectRatio="xMinYMid" width="1854.54" height="295"><path d="M1825.1,145.7l6.9,6.9c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.3-0.1l6.9-6.9c0.1-0.1,0.1-0.2,0.1-0.3c0-0.1,0-0.2-0.1-0.3l-0.7-0.7c-0.1-0.1-0.2-0.1-0.3-0.1s-0.2,0-0.3,0.1l-5.8,5.8l-5.8-5.8c-0.1-0.1-0.2-0.1-0.3-0.1c-0.1,0-0.2,0-0.3,0.1l-0.7,0.7c-0.1,0.1-0.1,0.2-0.1,0.3C1824.9,145.5,1825,145.6,1825.1,145.7z" fill="#000"/><rect width="1810" height="295" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,147 @@
/**
* darkmode-toggle.js — Floating theme switch (class-based, CSP-proof)
* @version 2.2.1
* Storage key: "theme" -> "light" | "dark"
* Corner from <body data-theme-fab-pos="br|bl|tr|tl"> (default br)
*/
(function () {
'use strict';
var STORAGE_KEY = 'theme';
var docEl = document.documentElement;
var mql = window.matchMedia('(prefers-color-scheme: dark)');
function getStored() { try { return localStorage.getItem(STORAGE_KEY); } catch (e) { return null; } }
function setStored(v) { try { localStorage.setItem(STORAGE_KEY, v); } catch (e) {} }
function clearStored() { try { localStorage.removeItem(STORAGE_KEY); } catch (e) {} }
function systemTheme() { return mql.matches ? 'dark' : 'light'; }
function applyTheme(theme) {
docEl.setAttribute('data-bs-theme', theme);
docEl.setAttribute('data-aria-theme', theme);
var meta = document.querySelector('meta[name="theme-color"]');
if (meta) {
meta.setAttribute('content', theme === 'dark' ? '#0f1115' : '#ffffff');
}
var sw = document.getElementById('mokoThemeSwitch');
if (sw) {
sw.setAttribute('aria-checked', theme === 'dark' ? 'true' : 'false');
}
}
function initTheme() {
var stored = getStored();
applyTheme(stored ? stored : systemTheme());
}
function posClassFromBody() {
var pos = (document.body.getAttribute('data-theme-fab-pos') || 'br').toLowerCase();
if (!/^(br|bl|tr|tl)$/.test(pos)) pos = 'br';
return 'pos-' + pos;
}
function buildToggle() {
if (document.getElementById('mokoThemeFab')) return;
var wrap = document.createElement('div');
wrap.id = 'mokoThemeFab';
wrap.className = posClassFromBody();
// Light label
var lblL = document.createElement('span');
lblL.className = 'label';
lblL.textContent = 'Light';
// Switch
var switchWrap = document.createElement('button');
switchWrap.id = 'mokoThemeSwitch';
switchWrap.type = 'button';
switchWrap.setAttribute('role', 'switch');
switchWrap.setAttribute('aria-label', 'Toggle dark mode');
switchWrap.setAttribute('aria-checked', 'false'); // updated after init
var track = document.createElement('span');
track.className = 'switch';
var knob = document.createElement('span');
knob.className = 'knob';
track.appendChild(knob);
switchWrap.appendChild(track);
// Dark label
var lblD = document.createElement('span');
lblD.className = 'label';
lblD.textContent = 'Dark';
// Auto button
var auto = document.createElement('button');
auto.id = 'mokoThemeAuto';
auto.type = 'button';
auto.className = 'btn btn-sm btn-link text-decoration-none px-2';
auto.setAttribute('aria-label', 'Follow system theme');
auto.textContent = 'Auto';
// Behavior
switchWrap.addEventListener('click', function () {
var current = (docEl.getAttribute('data-bs-theme') || 'light').toLowerCase();
var next = current === 'dark' ? 'light' : 'dark';
applyTheme(next);
setStored(next);
});
auto.addEventListener('click', function () {
clearStored();
applyTheme(systemTheme());
});
// Respond to OS changes only when not user-forced
var onMql = function () {
if (!getStored()) applyTheme(systemTheme());
};
if (typeof mql.addEventListener === 'function') mql.addEventListener('change', onMql);
else if (typeof mql.addListener === 'function') mql.addListener(onMql);
// Initial state
var initial = getStored() || systemTheme();
switchWrap.setAttribute('aria-checked', initial === 'dark' ? 'true' : 'false');
// Mount
wrap.appendChild(lblL);
wrap.appendChild(switchWrap);
wrap.appendChild(lblD);
wrap.appendChild(auto);
document.body.appendChild(wrap);
// Debug helper
window.mokoThemeFabStatus = function () {
var el = document.getElementById('mokoThemeFab');
if (!el) return { mounted: false };
var r = el.getBoundingClientRect();
return {
mounted: true,
rect: { top: r.top, left: r.left, width: r.width, height: r.height },
zIndex: window.getComputedStyle(el).zIndex,
posClass: el.className
};
};
// Outline if invisible
setTimeout(function () {
var r = wrap.getBoundingClientRect();
if (r.width < 10 || r.height < 10) {
wrap.classList.add('debug-outline');
console.warn('[moko] Theme FAB mounted but appears too small — check CSS collisions.');
}
}, 50);
}
function init() {
initTheme();
buildToggle();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();

View File

@@ -1,2 +1,11 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller || Moko Consulting — https://mokoconsulting.tech */ /**
* @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,31 +1,42 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller || Moko Consulting — https://mokoconsulting.tech */ /**
* @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia
* @file /media/templates/site/moko-cassiopeia/js/mod_menu/menu-metismenu-es5.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.
*/
(function () { (function () {
'use strict'; 'use strict';
/** /**
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia * @subpackage Templates.Moko-Cassiopeia
* @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org> * @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt * @license GNU General Public License version 2 or later; see LICENSE.txt
* @since 4.0.0 * @since 4.0.0
*/ */
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
var allMenus = document.querySelectorAll('ul.mod-menu_dropdown-metismenu'); var allMenus = document.querySelectorAll('ul.mod-menu_dropdown-metismenu');
allMenus.forEach(function (menu) { allMenus.forEach(function (menu) {
// eslint-disable-next-line no-new, no-undef // eslint-disable-next-line no-new, no-undef
var mm = new MetisMenu(menu, { var mm = new MetisMenu(menu, {
triggerElement: 'button.mm-toggler' triggerElement: 'button.mm-toggler'
}).on('shown.metisMenu', function (event) { }).on('shown.metisMenu', function (event) {
window.addEventListener('click', function mmClick(e) { window.addEventListener('click', function mmClick(e) {
if (!event.target.contains(e.target)) { if (!event.target.contains(e.target)) {
mm.hide(event.detail.shownElement); mm.hide(event.detail.shownElement);
window.removeEventListener('click', mmClick); window.removeEventListener('click', mmClick);
} }
}); });
}); });
}); });
}); });
})(); })();

View File

@@ -1,27 +1,29 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller || Moko Consulting — https://mokoconsulting.tech */
/** /**
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia * @subpackage Templates.Moko-Cassiopeia
* @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org> * @file /media/templates/site/moko-cassiopeia/js/mod_menu/menu-metismenu.js
* @copyright (C) 2025 Jonathan Miler || Moko Consulting <https://mokoconsulting.tech> * @copyright (C) 2025 Jonathan Miler || Moko Consulting <https://mokoconsulting.tech>
* @license GNU General Public License version 2 or later; see LICENSE.txt * @website: https://mokoconsulting.tech
* @since 4.0.0 * @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.
*/ */
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const allMenus = document.querySelectorAll('ul.mod-menu_dropdown-metismenu'); const allMenus = document.querySelectorAll('ul.mod-menu_dropdown-metismenu');
allMenus.forEach(menu => { allMenus.forEach(menu => {
// eslint-disable-next-line no-new, no-undef // eslint-disable-next-line no-new, no-undef
const mm = new MetisMenu(menu, { const mm = new MetisMenu(menu, {
triggerElement: 'button.mm-toggler' triggerElement: 'button.mm-toggler'
}).on('shown.metisMenu', event => { }).on('shown.metisMenu', event => {
window.addEventListener('click', function mmClick(e) { window.addEventListener('click', function mmClick(e) {
if (!event.target.contains(e.target)) { if (!event.target.contains(e.target)) {
mm.hide(event.detail.shownElement); mm.hide(event.detail.shownElement);
window.removeEventListener('click', mmClick); window.removeEventListener('click', mmClick);
} }
}); });
}); });
}); });
}); });

View File

@@ -1,76 +1,120 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller || Moko Consulting — https://mokoconsulting.tech */
/** /**
* template.js — Custom JavaScript for the Moko Cassiopeia Joomla template
*
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia * @subpackage Templates.Moko-Cassiopeia
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @file /media/templates/site/moko-cassiopeia/js/template.js
* @license GNU General Public License version 2 or later; see LICENSE.txt * @version 2.0
* @since 4.0.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 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/>.
*/ */
Joomla = window.Joomla || {}; (function (win, doc) {
"use strict";
(function(Joomla, document) { /**
'use strict'; * Utility: smooth scroll to top
*/
function backToTop() {
win.scrollTo({ top: 0, behavior: "smooth" });
}
function initTemplate(event) { /**
var target = event && event.target ? event.target : document; * Utility: toggle body class on scroll for sticky header styling
*/
function handleScroll() {
if (win.scrollY > 50) {
doc.body.classList.add("scrolled");
} else {
doc.body.classList.remove("scrolled");
}
}
/** /**
* Prevent clicks on buttons within a disabled fieldset * Initialize Bootstrap TOC if #toc element exists.
*/ * Requires bootstrap-toc.min.js to be loaded.
var fieldsets = target.querySelectorAll('fieldset.btn-group'); */
for (var i = 0; i < fieldsets.length; i++) { function initTOC() {
var self = fieldsets[i]; if (typeof win.Toc === "function" && doc.querySelector("#toc")) {
if (self.getAttribute('disabled') === true) { win.Toc.init({
self.style.pointerEvents = 'none'; $nav: $("#toc"),
var btns = self.querySelectorAll('.btn'); $scope: $("main")
for (var ib = 0; ib < btns.length; ib++) { });
btns[ib].classList.add('disabled'); }
} }
}
}
}
document.addEventListener('DOMContentLoaded', function (event) { /**
initTemplate(event); * Initialize offcanvas drawer buttons for left/right drawers.
* Uses Bootstrap's offcanvas component.
*/
function initDrawers() {
var leftBtn = doc.querySelector(".drawer-toggle-left");
var rightBtn = doc.querySelector(".drawer-toggle-right");
if (leftBtn) {
leftBtn.addEventListener("click", function () {
var target = doc.querySelector(leftBtn.getAttribute("data-bs-target"));
if (target) new bootstrap.Offcanvas(target).show();
});
}
if (rightBtn) {
rightBtn.addEventListener("click", function () {
var target = doc.querySelector(rightBtn.getAttribute("data-bs-target"));
if (target) new bootstrap.Offcanvas(target).show();
});
}
}
/** /**
* Back to top * Initialize back-to-top link if present
*/ */
var backToTop = document.getElementById('back-top'); function initBackTop() {
var backTop = doc.getElementById("back-top");
if (backTop) {
backTop.addEventListener("click", function (e) {
e.preventDefault();
backToTop();
});
}
}
if (backToTop) { /**
* Run all template JS initializations
*/
function init() {
// Sticky header behavior
handleScroll();
win.addEventListener("scroll", handleScroll);
function checkScrollPos() { // Init features
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { initTOC();
backToTop.classList.add('visible'); initDrawers();
} else { initBackTop();
backToTop.classList.remove('visible') }
}
}
checkScrollPos();
window.onscroll = function() {
checkScrollPos();
};
backToTop.addEventListener('click', function(event) {
event.preventDefault();
window.scrollTo(0, 0);
});
}
[].slice.call(document.head.querySelectorAll('link[rel="lazy-stylesheet"]'))
.forEach(function($link){
$link.rel = "stylesheet";
});
});
/**
* Initialize when a part of the page was updated
*/
document.addEventListener('joomla:updated', initTemplate);
})(Joomla, document);
if (doc.readyState === "loading") {
doc.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})(window, document);

View File

@@ -0,0 +1,111 @@
/**
* theme-init.js — Light/Dark mode initialization for Moko Cassiopeia
*
* @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 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/>.
*/
(function (win, doc) {
"use strict";
var storageKey = "theme"; // localStorage key
var mql = win.matchMedia("(prefers-color-scheme: dark)");
var root = doc.documentElement;
/**
* Apply theme to <html>, syncing both data-bs-theme and data-aria-theme.
* @param {"light"|"dark"} theme
*/
function applyTheme(theme) {
root.setAttribute("data-bs-theme", theme);
root.setAttribute("data-aria-theme", theme);
try { localStorage.setItem(storageKey, theme); } catch (e) {}
}
/**
* Clear stored preference so system preference is followed.
*/
function clearStored() {
try { localStorage.removeItem(storageKey); } catch (e) {}
}
/**
* Determine system theme.
*/
function systemTheme() {
return mql.matches ? "dark" : "light";
}
/**
* Initialize theme on load.
*/
function init() {
var stored = null;
try { stored = localStorage.getItem(storageKey); } catch (e) {}
var theme = stored ? stored : systemTheme();
applyTheme(theme);
// Listen for system changes only if Auto mode (no stored)
var onChange = function () {
if (!localStorage.getItem(storageKey)) {
applyTheme(systemTheme());
}
};
if (typeof mql.addEventListener === "function") {
mql.addEventListener("change", onChange);
} else if (typeof mql.addListener === "function") {
mql.addListener(onChange);
}
// Hook toggle UI if present
var switchEl = doc.getElementById("themeSwitch");
var autoBtn = doc.getElementById("themeAuto");
if (switchEl) {
switchEl.checked = (theme === "dark");
switchEl.addEventListener("change", function () {
var choice = switchEl.checked ? "dark" : "light";
applyTheme(choice);
});
}
if (autoBtn) {
autoBtn.addEventListener("click", function () {
clearStored();
applyTheme(systemTheme());
});
}
}
if (doc.readyState === "loading") {
doc.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})(window, document);

View File

@@ -0,0 +1,31 @@
/**
* user.js — User Custom JS File for Moko Cassiopeia
*
* @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 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/>.
*/

View File

@@ -1,4 +1,3 @@
/* MOKO-COPYRIGHT: © 2025-08-10 Jonathan Miller || Moko Consulting — https://mokoconsulting.tech */
/*! /*!
* Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/) * Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/)
* Copyright 2015 Aidan Feldman * Copyright 2015 Aidan Feldman

View File

@@ -1,6 +1,5 @@
<?php <?php
/** /**
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.Moko-Cassiopeia * @subpackage Templates.Moko-Cassiopeia
@@ -48,7 +47,7 @@ if ($paramsFontScheme) {
} }
// Enable assets // Enable assets
$wa->usePreset('template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')) $wa->usePreset('template.moko-cassiopeia.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr'))
->useStyle('template.active.language') ->useStyle('template.active.language')
->useStyle('template.user') ->useStyle('template.user')
->useScript('template.user') ->useScript('template.user')
@@ -64,7 +63,7 @@ $wa->usePreset('template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl'
// Override 'template.active' asset to set correct ltr/rtl dependency // Override 'template.active' asset to set correct ltr/rtl dependency
$wa->registerStyle('template.active', '', [], [], ['template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')]); $wa->registerStyle('template.active', '', [], [], ['template.moko-cassiopeia.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')]);
// Browsers support SVG favicons // Browsers support SVG favicons
$this->addHeadLink(HTMLHelper::_('image', 'joomla-favicon.svg', '', [], true, 1), 'icon', 'rel', ['type' => 'image/svg+xml']); $this->addHeadLink(HTMLHelper::_('image', 'joomla-favicon.svg', '', [], true, 1), 'icon', 'rel', ['type' => 'image/svg+xml']);
@@ -87,4 +86,3 @@ $wa->getAsset('style', 'fontawesome')->setAttribute('rel', 'lazy-stylesheet');
<jdoc:include type="component" /> <jdoc:include type="component" />
</body> </body>
</html> </html>

View File

@@ -1,24 +1,30 @@
<?php <?php
/** /**
*
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.moko-cassiopeia * @subpackage Templates.Moko-Cassiopeia
* @file /templates/moko-cassiopeia/custom.php * @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
* *
* @copyright © 2025 Moko Consulting — All Rights Reserved * SPDX-License-Identifier: GPL-3.0-or-later
* @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 released under the
* Email: hello@mokoconsulting.tech * GNU General Public License v3 or (at your option) any later version.
* Phone: +1 (931) 279-6313 * It 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.
*/ */
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) .
');'; ');';
if ($with_script_tags) { if ($with_script_tags) {
$js_code = '<script>' . $js_code . '</script>'; $js_code = '<script>' . $js_code . '</script>';
} }
echo $js_code; echo $js_code;
} }
?> ?>
Custom code included here Custom code included here

View File

@@ -1,16 +1,21 @@
<?php <?php
/** /**
* error.php — Error page template for Moko Cassiopeia
*
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.moko-cassiopeia * @subpackage Templates.Moko-Cassiopeia
* @file /templates/moko-cassiopeia/error.php * @file /templates/moko-cassiopeia/error.php
* * @version 2.1
* @copyright © 2025 Moko Consulting — All Rights Reserved * @copyright (C) 2025 Moko Consulting
* @license GNU General Public License version 2 or later; see LICENSE.txt * @author Jonathan Miller
* * @website https://mokoconsulting.tech
* Website: https://mokoconsulting.tech * @email hello@mokoconsulting.tech
* Email: hello@mokoconsulting.tech * @phone +1 (931) 279-6313
* Phone: +1 (931) 279-6313 * @license GNU General Public License version 3 or later; see LICENSE.txt
* @disclaimer 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.
*/ */
defined('_JEXEC') or die; defined('_JEXEC') or die;
@@ -20,213 +25,245 @@ use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text; use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri; use Joomla\CMS\Uri\Uri;
/** @var Joomla\CMS\Document\ErrorDocument $this */ /** @var Joomla\CMS\Document\ErrorDocument|Joomla\CMS\Document\HtmlDocument $this */
$app = Factory::getApplication();
$params = $this->params;
$wa = $this->getWebAssetManager();
$app = Factory::getApplication(); // ------------------ Params ------------------
$input = $app->getInput(); $colorLight = (string) $params->get('colorLightName', 'colors_standard');
$wa = $this->getWebAssetManager(); $colorDark = (string) $params->get('colorDarkName', 'colors_standard');
$themeFab = (int) $params->get('theme_fab_enabled', 1);
$fABodyPos = (string) $params->get('theme_fab_pos', 'br');
$gtmEnabled = (int) $params->get('googletagmanager', 0);
$gtmId = (string) $params->get('googletagmanagerid', '');
$fa6KitCode = (string) $params->get('fA6KitCode', '');
$stickyHeader = (bool) $params->get('stickyHeader', 0);
$brandEnabled = (int) $params->get('brand', 1);
$siteDescription = (string) $params->get('siteDescription', '');
// Drawer icon params (escaped)
$params_leftIcon = htmlspecialchars($params->get('drawerLeftIcon', 'fa-solid fa-chevron-right'), ENT_QUOTES, 'UTF-8');
$params_rightIcon = htmlspecialchars($params->get('drawerRightIcon', 'fa-solid fa-chevron-left'), ENT_QUOTES, 'UTF-8');
// Browsers support SVG favicons // ------------------ Styles ------------------
$this->addHeadLink(HTMLHelper::_('image', '../media/templates/site/moko-cassiopeia/images/favicon/favicon.svg', '', [], true, 1), 'icon', 'rel', ['type' => 'image/svg+xml']); $wa->useStyle('template.base');
$this->addHeadLink(HTMLHelper::_('image', '../media/templates/site/moko-cassiopeia/images/favicon/favicon.ico', '', [], true, 1), 'alternate icon', 'rel', ['type' => 'image/vnd.microsoft.icon']); $wa->useStyle('template.user');
$this->addHeadLink(HTMLHelper::_('image', '../media/templates/site/moko-cassiopeia/images/favicon/favicon.svg', '', [], true, 1), 'mask-icon', 'rel', ['color' => '#fff']); $wa->useStyle('vendor.vmbasic');
$wa->useStyle('vendor.gable');
//add Bootsrap 5 Support // Light/Dark variable sheets (load before consumers)
HTMLHelper::_('bootstrap.alert'); if ($wa->assetExists('style', 'template.light.' . $colorLight)) {
HTMLHelper::_('bootstrap.button'); $wa->useStyle('template.light.' . $colorLight);
HTMLHelper::_('bootstrap.carousel'); }
HTMLHelper::_('bootstrap.collapse'); if ($wa->assetExists('style', 'template.dark.' . $colorDark)) {
HTMLHelper::_('bootstrap.dropdown'); $wa->useStyle('template.dark.' . $colorDark);
HTMLHelper::_('bootstrap.modal');
HTMLHelper::_('bootstrap.offcanvas');
HTMLHelper::_('bootstrap.popover');
HTMLHelper::_('bootstrap.scrollspy');
HTMLHelper::_('bootstrap.tab');
HTMLHelper::_('bootstrap.tooltip');
HTMLHelper::_('bootstrap.toast');
// Detecting Active Variables
$option = $input->getCmd('option', '');
$view = $input->getCmd('view', '');
$layout = $input->getCmd('layout', '');
$task = $input->getCmd('task', '');
$itemid = $input->getCmd('Itemid', '');
$sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8');
$menu = $app->getMenu()->getActive();
$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';
// Template path
$templatePath = 'media/templates/site/moko-cassiopeia';
// Color Theme
$paramsColorName = $this->params->get('colorName', 'colors_standard');
$assetColorName = 'theme.' . $paramsColorName;
$wa->registerAndUseStyle($assetColorName, $templatePath . '/css/global/' . $paramsColorName . '.css');
// Use a font scheme if set in the template style options
$paramsFontScheme = $this->params->get('useFontScheme', false);
$fontStyles = '';
if ($paramsFontScheme) {
if (stripos($paramsFontScheme, 'https://') === 0) {
$this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']);
$this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']);
$this->getPreloadManager()->preload($paramsFontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']);
$wa->registerAndUseStyle('fontscheme.current', $paramsFontScheme, [], ['media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'', 'crossorigin' => 'anonymous']);
if (preg_match_all('/family=([^?:]*):/i', $paramsFontScheme, $matches) > 0) {
$fontStyles = '--font-family-body: "' . str_replace('+', ' ', $matches[1][0]) . '", sans-serif;
--font-family-headings: "' . str_replace('+', ' ', isset($matches[1][1]) ? $matches[1][1] : $matches[1][0]) . '", sans-serif;
--font-weight-normal: 400;
--font-weight-headings: 700;';
}
} else {
$wa->registerAndUseStyle('fontscheme.current', $paramsFontScheme, ['version' => 'auto'], ['media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'']);
$this->getPreloadManager()->preload($wa->getAsset('style', 'fontscheme.current')->getUri() . '?' . $this->getMediaVersion(), ['as' => 'style']);
}
} }
// Enable assets // ------------------ Scripts ------------------
$wa->usePreset('template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')) $wa->useScript('theme-init.js');
->useStyle('template.active.language') if ($themeFab === 1) {
->useStyle('template.user') $wa->useScript('darkmode-toggle.js');
->useScript('template.user') }
->addInlineStyle(":root { if ($gtmEnabled === 1) {
--hue: 214; $wa->useScript('gtm.js');
--template-bg-light: #f0f4fb; }
--template-text-dark: #495057;
--template-text-light: #ffffff;
--template-link-color: #2a69b8;
--template-special-color: #001B4C;
$fontStyles
}");
// Override 'template.active' asset to set correct ltr/rtl dependency // Optional Font Awesome 6 Kit (preferred) or FA5 fallback
$wa->registerStyle('template.active', '', [], [], ['template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')]); if (!empty($fa6KitCode)) {
HTMLHelper::_('script', 'https://kit.fontawesome.com/' . rawurlencode($fa6KitCode) . '.js', [
// Browsers support SVG favicons 'crossorigin' => 'anonymous'
$this->addHeadLink(HTMLHelper::_('image', 'joomla-favicon.svg', '', [], true, 1), 'icon', 'rel', ['type' => 'image/svg+xml']); ]);
$this->addHeadLink(HTMLHelper::_('image', 'favicon.ico', '', [], true, 1), 'alternate icon', 'rel', ['type' => 'image/vnd.microsoft.icon']);
$this->addHeadLink(HTMLHelper::_('image', 'joomla-favicon-pinned.svg', '', [], true, 1), 'mask-icon', 'rel', ['color' => '#000']);
// Logo file or site title param
if ($this->params->get('logoFile')) {
$logo = HTMLHelper::_('image', Uri::root(false) . htmlspecialchars($this->params->get('logoFile'), ENT_QUOTES), $sitename, ['loading' => 'eager', 'decoding' => 'async'], false, 0);
} elseif ($this->params->get('siteTitle')) {
$logo = '<span title="' . $sitename . '">' . htmlspecialchars($this->params->get('siteTitle'), ENT_COMPAT, 'UTF-8') . '</span>';
} else { } else {
$logo = HTMLHelper::_('image', 'logo.svg', $sitename, ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], true, 0); HTMLHelper::_('stylesheet', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css', ['version' => 'auto'], [
'crossorigin' => 'anonymous',
'referrerpolicy' => 'no-referrer',
]);
} }
// Container // ------------------ Context (logo, bootstrap needs) ------------------
$wrapper = $this->params->get('fluidContainer') ? 'wrapper-fluid' : 'wrapper-static'; $sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8');
$this->setMetaData('viewport', 'width=device-width, initial-scale=1'); // Build logo/title
if ($params->get('logoFile')) {
$logo = HTMLHelper::_(
'image',
Uri::root(false) . htmlspecialchars($params->get('logoFile'), ENT_QUOTES),
$sitename,
['loading' => 'eager', 'decoding' => 'async'],
false,
0
);
} elseif ($params->get('siteTitle')) {
$logo = '<span title="' . $sitename . '">' . htmlspecialchars($params->get('siteTitle'), ENT_COMPAT, 'UTF-8') . '</span>';
} else {
$logo = HTMLHelper::_('image', 'full_logo.png', $sitename, ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], true, 0);
}
// Defer font awesome // ------------------ Error details ------------------
$wa->getAsset('style', 'fontawesome')->setAttribute('rel', 'lazy-stylesheet'); $errorObj = isset($this->error) && is_object($this->error) ? $this->error : null;
$errorCode = $errorObj ? (int) $errorObj->getCode() : 500;
$errorMsg = $errorObj ? $errorObj->getMessage() : Text::_('JERROR_AN_ERROR_HAS_OCCURRED');
$debugOn = defined('JDEBUG') && JDEBUG;
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>"> <html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head> <head>
<jdoc:include type="metas" /> <meta charset="utf-8" />
<jdoc:include type="styles" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<jdoc:include type="scripts" /> <meta name="theme-color" content="#ffffff" id="meta-theme-color" />
<jdoc:include type="head" />
</head> </head>
<body data-theme-fab-pos="<?php echo htmlspecialchars($fABodyPos, ENT_QUOTES, 'UTF-8'); ?>">
<?php if ($gtmEnabled === 1 && !empty($gtmId)) : ?>
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=<?php echo htmlspecialchars($gtmId, ENT_QUOTES, 'UTF-8'); ?>"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->
<?php endif; ?>
<body class="site error_site <?php echo $option <!-- ========== DUPLICATED HEADER FROM INDEX ========== -->
. ' ' . $wrapper <header class="header container-header full-width<?php echo $stickyHeader ? ' position-sticky sticky-top' : ''; ?>">
. ' view-' . $view <?php if ($this->countModules('topbar')) : ?>
. ($layout ? ' layout-' . $layout : ' no-layout') <div class="container-topbar">
. ($task ? ' task-' . $task : ' no-task') <jdoc:include type="modules" name="topbar" style="none" />
. ($itemid ? ' itemid-' . $itemid : '') </div>
. ' ' . $pageclass; <?php endif; ?>
echo ($this->direction == 'rtl' ? ' rtl' : '');
?>">
<header class="header container-header full-width"> <div class="header-top">
<?php if ($this->params->get('brand', 1)) : ?> <?php if ($this->countModules('below-topbar')) : ?>
<div class="grid-child"> <div class="grid-child container-below-topbar">
<div class="navbar-brand"> <jdoc:include type="modules" name="below-topbar" style="none" />
<a class="brand-logo" href="<?php echo $this->baseurl; ?>/"> </div>
<?php echo $logo; ?> <?php endif; ?>
</a>
<?php if ($this->params->get('siteDescription')) : ?>
<div class="site-description"><?php echo htmlspecialchars($this->params->get('siteDescription')); ?></div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if ($this->countModules('menu') || $this->countModules('search')) : ?>
<div class="grid-child container-nav">
<?php if ($this->countModules('menu')) : ?>
<jdoc:include type="modules" name="menu" style="none" />
<?php endif; ?>
<?php if ($this->countModules('search')) : ?>
<div class="container-search">
<jdoc:include type="modules" name="search" style="none" />
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</header>
<div class="site-grid"> <?php if ($brandEnabled) : ?>
<div class="grid-child container-component"> <div class="grid-child">
<h1 class="page-header"><?php echo Text::_('JERROR_LAYOUT_PAGE_NOT_FOUND'); ?></h1> <div class="navbar-brand">
<div class="card"> <a class="brand-logo" href="<?php echo $this->baseurl; ?>/">
<div class="card-body"> <?php echo $logo; ?>
<jdoc:include type="message" /> </a>
<p><strong><?php echo Text::_('JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST'); ?></strong></p> <?php if (!empty($siteDescription)) : ?>
<p><?php echo Text::_('JERROR_LAYOUT_NOT_ABLE_TO_VISIT'); ?></p> <div class="site-description"><?php echo htmlspecialchars($siteDescription); ?></div>
<ul> <?php endif; ?>
<li><?php echo Text::_('JERROR_LAYOUT_AN_OUT_OF_DATE_BOOKMARK_FAVOURITE'); ?></li> </div>
<li><?php echo Text::_('JERROR_LAYOUT_MIS_TYPED_ADDRESS'); ?></li> </div>
<li><?php echo Text::_('JERROR_LAYOUT_SEARCH_ENGINE_OUT_OF_DATE_LISTING'); ?></li> <?php endif; ?>
<li><?php echo Text::_('JERROR_LAYOUT_YOU_HAVE_NO_ACCESS_TO_THIS_PAGE'); ?></li>
</ul>
<p><?php echo Text::_('JERROR_LAYOUT_GO_TO_THE_HOME_PAGE'); ?></p>
<p><a href="<?php echo $this->baseurl; ?>/index.php" class="btn btn-secondary"><span class="icon-home" aria-hidden="true"></span> <?php echo Text::_('JERROR_LAYOUT_HOME_PAGE'); ?></a></p>
<hr>
<p><?php echo Text::_('JERROR_LAYOUT_PLEASE_CONTACT_THE_SYSTEM_ADMINISTRATOR'); ?></p>
<blockquote>
<span class="badge bg-secondary"><?php echo $this->error->getCode(); ?></span> <?php echo htmlspecialchars($this->error->getMessage(), ENT_QUOTES, 'UTF-8'); ?>
</blockquote>
<?php if ($this->debug) : ?>
<div>
<?php echo $this->renderBacktrace(); ?>
<?php // Check if there are more Exceptions and render their data as well ?>
<?php if ($this->error->getPrevious()) : ?>
<?php $loop = true; ?>
<?php // Reference $this->_error here and in the loop as setError() assigns errors to this property and we need this for the backtrace to work correctly ?>
<?php // Make the first assignment to setError() outside the loop so the loop does not skip Exceptions ?>
<?php $this->setError($this->_error->getPrevious()); ?>
<?php while ($loop === true) : ?>
<p><strong><?php echo Text::_('JERROR_LAYOUT_PREVIOUS_ERROR'); ?></strong></p>
<p><?php echo htmlspecialchars($this->_error->getMessage(), ENT_QUOTES, 'UTF-8'); ?></p>
<?php echo $this->renderBacktrace(); ?>
<?php $loop = $this->setError($this->_error->getPrevious()); ?>
<?php endwhile; ?>
<?php // Reset the main error object to the base error ?>
<?php $this->setError($this->error); ?>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php if ($this->countModules('footer')) : ?>
<footer class="container-footer footer full-width">
<div class="grid-child">
<jdoc:include type="modules" name="footer" style="none" />
</div>
</footer>
<?php endif; ?>
<jdoc:include type="modules" name="debug" style="none" /> <?php if ($this->countModules('below-logo')) : ?>
<div class="grid container-below-logo">
<jdoc:include type="modules" name="below-logo" style="none" />
</div>
<?php endif; ?>
</div>
<?php if ($this->countModules('menu', true) || $this->countModules('search', true)) : ?>
<div class="grid-child container-nav">
<?php if ($this->countModules('menu', true)) : ?>
<jdoc:include type="modules" name="menu" style="none" />
<?php endif; ?>
<?php if ($this->countModules('search', true)) : ?>
<div class="container-search">
<jdoc:include type="modules" name="search" style="none" />
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</header>
<!-- ========== END DUPLICATED HEADER ========== -->
<main class="container my-4">
<div class="card border-0 shadow-sm mb-4">
<div class="card-body">
<h1 class="h3">
<span class="text-muted"><?php echo Text::_('JERROR_LAYOUT_ERROR_HAS_OCCURRED'); ?>:</span>
<strong><?php echo (int) $errorCode; ?></strong>
</h1>
<p class="lead mb-1">
<?php echo htmlspecialchars($errorMsg, ENT_QUOTES, 'UTF-8'); ?>
</p>
<p class="text-muted mb-0">
<?php echo Text::_('JERROR_LAYOUT_PLEASE_TRY_ONE_OF_THE_FOLLOWING_PAGES'); ?>
</p>
</div>
</div>
<div class="d-flex gap-2 flex-wrap">
<a class="btn btn-primary" href="<?php echo htmlspecialchars(Uri::base(), ENT_QUOTES, 'UTF-8'); ?>">
<i class="fas fa-home me-1" aria-hidden="true"></i>
<?php echo Text::_('JERROR_LAYOUT_HOME_PAGE'); ?>
</a>
<button class="btn btn-outline-secondary" type="button" onclick="history.back();">
<i class="fas fa-arrow-left me-1" aria-hidden="true"></i>
<?php echo Text::_('JPREV'); ?>
</button>
</div>
<?php if ($debugOn && $errorObj) : ?>
<section class="mt-4" role="region" aria-label="Debug Details">
<div class="alert alert-warning"><strong>Debug mode is ON</strong> — detailed error information is shown below.</div>
<div class="card mb-3">
<div class="card-header fw-bold">Exception</div>
<div class="card-body small">
<dl class="row mb-0">
<dt class="col-sm-3">Class</dt>
<dd class="col-sm-9"><?php echo htmlspecialchars(get_class($errorObj), ENT_QUOTES, 'UTF-8'); ?></dd>
<dt class="col-sm-3">Code</dt>
<dd class="col-sm-9"><?php echo (int) $errorObj->getCode(); ?></dd>
<dt class="col-sm-3">Message</dt>
<dd class="col-sm-9 text-break"><?php echo htmlspecialchars($errorObj->getMessage(), ENT_QUOTES, 'UTF-8'); ?></dd>
<dt class="col-sm-3">File</dt>
<dd class="col-sm-9 text-break"><?php echo htmlspecialchars($errorObj->getFile(), ENT_QUOTES, 'UTF-8'); ?> : <?php echo (int) $errorObj->getLine(); ?></dd>
</dl>
</div>
</div>
<?php $trace = method_exists($errorObj, 'getTrace') ? $errorObj->getTrace() : []; ?>
<div class="card mb-3">
<div class="card-header fw-bold">Stack Trace (<?php echo count($trace); ?> frames)</div>
<div class="card-body small">
<?php if ($trace) : ?>
<ol class="mb-0 ps-3">
<?php foreach ($trace as $i => $frame) :
$file = $frame['file'] ?? '[internal]';
$line = isset($frame['line']) ? (int) $frame['line'] : 0;
$func = $frame['function'] ?? '';
$class= $frame['class'] ?? '';
$type = $frame['type'] ?? '';
?>
<li class="mb-2">
<div class="text-break"><code>#<?php echo $i; ?></code> <?php echo htmlspecialchars($class . $type . $func, ENT_QUOTES, 'UTF-8'); ?>()</div>
<div class="text-muted"><?php echo htmlspecialchars($file, ENT_QUOTES, 'UTF-8'); ?><?php echo $line ? ':' . $line : ''; ?></div>
</li>
<?php endforeach; ?>
</ol>
<?php else : ?>
<em>No stack trace available.</em>
<?php endif; ?>
</div>
</div>
</section>
<?php endif; ?>
</main>
<footer class="container-footer footer full-width py-4">
<?php if ($this->countModules('footer-menu', true)) : ?>
<div class="grid-child footer-menu">
<jdoc:include type="modules" name="footer-menu" />
</div>
<?php endif; ?>
<?php if ($this->countModules('footer', true)) : ?>
<div class="grid-child">
<jdoc:include type="modules" name="footer" style="none" />
</div>
<?php endif; ?>
</footer>
<jdoc:include type="modules" name="debug" style="none" />
</body> </body>
</html> </html>

View File

@@ -1,110 +1,151 @@
{ {
"$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json",
"name": "moko-cassiopeia", "name": "tpl_moko-cassiopeia",
"version": "4.0.0", "version": "02.00",
"description": "This file contains details of the assets used by moko-cassiopeia, the default Joomla 4 site template.", "description": "Moko-Cassiopeia template assets",
"license": "GPL-2.0-or-later", "license": "GPL-3.0-or-later",
"assets": [ "x-header":
{ {
"name": "template.MOKO-CASSIOPEIA.ltr", "copyright_year": 2025,
"description": "The css file to be used when the site is left to right (LTR).", "author": "Jonathan Miller",
"type": "style", "owner": "Moko Consulting",
"uri": "template.min.css", "contact": "hello@mokoconsulting.tech",
"dependencies": [ "project": "Moko-Cassiopeia Template",
"fontawesome" "spdx_license": "GPL-3.0-or-later",
] "notice": "This file is part of a Moko Consulting project.",
}, "disclaimer": "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License; 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/."
{ },
"name": "template.MOKO-CASSIOPEIA.rtl", "assets": [
"description": "The css file to be used when the site is right to left (RTL).", {
"type": "style", "name": "template.base",
"uri": "template-rtl.min.css", "type": "style",
"dependencies": [ "uri": "media/templates/site/moko-cassiopeia/css/template.css",
"fontawesome" "attributes":
] {
}, "media": "all"
{ }
"name": "template.offline", },
"description": "The css file to be used when the site is offline and offline.php is being used.", {
"type": "style", "name": "template.user",
"uri": "offline.css" "type": "style",
}, "uri": "media/templates/site/moko-cassiopeia/css/user.css",
{ "attributes":
"name": "template.active.language", {
"description": "An asset to allow language specific css, eg 'language/[lang-CODE]/[lang-CODE].css', to use it as a dependency to the active template", "media": "all"
"type": "style", }
"uri": "", },
"class": "LangActiveAssetItem", {
"dependencies": [ "name": "template.editor",
"template.active" "type": "style",
] "uri": "media/templates/site/moko-cassiopeia/css/editor.css",
}, "attributes":
{ {
"name": "template.user", "media": "all"
"description": "A file where a user can add their own css.", }
"type": "style", },
"uri": "user.css", {
"weight": 500, "name": "vendor.vmbasic",
"dependencies": [ "type": "style",
"template.active", "uri": "media/templates/site/moko-cassiopeia/css/vendor/vmbasic.css",
"template.active.language" "attributes":
] {
}, "media": "all"
{ }
"name": "template.MOKO-CASSIOPEIA", },
"description": "The file containing the javascript for this template.", {
"type": "script", "name": "vendor.gable",
"uri": "template.js", "type": "style",
"attributes" : { "uri": "media/templates/site/moko-cassiopeia/css/vendor/gable.css",
"defer": true "attributes":
}, {
"dependencies": [ "media": "all"
"core" }
] },
}, {
{ "name": "vendor.bootstrap-toc",
"name": "template.active", "type": "style",
"description": "A dummy asset to allow extensions to use it as a dependency to the active template.", "uri": "media/templates/site/moko-cassiopeia/css/vendor/afeld/bootstrap-toc.min.css",
"type": "script", "attributes":
"uri": "", {
"dependencies": [ "media": "all"
"template.MOKO-CASSIOPEIA" }
] },
}, {
{ "name": "template.light.colors_standard",
"name": "template.user", "type": "style",
"description": "The name of a file where a user can add their own javascript", "uri": "media/templates/site/moko-cassiopeia/css/global/colors/light/colors_standard.css"
"type": "script", },
"uri": "user.js", {
"dependencies": [ "name": "template.light.colors_alternative",
"template.active" "type": "style",
] "uri": "media/templates/site/moko-cassiopeia/css/global/colors/light/colors_alternative.css"
}, },
{ {
"name": "template.MOKO-CASSIOPEIA.ltr", "name": "template.light.colors_custom",
"type": "preset", "type": "style",
"dependencies": [ "uri": "media/templates/site/moko-cassiopeia/css/global/colors/light/colors_custom.css"
"template.MOKO-CASSIOPEIA.ltr#style", },
"template.MOKO-CASSIOPEIA#script"
] {
}, "name": "template.dark.colors_standard",
{ "type": "style",
"name": "template.MOKO-CASSIOPEIA.rtl", "uri": "media/templates/site/moko-cassiopeia/css/global/colors/dark/colors_standard.css"
"type": "preset", },
"dependencies": [ {
"template.MOKO-CASSIOPEIA.rtl#style", "name": "template.dark.colors_alternative",
"template.MOKO-CASSIOPEIA#script" "type": "style",
] "uri": "media/templates/site/moko-cassiopeia/css/global/colors/dark/colors_alternative.css"
}, },
{ {
"name": "searchtools", "name": "template.dark.colors_custom",
"type": "style", "type": "style",
"uri": "system/searchtools/searchtools.min.css" "uri": "media/templates/site/moko-cassiopeia/css/global/colors/dark/colors_custom.css"
}, },
{
"name": "fontawesome", {
"type": "style", "name": "template.js",
"uri": "system/joomla-fontawesome.min.css" "type": "script",
} "uri": "media/templates/site/moko-cassiopeia/js/template.js",
] "attributes":
{
"defer": true
}
},
{
"name": "theme-init.js",
"type": "script",
"uri": "media/templates/site/moko-cassiopeia/js/theme-init.js",
"attributes":
{
"defer": true
}
},
{
"name": "darkmode-toggle.js",
"type": "script",
"uri": "media/templates/site/moko-cassiopeia/js/darkmode-toggle.js",
"attributes":
{
"defer": true
}
},
{
"name": "gtm.js",
"type": "script",
"uri": "media/templates/site/moko-cassiopeia/js/gtm.js",
"attributes":
{
"defer": true
}
},
{
"name": "vendor.bootstrap-toc.js",
"type": "script",
"uri": "media/templates/site/moko-cassiopeia/js/vendor/afeld/bootstrap-toc.min.js",
"attributes":
{
"defer": true
}
}
]
} }

View File

@@ -1,263 +1,91 @@
<?php <?php
/** /**
* @package Joomla.Site * @package Joomla.Site
* @subpackage Templates.moko-cassiopeia * @subpackage Templates.Moko-Cassiopeia
* @file /templates/moko-cassiopeia/offline.php
* *
* @copyright © 2025 Moko Consulting — All Rights Reserved * Offline template that explicitly loads css/template.css and css/colors_*.css.
* @license GNU General Public License version 2 or later; see LICENSE.txt * Includes: site-name-in-title rules, brand (logo OR title), theme switcher,
* * module positions (offline-header, offline), and login inside Bootstrap accordion.
* Website: https://mokoconsulting.tech
* Email: hello@mokoconsulting.tech
* Phone: +1 (931) 279-6313
*/ */
declare(strict_types=1);
defined('_JEXEC') or die; defined('_JEXEC') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory; use Joomla\CMS\Factory;
use Joomla\CMS\Helper\AuthenticationHelper;
use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text; use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route; use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri; use Joomla\CMS\Uri\Uri;
/** @var Joomla\CMS\Document\HtmlDocument $this */ /**
* @var \Joomla\CMS\Document\HtmlDocument $this
* @var \Joomla\Registry\Registry $this->params
* @var string $this->language
* @var string $this->direction
*/
$extraButtons = AuthenticationHelper::getLoginButtons('form-login'); $app = Factory::getApplication();
$app = Factory::getApplication(); $doc = Factory::getDocument();
$wa = $this->getWebAssetManager(); $params = $this->params ?: $app->getTemplate(true)->params;
$direction = $this->direction ?: 'ltr';
/* -----------------------
Load ONLY template.css + colors_*.css (with min toggle)
------------------------ */
$useMin = !((int) $params->get('development_mode', 0) === 1);
$assetSuffix = $useMin ? '.min' : '';
$base = rtrim(Uri::root(true), '/') . '/templates/' . $this->template . '/css/';
if ($this->params->get('offlineEmbed')) { $doc->addStyleSheet($base . 'template' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-template']);
$fullWidth = 1; /* If you have a template param for color variant, set it here; defaults to 'standard' */
$colorKey = (string) ($params->get('colors', 'standard') ?: 'standard');
$colorKey = preg_replace('~[^a-z0-9_-]~i', '', $colorKey);
$doc->addStyleSheet($base . 'colors_' . $colorKey . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-colors']);
/* Bootstrap CSS/JS for accordion behavior; safe to keep. */
HTMLHelper::_('bootstrap.loadCss', true, $doc);
HTMLHelper::_('bootstrap.framework');
/* -----------------------
Title + Meta (Include Site Name in Page Titles)
------------------------ */
$sitename = (string) $app->get('sitename');
$baseTitle = Text::_('JGLOBAL_OFFLINE') ?: 'Offline';
$snSetting = (int) $app->get('sitename_pagetitles', 0); // 0=no, 1=before, 2=after
if ($snSetting === 1) {
$doc->setTitle(Text::sprintf('JPAGETITLE', $sitename, $baseTitle)); // Site Name BEFORE
} elseif ($snSetting === 2) {
$doc->setTitle(Text::sprintf('JPAGETITLE', $baseTitle, $sitename)); // Site Name AFTER
} else { } else {
$fullWidth = 0; $doc->setTitle($baseTitle);
} }
$doc->setMetaData('robots', 'noindex, nofollow');
// Template path /* -----------------------
$templatePath = 'media/templates/site/moko-cassiopeia'; Offline content from Global Config
------------------------ */
// Color Theme $displayOfflineMessage = (int) $app->get('display_offline_message', 1); // 0|1|2
$paramsColorName = $this->params->get('colorName', 'colors_standard'); $offlineMessage = trim((string) $app->get('offline_message', ''));
$assetColorName = 'theme.' . $paramsColorName;
$wa->registerAndUseStyle($assetColorName, $templatePath . '/css/global/' . $paramsColorName . '.css');
// Use a font scheme if set in the template style options
$paramsFontScheme = $this->params->get('useFontScheme', false);
$fontStyles = '';
if ($paramsFontScheme) {
if (stripos($paramsFontScheme, 'https://') === 0) {
$this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']);
$this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']);
$this->getPreloadManager()->preload($paramsFontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']);
$wa->registerAndUseStyle('fontscheme.current', $paramsFontScheme, [], ['media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'', 'crossorigin' => 'anonymous']);
if (preg_match_all('/family=([^?:]*):/i', $paramsFontScheme, $matches) > 0) {
$fontStyles = '--font-family-body: "' . str_replace('+', ' ', $matches[1][0]) . '", sans-serif;
--font-family-headings: "' . str_replace('+', ' ', isset($matches[1][1]) ? $matches[1][1] : $matches[1][0]) . '", sans-serif;
--font-weight-normal: 400;
--font-weight-headings: 700;';
}
} else {
$wa->registerAndUseStyle('fontscheme.current', $paramsFontScheme, ['version' => 'auto'], ['media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'']);
$this->getPreloadManager()->preload($wa->getAsset('style', 'fontscheme.current')->getUri() . '?' . $this->getMediaVersion(), ['as' => 'style']);
}
}
// Enable assets
$wa->usePreset('template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr'))
->useStyle('template.active.language')
->useStyle('template.offline')
->useStyle('template.user')
->useScript('template.user')
->addInlineStyle(":root {
--hue: 214;
--template-bg-light: #f0f4fb;
--template-text-dark: #495057;
--template-text-light: #ffffff;
--template-link-color: #2a69b8;
--template-special-color: #001B4C;
$fontStyles
}");
// Override 'template.active' asset to set correct ltr/rtl dependency
$wa->registerStyle('template.active', '', [], [], ['template.MOKO-CASSIOPEIA.' . ($this->direction === 'rtl' ? 'rtl' : 'ltr')]);
$this->addStyleSheet('//cdn-images.mailchimp.com/embedcode/classic-061523.css');
// Logo file or site title param
$sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8');
// Browsers support SVG favicons
$this->addHeadLink(HTMLHelper::_('image', 'favicon.svg', '', [], true, 1), 'icon', 'rel', ['type' => 'image/svg+xml']);
$this->addHeadLink(HTMLHelper::_('image', 'favicon.ico', '', [], true, 1), 'alternate icon', 'rel', ['type' => 'image/vnd.microsoft.icon']);
$this->addHeadLink(HTMLHelper::_('image', 'favicon.svg', '', [], true, 1), 'mask-icon', 'rel', ['color' => '#fff']);
//add Bootsrap 5 Support
HTMLHelper::_('bootstrap.alert');
HTMLHelper::_('bootstrap.button');
HTMLHelper::_('bootstrap.carousel');
HTMLHelper::_('bootstrap.collapse');
HTMLHelper::_('bootstrap.dropdown');
HTMLHelper::_('bootstrap.modal');
HTMLHelper::_('bootstrap.offcanvas');
HTMLHelper::_('bootstrap.popover');
HTMLHelper::_('bootstrap.scrollspy');
HTMLHelper::_('bootstrap.tab');
HTMLHelper::_('bootstrap.tooltip');
HTMLHelper::_('bootstrap.toast');
if ($this->params->get('logoFile')) {
$logo = HTMLHelper::_('image', Uri::root(false) . htmlspecialchars($this->params->get('logoFile'), ENT_QUOTES), $sitename, ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], false, 0);
} elseif ($this->params->get('siteTitle')) {
$logo = '<span title="' . $sitename . '">' . htmlspecialchars($this->params->get('siteTitle'), ENT_COMPAT, 'UTF-8') . '</span>';
} else {
$logo = HTMLHelper::_('image', 'logo.svg', $sitename, ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], true, 0);
}
if($this->params->get('fA6KitCode')){
//build unique kit embed code
$fa6Kit="https://kit.fontawesome.com/".$this->params->get('fA6KitCode').".js";
//adding FontAwesome V6 Kit Code
JHtml::_('script', $fa6Kit, array('crossorigin' => 'anonymous'));
} else {
// Defer fontawesome for increased performance. Once the page is loaded javascript changes it to a stylesheet.
$wa->getAsset('style', 'fontawesome')->setAttribute('rel', 'lazy-stylesheet');
}
if ($app->get('offline_image')){
//echo HTMLHelper::_('image', $app->get('offline_image'), $sitename, ['class' => 'offline-image'], false, 0);
$backgroundstyle='
body {
background-image: url('.$app->get('offline_image').');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
}';
$this->addStyleDeclaration($backgroundstyle);
}
?>
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
<jdoc:include type="metas" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<jdoc:include type="styles" />
<jdoc:include type="scripts" />
</head>
<body class="site">
<div class="outer">
<div class="offline-card">
<div class="header">
<?php if (!empty($logo)) : ?>
<h1><?php echo $logo; ?></h1>
<?php else : ?>
<h1><?php echo $sitename; ?></h1>
<?php endif; ?>
<?php if ($this->countModules('offline-header')) : ?>
<jdoc:include type="modules" name="offline-header" style="none" />
<?php endif; ?></div><div class="offline-message">
<?php if ($app->get('display_offline_message', 1) == 1 && str_replace(' ', '', $app->get('offline_message')) != '') : ?>
<p><?php echo $app->get('offline_message'); ?></p>
<?php elseif ($app->get('display_offline_message', 1) == 2) : ?>
<p><?php echo Text::_('JOFFLINE_MESSAGE'); ?></p>
<?php endif; ?></div>
<?php if ($this->countModules('offline')) : ?>
<jdoc:include type="modules" name="offline" style="none" />
<?php endif; ?></div>
</div>
<a id="offline-login-link" data-bs-toggle="collapse" href="#collapseLogin" role="button" aria-expanded="false" aria-controls="collapseLogin">
<div class="logo-icon">
<svg version="1.1" xmlns="https://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 74.8 74.8" enable-background="new 0 0 74.8 74.8" xml:space="preserve">
<title>Login Override</title>
<g id="brandmark">
<path id="j-green" fill="#1C3D5C" d="M13.5,37.7L12,36.3c-4.5-4.5-5.8-10.8-4.2-16.5c-4.5-1-7.8-5-7.8-9.8c0-5.5,4.5-10,10-10 c5,0,9.1,3.6,9.9,8.4c5.4-1.3,11.3,0.2,15.5,4.4l0.6,0.6l-7.4,7.4l-0.6-0.6c-2.4-2.4-6.3-2.4-8.7,0c-2.4,2.4-2.4,6.3,0,8.7l1.4,1.4 l7.4,7.4l7.8,7.8l-7.4,7.4l-7.8-7.8L13.5,37.7L13.5,37.7z"/>
<path id="j-orange" fill="#1C3D5C" d="M21.8,29.5l7.8-7.8l7.4-7.4l1.4-1.4C42.9,8.4,49.2,7,54.8,8.6C55.5,3.8,59.7,0,64.8,0 c5.5,0,10,4.5,10,10c0,5.1-3.8,9.3-8.7,9.9c1.6,5.6,0.2,11.9-4.2,16.3l-0.6,0.6l-7.4-7.4l0.6-0.6c2.4-2.4,2.4-6.3,0-8.7 c-2.4-2.4-6.3-2.4-8.7,0l-1.4,1.4L37,29l-7.8,7.8L21.8,29.5L21.8,29.5z"/>
<path id="j-red" fill="#1C3D5C" d="M55,66.8c-5.7,1.7-12.1,0.4-16.6-4.1l-0.6-0.6l7.4-7.4l0.6,0.6c2.4,2.4,6.3,2.4,8.7,0 c2.4-2.4,2.4-6.3,0-8.7L53,45.1l-7.4-7.4l-7.8-7.8l7.4-7.4l7.8,7.8l7.4,7.4l1.5,1.5c4.2,4.2,5.7,10.2,4.4,15.7 c4.9,0.7,8.6,4.9,8.6,9.9c0,5.5-4.5,10-10,10C60,74.8,56,71.3,55,66.8L55,66.8z"/>
<path id="j-blue" fill="#1C3D5C" d="M52.2,46l-7.8,7.8L37,61.2l-1.4,1.4c-4.3,4.3-10.3,5.7-15.7,4.4c-1,4.5-5,7.8-9.8,7.8 c-5.5,0-10-4.5-10-10C0,60,3.3,56.1,7.7,55C6.3,49.5,7.8,43.5,12,39.2l0.6-0.6L20,46l-0.6,0.6c-2.4,2.4-2.4,6.3,0,8.7 c2.4,2.4,6.3,2.4,8.7,0l1.4-1.4l7.4-7.4l7.8-7.8L52.2,46L52.2,46z"/>
</g>
</svg>
</div></a>
<div class="collapse" id="collapseLogin">
<div class="login">
<jdoc:include type="message" />
<form action="<?php echo Route::_('index.php', true); ?>" method="post" id="form-login">
<fieldset>
<label for="username"><?php echo Text::_('JGLOBAL_USERNAME'); ?></label>
<input name="username" class="form-control" id="username" type="text">
<label for="password"><?php echo Text::_('JGLOBAL_PASSWORD'); ?></label>
<input name="password" class="form-control" id="password" type="password">
<?php foreach ($extraButtons as $button) :
$dataAttributeKeys = array_filter(array_keys($button), function ($key) {
return substr($key, 0, 5) == 'data-';
});
?>
<div class="mod-login__submit form-group">
<button type="button"
class="btn btn-secondary w-100 mt-4 <?php echo $button['class'] ?? '' ?>"
<?php foreach ($dataAttributeKeys as $key) : ?>
<?php echo $key ?>="<?php echo $button[$key] ?>"
<?php endforeach; ?>
<?php if ($button['onclick']) : ?>
onclick="<?php echo $button['onclick'] ?>"
<?php endif; ?>
title="<?php echo Text::_($button['label']) ?>"
id="<?php echo $button['id'] ?>"
>
<?php if (!empty($button['icon'])) : ?>
<span class="<?php echo $button['icon'] ?>"></span>
<?php elseif (!empty($button['image'])) : ?>
<?php echo $button['image']; ?>
<?php elseif (!empty($button['svg'])) : ?>
<?php echo $button['svg']; ?>
<?php endif; ?>
<?php echo Text::_($button['label']) ?>
</button>
</div>
<?php endforeach; ?>
<button type="submit" name="Submit" class="btn btn-primary"><?php echo Text::_('JLOGIN'); ?></button>
<input type="hidden" name="option" value="com_users">
<input type="hidden" name="task" value="user.login">
<input type="hidden" name="return" value="<?php echo base64_encode(Uri::base()); ?>">
<?php echo HTMLHelper::_('form.token'); ?>
</fieldset>
</form>
</div>
</div></div>
<?php if ($this->countModules('offline-footer')) : ?>
<jdoc:include type="modules" name="offline-footer" style="none" />
<?php endif; ?>
<footer class="container-footer footer full-width">
<?php if ($this->countModules('footer-menu', true)) : ?>
<div class="grid-child footer-menu">
<jdoc:include type="modules" name="footer-menu" />
</div>
<?php endif; ?>
<?php if ($this->countModules('footer')) : ?>
<jdoc:include type="modules" name="footer" style="none" />
<?php endif; ?>
</footer>
</div>
</div>
<?php if ($this->params->get('backTop') == 1) : ?>
<a href="#top" id="back-top" class="back-to-top-link" aria-label="<?php echo Text::_('TPL_MOKO-CASSIOPEIA_BACKTOTOP'); ?>">
<span class="icon-arrow-up icon-fw" aria-hidden="true"></span>
</a>
<?php endif; ?>
<jdoc:include type="modules" name="debug" style="none" />
</body>
</html>
/* -----------------------
Brand (mutually exclusive: logoFile OR siteTitle)
------------------------ */
if ($params->get('logoFile')) {
$logo = HTMLHelper::_(
'image',
Uri::root(false) . htmlspecialchars((string) $params->get('logoFile'), ENT_QUOTES, 'UTF-8'),
$sitename,
[
'class' => 'logo d-inline-block',
'loading' => 'eager',
'decoding' => 'async',
'style' => 'max-height:64px;height:auto;width:auto;'
],
false,
0
);
} elseif ($params->get('siteTitle')) {
$logo = '<sp

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
© 2025 Moko Consulting — All Rights Reserved @copyright © 2025 Moko Consulting — All Rights Reserved
@license GNU General Public License version 2 or later; see LICENSE.txt @license GNU General Public License version 2 or later; see LICENSE.txt
Website: https://mokoconsulting.tech Website: https://mokoconsulting.tech
@@ -21,8 +21,8 @@
<server type="extension" name="Moko Consulting">https://raw.githubusercontent.com/mokoconsulting-tech/MokoUpdates/refs/heads/main/joomla/moko-cassiopeia/updates.xml</server> <server type="extension" name="Moko Consulting">https://raw.githubusercontent.com/mokoconsulting-tech/MokoUpdates/refs/heads/main/joomla/moko-cassiopeia/updates.xml</server>
</updateservers> </updateservers>
<name>moko-cassiopeia</name> <name>moko-cassiopeia</name>
<version>1.15</version> <version>02.00</version>
<creationDate>2025-08-20</creationDate> <creationDate>2025-08-23</creationDate>
<author>Jonathan Miller || Moko Consulting</author> <author>Jonathan Miller || Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<copyright>(C)GNU General Public License Version 2 - 2025 Moko Consulting</copyright> <copyright>(C)GNU General Public License Version 2 - 2025 Moko Consulting</copyright>
@@ -37,6 +37,9 @@
<filename>templateDetails.xml</filename> <filename>templateDetails.xml</filename>
<folder>html</folder> <folder>html</folder>
</files> </files>
<stylesheets>
<stylesheet>media/templates/site/moko-cassiopeia/css/editor.css</stylesheet>
</stylesheets>
<media destination="templates/site/moko-cassiopeia" folder="media"> <media destination="templates/site/moko-cassiopeia" folder="media">
<folder>js</folder> <folder>js</folder>
<folder>css</folder> <folder>css</folder>
@@ -76,52 +79,21 @@
</languages> </languages>
<config> <config>
<fields name="params"> <fields name="params">
<!-- Advanced tab (non-theme/system options only) -->
<fieldset name="advanced"> <fieldset name="advanced">
<!--
<field name="developmentmode" type="radio" label="TPL_MOKO-CASSIOPEIA_DEVELOPMENTMODE_LABEL" description="TPL_MOKO-CASSIOPEIA_DEVELOPMENTMODE_DESC" default="1" layout="joomla.form.field.radio.switcher" filter="boolean"> <field name="developmentmode" type="radio" label="TPL_MOKO-CASSIOPEIA_DEVELOPMENTMODE_LABEL" description="TPL_MOKO-CASSIOPEIA_DEVELOPMENTMODE_DESC" default="1" layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option> <option value="0">JNO</option>
<option value="1">JYES</option> <option value="1">JYES</option>
</field> </field>
<field name="brand" type="radio" label="TPL_MOKO-CASSIOPEIA_BRAND_LABEL" default="1" layout="joomla.form.field.radio.switcher" filter="boolean"> -->
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="logoFile" type="media" default="media/templates/site/moko-cassiopeia/images/logo.svg" label="TPL_MOKO-CASSIOPEIA_LOGO_LABEL" showon="brand:1" />
<field name="siteTitle" type="text" default="" label="TPL_MOKO-CASSIOPEIA_TITLE" filter="string" showon="brand:1" />
<field name="siteDescription" type="text" default="" label="TPL_MOKO-CASSIOPEIA_TAGLINE_LABEL" description="TPL_MOKO-CASSIOPEIA_TAGLINE_DESC" filter="string" showon="brand:1" />
<field name="fA6KitCode" type="text" default="" label="TPL_MOKO-CASSIOPEIA_FA6KITCODE_LABEL" description="TPL_MOKO-CASSIOPEIA_FA6KITCODE_DESC" filter="string" />
<field name="offlineEmbed" type="text" default="" label="TPL_MOKO-CASSIOPEIA_OFFLINEEMBED_LABEL" description="TPL_MOKO-CASSIOPEIA_OFFLINEEMBED_DESC" filter="raw" />
<field name="useFontScheme" type="groupedlist" label="TPL_MOKO-CASSIOPEIA_FONT_LABEL" default="0">
<option value="0">JNONE</option>
<group label="TPL_MOKO-CASSIOPEIA_FONT_GROUP_LOCAL">
<option value="media/templates/site/moko-cassiopeia/css/global/fonts-local_roboto.css">Roboto
(local)</option>
</group>
<group label="TPL_MOKO-CASSIOPEIA_FONT_GROUP_WEB">
<option value="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&amp;display=swap">Fira
Sans (web)</option>
<option value="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&amp;family=Roboto:wght@100;300;400;700&amp;display=swap">Roboto
+ Noto Sans (web)</option>
</group>
</field>
<field name="noteFontScheme" type="note" description="TPL_MOKO-CASSIOPEIA_FONT_NOTE_TEXT" class="alert alert-warning" />
<field name="colorName" type="list" label="TPL_MOKO-CASSIOPEIA_COLOR_NAME_LABEL" default="colors_standard">
<option value="colors_standard">TPL_MOKO-CASSIOPEIA_COLOR_NAME_STANDARD</option>
<option value="colors_alternative">TPL_MOKO-CASSIOPEIA_COLOR_NAME_ALTERNATIVE</option>
<option value="colors_custom">TPL_MOKO-CASSIOPEIA_COLOR_NAME_CUSTOM</option>
</field>
<field name="fluidContainer" type="radio" layout="joomla.form.field.radio.switcher" default="0" label="TPL_MOKO-CASSIOPEIA_FLUID_LABEL"> <field name="fluidContainer" type="radio" layout="joomla.form.field.radio.switcher" default="0" label="TPL_MOKO-CASSIOPEIA_FLUID_LABEL">
<option value="0">TPL_MOKO-CASSIOPEIA_STATIC</option> <option value="0">TPL_MOKO-CASSIOPEIA_STATIC</option>
<option value="1">TPL_MOKO-CASSIOPEIA_FLUID</option> <option value="1">TPL_MOKO-CASSIOPEIA_FLUID</option>
</field> </field>
<field name="stickyHeader" type="radio" label="TPL_MOKO-CASSIOPEIA_STICKY_LABEL" layout="joomla.form.field.radio.switcher" default="0" filter="integer">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="backTop" type="radio" label="TPL_MOKO-CASSIOPEIA_BACKTOTOP_LABEL" layout="joomla.form.field.radio.switcher" default="0" filter="integer">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
</fieldset> </fieldset>
<!-- Google tab -->
<fieldset name="google"> <fieldset name="google">
<field name="googletagmanager" type="radio" label="TPL_MOKO-CASSIOPEIA_GOOGLETAGMANAGER_LABEL" description="TPL_MOKO-CASSIOPEIA_GOOGLETAGMANAGER_DESC" layout="joomla.form.field.radio.switcher" filter="boolean"> <field name="googletagmanager" type="radio" label="TPL_MOKO-CASSIOPEIA_GOOGLETAGMANAGER_LABEL" description="TPL_MOKO-CASSIOPEIA_GOOGLETAGMANAGER_DESC" layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option> <option value="0">JNO</option>
@@ -134,14 +106,132 @@
</field> </field>
<field name="googleanalyticsid" type="text" default="" label="TPL_MOKO-CASSIOPEIA_GOOGLEANALYTICSID_LABEL" description="TPL_MOKO-CASSIOPEIA_GOOGLEANALYTICSID_DESC" filter="string" showon="googleanalytics:1" /> <field name="googleanalyticsid" type="text" default="" label="TPL_MOKO-CASSIOPEIA_GOOGLEANALYTICSID_LABEL" description="TPL_MOKO-CASSIOPEIA_GOOGLEANALYTICSID_DESC" filter="string" showon="googleanalytics:1" />
</fieldset> </fieldset>
<fieldset name="custom_head">
<!-- Custom Code tab -->
<fieldset name="custom_head" label="TPL_MOKO-CASSIOPEIA_CUSTOM_CODE_FIELDSET">
<field name="custom_head_start" type="textarea" default="" label="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_START_LABEL" description="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_START_DESC" filter="raw" /> <field name="custom_head_start" type="textarea" default="" label="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_START_LABEL" description="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_START_DESC" filter="raw" />
<field name="custom_head_end" type="textarea" default="" label="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_END_LABEL" description="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_END_DESC" filter="raw" /> <field name="custom_head_end" type="textarea" default="" label="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_END_LABEL" description="TPL_MOKO-CASSIOPEIA_CUSTOM_HEAD_END_DESC" filter="raw" />
</fieldset> </fieldset>
<!-- Drawers tab -->
<fieldset name="drawers"> <fieldset name="drawers">
<field name="drawerLeftIcon" type="text" default="fa-solid fa-chevron-right" label="TPL_MOKO-CASSIOPEIA_DRAWER_LEFT_ICON_LABEL" description="TPL_MOKO-CASSIOPEIA_DRAWER_LEFT_ICON_DESC" filter="string" /> <field name="drawerLeftIcon" type="text" default="fa-solid fa-chevron-right" label="TPL_MOKO-CASSIOPEIA_DRAWER_LEFT_ICON_LABEL" description="TPL_MOKO-CASSIOPEIA_DRAWER_LEFT_ICON_DESC" filter="string" />
<field name="drawerRightIcon" type="text" default="fa-solid fa-chevron-left" label="TPL_MOKO-CASSIOPEIA_DRAWER_RIGHT_ICON_LABEL" description="TPL_MOKO-CASSIOPEIA_DRAWER_RIGHT_ICON_DESC" filter="string" /> <field name="drawerRightIcon" type="text" default="fa-solid fa-chevron-left" label="TPL_MOKO-CASSIOPEIA_DRAWER_RIGHT_ICON_LABEL" description="TPL_MOKO-CASSIOPEIA_DRAWER_RIGHT_ICON_DESC" filter="string" />
</fieldset> </fieldset>
<!-- THEME TAB (all style/theme settings grouped) -->
<fieldset name="theme" label="TPL_MOKO_THEME_FIELDSET">
<!-- General -->
<field name="theme_sep_general" type="spacer" label="General" hr="false" class="text fw-bold" />
<field name="theme_enabled" type="radio" default="1"
label="TPL_MOKO_THEME_ENABLED" description="TPL_MOKO_THEME_ENABLED_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="theme_control_type" type="list" default="radios"
label="TPL_MOKO_THEME_CONTROL_TYPE" description="TPL_MOKO_THEME_CONTROL_TYPE_DESC">
<option value="switch">Switch (Light↔Dark)</option>
<option value="radios">Radios (Light/Dark/System)</option>
<option value="none">No visible control</option>
</field>
<field name="theme_default_choice" type="list" default="system"
label="TPL_MOKO_THEME_DEFAULT_CHOICE" description="TPL_MOKO_THEME_DEFAULT_CHOICE_DESC">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</field>
<field name="theme_auto_dark" type="radio" default="0"
label="TPL_MOKO_THEME_AUTO_DARK" description="TPL_MOKO_THEME_AUTO_DARK_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="theme_meta_color_scheme" type="radio" default="1"
label="TPL_MOKO_THEME_META_COLOR_SCHEME" description="TPL_MOKO_THEME_META_COLOR_SCHEME_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="theme_meta_theme_color" type="radio" default="1"
label="TPL_MOKO_THEME_META_THEME_COLOR" description="TPL_MOKO_THEME_META_THEME_COLOR_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="theme_bridge_bs_aria" type="radio" default="1"
label="TPL_MOKO_THEME_BRIDGE" description="TPL_MOKO_THEME_BRIDGE_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<!-- Variables & Palettes -->
<field name="theme_sep_vars" type="spacer" label="Variables &amp; Palettes" hr="false" class="text fw-bold" />
<field name="colorLightName" type="list" label="TPL_MOKO-CASSIOPEIA_COLOR_LIGHT_NAME_LABEL" default="colors_standard">
<option value="colors_standard">TPL_MOKO-CASSIOPEIA_COLOR_NAME_STANDARD</option>
<option value="colors_alternative">TPL_MOKO-CASSIOPEIA_COLOR_NAME_ALTERNATIVE</option>
<option value="colors_custom">TPL_MOKO-CASSIOPEIA_COLOR_NAME_CUSTOM</option>
</field>
<field name="colorDarkName" type="list" label="TPL_MOKO-CASSIOPEIA_COLOR_DARK_NAME_LABEL" default="colors_standard">
<option value="colors_standard">TPL_MOKO-CASSIOPEIA_COLOR_NAME_STANDARD</option>
<option value="colors_alternative">TPL_MOKO-CASSIOPEIA_COLOR_NAME_ALTERNATIVE</option>
<option value="colors_custom">TPL_MOKO-CASSIOPEIA_COLOR_NAME_CUSTOM</option>
</field>
<!-- Typography -->
<field name="theme_sep_typo" type="spacer" label="Typography" hr="false" class="text fw-bold" />
<field name="useFontScheme" type="groupedlist" label="TPL_MOKO-CASSIOPEIA_FONT_LABEL" default="0">
<option value="0">JNONE</option>
<group label="TPL_MOKO-CASSIOPEIA_FONT_GROUP_LOCAL">
<option value="media/templates/site/moko-cassiopeia/css/global/fonts-local_roboto.css">Roboto (local)</option>
</group>
<group label="TPL_MOKO-CASSIOPEIA_FONT_GROUP_WEB">
<option value="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&amp;display=swap">Fira Sans (web)</option>
<option value="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&amp;family=Roboto:wght@100;300;400;700&amp;display=swap">Roboto + Noto Sans (web)</option>
</group>
</field>
<field name="noteFontScheme" type="note" description="TPL_MOKO-CASSIOPEIA_FONT_NOTE_TEXT" class="alert alert-warning" />
<!-- Branding & Icons -->
<field name="theme_sep_brand" type="spacer" label="Branding &amp; Icons" hr="false" class="text fw-bold" />
<field name="brand" type="radio" label="TPL_MOKO-CASSIOPEIA_BRAND_LABEL" default="1" layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="logoFile" type="media" default="media/templates/site/moko-cassiopeia/images/logo.svg" label="TPL_MOKO-CASSIOPEIA_LOGO_LABEL" showon="brand:1" />
<field name="siteTitle" type="text" default="" label="TPL_MOKO-CASSIOPEIA_TITLE" filter="string" showon="brand:1" />
<field name="siteDescription" type="text" default="" label="TPL_MOKO-CASSIOPEIA_TAGLINE_LABEL" description="TPL_MOKO-CASSIOPEIA_TAGLINE_DESC" filter="string" showon="brand:1" />
<field name="fA6KitCode" type="text" default="" label="TPL_MOKO-CASSIOPEIA_FA6KITCODE_LABEL" description="TPL_MOKO-CASSIOPEIA_FA6KITCODE_DESC" filter="string" />
<!-- Header & Navigation UI -->
<field name="theme_sep_header" type="spacer" label="Header &amp; Navigation" hr="false" class="text fw-bold" />
<field name="stickyHeader" type="radio" label="TPL_MOKO-CASSIOPEIA_STICKY_LABEL" layout="joomla.form.field.radio.switcher" default="0" filter="integer">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="backTop" type="radio" label="TPL_MOKO-CASSIOPEIA_BACKTOTOP_LABEL" layout="joomla.form.field.radio.switcher" default="0" filter="integer">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<!-- Toggle UI -->
<field name="theme_sep_toggle" type="spacer" label="Theme Toggle UI" hr="false" class="text fw-bold" />
<field name="theme_fab_enabled" type="radio" default="1"
label="TPL_MOKO_THEME_FAB_ENABLED" description="TPL_MOKO_THEME_FAB_ENABLED_DESC"
layout="joomla.form.field.radio.switcher" filter="boolean">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="theme_fab_pos" type="list" default="br"
label="TPL_MOKO_THEME_FAB_POS" description="TPL_MOKO_THEME_FAB_POS_DESC">
<option value="br">Bottom-right</option>
<option value="bl">Bottom-left</option>
<option value="tr">Top-right</option>
<option value="tl">Top-left</option>
</field>
</fieldset>
</fields> </fields>
</config> </config>
</extension> </extension>