diff --git a/.github/CLAUDE.md b/.github/CLAUDE.md new file mode 100644 index 0000000..bd84bb2 --- /dev/null +++ b/.github/CLAUDE.md @@ -0,0 +1,545 @@ +# What This Repo Is + +MokoCassiopeia is a modern, lightweight Joomla template that extends Cassiopeia (Joomla's default template) with enhanced features while maintaining maximum upgrade compatibility. It is used by Joomla 4.4.x and 5.x site administrators who want Font Awesome 7, Bootstrap 5 helpers, dark mode theming, and table of contents features without breaking core Joomla upgrades. This is NOT a standalone theme framework, NOT a template builder, and NOT a general-purpose UI library—it is specifically a Joomla site template extension that must be installed via Joomla's Extension Manager. Repository: https://github.com/mokoconsulting-tech/MokoCassiopeia + +# Repo Structure + +``` +MokoCassiopeia/ +├── .github/ # GitHub workflows (CI, testing, release), Copilot instructions +├── docs/ # Comprehensive documentation (guides, philosophy, CSS reference) +├── scripts/ # Build scripts (build-release.sh) +├── src/ # MAIN WORKING DIRECTORY: template source files +│ ├── index.php # Main template rendering file +│ ├── templateDetails.xml # Joomla manifest (metadata, params, files) +│ ├── joomla.asset.json # Web Asset Manager registration +│ ├── language/ # Frontend language files (en-GB, en-US .ini and .sys.ini) +│ ├── html/ # Alternative layout overrides (never replace defaults!) +│ └── media/ # CSS, JS, images, fonts, vendor libraries +├── templates/ # Color scheme templates for client customization +├── tests/ # Codeception acceptance and unit tests +├── phpcs.xml # PHP_CodeSniffer configuration (PSR-12 + Joomla standards) +└── phpstan.neon # PHPStan static analysis configuration +``` + +# File Header Requirements + +## Header Format + +All source files MUST include this standardized copyright header: + +### PHP Files (Full Header) + +```php + + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Template + REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia + PATH: ./templates/mokocassiopeia/filename.php + VERSION: XX.YY.ZZ + BRIEF: Brief description of file purpose + */ + +defined('_JEXEC') or die; +``` + +### JavaScript Files + +```javascript +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia + PATH: ./media/templates/site/mokocassiopeia/js/filename.js + VERSION: XX.YY.ZZ + BRIEF: Brief description of file purpose + */ + +(function (win, doc) { + "use strict"; + // Implementation +})(window, document); +``` + +### CSS Files + +```css +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Styles + PATH: ./media/templates/site/mokocassiopeia/css/filename.css + VERSION: XX.YY.ZZ + BRIEF: Brief description of file purpose + */ +``` + +### Markdown Documentation + +```markdown + +``` + +## FILE INFORMATION Block Fields + +- **DEFGROUP**: Top-level group (always `Joomla.Template.Site`) +- **INGROUP**: Subgroup (e.g., `MokoCassiopeia.Template`, `MokoCassiopeia.Documentation`) +- **REPO**: GitHub repository URL (required in docs, optional in code) +- **PATH** or **FILE**: Relative path from repository root +- **VERSION**: Semantic version `XX.YY.ZZ` +- **BRIEF**: One-line description of file purpose + +## Exempt Files + +These file types DO NOT require headers: +- `joomla.asset.json` and other JSON data files (metadata in `x-header` field instead) +- Binary files (images, fonts, compiled assets) +- Third-party vendor libraries in `src/media/vendor/` +- Generated files (minified CSS/JS with `.min.` in name) +- Empty placeholder files + +## When to Use Full vs Minimal Header + +- **Full header with GPL notice**: Required in all PHP files (use example above) +- **Minimal header without GPL notice**: JavaScript and CSS files (shorter version shown above) +- **Markdown format**: All documentation files in `docs/` + +# Coding Standards + +## Indentation + +From `.editorconfig`: +- **Default**: Tabs with 2-space visual width +- **PHP**: Tabs (PSR-12 uses tabs, Joomla uses tabs) +- **JavaScript**: Tabs with 2-space visual width +- **CSS**: Tabs with 2-space visual width +- **JSON/YAML**: Tabs with 2-space visual width +- **Markdown**: Spaces (for compatibility), trim_trailing_whitespace = false +- **Makefiles**: Always tabs + +## Line Length + +From `phpcs.xml`: +- **General**: No strict limit (Generic.Files.LineLength excluded) +- **Practical guideline**: Keep lines under 120 characters when reasonable +- **Long lines accepted for**: URLs, array definitions, Joomla HTML helpers + +## Naming Conventions + +### PHP (Joomla Standards + PSR-12) + +- **Classes**: `PascalCase` (e.g., `TemplateHelper`) +- **Methods**: `camelCase` (e.g., `getThemeOptions()`) +- **Variables**: `$camelCase` or `$snake_case` (Joomla prefers snake_case for local vars) +- **Constants**: `UPPER_SNAKE_CASE` (e.g., `THEME_LIGHT_MODE`) +- **Files**: Lowercase with hyphens for layouts (e.g., `mobile.php`, `toc-left.php`) +- **Private properties**: Prefix with underscore (e.g., `$_privateData`) + +### JavaScript (ES6+) + +- **Functions**: `camelCase` (e.g., `applyTheme()`) +- **Constants**: `UPPER_SNAKE_CASE` or `camelCase` (e.g., `storageKey`) +- **Classes**: `PascalCase` (e.g., `ThemeController`) +- **Files**: Lowercase with hyphens (e.g., `template.js`, `menu-metismenu.js`) + +### CSS + +- **Classes**: Kebab-case (e.g., `.theme-toggle`, `.fab-button`) +- **IDs**: Kebab-case (e.g., `#main-content`) +- **CSS Variables**: Kebab-case with double hyphen prefix (e.g., `--color-primary`, `--body-bg`) +- **Files**: Lowercase with dots and descriptive names (e.g., `light.standard.css`, `dark.custom.css`, `light.custom.css`) + +### General File Naming + +- **Alternative layouts**: Descriptive name + `.php` (e.g., `mobile.php`, `mainmenu.php`, `toc-left.php`) +- **NEVER use**: `default.php` (replaces core layout—FORBIDDEN) +- **Scripts**: Lowercase with hyphens (e.g., `build-release.sh`) + +## Primary Language + +- **PHP**: All new template logic, Joomla integration code +- **JavaScript**: All new client-side functionality (ES6+ syntax) +- **CSS**: All new styling (CSS variables for theming) +- **Bash**: Build and automation scripts (`.sh` files) + +# Language-Specific Requirements + +## PHP + +### Type Hints + +Required for all function signatures in PHP 8.0+ code: + +```php +public function getThemeOption(string $key, mixed $default = null): mixed +{ + return $this->params->get($key, $default); +} +``` + +### Docstring Format + +Use DocBlocks for all classes, methods, and functions: + +```php +/** + * Apply theme settings to document + * + * @param string $theme Theme name (light|dark) + * @param object $params Template parameters + * + * @return void + * + * @since 3.6.0 + */ +public function applyTheme(string $theme, object $params): void +{ + // Implementation +} +``` + +Required DocBlock sections: +- Brief description (first line) +- `@param` for each parameter (type, name, description) +- `@return` for return value +- `@since` for version introduced +- `@throws` if exceptions are thrown + +### Script Structure + +All PHP files must follow this pattern: + +```php + section +- Update paths to be relative from package root +- Ensures proper installation to JOOMLA_ROOT/language/ + +Refs: #42 +``` + +``` +Add dark mode color variables for custom themes + +- Add --color-primary-dark, --color-secondary-dark +- Update theme toggle to respect custom colors +- Document new variables in CSS_VARIABLES.md +``` + +**Bad examples:** + +``` +Update files +``` + +``` +WIP +``` + +``` +Fixed bug +``` + +## Commit Rules + +- Keep subject line under 50 characters +- Use imperative mood ("Add feature" not "Added feature") +- Capitalize first letter +- No period at end of subject +- Blank line between subject and body +- Wrap body at 72 characters +- Explain WHAT and WHY, not HOW (code shows HOW) + +# Running Validation + +Before committing, run these commands from repository root: + +```bash +# 1. PHP CodeSniffer (code style) +phpcs --standard=phpcs.xml src/ + +# 2. PHPStan (static analysis) +phpstan analyse --configuration=phpstan.neon + +# 3. XML validation (template manifest) +xmllint --noout src/templateDetails.xml + +# 4. Check file headers (if script exists) +# ./scripts/validate-headers.sh + +# 5. Run tests (if Codeception installed) +codecept run +``` + +If you don't have tools installed: + +```bash +# Install PHP quality tools globally +composer global require "squizlabs/php_codesniffer:^3.0" --with-all-dependencies +composer global require "phpstan/phpstan:^1.0" --with-all-dependencies + +# Install Codeception +composer global require "codeception/codeception" --with-all-dependencies +``` + +**Note:** CI runs these automatically on push, but running locally saves time. + +# Contribution Workflow + +1. **Fork** the repository on GitHub +2. **Clone** your fork locally: `git clone https://github.com/YOUR-USERNAME/MokoCassiopeia.git` +3. **Create branch** from current development branch: `git checkout -b feature/your-feature-name` + - Branch naming: `feature/description`, `fix/issue-description`, `docs/topic` +4. **Make changes** in the `src/` directory (this is the working copy) +5. **Run validation** (see commands above) +6. **Commit changes** with descriptive messages +7. **Push to your fork**: `git push origin feature/your-feature-name` +8. **Open Pull Request** on GitHub targeting the appropriate base branch + +## Branch Strategy + +- **main**: Stable releases only (protected) +- **version/XX.YY**: Version-specific branches (protected) +- **dev/XX.YY.ZZ**: Active development branches +- **rc/XX.YY.ZZ**: Release candidate branches +- **feature/**, **fix/**, **docs/**: Working branches + +## Merge Strategy + +- Pull requests use **squash merge** to main/version branches +- Commits go to development branches first, then promoted through rc → version → main +- NEVER commit directly to protected branches (main, version/*) + +# PR Checklist + +Before opening a pull request: + +- [ ] Code follows Joomla coding standards (PSR-12 + Joomla) +- [ ] All files have proper copyright headers +- [ ] PHP files have `defined('_JEXEC') or die;` at top +- [ ] No `default.php` layout files (use alternative layout names) +- [ ] Language files: metadata in `.sys.ini`, runtime strings in `.ini` +- [ ] Assets registered in `joomla.asset.json` (not inline in template) +- [ ] CSS uses CSS variables for colors (supports light/dark themes) +- [ ] PHP CodeSniffer passes: `phpcs --standard=phpcs.xml src/` +- [ ] PHPStan passes: `phpstan analyse --configuration=phpstan.neon` +- [ ] Tested in Joomla 4.4.x AND 5.x +- [ ] Tested in light mode AND dark mode +- [ ] Documentation updated if adding features +- [ ] No hardcoded absolute paths (use Joomla path constants) +- [ ] No credentials, API keys, or secrets in code +- [ ] Version numbers NOT added to revision history tables +- [ ] Alternative layouts documented with activation instructions + +# What NOT to Do + +## Absolutely Forbidden + +- ❌ **NEVER create `default.php` layout files** - This replaces core layouts and breaks upgrades. Use alternative layout names like `mobile.php`, `mainmenu.php` +- ❌ **NEVER commit without copyright headers** - All source files must have proper headers +- ❌ **NEVER add `folder` attribute to `` section in templateDetails.xml** - Language file paths must be relative from package root +- ❌ **NEVER put template metadata in `.ini` files** - Template name and description belong ONLY in `.sys.ini` files +- ❌ **NEVER hardcode absolute paths** - Use Joomla path constants (`JPATH_ROOT`, `JPATH_SITE`, etc.) +- ❌ **NEVER commit credentials or API keys** - Use Joomla's configuration management +- ❌ **NEVER modify vendor libraries** - Third-party code in `src/media/vendor/` is immutable +- ❌ **NEVER remove `defined('_JEXEC') or die;`** - This is a critical security check + +## Strong Discouragements + +- ⚠️ Avoid committing without running `phpcs` and `phpstan` +- ⚠️ Avoid adding version numbers to revision history tables (use VERSION metadata instead) +- ⚠️ Avoid inline styles or scripts (register assets in `joomla.asset.json`) +- ⚠️ Avoid hardcoded color values (use CSS variables: `--color-primary`, etc.) +- ⚠️ Avoid direct commits to `main` or `version/*` branches (use PRs) +- ⚠️ Avoid changing more than one concern per commit +- ⚠️ Avoid long lines when reasonable (aim for 120 chars) + +## Common Mistakes + +- Using spaces instead of tabs (check `.editorconfig`) +- Forgetting `SPDX-License-Identifier: GPL-3.0-or-later` in headers +- Mixing frontend strings (.ini) and metadata strings (.sys.ini) +- Creating layout overrides that replace defaults instead of providing alternatives +- Not testing in both Joomla 4.x and 5.x +- Not testing light/dark mode theme switching + +# Key Policy Documents + +Must-read before contributing: + +1. **[OVERRIDE_PHILOSOPHY.md](./docs/OVERRIDE_PHILOSOPHY.md)** - CRITICAL: Explains why we NEVER replace default layouts and how alternative layouts work +2. **[QUICK_START.md](./docs/QUICK_START.md)** - 5-minute setup guide for first-time contributors +3. **[JOOMLA_DEVELOPMENT.md](./docs/JOOMLA_DEVELOPMENT.md)** - Complete development guide: testing, quality checks, deployment +4. **[WORKFLOW_GUIDE.md](./docs/WORKFLOW_GUIDE.md)** - Git workflow, branching strategy, CI/CD pipelines +5. **[CSS_VARIABLES.md](./docs/CSS_VARIABLES.md)** - Complete reference for theme customization +6. **[CONTRIBUTING.md](./CONTRIBUTING.md)** - Formal contribution guidelines and governance +7. **[SECURITY.md](./SECURITY.md)** - Security reporting procedures (never report publicly) +8. **[MODULE_OVERRIDES.md](./docs/MODULE_OVERRIDES.md)** - Documentation of all alternative layouts and activation instructions + +## Related Documentation + +- **README.md** - Overview, features, installation, configuration +- **CHANGELOG.md** - Version history and release notes +- **GOVERNANCE.md** - Project governance model and decision-making +- **CODE_OF_CONDUCT.md** - Community standards and expectations diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..c10ffb0 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,346 @@ +# GitHub Copilot Instructions for MokoCassiopeia + +## Repository Context + +MokoCassiopeia is a modern, lightweight Joomla template that extends Cassiopeia (Joomla's default template). It follows a strict **non-replacement philosophy** for maximum upgrade compatibility. + +**Key Characteristics:** +- Joomla 4.4.x and 5.x compatible +- PHP 8.0+ required +- Built on Cassiopeia template +- Minimal core template overrides +- Alternative layout naming convention (not default replacements) +- GPL-3.0-or-later license + +## Project Structure + +``` +MokoCassiopeia/ +├── .github/ # GitHub workflows and configuration +├── docs/ # Comprehensive documentation +├── scripts/ # Build and deployment scripts +├── src/ # Template source files (main working directory) +│ ├── index.php # Main template file +│ ├── templateDetails.xml # Joomla template manifest +│ ├── joomla.asset.json # Web Asset Manager configuration +│ ├── language/ # Frontend language files (en-GB, en-US) +│ ├── html/ # Alternative layout overrides +│ └── media/ # CSS, JS, images, fonts, vendors +├── templates/ # Custom color scheme templates +└── tests/ # Codeception tests +``` + +## Critical Conventions + +### 1. Override Philosophy: Alternative Layouts Only + +**NEVER replace default layouts.** All overrides must use alternative layout names. + +✅ **Correct:** +- `mobile.php` (alternative layout) +- `mainmenu.php` (alternative layout for mod_menu) +- `toc-left.php`, `toc-right.php` (alternative layouts with TOC) + +❌ **Incorrect:** +- `default.php` (replaces core layout - FORBIDDEN) +- Any file that replaces Cassiopeia's default behavior + +**Rationale:** Ensures Joomla core updates don't break the template and gives users choice. + +### 2. File Headers + +All source files must include standardized copyright headers: + +```php + + * + * This file is part of a Moko Consulting project. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * @defgroup Joomla.Template.Site + * @ingroup MokoCassiopeia.Template + * @brief [Brief description] + * @version [Version number] + */ + +defined('_JEXEC') or die; +``` + +### 3. Language Files + +**Key Rules:** +- Template metadata (name, description) goes in `.sys.ini` files ONLY +- Frontend runtime strings go in `.ini` files +- Language files location: `src/language/{locale}/` +- NO `folder` attribute in `` section of templateDetails.xml +- Paths must be relative from package root (e.g., `language/en-GB/tpl_mokocassiopeia.sys.ini`) + +**Example templateDetails.xml:** +```xml + + en-GB/tpl_mokocassiopeia.ini + en-GB/tpl_mokocassiopeia.sys.ini + +``` + +### 4. Hardcoded XML Description + +The template description in `templateDetails.xml` is **hardcoded using CDATA**, not a language constant: + +```xml + +``` + +**Rationale:** Ensures immediate availability during installation without language file dependency. + +### 5. Version Format + +Follow semantic versioning: `XX.YY.ZZ` +- XX: Major version +- YY: Minor version +- ZZ: Patch version + +**Examples:** `03.06.03`, `03.08.04` + +## Coding Standards + +### PHP + +- **PSR-12 compliant** where not conflicting with Joomla standards +- **Joomla Coding Standards** for Joomla-specific code +- Use `defined('_JEXEC') or die;` at the top of every PHP file +- Type hints for PHP 8.0+ features +- Strict types declarations where appropriate + +### JavaScript + +- **ES6+** syntax +- Use `'use strict';` +- Prefer `const` and `let` over `var` +- Document functions with JSDoc comments +- Integrate with Joomla's Web Asset Manager + +### CSS + +- **CSS Variables** for theming (see `docs/CSS_VARIABLES.md`) +- Light/dark mode support via `data-bs-theme` attribute +- Bootstrap 5 utility classes +- Mobile-first responsive design +- Namespace custom classes to avoid conflicts + +### Asset Management + +All assets must be registered in `joomla.asset.json`: + +```json +{ + "name": "template.mokocassiopeia.custom", + "version": "1.0.0", + "description": "Custom asset", + "license": "GPL-3.0-or-later", + "dependencies": ["core"], + "js": ["js/custom.js"], + "css": ["css/custom.css"] +} +``` + +## Development Workflow + +### Branching Strategy + +- **Development:** Work on feature branches +- **Branch naming:** `feature/description`, `fix/issue-description` +- **Protected branches:** Cannot commit directly to `main` or version branches +- See `docs/WORKFLOW_GUIDE.md` for complete workflow + +### Commit Messages + +``` +Brief summary (50 chars or less) + +Detailed explanation if needed: +- What changed +- Why it changed +- Impact of the change +``` + +**Example:** +``` +Fix language file installation paths in templateDetails.xml + +- Remove folder attribute from section +- Update paths to be relative from package root +- Ensures proper installation to JOOMLA_ROOT/language/ +``` + +### Quality Checks + +Before committing: +1. **PHP CodeSniffer:** `phpcs --standard=Joomla src/` +2. **PHPStan:** Static analysis for PHP code +3. **Pre-commit hooks:** Automatically run validation + +## Testing + +### Manual Testing +- Test in Joomla 4.4.x and 5.x +- Test on PHP 8.0, 8.1, 8.2 +- Test light/dark mode switching +- Test responsive layouts (mobile/tablet/desktop) +- Test alternative layouts activation + +### Test Environment +- Use local Joomla installation +- See `docs/JOOMLA_DEVELOPMENT.md` for setup + +## Documentation Standards + +### Markdown Files + +All documentation must include: + +1. **Copyright header** +```markdown + +``` + +2. **Metadata section** (at end) +3. **Revision history table** (at end) + +### Code Comments + +- Use DocBlocks for functions and classes +- Explain "why" not just "what" +- Keep comments up-to-date with code changes + +## Common Patterns + +### Theme System Integration + +Use CSS variables for colors: +```css +:root[data-bs-theme="light"] { + --color-primary: #1e40af; + --body-bg: #ffffff; +} + +:root[data-bs-theme="dark"] { + --color-primary: #60a5fa; + --body-bg: #1f2937; +} +``` + +### Alternative Layout Structure + +```php + +``` + +### JavaScript Asset Loading + +```javascript +// Register in joomla.asset.json, then use: +Joomla.getOptions('template.mokocassiopeia.options'); +``` + +## Build and Release + +### Local Build +```bash +cd scripts +./build-release.sh +``` + +### Automated Release +- Tags trigger GitHub Actions workflow +- Format: `XX.YY.ZZ` +- Generates ZIP packages with checksums +- Updates `updates.xml` automatically + +## Important Don'ts + +❌ **Never:** +- Replace default Joomla layouts (use alternative layouts) +- Commit without running code quality checks +- Add version numbers to revision history (use VERSION metadata) +- Hardcode absolute paths (use Joomla path constants) +- Remove copyright headers +- Modify `vendor/` directory contents +- Change language constants location (.sys.ini vs .ini) +- Add `folder` attribute to `` in templateDetails.xml + +## Important Do's + +✅ **Always:** +- Use alternative layout names (mobile.php, mainmenu.php, etc.) +- Include copyright headers in all files +- Test in both Joomla 4.x and 5.x +- Test light/dark mode themes +- Update documentation when changing functionality +- Follow semantic versioning +- Register assets in joomla.asset.json +- Use CSS variables for theming +- Keep minimal overrides philosophy +- Document activation steps for alternative layouts + +## Key Documentation References + +- **Quick Start:** `docs/QUICK_START.md` - First-time setup +- **Override Philosophy:** `docs/OVERRIDE_PHILOSOPHY.md` - Critical reading +- **Development Guide:** `docs/JOOMLA_DEVELOPMENT.md` - Complete dev workflow +- **CSS Variables:** `docs/CSS_VARIABLES.md` - Theming reference +- **Workflow Guide:** `docs/WORKFLOW_GUIDE.md` - Git workflow + +## Security Considerations + +- Follow `SECURITY.md` for security issues +- Never commit credentials or API keys +- Validate and sanitize all user inputs +- Use Joomla's security features (CSRF tokens, etc.) +- Keep dependencies updated + +## License Compliance + +All code contributions must be: +- GPL-3.0-or-later compatible +- Properly attributed (third-party code) +- Include SPDX license identifiers +- Maintain existing copyright notices + +## Contact and Support + +- **Issues:** GitHub Issues +- **Discussions:** GitHub Discussions +- **Security:** Follow SECURITY.md procedures +- **Maintainer:** Moko Consulting Engineering + +--- + +**Last Updated:** 2026-03-04 +**Repository:** https://github.com/mokoconsulting-tech/MokoCassiopeia +**Version:** 03.08.04 diff --git a/.github/workflows/auto-update-sha.yml b/.github/workflows/auto-update-sha.yml new file mode 100644 index 0000000..2aa5fb6 --- /dev/null +++ b/.github/workflows/auto-update-sha.yml @@ -0,0 +1,147 @@ +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# FILE INFORMATION +# DEFGROUP: GitHub.Workflow +# INGROUP: MokoCassiopeia.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia +# PATH: /.github/workflows/auto-update-sha.yml +# VERSION: 01.00.00 +# BRIEF: Automatically update SHA-256 hash in updates.xml after release +# NOTE: Ensures updates.xml stays synchronized with release packages + +name: Auto-Update SHA Hash + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Release tag to update SHA for (e.g., 03.08.03)' + required: true + type: string + +permissions: + contents: write + +jobs: + update-sha: + name: Update SHA-256 Hash in updates.xml + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: main + + - name: Get release tag + id: tag + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + TAG="${{ inputs.tag }}" + else + TAG="${{ github.event.release.tag_name }}" + fi + echo "tag=${TAG}" >> $GITHUB_OUTPUT + echo "Processing release: ${TAG}" + + - name: Download release package + run: | + TAG="${{ steps.tag.outputs.tag }}" + PACKAGE_NAME="mokocassiopeia-src-${TAG}.zip" + DOWNLOAD_URL="https://github.com/${{ github.repository }}/releases/download/${TAG}/${PACKAGE_NAME}" + + echo "Downloading: ${DOWNLOAD_URL}" + curl -L -o "${PACKAGE_NAME}" "${DOWNLOAD_URL}" + + if [ ! -f "${PACKAGE_NAME}" ]; then + echo "Error: Failed to download package" + exit 1 + fi + + echo "PACKAGE_NAME=${PACKAGE_NAME}" >> $GITHUB_ENV + + - name: Calculate SHA-256 hash + id: sha + run: | + SHA256_HASH=$(sha256sum "${PACKAGE_NAME}" | cut -d' ' -f1) + echo "sha256=${SHA256_HASH}" >> $GITHUB_OUTPUT + echo "SHA-256 Hash: ${SHA256_HASH}" + + - name: Update updates.xml + run: | + TAG="${{ steps.tag.outputs.tag }}" + SHA256="${{ steps.sha.outputs.sha256 }}" + DATE=$(date +%Y-%m-%d) + + # Update version + sed -i "s|.*|${TAG}|" updates.xml + + # Update creation date + sed -i "s|.*|${DATE}|" updates.xml + + # Update download URL + sed -i "s|.*|https://github.com/${{ github.repository }}/releases/download/${TAG}/mokocassiopeia-src-${TAG}.zip|" updates.xml + + # Update or add SHA-256 hash + if grep -q "" updates.xml; then + sed -i "s|.*|sha256:${SHA256}|" updates.xml + else + # Add SHA-256 after downloadurl + sed -i "/<\/downloadurl>/a\ sha256:${SHA256}<\/sha256>" updates.xml + fi + + echo "Updated updates.xml with:" + echo " Version: ${TAG}" + echo " Date: ${DATE}" + echo " SHA-256: ${SHA256}" + + - name: Check for changes + id: changes + run: | + if git diff --quiet updates.xml; then + echo "has_changes=false" >> $GITHUB_OUTPUT + echo "No changes to updates.xml" + else + echo "has_changes=true" >> $GITHUB_OUTPUT + echo "Changes detected in updates.xml" + git diff updates.xml + fi + + - name: Commit and push changes + if: steps.changes.outputs.has_changes == 'true' + run: | + TAG="${{ steps.tag.outputs.tag }}" + + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + git add updates.xml + git commit -m "chore: Update SHA-256 hash for release ${TAG} + +Auto-generated by auto-update-sha workflow +SHA-256: ${{ steps.sha.outputs.sha256 }}" + + git push origin main + + echo "Successfully updated updates.xml with SHA-256 hash for release ${TAG}" + + - name: Summary + if: steps.changes.outputs.has_changes == 'true' + run: | + echo "### SHA-256 Hash Updated Successfully" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- Release: ${{ steps.tag.outputs.tag }}" >> $GITHUB_STEP_SUMMARY + echo "- SHA-256: \`${{ steps.sha.outputs.sha256 }}\`" >> $GITHUB_STEP_SUMMARY + echo "- File: updates.xml" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "The Joomla update server will now provide the correct package hash." >> $GITHUB_STEP_SUMMARY + + - name: Summary (no changes) + if: steps.changes.outputs.has_changes == 'false' + run: | + echo "### No Updates Needed" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "updates.xml already contains the correct SHA-256 hash for release ${{ steps.tag.outputs.tag }}" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0ba0908 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,210 @@ +# Copyright (C) 2026 Moko Consulting +# +# This file is part of a Moko Consulting project. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# FILE INFORMATION +# DEFGROUP: GitHub.Workflow +# INGROUP: MokoCassiopeia.Release +# REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia +# PATH: /.github/workflows/release.yml +# VERSION: 01.00.00 +# BRIEF: Automated release workflow for MokoCassiopeia Joomla template +# NOTE: Creates release packages and publishes to GitHub Releases + +name: Create Release + +on: + push: + tags: + - '[0-9][0-9].[0-9][0-9].[0-9][0-9]' + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g., 03.08.03)' + required: true + type: string + prerelease: + description: 'Mark as pre-release' + required: false + type: boolean + default: false + +permissions: + contents: write + +jobs: + build: + name: Build Release Package + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, xml, zip + tools: composer:v2 + + - name: Get version + id: version + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + VERSION="${{ inputs.version }}" + else + VERSION=${GITHUB_REF#refs/tags/} + fi + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "Building version: ${VERSION}" + + - name: Install dependencies + run: | + if [ -f "composer.json" ]; then + composer install --no-dev --optimize-autoloader + fi + + - name: Update version in manifest files + run: | + VERSION="${{ steps.version.outputs.version }}" + # Update version in templateDetails.xml + sed -i "s/.*<\/version>/${VERSION}<\/version>/g" src/templateDetails.xml + # Update version in updates.xml + sed -i "s/.*<\/version>/${VERSION}<\/version>/g" updates.xml + # Update creation date to today + DATE=$(date +%Y-%m-%d) + sed -i "s/.*<\/creationDate>/${DATE}<\/creationDate>/g" src/templateDetails.xml + sed -i "s/.*<\/creationDate>/${DATE}<\/creationDate>/g" updates.xml + + - name: Create package structure + run: | + mkdir -p build/package + + # Copy template files from src (excluding media directory) + rsync -av --exclude='media' src/ build/package/ + + # Copy media files from src/media to package/media directory + mkdir -p build/package/media + rsync -av src/media/ build/package/media/ + + - name: Create source ZIP package + run: | + cd build/package + VERSION="${{ steps.version.outputs.version }}" + ZIP_NAME="mokocassiopeia-src-${VERSION}.zip" + zip -r "../${ZIP_NAME}" . + cd ../.. + echo "ZIP_NAME=${ZIP_NAME}" >> $GITHUB_ENV + echo "Created package: ${ZIP_NAME}" + + - name: Generate checksums + run: | + cd build + sha256sum "${ZIP_NAME}" > "${ZIP_NAME}.sha256" + md5sum "${ZIP_NAME}" > "${ZIP_NAME}.md5" + + # Extract just the hash for updates.xml + SHA256_HASH=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1) + echo "SHA256_HASH=${SHA256_HASH}" >> $GITHUB_ENV + echo "SHA-256: ${SHA256_HASH}" + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: release-package + path: | + build/*.zip + build/*.sha256 + build/*.md5 + + release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: build + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: release-package + path: ./artifacts + + - name: Get version + id: version + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + VERSION="${{ inputs.version }}" + else + VERSION=${GITHUB_REF#refs/tags/} + fi + echo "version=${VERSION}" >> $GITHUB_OUTPUT + + - name: Extract changelog + id: changelog + run: | + if [ -f "CHANGELOG.md" ]; then + # Extract changelog for this version + VERSION="${{ steps.version.outputs.version }}" + awk "/## \[${VERSION}\]/,/## \[/{if(/## \[${VERSION}\]/)print;else if(/## \[/)exit;else print}" CHANGELOG.md > release_notes.md + + if [ ! -s release_notes.md ]; then + echo "No specific changelog found for version ${VERSION}" > release_notes.md + echo "" >> release_notes.md + echo "Please refer to the full CHANGELOG.md for details." >> release_notes.md + fi + else + echo "Release version ${{ steps.version.outputs.version }}" > release_notes.md + fi + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ steps.version.outputs.version }} + name: Release ${{ steps.version.outputs.version }} + body_path: release_notes.md + draft: false + prerelease: ${{ inputs.prerelease || false }} + files: | + artifacts/*.zip + artifacts/*.sha256 + artifacts/*.md5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Release summary + run: | + echo "### Release Created Successfully" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- Version: ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "- Repository: $GITHUB_REPOSITORY" >> $GITHUB_STEP_SUMMARY + echo "- Tag: ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "- Pre-release: ${{ inputs.prerelease || false }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Package files:" >> $GITHUB_STEP_SUMMARY + ls -lh artifacts/ >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Next Steps" >> $GITHUB_STEP_SUMMARY + echo "1. Verify the release at: https://github.com/$GITHUB_REPOSITORY/releases/tag/${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "2. Update updates.xml with the SHA-256 hash from the .sha256 file" >> $GITHUB_STEP_SUMMARY + echo "3. Test the installation package" >> $GITHUB_STEP_SUMMARY diff --git a/.gitignore b/.gitignore index abfdb17..d5011f1 100644 --- a/.gitignore +++ b/.gitignore @@ -208,9 +208,13 @@ htdocs/logs/ # ============================================================ # Template Customizations # ============================================================ -# Ignore custom color scheme files to prevent fork-specific customizations -src/media/css/colors/light/colors_custom.css -src/media/css/colors/dark/colors_custom.css +# Ignore custom theme files to prevent fork-specific customizations +src/media/css/theme/light.custom.css +src/media/css/theme/dark.custom.css + +# Ignore user customization files to prevent local development overrides +src/media/css/user.css +src/media/js/user.js # ============================================================ # Joomla Core diff --git a/CHANGELOG.md b/CHANGELOG.md index d27fba4..0d47807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,17 +8,179 @@ DEFGROUP: Joomla.Template.Site INGROUP: MokoCassiopeia.Documentation PATH: ./CHANGELOG.md - VERSION: 03.08.00 + VERSION: 03.08.03 BRIEF: Changelog file documenting version history of MokoCassiopeia --> -# Changelog — MokoCassiopeia (VERSION: 03.08.00) +# Changelog — MokoCassiopeia (VERSION: 03.08.03) All notable changes to the MokoCassiopeia Joomla template are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [03.08.03] - 2026-02-27 + +### Added - Main Menu Collapsible Dropdown Override + +**New feature**: Added responsive "Main Menu" mod_menu override with Bootstrap 5 collapsible dropdown functionality. + +#### What's New +- **Main Menu module override** with full Bootstrap 5 responsive navbar +- Collapsible hamburger menu for mobile devices +- Multi-level dropdown support with hover on desktop, tap on mobile +- WCAG 2.1 compliant touch targets (48px on mobile, 44px on desktop) +- BEM naming convention: `.mod-menu-main__*` +- **Appears as "Mainmenu" layout option** in Joomla admin module settings + +#### Files Added +- `src/templates/html/mod_menu/mainmenu.php` - Main layout with Bootstrap navbar +- `src/templates/html/mod_menu/mainmenu_component.php` - Component menu items +- `src/templates/html/mod_menu/mainmenu_heading.php` - Heading menu items +- `src/templates/html/mod_menu/mainmenu_separator.php` - Separator menu items +- `src/templates/html/mod_menu/mainmenu_url.php` - URL menu items +- `src/templates/html/mod_menu/index.html` - Security file + +#### Features +- **Bootstrap 5 Navbar**: Uses Bootstrap's native navbar-nav structure +- **Collapsible on Mobile**: Hamburger menu with smooth collapse animation +- **Dropdown Menus**: Multi-level dropdown support with caret indicators +- **Responsive Breakpoints**: Mobile-first design adapting at 768px and 992px +- **Touch-Friendly**: 48px minimum touch targets on mobile +- **Accessible**: ARIA labels and keyboard navigation support +- **Active States**: Visual indicators for current and active menu items +- **Alternative Layout**: Named `mainmenu.php` (not `default.php`) to appear as selectable layout option in Joomla admin + +#### CSS Architecture +- 200+ lines of responsive CSS in template.css +- BEM naming: `.mod-menu-main`, `.mod-menu-main__list`, `.mod-menu-main__link` +- CSS variables integration for colors and borders +- Hover effects on desktop, tap effects on mobile +- Smooth transitions and animations + +#### Module Count Update +- **Before**: 16 module overrides +- **After**: 17 module overrides (added mod_menu "Main Menu") +- **Component overrides**: Still 7 (unchanged) + +### Removed - mod_search Override + +**Cassiopeia approach**: Removed mod_search override to align with Cassiopeia template philosophy of not overriding standard Joomla modules. + +#### Reason for Removal +- mod_search is a standard Joomla core module +- Following Cassiopeia template approach: use core layouts for standard modules +- Prevents potential language loading issues +- Ensures compatibility with future Joomla updates +- Core mod_search already includes responsive design and accessibility features + +#### Files Removed +- `src/templates/html/mod_search/default.php` - Custom search module layout +- `src/templates/html/mod_search/index.html` - Security file + +#### Module Count Update (After Removal) +- **Before**: 17 module overrides +- **After**: 16 module overrides (removed mod_search) +- **Component overrides**: Still 7 (unchanged) + +### Removed - Documentation Cleanup + +**Documentation policy**: Removed all markdown files from `src/templates/html/` directory. All documentation belongs in `docs/` folder only. + +#### Files Removed (9 markdown files) +- `src/templates/html/STANDARD_MODULES_README.md` +- `src/templates/html/INDUSTRY_MODULES_README.md` +- `src/templates/html/VIRTUEMART_MODULES_README.md` +- `src/templates/html/mod_virtuemart_cart/README.md` +- `src/templates/html/mod_virtuemart_category/README.md` +- `src/templates/html/mod_virtuemart_currencies/README.md` +- `src/templates/html/mod_virtuemart_manufacturer/README.md` +- `src/templates/html/mod_virtuemart_product/README.md` +- `src/templates/html/mod_search/README.md` + +**Note**: All module override documentation is consolidated in `docs/MODULE_OVERRIDES.md`. The `src/templates/html/` directory now contains only PHP override files and `index.html` security files. + +**Note**: Unlike the previously removed mod_menu override (v03.08.01), this new "Main Menu" override is properly structured based on Joomla core layouts and Bootstrap 5, ensuring language strings load correctly and menu functionality works as expected. The layout is named `mainmenu.php` (not `default.php`) to appear as an alternative layout option "Mainmenu" in the Joomla admin module dropdown selector, preserving Joomla's core default menu layout. + +## [03.08.02] - 2026-02-27 + +### Removed - Fix Language Loading in All Module Overrides + +**Critical fix**: Removed standard Joomla module overrides to fix language string loading issues. Following Cassiopeia template approach. + +#### Problem +- Default language strings not loading in module overrides (mod_breadcrumbs, mod_login, mod_articles_latest) +- Language constants displayed instead of translated text (e.g., "MOD_LOGIN_VALUE_USERNAME" instead of "Username") +- Custom overrides interfered with Joomla's module initialization and language loading process + +#### Solution - Cassiopeia Approach +- **Removed** standard Joomla module overrides: + - `src/templates/html/mod_breadcrumbs/` (2 files) + - `src/templates/html/mod_login/` (2 files) + - `src/templates/html/mod_articles_latest/` (2 files) +- Template now uses Joomla's core module layouts for standard modules +- Language files load automatically via Joomla's module system +- Custom styling can still be applied via CSS using module-specific classes +- **Retained** third-party extension overrides where they add mobile-responsive value: + - VirtueMart modules (5): mod_virtuemart_cart, _category, _currencies, _manufacturer, _product + - Community Builder modules (2): mod_cblogin, mod_comprofilerOnline + - Other extensions (9): mod_acymailing, mod_hikashop_cart, mod_k2_content, mod_kunena*, mod_osmembership, mod_search + +#### Cassiopeia Template Philosophy +- Cassiopeia (Joomla's default template) does NOT override standard module layouts +- It relies on core Joomla module files and applies styling via CSS +- Overrides are only created when structural changes are absolutely necessary +- This ensures compatibility, automatic language loading, and easier maintenance + +#### Module Count Update +- **Before**: 19 module overrides +- **After**: 16 module overrides +- **Removed**: 3 standard Joomla modules (breadcrumbs, login, articles_latest) +- **Component overrides**: Still 7 (unchanged) + +#### Files Removed +- `src/templates/html/mod_breadcrumbs/default.php` +- `src/templates/html/mod_breadcrumbs/index.html` +- `src/templates/html/mod_login/default.php` +- `src/templates/html/mod_login/index.html` +- `src/templates/html/mod_articles_latest/default.php` +- `src/templates/html/mod_articles_latest/index.html` + +**Note**: This follows Joomla best practices by using core layouts for standard modules. Styling is handled via CSS. Third-party extension overrides remain for mobile responsiveness. + +## [03.08.01] - 2026-02-27 + +### Removed - Fix Breaking Overrides + +**Critical fix**: Removed mod_menu override that was causing menu links to break and language strings not to load. + +#### Problem +- mod_menu override files (default.php, default_component.php, default_url.php) were attempting to load menu-specific layouts that don't exist in the template +- This broke Joomla's core menu rendering system +- Menu links were not functional +- Language strings were not loading properly in menus + +#### Solution +- **Removed** entire `src/templates/html/mod_menu/` directory (4 files) +- Template now uses Joomla's default menu rendering +- Custom styling can still be applied via CSS using `.mod-menu` class +- All menu functionality restored to standard Joomla behavior + +#### Documentation Updates +- Updated MODULE_OVERRIDES.md: Changed count from 20 to 19 module overrides, removed mod_menu section, added note about removal +- Updated STANDARD_MODULES_README.md: Removed mod_menu documentation, renumbered remaining modules, updated file structure +- Updated testing checklists to remove mod_menu references +- **Added clarification**: MokoCassiopeia is a standalone template extension (not a package) +- Updated updates.xml to version 03.08.01 + +#### Files Removed +- `src/templates/html/mod_menu/default.php` +- `src/templates/html/mod_menu/default_component.php` +- `src/templates/html/mod_menu/default_url.php` +- `src/templates/html/mod_menu/index.html` + +**Note**: This is a patch release that removes problematic overrides to restore core functionality. Menu styling via CSS remains intact. MokoCassiopeia remains a standalone Joomla template extension (type="template"), not bundled as a package. + ## [03.08.00] - 2026-02-22 ### Added - Community Builder Component Overrides diff --git a/CLIENT_FORK_README.md b/CLIENT_FORK_README.md deleted file mode 100644 index 2b8aa85..0000000 --- a/CLIENT_FORK_README.md +++ /dev/null @@ -1,455 +0,0 @@ - - -# [CLIENT NAME] - MokoCassiopeia Custom Fork - -**Custom Joomla Template Fork for [CLIENT NAME]** - -This is a customized fork of the [MokoCassiopeia](https://github.com/mokoconsulting-tech/MokoCassiopeia) Joomla template, tailored specifically for [CLIENT NAME]'s website. - -> **💡 Tip**: This fork was likely created using the automated [Client Fork Workflow](./docs/CLIENT_FORK_WORKFLOW.md). If you're creating a new client fork, use the workflow for instant setup! - ---- - -## 📋 About This Fork - -This repository contains client-specific customizations built on top of the MokoCassiopeia template. The template provides a modern, lightweight enhancement layer for Joomla with advanced theming, Font Awesome 7, Bootstrap 5, and dark mode support. - -### Customization Strategy - -This fork maintains the following customizations: -- **Custom Color Schemes**: Brand-specific colors for light and dark modes -- **Custom Code**: Client-specific HTML, CSS, and JavaScript customizations -- **Configuration**: Pre-configured template settings for the client environment - -All customizations are designed to be preserved when syncing with upstream MokoCassiopeia updates. - ---- - -## 🚀 Quick Start - -### Prerequisites - -- **Joomla**: 4.4.x or 5.x -- **PHP**: 8.0 or higher -- **Git**: For version control and syncing with upstream -- **Local Development**: MAMP/XAMPP/Docker for local testing - -### Installation for Development - -1. **Clone this repository**: - ```bash - git clone [YOUR-FORK-URL] - cd [YOUR-FORK-NAME] - ``` - -2. **Set up upstream remote** (for syncing updates): - ```bash - git remote add upstream https://github.com/mokoconsulting-tech/MokoCassiopeia.git - git fetch upstream - ``` - -3. **Install into Joomla**: - - Copy the `src/` directory contents to your Joomla installation: - - `src/templates/` → `[joomla]/templates/` - - `src/media/` → `[joomla]/media/templates/site/mokocassiopeia/` - - `src/language/` → `[joomla]/language/` - - `src/administrator/language/` → `[joomla]/administrator/language/` - -4. **Enable the template**: - - Log into Joomla admin - - Navigate to **System → Site Templates** - - Set **MokoCassiopeia** as the default template - ---- - -## 🎨 Custom Branding & Colors - -### Custom Color Schemes - -This fork includes custom color schemes specific to [CLIENT NAME]'s brand: - -**Location**: -- Light mode: `src/media/css/colors/light/colors_custom.css` -- Dark mode: `src/media/css/colors/dark/colors_custom.css` - -**Note**: These files are gitignored in the upstream repository to prevent conflicts, but are tracked in this fork. - -### Modifying Brand Colors - -1. **Edit the custom color files**: - ```bash - # Light mode colors - edit src/media/css/colors/light/colors_custom.css - - # Dark mode colors - edit src/media/css/colors/dark/colors_custom.css - ``` - -2. **Key variables to customize**: - ```css - :root[data-bs-theme="light"] { - --color-primary: #YOUR-BRAND-COLOR; - --accent-color-primary: #YOUR-ACCENT-COLOR; - --color-link: #YOUR-LINK-COLOR; - --nav-bg-color: #YOUR-NAV-BG; - } - ``` - -3. **Test your changes**: - - Clear Joomla cache: System → Clear Cache - - Clear browser cache (Ctrl+Shift+R / Cmd+Shift+R) - - View your site in light and dark modes - -### Available CSS Variables - -For a complete reference of all customizable CSS variables, see the [CSS Variables Documentation](./docs/CSS_VARIABLES.md) in the upstream repository. - ---- - -## 🔧 Custom Code Injection - -### Using custom.php - -The `src/templates/custom.php` file allows for custom PHP functions and HTML snippets: - -**Location**: `src/templates/custom.php` - -**Example Use Cases**: -- Custom helper functions -- Client-specific HTML snippets -- Custom console logging -- Integration code - -**Example**: -```php -' . $js_code . ''; - } - echo $js_code; -} -?> - -``` - -### Custom Code via Joomla Template Settings - -You can also inject custom code via the Joomla admin interface: - -1. Navigate to **System → Site Templates → MokoCassiopeia** -2. Go to the **Custom Code** tab -3. Add custom HTML/CSS/JS in: - - **Custom Head Start**: Injected at the beginning of `` - - **Custom Head End**: Injected at the end of `` - -This approach is ideal for: -- Analytics tracking codes -- Custom meta tags -- External script includes -- Custom CSS snippets - ---- - -## 🔄 Syncing with Upstream Updates - -To keep your fork up-to-date with new features and bug fixes from the upstream MokoCassiopeia repository: - -### 1. Fetch Upstream Changes - -```bash -# Ensure upstream remote is configured -git remote -v -# If upstream is not listed, add it: -# git remote add upstream https://github.com/mokoconsulting-tech/MokoCassiopeia.git - -# Fetch latest changes -git fetch upstream -``` - -### 2. Review Changes - -```bash -# See what changed in upstream -git log HEAD..upstream/main --oneline - -# Review the diff -git diff HEAD..upstream/main -``` - -### 3. Merge Upstream Changes - -```bash -# Switch to your main branch -git checkout main - -# Merge upstream changes -git merge upstream/main - -# Or rebase (preserves cleaner history): -# git rebase upstream/main -``` - -### 4. Resolve Conflicts - -If conflicts occur (typically in custom files): - -1. **Check conflict status**: - ```bash - git status - ``` - -2. **Resolve conflicts manually** in your editor: - - Look for conflict markers: `<<<<<<<`, `=======`, `>>>>>>>` - - Keep your custom changes - - Remove conflict markers - -3. **Complete the merge**: - ```bash - git add . - git commit -m "Merge upstream updates and resolve conflicts" - ``` - -### 5. Test After Merging - -- Clear Joomla cache -- Test critical functionality: - - Homepage loads correctly - - Custom colors are preserved - - Dark mode toggle works - - Navigation functions properly - - Custom code still executes - -### Protected Files - -The following files contain your customizations and should be carefully reviewed during merges: - -- `src/media/css/colors/light/colors_custom.css` (custom light mode colors) -- `src/media/css/colors/dark/colors_custom.css` (custom dark mode colors) -- `src/templates/custom.php` (custom PHP code) -- Template configuration (stored in Joomla database, not in files) - ---- - -## 📦 Building & Deployment - -### Creating a Template Package - -To create an installable ZIP package of your customized template: - -1. **Prepare the package**: - ```bash - cd src - zip -r ../mokocassiopeia-[CLIENT-NAME]-[VERSION].zip . -x "*.git*" "*.DS_Store" - ``` - -2. **Install via Joomla**: - - Upload the ZIP file via **System → Install → Extensions** - - Or manually copy files to the Joomla installation - -### Deployment to Production - -**Recommended Deployment Methods**: - -1. **Via Joomla Extension Manager** (Easiest): - - Create a ZIP package as described above - - Upload via Joomla admin interface - - The template will automatically overwrite the existing installation - -2. **Via FTP/SFTP**: - - Upload changed files directly to the server - - Clear Joomla cache after deployment - -3. **Via Git** (Advanced): - - Push changes to a deployment branch - - Use Git hooks or CI/CD to deploy to production - - Ensure proper file permissions - -**Post-Deployment Checklist**: -- [ ] Clear Joomla cache (System → Clear Cache) -- [ ] Test homepage -- [ ] Test navigation and menus -- [ ] Verify custom colors appear correctly -- [ ] Test dark mode toggle -- [ ] Check mobile responsiveness -- [ ] Verify analytics tracking (if enabled) - ---- - -## 🛠 Local Development Setup - -### Setting Up a Local Joomla Environment - -1. **Install a local server stack**: - - **MAMP** (Mac/Windows): https://www.mamp.info/ - - **XAMPP** (Cross-platform): https://www.apachefriends.org/ - - **Docker**: https://github.com/joomla-docker/docker-joomla - -2. **Install Joomla**: - - Download Joomla from https://downloads.joomla.org/ - - Extract to your local server's web directory - - Follow the Joomla installation wizard - -3. **Install this template**: - - Copy files from this repository to your Joomla installation - - Or upload the ZIP package via Joomla's Extension Manager - -4. **Enable development mode**: - - Edit `configuration.php`: - ```php - public $debug = '1'; - public $error_reporting = 'maximum'; - ``` - -### Development Workflow - -1. **Make changes** to template files in your local Joomla installation -2. **Test changes** in your browser -3. **Copy changes back** to this repository: - ```bash - # From Joomla installation - cp [joomla]/templates/mokocassiopeia/* [repo]/src/templates/ - cp [joomla]/media/templates/site/mokocassiopeia/css/* [repo]/src/media/css/ - ``` -4. **Commit and push** to your fork -5. **Deploy** to staging/production when ready - -### Quick Testing Commands - -```bash -# Clear Joomla cache from command line -rm -rf [joomla]/cache/* -rm -rf [joomla]/administrator/cache/* - -# Watch for CSS changes (if using a build tool) -# npm run watch -``` - ---- - -## 📝 Customization Checklist - -Use this checklist when setting up or modifying your custom fork: - -### Initial Setup -- [ ] Fork the MokoCassiopeia repository -- [ ] Update this README with client name and details -- [ ] Configure custom brand colors -- [ ] Test light and dark modes -- [ ] Add custom code if needed -- [ ] Configure template settings in Joomla -- [ ] Set up analytics tracking (if required) -- [ ] Test on multiple devices and browsers - -### Ongoing Maintenance -- [ ] Sync with upstream periodically (monthly recommended) -- [ ] Review upstream changelog for breaking changes -- [ ] Test thoroughly after merging upstream updates -- [ ] Keep this README updated with customization notes -- [ ] Document any client-specific configurations -- [ ] Maintain backup before major updates - ---- - -## 📚 Documentation Resources - -### MokoCassiopeia Documentation - -- **[Main README](https://github.com/mokoconsulting-tech/MokoCassiopeia/blob/main/README.md)** - Features and overview -- **[CSS Variables Reference](./docs/CSS_VARIABLES.md)** - Complete CSS customization guide -- **[Development Guide](./docs/JOOMLA_DEVELOPMENT.md)** - Development and testing -- **[Quick Start](./docs/QUICK_START.md)** - Quick setup guide -- **[Changelog](./CHANGELOG.md)** - Version history - -### Joomla Resources - -- **[Joomla Documentation](https://docs.joomla.org/)** - Official Joomla docs -- **[Joomla Templates](https://docs.joomla.org/J4.x:How_to_Create_a_Joomla_Template)** - Template development guide -- **[Cassiopeia Documentation](https://docs.joomla.org/J4.x:Cassiopeia)** - Parent template docs - ---- - -## 🔒 Security & Best Practices - -### Security Considerations - -1. **Keep Joomla Updated**: Always run the latest stable Joomla version -2. **Update Dependencies**: Regularly sync with upstream MokoCassiopeia for security patches -3. **Secure Custom Code**: Review all custom code for security vulnerabilities -4. **Use HTTPS**: Always serve production sites over HTTPS -5. **Regular Backups**: Maintain regular backups of both files and database - -### Best Practices - -1. **Version Control**: Commit changes frequently with clear messages -2. **Testing**: Always test changes locally before deploying to production -3. **Documentation**: Document all customizations in this README -4. **Code Review**: Have changes reviewed before deploying to production -5. **Staging Environment**: Use a staging site to test updates before production - ---- - -## 📞 Support & Contact - -### Client-Specific Support - -**Client Contact**: [CLIENT CONTACT INFO] -**Developer Contact**: [DEVELOPER CONTACT INFO] -**Hosting Provider**: [HOSTING INFO] - -### Upstream MokoCassiopeia Support - -- **Repository**: https://github.com/mokoconsulting-tech/MokoCassiopeia -- **Issues**: https://github.com/mokoconsulting-tech/MokoCassiopeia/issues -- **Documentation**: https://github.com/mokoconsulting-tech/MokoCassiopeia/blob/main/README.md -- **Moko Consulting**: https://mokoconsulting.tech - ---- - -## 📄 License - -This fork maintains the original GPL-3.0-or-later license from MokoCassiopeia. - -- **MokoCassiopeia**: GPL-3.0-or-later -- **Client Customizations**: GPL-3.0-or-later (or as specified by client agreement) -- **Third-Party Libraries**: See [Included Libraries](https://github.com/mokoconsulting-tech/MokoCassiopeia#-included-libraries) - ---- - -## 📊 Fork Information - -- **Upstream Repository**: https://github.com/mokoconsulting-tech/MokoCassiopeia -- **Fork Repository**: [YOUR-FORK-URL] -- **Client**: [CLIENT NAME] -- **Created**: [DATE] -- **Last Synced with Upstream**: [DATE] -- **Current Version**: 03.06.03 - ---- - -## 🔄 Revision History - -| Date | Version | Change Summary | Author | -|------|---------|----------------|--------| -| [DATE] | 03.06.03 | Initial fork setup with custom colors and branding | [YOUR NAME] | - ---- - -**Maintained by [CLIENT NAME] / [DEVELOPER NAME]** diff --git a/README.md b/README.md index f7ae954..5a975fc 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,8 @@ MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla ## 📦 Installation +**Note**: MokoCassiopeia is a **standalone Joomla template extension** (not bundled as a package). Install it directly via Joomla's Extension Manager. + ### Via Joomla Extension Manager 1. Download the latest `mokocassiopeia-{version}.zip` from [Releases](https://github.com/mokoconsulting-tech/MokoCassiopeia/releases) @@ -201,13 +203,13 @@ Access template configuration via **System → Site Templates → MokoCassiopeia - **Left Drawer Icon**: Font Awesome icon class (e.g., `fa-solid fa-chevron-right`) - **Right Drawer Icon**: Font Awesome icon class (e.g., `fa-solid fa-chevron-left`) -### Custom Color Palettes +### Custom Theme Palettes -MokoCassiopeia supports custom color schemes: +MokoCassiopeia supports custom theme schemes: 1. **Copy template files** from `/templates/` directory: - - `colors_custom_light.css` → `media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css` - - `colors_custom_dark.css` → `media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css` + - `light.custom.css` → `media/templates/site/mokocassiopeia/css/theme/light.custom.css` + - `dark.custom.css` → `media/templates/site/mokocassiopeia/css/theme/dark.custom.css` 2. **Customize** the CSS variables to match your brand colors 3. **Enable in Joomla**: System → Site Templates → MokoCassiopeia → Theme tab → Set palette to "Custom" 4. **Save** and view your site with custom colors @@ -326,16 +328,6 @@ See [Joomla Development Guide](./docs/JOOMLA_DEVELOPMENT.md) for packaging instr - **[CSS Variables Reference](./docs/CSS_VARIABLES.md)** - Complete CSS customization guide - **[Documentation Index](./docs/README.md)** - All documentation links -### Customization Resources - -- **[Template Files](./templates/)** - Ready-to-use templates for customization - - `colors_custom.css` - Custom color palette template - - `CLIENT_FORK_README_TEMPLATE.md` - Template for client fork documentation - -### Client Forks - -- **[Client Fork Guide](./CLIENT_FORK_README.md)** - Comprehensive guide for creating and maintaining client custom code forks - ### Governance - **[Contributing](./CONTRIBUTING.md)** - How to contribute @@ -402,18 +394,9 @@ We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for gu See [Workflow Guide](./docs/WORKFLOW_GUIDE.md) for detailed Git workflow. -### Client Custom Forks +### Customizations -Creating a custom fork for client-specific branding and code? - -**Quick Setup**: Use our automated workflow to create a client fork in minutes: -- **[Client Fork Workflow Guide](./docs/CLIENT_FORK_WORKFLOW.md)** - Automated GitHub Actions workflow or local bash script - -**Comprehensive Guide**: See our [Client Fork Guide](./CLIENT_FORK_README.md) for: -- Setting up custom color schemes -- Maintaining fork-specific customizations -- Syncing with upstream updates -- Deployment workflows +For template customizations, use Joomla's built-in template settings (System → Site Templates → MokoCassiopeia → Custom Code tab) for HTML/CSS/JS customizations. --- diff --git a/docs/CLIENT_FORK_WORKFLOW.md b/docs/CLIENT_FORK_WORKFLOW.md deleted file mode 100644 index 131ceaf..0000000 --- a/docs/CLIENT_FORK_WORKFLOW.md +++ /dev/null @@ -1,320 +0,0 @@ - - -# Client Fork Creation Workflow - -This document explains how to use the automated client fork creation tools to set up a new client-specific fork of MokoCassiopeia. - ---- - -## Overview - -The client fork creation workflow automates the process of preparing a repository for a client-specific fork. It performs the following actions: - -1. ✅ Copies `templates/colors_custom.css` to `src/media/css/colors/light/colors_custom.css` -2. ✅ Copies `templates/colors_custom.css` to `src/media/css/colors/dark/colors_custom.css` -3. ✅ Replaces `README.md` with customized `CLIENT_FORK_README.md` -4. ✅ Removes `CLIENT_FORK_README.md` from root -5. ✅ Removes `templates/CLIENT_FORK_README_TEMPLATE.md` -6. ✅ Updates `templates/README.md` to remove fork template references -7. ✅ Keeps `templates/colors_custom.css` as a template for reference - ---- - -## Method 1: GitHub Actions Workflow (Recommended) - -### Prerequisites - -- Repository admin or maintainer access -- GitHub Actions enabled for the repository - -### Steps - -1. **Navigate to Actions** - - Go to your repository on GitHub - - Click on the "Actions" tab - -2. **Run the Workflow** - - Select "Create Client Fork" from the workflow list - - Click "Run workflow" - - Fill in the required inputs: - - **Client Name**: Full client name (e.g., "Acme Corporation") - - **Confirm**: Type "CONFIRM" to proceed - - Click "Run workflow" button - -3. **Monitor Progress** - - The workflow will create a new branch named `client-fork/{client-slug}` - - You can monitor the progress in the Actions tab - - Once complete, you'll see a summary of changes - -4. **Review the Branch** - - Navigate to the new branch: `client-fork/{client-slug}` - - Review the changes made - - The README will be customized with the client name - - Custom color files will be in place - -5. **Create Client Repository** - - Create a new repository for the client - - Push the branch to the new repository: - ```bash - git remote add client-repo - git push client-repo client-fork/{client-slug}:main - ``` - -### Workflow Features - -- ✅ **Safe Confirmation**: Requires typing "CONFIRM" to prevent accidental runs -- ✅ **Automated Branch Creation**: Creates a properly named branch automatically -- ✅ **Customized README**: Automatically fills in client name and date -- ✅ **Git Tracking**: Commits all changes with a descriptive message -- ✅ **Summary Report**: Provides a complete summary of actions taken - ---- - -## Method 2: Local Bash Script - -### Prerequisites - -- Git installed on your local machine -- Bash shell (Linux, macOS, or Git Bash on Windows) -- Local clone of the MokoCassiopeia repository - -### Steps - -1. **Clone the Repository** - ```bash - git clone https://github.com/mokoconsulting-tech/MokoCassiopeia.git - cd MokoCassiopeia - ``` - -2. **Make Script Executable** - ```bash - chmod +x scripts/create-client-fork.sh - ``` - -3. **Run the Script** - ```bash - ./scripts/create-client-fork.sh "Client Name" - ``` - - Example: - ```bash - ./scripts/create-client-fork.sh "Acme Corporation" - ``` - -4. **Confirm Actions** - - The script will show you what it will do - - Type "yes" to proceed - - Review the changes shown - - Type "yes" to commit - -5. **Push to New Repository** - ```bash - # Add the client's repository as a remote - git remote add client-repo - - # Push the branch - git push client-repo client-fork/{client-slug}:main - ``` - -### Script Features - -- 🎨 **Colored Output**: Easy-to-read colored terminal output -- ✅ **Interactive Confirmation**: Asks for confirmation before making changes -- ✅ **Safety Checks**: Verifies you're in the correct directory -- ✅ **Progress Indicators**: Shows each step as it completes -- ✅ **Git Status**: Shows what files changed before committing -- ✅ **Summary**: Provides a complete summary at the end - ---- - -## What Gets Changed - -### Files Created - -``` -src/media/css/colors/light/colors_custom.css [NEW] -src/media/css/colors/dark/colors_custom.css [NEW] -``` - -### Files Modified - -``` -README.md [REPLACED] -templates/README.md [UPDATED] -``` - -### Files Removed - -``` -CLIENT_FORK_README.md [DELETED] -templates/CLIENT_FORK_README_TEMPLATE.md [DELETED] -``` - -### Files Kept - -``` -templates/colors_custom.css [UNCHANGED] -``` - ---- - -## Post-Setup Steps - -After running the workflow or script, you should: - -1. **Customize Brand Colors** - - Edit `src/media/css/colors/light/colors_custom.css` - - Edit `src/media/css/colors/dark/colors_custom.css` - - Update CSS variables to match client branding - -2. **Update README** - - Fill in client-specific contact information - - Add custom notes or configurations - - Update fork URL references - -3. **Test Locally** - - Install the template in a local Joomla instance - - Test light and dark modes - - Verify custom colors appear correctly - -4. **Create Client Repository** - - Create a new repository for the client - - Push the prepared branch to the new repo - - Set up appropriate access controls - -5. **Enable Custom Palette in Joomla** - - Log into Joomla admin - - Navigate to System → Site Templates → MokoCassiopeia - - Under Theme tab, set palette to "Custom" - - Save and test - ---- - -## Troubleshooting - -### Workflow Fails with "CONFIRM" Error - -**Problem**: Workflow stops immediately with confirmation error. - -**Solution**: Make sure you type "CONFIRM" (in all caps) in the confirmation field. - -### Script Says "CLIENT_FORK_README.md not found" - -**Problem**: Script can't find required files. - -**Solution**: Make sure you're running the script from the repository root directory: -```bash -cd /path/to/MokoCassiopeia -./scripts/create-client-fork.sh "Client Name" -``` - -### Colors Don't Appear After Setup - -**Problem**: Custom colors don't show in Joomla. - -**Solution**: -1. Enable custom palette in template settings -2. Clear Joomla cache (System → Clear Cache) -3. Clear browser cache (Ctrl+Shift+R / Cmd+Shift+R) - -### Branch Already Exists - -**Problem**: Branch name conflicts with existing branch. - -**Solution**: Either delete the old branch or choose a different client name: -```bash -# Delete old branch -git branch -D client-fork/{client-slug} - -# Or use a more specific client name -./scripts/create-client-fork.sh "Client Name - Division" -``` - ---- - -## Examples - -### Example 1: Simple Client Fork - -```bash -# Using the script -./scripts/create-client-fork.sh "Acme Corporation" -``` - -This creates: -- Branch: `client-fork/acme-corporation` -- README title: "Acme Corporation - MokoCassiopeia Custom Fork" - -### Example 2: Client with Multiple Words - -```bash -# Using the script -./scripts/create-client-fork.sh "Global Tech Solutions Inc" -``` - -This creates: -- Branch: `client-fork/global-tech-solutions-inc` -- README title: "Global Tech Solutions Inc - MokoCassiopeia Custom Fork" - -### Example 3: Using GitHub Actions - -1. Go to Actions → Create Client Fork -2. Enter: "Mountain View Medical Center" -3. Enter: "CONFIRM" -4. Click "Run workflow" - -Result: -- Branch: `client-fork/mountain-view-medical-center` -- README title: "Mountain View Medical Center - MokoCassiopeia Custom Fork" - ---- - -## Best Practices - -1. **Naming Convention**: Use the official client name as it should appear in documentation - -2. **Branch Management**: - - Keep the branch until the client repository is set up - - Don't merge client fork branches back to main - -3. **Custom Colors**: - - Document color choices in README - - Keep a backup of custom color files - - Test in both light and dark modes - -4. **Version Tracking**: - - Note the upstream version in fork README - - Track when you last synced with upstream - -5. **Security**: - - Don't commit client-specific credentials - - Review custom code before deployment - - Keep client forks private if they contain sensitive branding - ---- - -## Related Documentation - -- **[CLIENT_FORK_README.md](../CLIENT_FORK_README.md)** - Full client fork guide -- **[CSS Variables](../docs/CSS_VARIABLES.md)** - Complete CSS variable reference -- **[Main README](../README.md)** - MokoCassiopeia documentation - ---- - -## Support - -For issues with the workflow or script: -- Check this documentation first -- Review error messages carefully -- Contact: hello@mokoconsulting.tech - ---- - -**Document Version**: 1.0 -**Last Updated**: 2026-02-20 -**Maintained by**: Moko Consulting diff --git a/docs/CSS_VARIABLES.md b/docs/CSS_VARIABLES.md index 053741f..f4adec4 100644 --- a/docs/CSS_VARIABLES.md +++ b/docs/CSS_VARIABLES.md @@ -46,8 +46,8 @@ This document provides a complete reference of all CSS variables available in th To create custom color schemes: 1. **Copy template files** from `./templates/` directory: - - `colors_custom_light.css` → `media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css` - - `colors_custom_dark.css` → `media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css` + - `light.custom.css` → `media/templates/site/mokocassiopeia/css/theme/light.custom.css` + - `dark.custom.css` → `media/templates/site/mokocassiopeia/css/theme/dark.custom.css` 2. **Edit the variables** in the copied files to match your brand @@ -403,6 +403,51 @@ Available in 9 shades: `--gray-100` through `--gray-900` Light mode ranges from very light (`#f9fafb`) to very dark (`#22262a`). Dark mode ranges are inverted for better contrast on dark backgrounds. +### Opacity Utilities + +**New in v03.08.04**: Opacity utility variables for creating translucent colors: + +- `--opacity-0`: `0` (fully transparent) +- `--opacity-5`: `0.05` +- `--opacity-10`: `0.1` +- `--opacity-15`: `0.15` +- `--opacity-20`: `0.2` +- `--opacity-25`: `0.25` +- `--opacity-30`: `0.3` +- `--opacity-50`: `0.5` +- `--opacity-75`: `0.75` +- `--opacity-100`: `1` (fully opaque) + +**Usage Example:** +```css +background-color: rgba(var(--black-rgb), var(--opacity-10)); +border-color: rgba(var(--white-rgb), var(--opacity-25)); +``` + +### Shadow Color Utilities + +**New in v03.08.04**: Pre-defined shadow color variables for consistent shadow styling: + +**Light Theme:** +- `--shadow-color-light`: `rgba(var(--black-rgb), var(--opacity-15))` - Light shadows +- `--shadow-color-medium`: `rgba(var(--black-rgb), var(--opacity-25))` - Medium shadows +- `--shadow-color-dark`: `rgba(var(--black-rgb), var(--opacity-30))` - Dark shadows +- `--border-color-translucent`: `rgba(var(--black-rgb), var(--opacity-10))` - Translucent borders +- `--highlight-translucent`: `rgba(var(--white-rgb), var(--opacity-15))` - Highlight overlays + +**Dark Theme:** +- `--shadow-color-light`: `rgba(var(--black-rgb), var(--opacity-30))` - Adjusted for dark backgrounds +- `--shadow-color-medium`: `rgba(var(--black-rgb), var(--opacity-50))` +- `--shadow-color-dark`: `rgba(var(--black-rgb), var(--opacity-75))` +- `--border-color-translucent`: `rgba(var(--white-rgb), var(--opacity-10))` +- `--highlight-translucent`: `rgba(var(--white-rgb), var(--opacity-5))` + +**Usage Example:** +```css +box-shadow: 0 0.5rem 1rem var(--shadow-color-light); +border: 1px solid var(--border-color-translucent); +``` + --- ## Body & Typography @@ -535,6 +580,68 @@ Dark mode ranges are inverted for better contrast on dark backgrounds. --- +## Bootstrap Button Variants + +**New in v03.08.04**: Complete Bootstrap button color definitions for both light and dark themes. + +### Available Button Classes + +All button variants support hover, active, focus, and disabled states using CSS variables: + +**Solid Buttons:** +- `.btn-primary` - Primary brand button +- `.btn-secondary` - Secondary button +- `.btn-success` - Success/positive action button +- `.btn-info` - Informational button +- `.btn-warning` - Warning/caution button +- `.btn-danger` - Danger/destructive action button +- `.btn-light` - Light background button +- `.btn-dark` - Dark background button + +**Outline Buttons:** +- `.btn-outline-primary` through `.btn-outline-dark` - Outlined variants of above + +### Button CSS Variables + +Each button variant defines the following CSS variables: + +- `--btn-color`: Text color +- `--btn-bg`: Background color +- `--btn-border-color`: Border color +- `--btn-hover-color`: Hover state text color +- `--btn-hover-bg`: Hover state background +- `--btn-hover-border-color`: Hover state border +- `--btn-focus-shadow-rgb`: Focus ring RGB values +- `--btn-active-color`: Active state text color +- `--btn-active-bg`: Active state background +- `--btn-active-border-color`: Active state border +- `--btn-active-shadow`: Active state shadow +- `--btn-disabled-color`: Disabled state text color +- `--btn-disabled-bg`: Disabled state background +- `--btn-disabled-border-color`: Disabled state border + +### Customizing Button Colors + +To customize button colors in your custom color palette: + +```css +:root[data-bs-theme="light"] { + /* Override Bootstrap state colors */ + --success: #28a745; + --danger: #dc3545; +} + +.btn-primary { + --btn-bg: var(--color-primary); + --btn-border-color: var(--color-primary); + /* Other button states... */ +} +``` + +See `templates/light.custom.css` and `templates/dark.custom.css` for complete examples. + +--- + ## Button Utilities ### `--btn-border-radius` @@ -673,6 +780,35 @@ Dark mode ranges are inverted for better contrast on dark backgrounds. - Dark: `#ff8e86` - `--form-invalid-border-color`: Matching border color +### Form Control Enhancements + +**New in v03.08.04**: Additional form control color variables: + +#### `--input-file-button-active-bg` +- **Light Mode**: `#dee1e4` +- **Dark Mode**: `#2b3441` +- **Usage**: Background color for file input button in active state + +#### `--form-range-thumb-active-bg` +- **Light Mode**: `#b8bfcc` +- **Dark Mode**: `#4a5766` +- **Usage**: Background color for range slider thumb in active state + +### Alert Link Colors + +**New in v03.08.04**: Dedicated variables for alert link colors: + +- `--alert-primary-link-color`: Link color in primary alerts +- `--alert-secondary-link-color`: Link color in secondary alerts +- `--alert-success-link-color`: Link color in success alerts +- `--alert-info-link-color`: Link color in info alerts +- `--alert-warning-link-color`: Link color in warning alerts +- `--alert-danger-link-color`: Link color in danger alerts +- `--alert-light-link-color`: Link color in light alerts +- `--alert-dark-link-color`: Link color in dark alerts + +These ensure optimal readability for links within alert boxes. + --- ## Responsive Tokens & Breakpoints diff --git a/docs/MANUAL_DEPLOYMENT.md b/docs/MANUAL_DEPLOYMENT.md new file mode 100644 index 0000000..ece9f6c --- /dev/null +++ b/docs/MANUAL_DEPLOYMENT.md @@ -0,0 +1,310 @@ +# Manual Deployment Guide - MokoCassiopeia + +This guide explains how to manually deploy the MokoCassiopeia template from the `src` directory to a Joomla installation without using the build/packaging process. + +## Table of Contents + +- [Overview](#overview) +- [Understanding the Structure](#understanding-the-structure) +- [Manual Deployment Methods](#manual-deployment-methods) +- [Troubleshooting](#troubleshooting) +- [When to Use Manual Deployment](#when-to-use-manual-deployment) + +## Overview + +**Important**: The `src` directory in this repository is the development source, not a ready-to-install package. For production use, we recommend using the packaged ZIP file from [Releases](https://github.com/mokoconsulting-tech/MokoCassiopeia/releases). + +However, for development or testing purposes, you can manually deploy files from the `src` directory to your Joomla installation. + +## Understanding the Structure + +### Repository Structure + +The `src/` directory contains: + +``` +src/ +├── component.php # Template file +├── error.php # Template file +├── index.php # Main template file +├── offline.php # Template file +├── templateDetails.xml # Template manifest +├── joomla.asset.json # Asset registration +├── html/ # Module & component overrides +├── language/ # Frontend language files +├── administrator/ # Backend language files +│ └── language/ +└── media/ # Assets (CSS, JS, images, fonts) + ├── css/ + ├── js/ + ├── images/ + └── fonts/ +``` + +### Joomla Installation Structure + +Joomla expects template files in these locations: + +``` +YOUR_JOOMLA_ROOT/ +├── templates/ +│ └── mokocassiopeia/ # Template files go here +│ ├── component.php +│ ├── error.php +│ ├── index.php +│ ├── offline.php +│ ├── templateDetails.xml +│ ├── joomla.asset.json +│ ├── html/ +│ ├── language/ +│ └── administrator/ +└── media/ + └── templates/ + └── site/ + └── mokocassiopeia/ # Media files go here + ├── css/ + ├── js/ + ├── images/ + └── fonts/ +``` + +**Key Point**: Template files and media files go to **different locations** in Joomla! + +## Manual Deployment Methods + +### Method 1: Recommended - Upload as ZIP (Still Manual) + +This method mimics what Joomla's installer does automatically. + +1. **Prepare the template directory**: + ```bash + # From the repository root + cd src + + # Copy all files EXCEPT media to a temp directory + mkdir -p /tmp/mokocassiopeia + cp component.php /tmp/mokocassiopeia/ + cp error.php /tmp/mokocassiopeia/ + cp index.php /tmp/mokocassiopeia/ + cp offline.php /tmp/mokocassiopeia/ + cp templateDetails.xml /tmp/mokocassiopeia/ + cp joomla.asset.json /tmp/mokocassiopeia/ + cp -r html /tmp/mokocassiopeia/ + cp -r language /tmp/mokocassiopeia/ + cp -r administrator /tmp/mokocassiopeia/ + + # Copy media to a separate temp directory + mkdir -p /tmp/mokocassiopeia_media + cp -r media/* /tmp/mokocassiopeia_media/ + ``` + +2. **Upload to Joomla via FTP/SFTP**: + ```bash + # Upload template files + # Replace with your actual Joomla path + scp -r /tmp/mokocassiopeia/* user@yourserver:/path/to/joomla/templates/mokocassiopeia/ + + # Upload media files + scp -r /tmp/mokocassiopeia_media/* user@yourserver:/path/to/joomla/media/templates/site/mokocassiopeia/ + ``` + +3. **Set proper permissions**: + ```bash + # On your server + cd /path/to/joomla + chmod 755 templates/mokocassiopeia + chmod 644 templates/mokocassiopeia/* + chmod 755 templates/mokocassiopeia/html + chmod 755 media/templates/site/mokocassiopeia + ``` + +### Method 2: Direct Copy to Existing Installation + +If you have direct filesystem access (e.g., local development): + +1. **Copy template files** (excluding media): + ```bash + # From repository root + cd src + + # Copy to Joomla templates directory + cp component.php /path/to/joomla/templates/mokocassiopeia/ + cp error.php /path/to/joomla/templates/mokocassiopeia/ + cp index.php /path/to/joomla/templates/mokocassiopeia/ + cp offline.php /path/to/joomla/templates/mokocassiopeia/ + cp templateDetails.xml /path/to/joomla/templates/mokocassiopeia/ + cp joomla.asset.json /path/to/joomla/templates/mokocassiopeia/ + + # Copy directories + cp -r html /path/to/joomla/templates/mokocassiopeia/ + cp -r language /path/to/joomla/templates/mokocassiopeia/ + cp -r administrator /path/to/joomla/templates/mokocassiopeia/ + ``` + +2. **Copy media files separately**: + ```bash + # Copy media to the media directory + cp -r media/* /path/to/joomla/media/templates/site/mokocassiopeia/ + ``` + +3. **Clear Joomla cache**: + - In Joomla admin: **System → Clear Cache** + - Or delete: `/path/to/joomla/cache/*` and `/path/to/joomla/administrator/cache/*` + +### Method 3: Symlink for Development (Linux/Mac only) + +For active development where you want changes to immediately reflect: + +1. **Create symlinks**: + ```bash + # Remove existing directory if present + rm -rf /path/to/joomla/templates/mokocassiopeia + rm -rf /path/to/joomla/media/templates/site/mokocassiopeia + + # Create parent directories if needed + mkdir -p /path/to/joomla/templates + mkdir -p /path/to/joomla/media/templates/site + + # Symlink template files + ln -s /path/to/MokoCassiopeia/src /path/to/joomla/templates/mokocassiopeia + + # Symlink media files + ln -s /path/to/MokoCassiopeia/src/media /path/to/joomla/media/templates/site/mokocassiopeia + ``` + +2. **Note**: This won't work as-is because the src directory includes the media folder. You'll need to: + ```bash + # Better approach for symlinks: + # Link everything except media at template root + cd /path/to/joomla/templates + mkdir -p mokocassiopeia + cd mokocassiopeia + + ln -s /path/to/MokoCassiopeia/src/component.php + ln -s /path/to/MokoCassiopeia/src/error.php + ln -s /path/to/MokoCassiopeia/src/index.php + ln -s /path/to/MokoCassiopeia/src/offline.php + ln -s /path/to/MokoCassiopeia/src/templateDetails.xml + ln -s /path/to/MokoCassiopeia/src/joomla.asset.json + ln -s /path/to/MokoCassiopeia/src/html + ln -s /path/to/MokoCassiopeia/src/language + ln -s /path/to/MokoCassiopeia/src/administrator + + # Link media separately + ln -s /path/to/MokoCassiopeia/src/media /path/to/joomla/media/templates/site/mokocassiopeia + ``` + +## Troubleshooting + +### Language Files Not Loading + +**Problem**: Language strings appear as language keys (e.g., `TPL_MOKOCASSIOPEIA_LABEL`) + +**Solution**: Ensure the `language` and `administrator` folders are present in your template directory: + +```bash +# Check if folders exist +ls -la /path/to/joomla/templates/mokocassiopeia/language +ls -la /path/to/joomla/templates/mokocassiopeia/administrator +``` + +The `templateDetails.xml` should contain (lines 54-55): +```xml + + + language + administrator + +``` + +### CSS/JS Not Loading + +**Problem**: Styles or scripts don't apply + +**Solution**: Verify media files are in the correct location: + +```bash +# Check media directory structure +ls -la /path/to/joomla/media/templates/site/mokocassiopeia/ +# Should show: css/, js/, images/, fonts/ +``` + +Clear Joomla cache: +- Admin: **System → Clear Cache** +- Check browser developer console for 404 errors + +### Template Not Appearing in Template Manager + +**Problem**: MokoCassiopeia doesn't show in **System → Site Templates** + +**Solution**: +1. Verify `templateDetails.xml` is present in `/path/to/joomla/templates/mokocassiopeia/` +2. Check file permissions (should be readable by web server) +3. Verify XML is well-formed: + ```bash + xmllint --noout /path/to/joomla/templates/mokocassiopeia/templateDetails.xml + ``` +4. Check Joomla's error logs for XML parsing errors + +### File Permission Issues + +**Problem**: "Permission denied" or template files not readable + +**Solution**: +```bash +# Set proper ownership (replace www-data with your web server user) +chown -R www-data:www-data /path/to/joomla/templates/mokocassiopeia +chown -R www-data:www-data /path/to/joomla/media/templates/site/mokocassiopeia + +# Set proper permissions +find /path/to/joomla/templates/mokocassiopeia -type d -exec chmod 755 {} \; +find /path/to/joomla/templates/mokocassiopeia -type f -exec chmod 644 {} \; +find /path/to/joomla/media/templates/site/mokocassiopeia -type d -exec chmod 755 {} \; +find /path/to/joomla/media/templates/site/mokocassiopeia -type f -exec chmod 644 {} \; +``` + +## When to Use Manual Deployment + +### ✅ Use Manual Deployment For: + +- **Active Development**: Testing changes immediately without rebuilding packages +- **Local Development**: Working on a local Joomla instance +- **Quick Fixes**: Making emergency hotfixes directly on a development server +- **Learning**: Understanding the template structure and Joomla's file organization + +### ❌ Don't Use Manual Deployment For: + +- **Production Sites**: Always use packaged ZIP files from releases +- **Client Sites**: Use proper Joomla extension installation +- **Version Control**: Can lead to inconsistent deployments +- **Staging Environments**: Use CI/CD or release packages + +## Best Practices + +1. **Always Test Locally First**: Don't deploy untested changes to production +2. **Keep Backups**: Back up both template and media directories before updating +3. **Use Version Control**: Track your customizations separately from manual deployments +4. **Document Changes**: Note any manual file modifications +5. **Clear Cache**: Always clear Joomla cache after manual file updates +6. **Verify Permissions**: Ensure web server can read all files + +## Related Documentation + +- **[Quick Start Guide](QUICK_START.md)** - Development environment setup +- **[Joomla Development Guide](JOOMLA_DEVELOPMENT.md)** - Complete development workflows +- **[Release Process](RELEASE_PROCESS.md)** - How to create proper release packages + +## Support + +If you encounter issues with manual deployment: + +1. Check this troubleshooting guide first +2. Review [Joomla's template documentation](https://docs.joomla.org/J4.x:Creating_a_Simple_Template) +3. Open an issue on [GitHub](https://github.com/mokoconsulting-tech/MokoCassiopeia/issues) +4. Contact: hello@mokoconsulting.tech + +--- + +**Document Version**: 1.0.0 +**Last Updated**: 2026-03-01 +**Status**: Active diff --git a/docs/MODULE_OVERRIDES.md b/docs/MODULE_OVERRIDES.md index 8dcbe8c..100ba07 100644 --- a/docs/MODULE_OVERRIDES.md +++ b/docs/MODULE_OVERRIDES.md @@ -24,7 +24,7 @@ INGROUP: MokoCassiopeia.Documentation REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia FILE: docs/MODULE_OVERRIDES.md - VERSION: 03.08.00 + VERSION: 03.08.03 BRIEF: Comprehensive guide to MokoCassiopeia mobile-responsive module overrides PATH: /docs/MODULE_OVERRIDES.md --> @@ -35,7 +35,20 @@ This document provides a comprehensive guide to all mobile-responsive module and ## Overview -MokoCassiopeia includes **20 mobile-responsive module overrides** and **7 component view overrides** designed to enhance the mobile user experience across standard Joomla, VirtueMart, Community Builder, and popular third-party extensions. +MokoCassiopeia includes **16 mobile-responsive module overrides** and **12 component view overrides** designed to enhance the mobile user experience for third-party extensions and the Main Menu navigation. + +**Important**: Following Cassiopeia template best practices, MokoCassiopeia avoids overriding standard Joomla core modules (such as mod_search, mod_login, mod_breadcrumbs) to ensure proper language loading and compatibility. **Exception**: mod_menu "Main Menu" override provides essential Bootstrap 5 collapsible dropdown functionality. + +### Alternative Layouts, Not Replacements + +**All MokoCassiopeia overrides use alternative layout names (`mobile.php`) instead of replacing default layouts (`default.php`).** This means: + +- ✅ Default Joomla layouts continue to work unchanged +- ✅ You must explicitly select the "mobile" layout in module/menu item settings +- ✅ Joomla core updates don't break your site +- ✅ Full control over which modules use enhanced layouts + +**📖 See [OVERRIDE_PHILOSOPHY.md](OVERRIDE_PHILOSOPHY.md) for complete details on how to activate and use these alternative layouts.** ### Key Features @@ -52,31 +65,14 @@ All module overrides share these characteristics: ## Module Categories -### 1. Search Module - -#### mod_search -**Location**: `src/templates/html/mod_search/` - -Search box with multiple button position options and responsive design. - -**Features**: -- Button positions: left, right, top, bottom -- Text, icon, or both display modes -- 48px touch targets on mobile -- Prevents iOS zoom with 16px input font - -**Documentation**: [mod_search/README.md](../src/templates/html/mod_search/README.md) - ---- - -### 2. VirtueMart E-Commerce Modules +### 1. VirtueMart E-Commerce Modules Five comprehensive overrides for VirtueMart shopping functionality. -**Master Documentation**: [VIRTUEMART_MODULES_README.md](../src/templates/html/VIRTUEMART_MODULES_README.md) +**Master Documentation**: [VIRTUEMART_MODULES_README.md](../src/html/VIRTUEMART_MODULES_README.md) #### mod_virtuemart_cart -**Location**: `src/templates/html/mod_virtuemart_cart/` +**Location**: `src/html/mod_virtuemart_cart/` Shopping cart display with product list and checkout button. @@ -87,7 +83,7 @@ Shopping cart display with product list and checkout button. - Checkout button with prominent styling #### mod_virtuemart_product -**Location**: `src/templates/html/mod_virtuemart_product/` +**Location**: `src/html/mod_virtuemart_product/` Product showcase with grid layouts. @@ -98,7 +94,7 @@ Product showcase with grid layouts. - Rating display support #### mod_virtuemart_currencies -**Location**: `src/templates/html/mod_virtuemart_currencies/` +**Location**: `src/html/mod_virtuemart_currencies/` Currency selector dropdown for multi-currency stores. @@ -108,7 +104,7 @@ Currency selector dropdown for multi-currency stores. - Responsive button styling #### mod_virtuemart_category -**Location**: `src/templates/html/mod_virtuemart_category/` +**Location**: `src/html/mod_virtuemart_category/` Category navigation with hierarchical display. @@ -119,7 +115,7 @@ Category navigation with hierarchical display. - Active category highlighting #### mod_virtuemart_manufacturer -**Location**: `src/templates/html/mod_virtuemart_manufacturer/` +**Location**: `src/html/mod_virtuemart_manufacturer/` Manufacturer/brand display with grid layout. @@ -130,63 +126,37 @@ Manufacturer/brand display with grid layout. --- -### 3. Standard Joomla & Community Builder Modules +### 2. Main Menu & Community Builder Modules -Six essential Joomla core and Community Builder module overrides. +Three essential Community Builder and navigation module overrides. -**Master Documentation**: [STANDARD_MODULES_README.md](../src/templates/html/STANDARD_MODULES_README.md) +#### mod_menu (Main Menu) +**Location**: `src/html/mod_menu/` -#### mod_menu -**Location**: `src/templates/html/mod_menu/` - -Main navigation menu with multiple layout files. - -**Features**: -- Responsive horizontal/vertical layouts -- Multi-level menu support -- Active state highlighting -- Keyboard navigation +Bootstrap 5 responsive navigation menu with collapsible dropdown functionality. **Files**: -- `default.php` - Main menu layout -- `default_component.php` - Component links -- `default_url.php` - External URLs - -#### mod_breadcrumbs -**Location**: `src/templates/html/mod_breadcrumbs/` - -Breadcrumb navigation with Schema.org markup. +- `mainmenu.php` - Main layout with Bootstrap navbar +- `mainmenu_component.php` - Component menu items +- `mainmenu_heading.php` - Heading menu items +- `mainmenu_separator.php` - Separator menu items +- `mainmenu_url.php` - URL menu items **Features**: -- Structured data for SEO -- Responsive text truncation -- Proper separators -- Home icon support +- Bootstrap 5 navbar structure with collapsible hamburger menu +- Multi-level dropdown support (hover on desktop, tap on mobile) +- WCAG 2.1 compliant touch targets (48px mobile, 44px desktop) +- BEM naming convention: `.mod-menu-main__*` +- Active state indicators for current menu items +- ARIA labels and keyboard navigation support +- Alternative layout named `mainmenu.php` (not `default.php`) -#### mod_login -**Location**: `src/templates/html/mod_login/` +**Activation**: Select "Mainmenu" layout in Joomla Administrator → Modules → Menu Module → Advanced Tab → Alternative Layout -User login/logout form with 2FA support. - -**Features**: -- Login and logout states -- Two-factor authentication fields -- Remember me checkbox -- User greeting when logged in - -#### mod_articles_latest -**Location**: `src/templates/html/mod_articles_latest/` - -Latest articles display with metadata. - -**Features**: -- Responsive article cards -- Author, date, category metadata -- Read more links -- Featured article badges +**Note**: Unlike the broken mod_menu override removed in v03.08.01, this v03.08.03 version is properly structured based on Joomla core layouts and Bootstrap 5, ensuring language strings load correctly and menu functionality works as expected. #### mod_cblogin -**Location**: `src/templates/html/mod_cblogin/` +**Location**: `src/html/mod_cblogin/` Community Builder login with avatar display. @@ -197,7 +167,7 @@ Community Builder login with avatar display. - Logout button #### mod_comprofilerOnline -**Location**: `src/templates/html/mod_comprofilerOnline/` +**Location**: `src/html/mod_comprofilerOnline/` Community Builder online users display. @@ -209,16 +179,14 @@ Community Builder online users display. --- -### 4. Industry Extension Modules +### 3. Industry Extension Modules Eight popular third-party extension module overrides plus component views. -**Master Documentation**: [INDUSTRY_MODULES_README.md](../src/templates/html/INDUSTRY_MODULES_README.md) - #### K2 Content Extension ##### mod_k2_content -**Location**: `src/templates/html/mod_k2_content/` +**Location**: `src/html/mod_k2_content/` K2 content display with advanced layouts. @@ -232,7 +200,7 @@ K2 content display with advanced layouts. #### AcyMailing Newsletter ##### mod_acymailing -**Location**: `src/templates/html/mod_acymailing/` +**Location**: `src/html/mod_acymailing/` Newsletter subscription form. @@ -245,7 +213,7 @@ Newsletter subscription form. #### HikaShop E-Commerce ##### mod_hikashop_cart -**Location**: `src/templates/html/mod_hikashop_cart/` +**Location**: `src/html/mod_hikashop_cart/` HikaShop shopping cart module. @@ -260,7 +228,7 @@ HikaShop shopping cart module. Four comprehensive forum modules plus component view. ##### mod_kunenalatest -**Location**: `src/templates/html/mod_kunenalatest/` +**Location**: `src/html/mod_kunenalatest/` Latest forum posts display. @@ -271,7 +239,7 @@ Latest forum posts display. - Post date ##### mod_kunenalogin -**Location**: `src/templates/html/mod_kunenalogin/` +**Location**: `src/html/mod_kunenalogin/` Forum-specific login module. @@ -282,7 +250,7 @@ Forum-specific login module. - Profile link ##### mod_kunenasearch -**Location**: `src/templates/html/mod_kunenasearch/` +**Location**: `src/html/mod_kunenasearch/` Forum search with button positions. @@ -293,7 +261,7 @@ Forum search with button positions. - 48px touch targets ##### mod_kunenastats -**Location**: `src/templates/html/mod_kunenastats/` +**Location**: `src/html/mod_kunenastats/` Forum statistics display. @@ -305,7 +273,7 @@ Forum statistics display. - Responsive grid layout ##### com_kunena (Component) -**Location**: `src/templates/html/com_kunena/` +**Location**: `src/html/com_kunena/` Forum category list view. @@ -317,7 +285,7 @@ Forum category list view. Module and component overrides for membership management. ##### mod_osmembership -**Location**: `src/templates/html/mod_osmembership/` +**Location**: `src/html/mod_osmembership/` Membership plans module. @@ -328,7 +296,7 @@ Membership plans module. - Badge displays (popular, featured) ##### com_osmembership (Component) -**Location**: `src/templates/html/com_osmembership/` +**Location**: `src/html/com_osmembership/` Membership pricing tables. @@ -337,12 +305,12 @@ Membership pricing tables. --- -### 5. Community Builder Components +### 4. Community Builder Components Four comprehensive component view overrides for Community Builder user management. #### com_comprofiler -**Location**: `src/templates/html/com_comprofiler/` +**Location**: `src/html/com_comprofiler/` Mobile-responsive views for Community Builder user profiles, registration, and login. @@ -390,6 +358,79 @@ Login page with remember me and helper links. - CSRF token support - Responsive padding adjustments +### 5. JEM (Joomla Event Manager) Components + +Five comprehensive component view overrides for JEM event management. + +#### com_jem +**Location**: `src/html/com_jem/` + +Mobile-responsive views for JEM event listings, details, calendar, venues, and categories. + +##### eventslist +Event listing with card-based layout. + +**Features**: +- Event cards with date, time, and venue +- Category badges with color coding +- Responsive event grid layout +- Event description excerpts +- Read more buttons with clear calls-to-action +- Pagination support +- Empty state messaging + +##### event +Single event details view with comprehensive information. + +**Features**: +- Large event image display (responsive) +- Date and time with structured data +- Venue information with maps link +- Event description with full content +- Category display with badges +- Registration information (if enabled) +- Contact information display +- Back to events navigation +- Meta information with icons + +##### calendar +Monthly calendar view with event indicators. + +**Features**: +- Month navigation (previous/next) +- Calendar grid with weekday headers +- Event indicators on dates with events +- Responsive calendar layout +- Today highlighting +- Event list for selected month +- Event count per day display +- Touch-friendly navigation buttons + +##### venue +Venue details with location and upcoming events. + +**Features**: +- Venue image display +- Complete address information +- Website link (external) +- Google Maps integration +- Venue description +- Upcoming events at venue +- Location coordinates display +- Back navigation + +##### categories +Event category listing with descriptions. + +**Features**: +- Category cards with images +- Category descriptions +- Event count per category +- View category buttons +- Responsive grid layout +- Empty state messaging +- Pagination support + --- ## CSS Architecture @@ -431,6 +472,13 @@ All module styles are located in `src/media/css/template.css` with dedicated sec - Login pages - Tab interfaces +6. **JEM COMPONENT STYLES** (Lines ~22000+) + - Event list cards + - Event details layout + - Calendar grid + - Venue information + - Category displays + ### CSS Variables Integration All modules integrate with template CSS variables: @@ -509,17 +557,17 @@ Each module can be customized in two ways: Edit `src/media/css/user.css` to add custom styles: ```css -/* Example: Customize search button color */ -.mod-search__button { - background-color: #ff6600; -} - /* Example: Change product grid columns */ @media (min-width: 768px) { .mod-vm-product__grid { grid-template-columns: repeat(3, 1fr); } } + +/* Example: Customize cart button */ +.mod-vm-cart__checkout-button { + background-color: #28a745; +} ``` #### 2. Template Override Customization @@ -528,10 +576,10 @@ Copy the entire module directory and modify: ```bash # Keep original override as reference -cp -r src/templates/html/mod_search src/templates/html/mod_search_original +cp -r src/html/mod_virtuemart_cart src/html/mod_virtuemart_cart_original # Modify your version -# Edit src/templates/html/mod_search/default.php +# Edit src/html/mod_virtuemart_cart/default.php ``` ### CSS Variables Override @@ -539,11 +587,11 @@ cp -r src/templates/html/mod_search src/templates/html/mod_search_original Override CSS variables in your custom color scheme: ```css -/* src/media/css/colors/light/colors_custom.css */ +/* src/media/css/theme/light.custom.css */ :root { - --mod-search-bg: #f8f9fa; - --mod-search-border: #dee2e6; --vm-price-color: #28a745; + --vm-cart-bg: #f8f9fa; + --vm-button-primary: #007bff; } ``` @@ -604,16 +652,54 @@ Override CSS variables in your custom color scheme: --- +## How to Activate Alternative Layouts + +All MokoCassiopeia overrides are **alternative layouts** that must be explicitly activated. They do not automatically replace default layouts. + +### Quick Start: Enable Mobile Layout + +1. **Go to Joomla Administrator** → Extensions → Modules +2. **Open the module** you want to enhance (e.g., VirtueMart Cart) +3. **Navigate to Advanced tab** +4. **Find "Alternative Layout" field** +5. **Select "MokoCassiopeia - mobile"** from dropdown +6. **Save & Close** + +### For Menu Items (Component Views) + +1. **Go to Menus** → Select your menu +2. **Open the menu item** (e.g., Events List) +3. **Navigate to Advanced Options or Page Display tab** +4. **Find "Alternative Layout" field** +5. **Select "MokoCassiopeia - mobile"** from dropdown +6. **Save & Close** + +### Apply to All Modules in a Position + +In your template's `index.php`, specify layout for entire module position: + +```php + +``` + +**📖 For complete documentation, see [OVERRIDE_PHILOSOPHY.md](OVERRIDE_PHILOSOPHY.md)** + +--- + ## Version History | Version | Date | Changes | |----------|------------|--------------------------------------------------| +| 03.08.04 | 2026-02-27 | Added alternative layout activation instructions, JEM overrides | +| 03.08.03 | 2026-02-25 | Removed mod_search override per Cassiopeia philosophy | +| 03.08.00 | 2026-02-22 | Added Community Builder component overrides | | 03.07.00 | 2026-02-22 | Initial release of all mobile-responsive overrides | --- ## Additional Resources +- **Override Philosophy**: [OVERRIDE_PHILOSOPHY.md](OVERRIDE_PHILOSOPHY.md) ⭐ **Start here** - **Main README**: [README.md](../README.md) - **Changelog**: [CHANGELOG.md](../CHANGELOG.md) - **CSS Variables**: [CSS_VARIABLES.md](CSS_VARIABLES.md) diff --git a/docs/OVERRIDE_PHILOSOPHY.md b/docs/OVERRIDE_PHILOSOPHY.md new file mode 100644 index 0000000..99960cb --- /dev/null +++ b/docs/OVERRIDE_PHILOSOPHY.md @@ -0,0 +1,332 @@ + + +# Override Philosophy — MokoCassiopeia + +## Core Principle: Add-On, Not Replacement + +**MokoCassiopeia overrides are designed as alternative layouts, not replacements of default Joomla layouts.** + +This means: +- ✅ Default Joomla layouts continue to work unchanged +- ✅ Site administrators can choose when to use our enhanced layouts +- ✅ Updates to Joomla core layouts don't break the site +- ✅ Compatibility with other extensions is maintained +- ✅ Users have control over which layouts to use + +--- + +## Technical Implementation + +### Layout Naming Convention + +All MokoCassiopeia overrides use **`mobile.php`** naming instead of **`default.php`**: + +``` +❌ BAD (Replaces default): +src/html/mod_virtuemart_cart/default.php + +✅ GOOD (Alternative layout): +src/html/mod_virtuemart_cart/mobile.php +``` + +### How Joomla Handles Layouts + +When a module or component looks for a layout, Joomla searches in this order: + +1. **Template override with specified layout name**: `templates/mokocassiopeia/html/{extension}/{view}/{layout}.php` +2. **Extension's specified layout**: `{extension}/tmpl/{view}/{layout}.php` +3. **Template override for default layout**: `templates/mokocassiopeia/html/{extension}/{view}/default.php` +4. **Extension's default layout**: `{extension}/tmpl/{view}/default.php` + +By naming our overrides `mobile.php` instead of `default.php`, they become **step 1** alternatives that must be explicitly selected, rather than **step 3** replacements that are automatically used. + +--- + +## How to Use Alternative Layouts + +### Method 1: Module/Menu Item Settings + +When editing a module or menu item in Joomla administrator: + +1. Open the module/menu item for editing +2. Navigate to the **Advanced** tab +3. Find the **Alternative Layout** field +4. Select **MokoCassiopeia - mobile** from the dropdown +5. Save + +### Method 2: Override in Module Position + +If you want all modules in a specific position to use the mobile layout: + +```php + +countModules('sidebar-left')) : ?> + + +``` + +### Method 3: Module Chrome (Advanced) + +Create a custom module chrome in `templates/mokocassiopeia/html/layouts/chromes/` that automatically applies the mobile layout. + +--- + +## Exception: Main Menu + +**The only exception** to this philosophy is `mod_menu` with the "Main Menu" module type. + +The template includes files like: +- `src/html/mod_menu/mainmenu.php` +- `src/html/mod_menu/mainmenu_component.php` +- `src/html/mod_menu/mainmenu_heading.php` +- `src/html/mod_menu/mainmenu_url.php` +- `src/html/mod_menu/mainmenu_separator.php` + +These use a **custom layout name** (`mainmenu`) instead of replacing `default.php`, which allows the site to: +- Use the enhanced Bootstrap 5 collapsible menu for main navigation +- Keep standard Joomla menus working in other positions +- Provide better mobile navigation without breaking existing menus + +To use this layout, set the module's **Alternative Layout** to **MokoCassiopeia - mainmenu**. + +--- + +## Override Inventory + +### Module Overrides (16 total) + +All use `mobile.php` naming (alternative layout): + +**VirtueMart (5)**: +- `mod_virtuemart_cart/mobile.php` +- `mod_virtuemart_product/mobile.php` +- `mod_virtuemart_currencies/mobile.php` +- `mod_virtuemart_category/mobile.php` +- `mod_virtuemart_manufacturer/mobile.php` + +**Community Builder (2)**: +- `mod_cblogin/mobile.php` +- `mod_comprofilerOnline/mobile.php` + +**Main Menu (1)**: +- `mod_menu/mainmenu.php` (custom layout name) + +**Industry Extensions (8)**: +- `mod_k2_content/mobile.php` +- `mod_acymailing/mobile.php` +- `mod_hikashop_cart/mobile.php` +- `mod_kunenalatest/mobile.php` +- `mod_kunenalogin/mobile.php` +- `mod_kunenasearch/mobile.php` +- `mod_kunenastats/mobile.php` +- `mod_osmembership/mobile.php` + +### Component View Overrides (12 total) + +All use `mobile.php` naming (alternative layout): + +**Community Builder (4)**: +- `com_comprofiler/userprofile/mobile.php` +- `com_comprofiler/userslist/mobile.php` +- `com_comprofiler/registers/mobile.php` +- `com_comprofiler/login/mobile.php` + +**JEM - Joomla Event Manager (5)**: +- `com_jem/eventslist/mobile.php` +- `com_jem/event/mobile.php` +- `com_jem/calendar/mobile.php` +- `com_jem/venue/mobile.php` +- `com_jem/categories/mobile.php` + +**Kunena Forum (1)**: +- `com_kunena/category/mobile.php` + +**OSMembership (2)**: +- `com_osmembership/plan/mobile.php` +- `com_osmembership/plans/mobile.php` + +**Joomla Core (2)**: +- `com_content/article/toc-left.php` (custom layout name) +- `com_content/article/toc-right.php` (custom layout name) + +--- + +## Benefits of This Approach + +### 1. **Zero Breaking Changes** + +Existing sites continue to work exactly as before. No layouts are forcibly changed. + +### 2. **Gradual Adoption** + +Site administrators can: +- Test mobile layouts on specific modules first +- Roll out changes module-by-module +- Keep some modules using default layouts if needed +- Easily revert by changing the Alternative Layout setting + +### 3. **Extension Compatibility** + +Third-party extensions' default layouts remain untouched, preventing conflicts with: +- Extension updates +- Other templates +- Custom development + +### 4. **Joomla Core Updates** + +When Joomla core updates: +- Default layouts get new features/bug fixes automatically +- Mobile layouts remain stable and tested +- No emergency fixes needed after Joomla updates + +### 5. **Multi-Language Support** + +Joomla's language system loads extension language files properly because: +- Extensions aren't hijacked by template overrides +- Language strings come from the correct source +- Translations work as expected + +--- + +## Standards Not Overridden + +Following Cassiopeia template best practices, MokoCassiopeia **does not override** standard Joomla core modules: + +- ❌ `mod_breadcrumbs` - Use Joomla core layout +- ❌ `mod_login` - Use Joomla core layout +- ❌ `mod_articles_latest` - Use Joomla core layout +- ❌ `mod_articles_category` - Use Joomla core layout +- ❌ `mod_articles_news` - Use Joomla core layout +- ❌ `mod_search` - Use Joomla core layout (removed in v03.08.03) + +**Reason**: These modules have robust core layouts with proper language loading, accessibility, and ongoing Joomla maintenance. + +--- + +## Developer Guidelines + +When adding new overrides to MokoCassiopeia: + +### ✅ DO: + +1. Name files `mobile.php` or use descriptive custom names (`mainmenu.php`, `toc-left.php`) +2. Document the alternative layout in MODULE_OVERRIDES.md +3. Add CSS with BEM naming: `.{extension}-{view}__element` +4. Test that default layouts still work +5. Provide clear instructions for selecting the layout + +### ❌ DON'T: + +1. Create `default.php` files that replace core layouts +2. Override standard Joomla core modules without strong justification +3. Break backward compatibility +4. Assume users will automatically get your layout +5. Forget to document how to enable the alternative layout + +--- + +## Migration from Replacing Overrides + +If you're migrating from a template that used `default.php` overrides: + +### Step 1: Identify Replaced Layouts + +```bash +find templates/oldtemplate/html -name "default.php" +``` + +### Step 2: Rename to Alternative Layouts + +```bash +# For each default.php found: +mv default.php mobile.php +``` + +### Step 3: Update Module Settings + +For each module using the old override: +1. Edit module in administrator +2. Advanced tab → Alternative Layout +3. Select "mobile" from dropdown +4. Save + +### Step 4: Test + +- Verify module displays correctly +- Check that other modules still use default layouts +- Confirm language strings load properly + +--- + +## Troubleshooting + +### My Alternative Layout Doesn't Appear in Dropdown + +**Check:** +1. File is in correct location: `templates/mokocassiopeia/html/{extension}/{view}/` +2. File has `.php` extension +3. File is not named `default.php` +4. Cache is cleared (System → Clear Cache) + +### Module Still Uses Default Layout + +**Check:** +1. Module's Alternative Layout setting in administrator +2. Module position's `layout` parameter in `` tag +3. File permissions (must be readable) +4. Template is assigned to correct pages + +### Layout Works But Looks Wrong + +**Check:** +1. CSS is loaded: inspect element and check for `.{extension}-{view}__` classes +2. `template.css` is up to date +3. Browser cache is cleared +4. CSS variables are defined in template + +--- + +## References + +- [Joomla Docs: Layout Overrides](https://docs.joomla.org/Layout_Overrides_in_Joomla) +- [Joomla Docs: Alternative Layouts](https://docs.joomla.org/J3.x:How_to_use_the_alternative_layout_feature) +- [MODULE_OVERRIDES.md](MODULE_OVERRIDES.md) - Complete override inventory +- [CSS_VARIABLES.md](CSS_VARIABLES.md) - Template styling system + +--- + +## Version History + +- **03.08.04**: Created OVERRIDE_PHILOSOPHY.md document +- **03.08.03**: Removed mod_search override to align with philosophy +- **03.08.02**: Removed standard Joomla module overrides for proper language loading +- **Earlier**: Renamed all overrides from default.php to mobile.php (21 files) diff --git a/docs/QUICK_START.md b/docs/QUICK_START.md index 012541e..32ef8a7 100644 --- a/docs/QUICK_START.md +++ b/docs/QUICK_START.md @@ -50,7 +50,7 @@ make validate ```bash # 1. Make your changes -vim src/templates/index.php +vim src/index.php # 2. Validate locally make validate-required @@ -143,13 +143,20 @@ make all # Complete build pipeline ``` moko-cassiopeia/ -├── src/ # Joomla template source -│ ├── templates/ # Template files -│ ├── media/ # Assets (CSS, JS, images) -│ ├── language/ # Language files -│ └── administrator/ # Admin files +├── src/ # Joomla template source (template root) +│ ├── component.php # Component template file +│ ├── index.php # Main template file +│ ├── offline.php # Offline page template +│ ├── error.php # Error page template +│ ├── templateDetails.xml # Template manifest +│ ├── html/ # Module & component overrides +│ ├── media/ # Assets (CSS, JS, images, fonts) +│ ├── language/ # Frontend language files (en-GB, en-US) +│ └── administrator/ # Backend files +│ └── language/ # Backend language files ├── tests/ # Test suites ├── docs/ # Documentation +├── scripts/ # Build scripts ├── .github/workflows/ # CI/CD workflows ├── Makefile # Make commands └── README.md # Project overview @@ -179,7 +186,7 @@ moko-cassiopeia/ 3. **Make changes and test**: ```bash # Edit files - vim src/templates/index.php + vim src/index.php # Validate make validate-required diff --git a/docs/README.md b/docs/README.md index 6696f6f..f2909ef 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,15 +45,27 @@ This directory contains comprehensive documentation for the MokoCassiopeia Jooml * **[Workflow Guide](WORKFLOW_GUIDE.md)** - Complete workflow reference * Git branching strategy * Development workflow - * Release process * Pull request guidelines +* **[Release Process](RELEASE_PROCESS.md)** ⭐ - Complete release documentation + * Automated release workflow with GitHub Actions + * Manual release procedures + * Update server configuration + * Testing and rollback procedures + * Build scripts and tools + * **[Joomla Development Guide](JOOMLA_DEVELOPMENT.md)** - Joomla-specific development * Testing with Codeception * PHP quality checks (PHPStan, PHPCS) * Joomla extension packaging * Multi-version testing +* **[Manual Deployment Guide](MANUAL_DEPLOYMENT.md)** - Deploy src directory without building + * Understanding src vs. installed structure + * Manual deployment methods (copy, symlink) + * Troubleshooting language files and media + * Best practices for development deployments + * **[CSS Variables Reference](CSS_VARIABLES.md)** - Complete CSS customization guide * All available CSS variables * Custom color palette creation @@ -61,11 +73,17 @@ This directory contains comprehensive documentation for the MokoCassiopeia Jooml * Light and dark mode theming * **[Module & Component Overrides](MODULE_OVERRIDES.md)** - Mobile-responsive overrides guide - * 20 module overrides + 3 component overrides - * VirtueMart, Joomla core, Community Builder, industry extensions + * 16 module overrides + 12 component overrides + * VirtueMart, Community Builder, JEM, Kunena, industry extensions * Mobile-first responsive design patterns * Accessibility features and customization +* **[Override Philosophy](OVERRIDE_PHILOSOPHY.md)** ⭐ - Alternative layouts, not replacements + * Why overrides use `mobile.php` naming instead of `default.php` + * How to activate alternative layouts in Joomla + * Benefits of non-replacing overrides + * Developer guidelines and best practices + * **[Roadmap](ROADMAP.md)** - Version-specific roadmap * Current features (v03.07.00) * Feature evolution timeline @@ -76,21 +94,6 @@ This directory contains comprehensive documentation for the MokoCassiopeia Jooml For end-user documentation, installation instructions, and feature guides, see the main [README.md](../README.md) in the repository root. -### Client Fork Documentation - -* **[Client Fork Workflow](CLIENT_FORK_WORKFLOW.md)** - Automated client fork creation - * GitHub Actions workflow for instant fork setup - * Local bash script alternative - * Complete setup automation in minutes - * Post-setup customization guide - -* **[Client Fork Guide](../CLIENT_FORK_README.md)** - Comprehensive guide for client custom code forks - * Setting up custom branding and colors - * Maintaining fork-specific customizations - * Syncing with upstream MokoCassiopeia - * Deployment and development workflows - * Template README for client forks - ## Project Structure ``` @@ -103,20 +106,32 @@ moko-cassiopeia/ │ ├── CSS_VARIABLES.md # CSS variables reference │ ├── MODULE_OVERRIDES.md # Module & component overrides guide │ └── ROADMAP.md # Version-specific roadmap -├── src/ # Template source code -│ ├── templates/ # Joomla template files -│ │ └── html/ # Module & component overrides (20 modules, 3 components) -│ ├── media/ # Assets (CSS, JS, images) -│ │ └── css/colors/ # Color schemes (light/dark subdirectories) -│ │ ├── light/ # Light mode color files (colors_custom.css) -│ │ └── dark/ # Dark mode color files (colors_custom.css) -│ └── language/ # Translation files -├── templates/ # Template files for customization -│ ├── colors_custom.css # Custom color palette template (copy to src/media/css/colors/) -│ ├── CLIENT_FORK_README_TEMPLATE.md # Template for client fork docs -│ └── README.md # Guide to using templates +├── src/ # Template source code (Joomla template root) +│ ├── component.php # Component template +│ ├── index.php # Main template file +│ ├── offline.php # Offline template +│ ├── error.php # Error page template +│ ├── templateDetails.xml # Template manifest +│ ├── html/ # Module & component overrides (16 modules, 12 components) +│ ├── media/ # Assets (CSS, JS, images, fonts) +│ │ ├── css/ # Stylesheets +│ │ │ └── colors/ # Color schemes +│ │ │ ├── light/ # Light mode color files (colors_standard.css) +│ │ │ └── dark/ # Dark mode color files (colors_standard.css) +│ │ ├── js/ # JavaScript files +│ │ ├── images/ # Image assets +│ │ └── fonts/ # Font files +│ ├── language/ # Frontend language files +│ │ ├── en-GB/ # English (UK) translations +│ │ └── en-US/ # English (US) translations +│ └── administrator/ # Backend files +│ └── language/ # Backend language files +│ ├── en-GB/ # English (UK) system translations +│ └── en-US/ # English (US) system translations +├── templates/ # Reserved for future template files +│ └── README.md # Templates directory guide +├── scripts/ # Build and utility scripts ├── tests/ # Automated tests -├── CLIENT_FORK_README.md # Client fork guide └── .github/ # GitHub configuration and workflows ``` diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md new file mode 100644 index 0000000..e2095ba --- /dev/null +++ b/docs/RELEASE_PROCESS.md @@ -0,0 +1,638 @@ + + +# Release Process — MokoCassiopeia + +This document describes the complete release process for MokoCassiopeia Joomla template, including automated workflows and manual procedures. + +## Table of Contents + +1. [Overview](#overview) +2. [Release Types](#release-types) +3. [Automated Release Process](#automated-release-process) +4. [Manual Release Process](#manual-release-process) +5. [Update Server Configuration](#update-server-configuration) +6. [Testing Releases](#testing-releases) +7. [Rollback Procedures](#rollback-procedures) +8. [Troubleshooting](#troubleshooting) + +--- + +## Overview + +MokoCassiopeia uses an automated release system powered by GitHub Actions. The system: + +- **Builds** installation packages automatically +- **Generates** checksums for security verification +- **Creates** GitHub Releases with downloadable artifacts +- **Updates** the Joomla update server (`updates.xml`) automatically +- **Validates** package integrity with SHA-256 hashes + +### Key Components + +1. **Release Workflow** (`.github/workflows/release.yml`): Builds and publishes releases +2. **Auto-Update SHA** (`.github/workflows/auto-update-sha.yml`): Updates `updates.xml` after release +3. **Build Script** (`scripts/build-release.sh`): Local development builds +4. **Update Server** (`updates.xml`): Joomla update server manifest + +--- + +## Release Types + +### Patch Release (Third Digit) + +**Format**: `XX.XX.XX` → `XX.XX.XX+1` (e.g., `03.08.03` → `03.08.04`) + +**When to use**: +- Bug fixes +- Security patches +- Documentation updates +- Minor CSS/styling tweaks +- No breaking changes + +**Example**: `03.08.03` → `03.08.04` + +### Minor Release (Second Digit) + +**Format**: `XX.XX.00` → `XX.XX+1.00` (e.g., `03.08.03` → `03.09.00`) + +**When to use**: +- New features +- New module/component overrides +- Significant styling changes +- Backward-compatible changes + +**Example**: `03.08.03` → `03.09.00` + +### Major Release (First Digit) + +**Format**: `XX.00.00` → `XX+1.00.00` (e.g., `03.08.03` → `04.00.00`) + +**When to use**: +- Breaking changes +- Major architecture changes +- Joomla version upgrades +- Complete redesigns + +**Example**: `03.08.03` → `04.00.00` + +--- + +## Automated Release Process + +**Recommended for most releases** + +### Prerequisites + +- [ ] All changes merged to `main` branch +- [ ] Tests passing +- [ ] Documentation updated +- [ ] CHANGELOG.md updated +- [ ] Local testing completed + +### Step 1: Prepare Release Branch + +```bash +# Create release branch +git checkout main +git pull +git checkout -b release/03.08.04 + +# Update version in templateDetails.xml +# Edit: src/templateDetails.xml +# Change: 03.08.03 +# To: 03.08.04 + +# Update CHANGELOG.md +# Add new section: +## [03.08.04] - 2026-02-27 + +### Added +- Feature descriptions + +### Fixed +- Bug fix descriptions + +### Changed +- Change descriptions + +# Commit changes +git add src/templateDetails.xml CHANGELOG.md +git commit -m "chore: Prepare release 03.08.04" +git push origin release/03.08.04 +``` + +### Step 2: Create Pull Request + +1. Go to GitHub repository +2. Click "Pull requests" → "New pull request" +3. Base: `main`, Compare: `release/03.08.04` +4. Title: `Release 03.08.04` +5. Description: Copy relevant CHANGELOG entries +6. Create pull request +7. Review and merge + +### Step 3: Create and Push Tag + +```bash +# Switch to main and pull changes +git checkout main +git pull + +# Create tag +git tag 03.08.04 + +# Push tag (triggers release workflow) +git push origin 03.08.04 +``` + +### Step 4: Monitor Automated Process + +1. **Go to GitHub Actions tab** +2. **Watch "Create Release" workflow**: + - Builds package + - Generates checksums + - Creates GitHub Release + - Uploads artifacts + +3. **Watch "Auto-Update SHA Hash" workflow**: + - Downloads release package + - Calculates SHA-256 hash + - Updates `updates.xml` + - Commits to main branch + +### Step 5: Verify Release + +1. **Check GitHub Release**: + - Go to Releases tab + - Verify release `03.08.04` exists + - Download ZIP package + - Verify checksums match + +2. **Check updates.xml**: + ```bash + git pull + cat updates.xml + ``` + - Verify version is `03.08.04` + - Verify download URL is correct + - Verify SHA-256 hash is present + +3. **Test Joomla Update**: + - Install previous version in Joomla + - Go to Extensions → Update + - Verify update is detected + - Perform update + - Verify template works correctly + +--- + +## Manual Release Process + +**Use when automation fails or for local testing** + +### Step 1: Prepare Repository + +```bash +# Update version numbers +# Edit: src/templateDetails.xml +# Edit: CHANGELOG.md + +# Commit changes +git add src/templateDetails.xml CHANGELOG.md +git commit -m "chore: Prepare release 03.08.04" +git push +``` + +### Step 2: Build Package Locally + +```bash +# Run build script +./scripts/build-release.sh 03.08.04 + +# Output will be in build/ directory: +# - mokocassiopeia-src-03.08.04.zip +# - mokocassiopeia-src-03.08.04.zip.sha256 +# - mokocassiopeia-src-03.08.04.zip.md5 +``` + +### Step 3: Test Package + +```bash +# Install in Joomla test environment +# Extensions → Manage → Install → Upload Package File +# Select: build/mokocassiopeia-src-03.08.04.zip + +# Test all features: +# - Template displays correctly +# - Module overrides work +# - Alternative layouts selectable +# - Dark mode works +# - No JavaScript errors +``` + +### Step 4: Create GitHub Release + +1. **Go to GitHub Releases** +2. **Click "Create a new release"** +3. **Tag**: `03.08.04` (create new tag) +4. **Release title**: `Release 03.08.04` +5. **Description**: Copy from CHANGELOG.md +6. **Upload files**: + - `mokocassiopeia-src-03.08.04.zip` + - `mokocassiopeia-src-03.08.04.zip.sha256` + - `mokocassiopeia-src-03.08.04.zip.md5` +7. **Publish release** + +### Step 5: Update updates.xml Manually + +```bash +# Extract SHA-256 hash +cat build/mokocassiopeia-src-03.08.04.zip.sha256 +# Example output: a1b2c3d4e5f6... + +# Edit updates.xml +# Update 03.08.04 +# Update 2026-02-27 +# Update https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/03.08.04/mokocassiopeia-src-03.08.04.zip +# Update sha256:a1b2c3d4e5f6... + +# Commit and push +git add updates.xml +git commit -m "chore: Update updates.xml for release 03.08.04" +git push +``` + +--- + +## Update Server Configuration + +### updates.xml Structure + +```xml + + + MokoCassiopeia + Moko Consulting's site template based on Cassiopeia. + mokocassiopeia + template + site + + 03.08.04 + 2026-02-27 + Jonathan Miller || Moko Consulting + hello@mokoconsulting.tech + (C)GNU General Public License Version 3 - 2026 Moko Consulting + + https://github.com/mokoconsulting-tech/MokoCassiopeia + + + https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/03.08.04/mokocassiopeia-src-03.08.04.zip + sha256:a1b2c3d4e5f6... + + + + stable + + + Moko Consulting + https://www.mokoconsulting.tech + + + + +``` + +### Hosting Update Server + +The `updates.xml` file is hosted directly on GitHub: + +**URL**: `https://raw.githubusercontent.com/mokoconsulting-tech/MokoCassiopeia/main/updates.xml` + +This URL is configured in `src/templateDetails.xml`: + +```xml + + + https://raw.githubusercontent.com/mokoconsulting-tech/MokoCassiopeia/main/updates.xml + + +``` + +--- + +## Testing Releases + +### Pre-Release Testing + +```bash +# 1. Build package locally +./scripts/build-release.sh + +# 2. Set up Joomla test environment +# - Clean Joomla 5.x installation +# - Previous MokoCassiopeia version installed + +# 3. Test current version features +# - All module overrides +# - Alternative layouts +# - Dark mode toggle +# - Responsive behavior + +# 4. Install new package +# Extensions → Manage → Install → Upload Package + +# 5. Verify upgrade process +# - No errors during installation +# - Settings preserved +# - Custom modifications retained + +# 6. Test new features +# - New functionality works +# - Bug fixes applied +# - No regressions +``` + +### Update Server Testing + +```bash +# 1. Install previous version in Joomla +# 2. Go to: Extensions → Update +# 3. Click "Find Updates" +# 4. Verify update shows: "MokoCassiopeia 03.08.04" +# 5. Click "Update" +# 6. Verify successful update +# 7. Test template functionality +``` + +### Checklist + +- [ ] Package installs without errors +- [ ] Template activates correctly +- [ ] All module overrides work +- [ ] Alternative layouts selectable +- [ ] Dark mode functions +- [ ] Responsive on mobile/tablet/desktop +- [ ] No JavaScript console errors +- [ ] No PHP errors in Joomla logs +- [ ] Update server detects new version +- [ ] Update process completes successfully + +--- + +## Rollback Procedures + +### Rollback Release + +If a release has critical issues: + +1. **Delete GitHub Release**: + - Go to Releases + - Click release to delete + - Click "Delete" + - Confirm deletion + +2. **Delete Git Tag**: + ```bash + # Delete local tag + git tag -d 03.08.04 + + # Delete remote tag + git push --delete origin 03.08.04 + ``` + +3. **Revert updates.xml**: + ```bash + # Revert to previous version + git revert + git push + ``` + +4. **Notify Users**: + - Create GitHub issue explaining the problem + - Pin the issue + - Provide rollback instructions for users + +### User Rollback Instructions + +For users who installed the problematic version: + +1. **Download previous version** from GitHub Releases +2. **Uninstall current version**: + - Extensions → Manage → Manage + - Find MokoCassiopeia + - Click "Uninstall" +3. **Install previous version**: + - Extensions → Manage → Install + - Upload previous version ZIP +4. **Verify functionality** + +--- + +## Troubleshooting + +### Release Workflow Fails + +**Problem**: Build fails with "rsync: command not found" + +**Solution**: The GitHub Actions runner always has rsync installed. If this occurs, check the workflow file syntax. + +**Problem**: ZIP creation fails + +**Solution**: Check that `src/` and `src/media/` directories exist and contain files. + +**Problem**: Version update fails + +**Solution**: Verify `sed` commands in workflow match actual XML structure. + +### Auto-Update SHA Fails + +**Problem**: Cannot download release package + +**Solution**: +- Verify release was published (not draft) +- Check package naming: `mokocassiopeia-src-{version}.zip` +- Verify release tag format + +**Problem**: SHA-256 hash mismatch + +**Solution**: +- Package may have been modified after calculation +- Re-run the workflow manually +- Verify package integrity + +**Problem**: Commit fails + +**Solution**: +- Check workflow has write permissions +- Verify no branch protection rules blocking bot commits + +### Manual Build Issues + +**Problem**: `./scripts/build-release.sh: Permission denied` + +**Solution**: +```bash +chmod +x scripts/build-release.sh +./scripts/build-release.sh +``` + +**Problem**: Build directory exists + +**Solution**: +```bash +rm -rf build/ +./scripts/build-release.sh +``` + +### Update Server Issues + +**Problem**: Joomla doesn't detect update + +**Solution**: +1. Check `updates.xml` is accessible: + ```bash + curl https://raw.githubusercontent.com/mokoconsulting-tech/MokoCassiopeia/main/updates.xml + ``` +2. Verify version number is higher than installed version +3. Clear Joomla cache: System → Clear Cache +4. Check update URL in templateDetails.xml + +**Problem**: Update fails with "Invalid package" + +**Solution**: +- Verify SHA-256 hash matches +- Re-download package and check integrity +- Verify package structure is correct + +--- + +## Best Practices + +### Version Numbering + +- **Always increment** version numbers sequentially +- **Never reuse** version numbers +- **Use consistent** format: `XX.XX.XX` + +### Changelog + +- **Update before** release +- **Include all changes** since last version +- **Categorize** changes: Added, Changed, Fixed, Removed +- **Write clear descriptions** for users + +### Testing + +- **Test locally** before pushing tag +- **Test update process** from previous version +- **Test on clean** Joomla installation +- **Test different** configurations + +### Communication + +- **Announce releases** on GitHub Discussions +- **Document breaking changes** clearly +- **Provide migration guides** for major changes +- **Respond promptly** to issue reports + +--- + +## Quick Reference + +### Automated Release Commands + +```bash +# 1. Create release branch +git checkout -b release/03.08.04 + +# 2. Update version and CHANGELOG +# (edit files) + +# 3. Commit and push +git add . +git commit -m "chore: Prepare release 03.08.04" +git push origin release/03.08.04 + +# 4. Create and merge PR (via GitHub UI) + +# 5. Create and push tag +git checkout main +git pull +git tag 03.08.04 +git push origin 03.08.04 + +# 6. Wait for automation to complete +``` + +### Manual Release Commands + +```bash +# Build locally +./scripts/build-release.sh 03.08.04 + +# Test installation +# (manual Joomla testing) + +# Create release on GitHub +# (via GitHub UI) + +# Update updates.xml +# (edit file with SHA-256) +git add updates.xml +git commit -m "chore: Update updates.xml for 03.08.04" +git push +``` + +--- + +## Related Documentation + +- **Build Scripts**: [scripts/README.md](../scripts/README.md) +- **Workflow Guide**: [WORKFLOW_GUIDE.md](WORKFLOW_GUIDE.md) +- **Contributing**: [CONTRIBUTING.md](../CONTRIBUTING.md) +- **Changelog**: [CHANGELOG.md](../CHANGELOG.md) + +--- + +## Support + +- **Issues**: [GitHub Issues](https://github.com/mokoconsulting-tech/MokoCassiopeia/issues) +- **Discussions**: [GitHub Discussions](https://github.com/mokoconsulting-tech/MokoCassiopeia/discussions) +- **Email**: hello@mokoconsulting.tech + +--- + +## License + +Copyright (C) 2026 Moko Consulting + +This documentation is licensed under GPL-3.0-or-later. diff --git a/docs/WORKFLOW_GUIDE.md b/docs/WORKFLOW_GUIDE.md index c06a240..90a5cf7 100644 --- a/docs/WORKFLOW_GUIDE.md +++ b/docs/WORKFLOW_GUIDE.md @@ -241,7 +241,7 @@ git fetch origin git checkout dev/X.Y.Z # 3. Make your changes -vim src/templates/index.php +vim src/index.php # 4. Validate locally make validate-required @@ -293,7 +293,7 @@ Update CHANGELOG.md manually or via pull request following the existing format. ```bash # Check specific file -php -l src/templates/index.php +php -l src/index.php # Run validation make validate-required diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..0c3f452 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,276 @@ +# Scripts — MokoCassiopeia + +This directory contains utility scripts for building, releasing, and managing the MokoCassiopeia Joomla template. + +## Available Scripts + +### build-release.sh + +**Purpose**: Build a release package for MokoCassiopeia template. + +**Usage**: +```bash +# Build with auto-detected version from templateDetails.xml +./scripts/build-release.sh + +# Build with specific version +./scripts/build-release.sh 03.08.03 +``` + +**What it does**: +1. Creates a `build/` directory +2. Copies template files from `src/` +3. Copies media files from `src/media/` to `media/` +4. Creates a ZIP package: `mokocassiopeia-src-{version}.zip` +5. Generates SHA-256 and MD5 checksums +6. Outputs package location and checksums + +**Output**: +- `build/mokocassiopeia-src-{version}.zip` - Installation package +- `build/mokocassiopeia-src-{version}.zip.sha256` - SHA-256 checksum +- `build/mokocassiopeia-src-{version}.zip.md5` - MD5 checksum + +**Requirements**: +- `rsync` for file copying +- `zip` for package creation +- `sha256sum` and `md5sum` for checksums + +--- + +## Automated Workflows + +The repository includes GitHub Actions workflows that automate the build and release process: + +### `.github/workflows/release.yml` + +**Purpose**: Automated release creation when tags are pushed. + +**Triggers**: +- Push of version tag (e.g., `03.08.03`) +- Manual workflow dispatch with version input + +**Process**: +1. Checks out repository +2. Sets up PHP environment +3. Installs dependencies (if composer.json exists) +4. Updates version numbers in manifest files +5. Creates package structure +6. Builds ZIP package +7. Generates checksums +8. Creates GitHub Release with artifacts + +**Usage**: +```bash +# Create and push a tag +git tag 03.08.04 +git push origin 03.08.04 + +# Or use GitHub UI to run manually +``` + +--- + +### `.github/workflows/auto-update-sha.yml` + +**Purpose**: Automatically update SHA-256 hash in `updates.xml` after a release is published. + +**Triggers**: +- GitHub Release published +- Manual workflow dispatch with tag input + +**Process**: +1. Downloads the release package +2. Calculates SHA-256 hash +3. Updates `updates.xml` with: + - New version number + - Current date + - Download URL + - SHA-256 hash +4. Commits and pushes changes to main branch + +**Benefits**: +- Ensures `updates.xml` always has correct SHA-256 hash +- Enables Joomla update server functionality +- Reduces manual update errors +- Automates security verification + +--- + +## Release Process + +### Manual Release (Local Build) + +1. **Update version numbers**: + ```bash + # Update these files manually: + # - src/templateDetails.xml + # - updates.xml + # - CHANGELOG.md + ``` + +2. **Build package**: + ```bash + ./scripts/build-release.sh 03.08.04 + ``` + +3. **Test package**: + - Install ZIP in Joomla test environment + - Verify all features work correctly + +4. **Create GitHub Release**: + - Go to GitHub Releases + - Click "Create a new release" + - Upload the ZIP, SHA256, and MD5 files + - Add release notes from CHANGELOG.md + +5. **Update updates.xml**: + - Copy SHA-256 hash from `.sha256` file + - Update `updates.xml` with new hash + - Commit and push changes + +--- + +### Automated Release (GitHub Actions) + +1. **Update version numbers**: + ```bash + # Update these files in a branch: + # - src/templateDetails.xml + # - CHANGELOG.md + + git checkout -b release/03.08.04 + # Make changes + git commit -m "chore: Prepare release 03.08.04" + git push origin release/03.08.04 + ``` + +2. **Create and merge PR**: + - Create PR from release branch + - Review changes + - Merge to main + +3. **Create and push tag**: + ```bash + git checkout main + git pull + git tag 03.08.04 + git push origin 03.08.04 + ``` + +4. **Automated process**: + - GitHub Actions builds package automatically + - Creates GitHub Release with artifacts + - `auto-update-sha` workflow updates `updates.xml` + +5. **Verify**: + - Check GitHub Release is created + - Verify `updates.xml` has correct SHA-256 + - Test Joomla update server + +--- + +## Development Workflow + +### Testing Local Builds + +```bash +# Build current version +./scripts/build-release.sh + +# Install in Joomla +# Navigate to Extensions > Manage > Install > Upload Package File +# Select: build/mokocassiopeia-src-{version}.zip +``` + +### Pre-Release Checklist + +- [ ] All code changes merged to main +- [ ] Version numbers updated: + - [ ] `src/templateDetails.xml` + - [ ] `CHANGELOG.md` +- [ ] CHANGELOG.md updated with release notes +- [ ] Tests passing +- [ ] Documentation updated +- [ ] Local build tested in Joomla + +--- + +## Troubleshooting + +### Build Fails + +**Problem**: `rsync: command not found` +```bash +# Ubuntu/Debian +sudo apt-get install rsync + +# macOS +brew install rsync +``` + +**Problem**: `zip: command not found` +```bash +# Ubuntu/Debian +sudo apt-get install zip + +# macOS (usually pre-installed) +brew install zip +``` + +### GitHub Actions Fails + +**Problem**: Release workflow fails on tag push + +Check: +1. Tag format matches pattern: `[0-9][0-9].[0-9][0-9].[0-9][0-9]` +2. Repository has write permissions for GITHUB_TOKEN +3. `src/` and `src/media/` directories exist + +**Problem**: auto-update-sha fails + +Check: +1. Release package was published successfully +2. Workflow has write permissions +3. Package naming matches expected format + +--- + +## File Structure + +``` +scripts/ +├── README.md # This file +└── build-release.sh # Local build script + +.github/workflows/ +├── release.yml # Automated release workflow +└── auto-update-sha.yml # SHA hash update workflow +``` + +--- + +## Contributing + +When adding new scripts: + +1. Add GPL-3.0-or-later license header +2. Include FILE INFORMATION block +3. Add usage documentation in this README +4. Make scripts executable: `chmod +x scripts/your-script.sh` +5. Test thoroughly before committing + +--- + +## Support + +- **Issues**: [GitHub Issues](https://github.com/mokoconsulting-tech/MokoCassiopeia/issues) +- **Email**: hello@mokoconsulting.tech +- **Documentation**: [docs/](../docs/) + +--- + +## License + +All scripts are licensed under GPL-3.0-or-later. + +Copyright (C) 2026 Moko Consulting diff --git a/scripts/build-release.sh b/scripts/build-release.sh new file mode 100755 index 0000000..5e8055d --- /dev/null +++ b/scripts/build-release.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: Build.Scripts +# INGROUP: MokoCassiopeia.Build +# REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia +# PATH: /scripts/build-release.sh +# VERSION: 01.00.00 +# BRIEF: Build release package for MokoCassiopeia template +# USAGE: ./scripts/build-release.sh [version] + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" + +# Functions +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check if version is provided +if [ -z "$1" ]; then + # Try to extract version from templateDetails.xml + if [ -f "${PROJECT_ROOT}/src/templateDetails.xml" ]; then + VERSION=$(grep -oP '\K[^<]+' "${PROJECT_ROOT}/src/templateDetails.xml" | head -1) + log_info "Detected version: ${VERSION}" + else + log_error "Please provide version as argument: ./build-release.sh 03.08.03" + exit 1 + fi +else + VERSION="$1" +fi + +log_info "Building MokoCassiopeia release package" +log_info "Version: ${VERSION}" + +# Change to project root +cd "${PROJECT_ROOT}" + +# Create build directory +BUILD_DIR="${PROJECT_ROOT}/build" +PACKAGE_DIR="${BUILD_DIR}/package" +rm -rf "${BUILD_DIR}" +mkdir -p "${PACKAGE_DIR}" + +log_info "Creating package structure..." + +# Copy template files from src (excluding media directory) +if [ -d "src" ]; then + rsync -av --exclude='.git*' --exclude='media' src/ "${PACKAGE_DIR}/" +else + log_error "src directory not found!" + exit 1 +fi + +# Copy media files from src/media +if [ -d "src/media" ]; then + mkdir -p "${PACKAGE_DIR}/media" + rsync -av --exclude='.git*' src/media/ "${PACKAGE_DIR}/media/" +else + log_warning "src/media directory not found, skipping media files" +fi + +log_info "Package structure created" + +# Create ZIP package +cd "${PACKAGE_DIR}" +ZIP_NAME="mokocassiopeia-src-${VERSION}.zip" +log_info "Creating ZIP package: ${ZIP_NAME}" + +zip -r "../${ZIP_NAME}" . -q + +if [ $? -ne 0 ]; then + log_error "Failed to create ZIP package" + exit 1 +fi + +cd "${BUILD_DIR}" +log_success "Created: ${ZIP_NAME}" + +# Generate checksums +log_info "Generating checksums..." +sha256sum "${ZIP_NAME}" > "${ZIP_NAME}.sha256" +md5sum "${ZIP_NAME}" > "${ZIP_NAME}.md5" + +# Extract just the hash +SHA256_HASH=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1) + +log_success "SHA-256: ${SHA256_HASH}" +log_success "MD5: $(md5sum "${ZIP_NAME}" | cut -d' ' -f1)" + +# Show file info +FILE_SIZE=$(du -h "${ZIP_NAME}" | cut -f1) +log_info "Package size: ${FILE_SIZE}" + +# Summary +echo "" +log_success "Build completed successfully!" +echo "" +echo "Package: ${BUILD_DIR}/${ZIP_NAME}" +echo "SHA-256: ${BUILD_DIR}/${ZIP_NAME}.sha256" +echo "MD5: ${BUILD_DIR}/${ZIP_NAME}.md5" +echo "" +echo "Next steps:" +echo "1. Test the package installation in Joomla" +echo "2. Create a GitHub release with this package" +echo "3. Update updates.xml with the new version and SHA-256 hash" +echo "" diff --git a/scripts/create-client-fork.sh b/scripts/create-client-fork.sh deleted file mode 100755 index 6f6b321..0000000 --- a/scripts/create-client-fork.sh +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/bash -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Script: Create Client Fork Setup -# This script prepares the repository for a client-specific fork by: -# - Copying custom color templates to the appropriate locations -# - Replacing the main README with the client fork README -# - Cleaning up template documentation files - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Function to print colored output -print_success() { echo -e "${GREEN}✓${NC} $1"; } -print_error() { echo -e "${RED}✗${NC} $1"; } -print_info() { echo -e "${BLUE}ℹ${NC} $1"; } -print_warning() { echo -e "${YELLOW}⚠${NC} $1"; } - -# Check if client name is provided -if [ -z "$1" ]; then - print_error "Usage: $0 " - echo "Example: $0 \"Acme Corporation\"" - exit 1 -fi - -CLIENT_NAME="$1" -CLIENT_SLUG=$(echo "${CLIENT_NAME}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-') -BRANCH_NAME="client-fork/${CLIENT_SLUG}" - -echo "" -echo "╔════════════════════════════════════════════════════════════════╗" -echo "║ MokoCassiopeia - Client Fork Setup Script ║" -echo "╚════════════════════════════════════════════════════════════════╝" -echo "" -print_info "Client Name: ${CLIENT_NAME}" -print_info "Branch Name: ${BRANCH_NAME}" -echo "" - -# Confirm before proceeding -read -p "Do you want to proceed? (yes/no): " -r -echo -if [[ ! $REPLY =~ ^[Yy]es$ ]]; then - print_warning "Operation cancelled by user" - exit 0 -fi - -# Check if we're in the right directory -if [ ! -f "CLIENT_FORK_README.md" ]; then - print_error "CLIENT_FORK_README.md not found. Are you in the repository root?" - exit 1 -fi - -# Create new branch -print_info "Creating branch: ${BRANCH_NAME}" -git checkout -b "${BRANCH_NAME}" -print_success "Branch created" - -# Copy custom color templates -print_info "Copying colors_custom.css to light and dark mode directories..." -cp templates/colors_custom.css src/media/css/colors/light/colors_custom.css -cp templates/colors_custom.css src/media/css/colors/dark/colors_custom.css - -if [ -f "src/media/css/colors/light/colors_custom.css" ] && [ -f "src/media/css/colors/dark/colors_custom.css" ]; then - print_success "Created src/media/css/colors/light/colors_custom.css" - print_success "Created src/media/css/colors/dark/colors_custom.css" -else - print_error "Failed to create colors_custom.css files" - exit 1 -fi - -# Replace README with client fork README -print_info "Replacing README.md with CLIENT_FORK_README.md..." -sed "s/\[CLIENT NAME\]/${CLIENT_NAME}/g" CLIENT_FORK_README.md > README.md.new -mv README.md.new README.md - -# Update fork information section -CURRENT_DATE=$(date +"%Y-%m-%d") -sed -i.bak "s/\[DATE\]/${CURRENT_DATE}/g" README.md -sed -i.bak "s/\[YOUR-FORK-URL\]/[UPDATE-WITH-YOUR-FORK-URL]/g" README.md -rm -f README.md.bak - -print_success "README.md replaced with customized client fork README" - -# Clean up template files -print_info "Removing template documentation files..." - -if [ -f "CLIENT_FORK_README.md" ]; then - rm CLIENT_FORK_README.md - print_success "Removed CLIENT_FORK_README.md" -fi - -if [ -f "templates/CLIENT_FORK_README_TEMPLATE.md" ]; then - rm templates/CLIENT_FORK_README_TEMPLATE.md - print_success "Removed templates/CLIENT_FORK_README_TEMPLATE.md" -fi - -# Update templates/README.md -if [ -f "templates/README.md" ]; then - # Create a backup - cp templates/README.md templates/README.md.bak - - # Remove references to CLIENT_FORK_README_TEMPLATE.md - sed '/CLIENT_FORK_README_TEMPLATE.md/d' templates/README.md > templates/README.md.tmp - mv templates/README.md.tmp templates/README.md - rm -f templates/README.md.bak - - print_success "Updated templates/README.md" -fi - -print_success "Keeping templates/colors_custom.css as template" - -# Show git status -echo "" -print_info "Git status:" -git status --short - -# Commit changes -echo "" -read -p "Commit these changes? (yes/no): " -r -echo -if [[ $REPLY =~ ^[Yy]es$ ]]; then - git add . - git commit -m "Setup client fork for ${CLIENT_NAME} - -- Copied colors_custom.css to src/media/css/colors/light/ and dark/ -- Replaced README.md with customized CLIENT_FORK_README.md -- Removed CLIENT_FORK_README.md and templates/CLIENT_FORK_README_TEMPLATE.md -- Kept templates/colors_custom.css as template - -This commit prepares the repository for ${CLIENT_NAME}'s custom fork." - - print_success "Changes committed successfully" - - echo "" - print_info "To push this branch, run:" - echo " git push origin ${BRANCH_NAME}" -fi - -# Summary -echo "" -echo "╔════════════════════════════════════════════════════════════════╗" -echo "║ Setup Complete! 🎉 ║" -echo "╚════════════════════════════════════════════════════════════════╝" -echo "" -echo "Changes Applied:" -print_success "Copied colors_custom.css to src/media/css/colors/light/" -print_success "Copied colors_custom.css to src/media/css/colors/dark/" -print_success "Replaced README.md with customized client fork README" -print_success "Removed CLIENT_FORK_README.md" -print_success "Removed templates/CLIENT_FORK_README_TEMPLATE.md" -print_success "Kept templates/colors_custom.css as template" -echo "" -echo "Next Steps:" -echo "1. Review the changes in branch: ${BRANCH_NAME}" -echo "2. Customize colors in src/media/css/colors/light/colors_custom.css" -echo "3. Customize colors in src/media/css/colors/dark/colors_custom.css" -echo "4. Update README.md with client-specific details" -echo "5. Create a new repository for ${CLIENT_NAME}" -echo "6. Push this branch to the new repository" -echo "" diff --git a/scripts/download-google-fonts.sh b/scripts/download-google-fonts.sh new file mode 100755 index 0000000..dc861b1 --- /dev/null +++ b/scripts/download-google-fonts.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# +# Download Google Fonts for self-hosting +# This script downloads Roboto, Noto Sans, and Fira Sans fonts + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Target directory +FONTS_DIR="../src/media/fonts" + +echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}" +echo -e "${BLUE}║ Google Fonts Downloader for MokoCassiopeia ║${NC}" +echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}" +echo "" + +# Check if fonts directory exists +if [ ! -d "$FONTS_DIR" ]; then + echo -e "${RED}✗ Error: Fonts directory not found: $FONTS_DIR${NC}" + exit 1 +fi + +cd "$FONTS_DIR" + +echo -e "${YELLOW}Target directory: $(pwd)${NC}" +echo "" + +# Function to download font CSS and extract font files +download_font() { + local font_name="$1" + local font_url="$2" + local display_name="$3" + + echo -e "${GREEN}Downloading $display_name...${NC}" + + # Download CSS with user agent for woff2 format + css=$(curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "$font_url") + + if [ -z "$css" ]; then + echo -e "${RED} ✗ Failed to download CSS${NC}" + return 1 + fi + + # Extract woff2 URLs + urls=$(echo "$css" | grep -oP 'https://fonts\.gstatic\.com[^\)]*\.woff2' || true) + + if [ -z "$urls" ]; then + echo -e "${RED} ✗ No font URLs found in CSS${NC}" + return 1 + fi + + count=0 + while IFS= read -r url; do + if [ -z "$url" ]; then + continue + fi + + filename=$(basename "$url") + echo -e " → Downloading ${filename}..." + + if curl -s "$url" -o "$filename"; then + size=$(du -h "$filename" | cut -f1) + echo -e "${GREEN} ✓ Downloaded ($size)${NC}" + ((count++)) + else + echo -e "${RED} ✗ Failed${NC}" + fi + done <<< "$urls" + + echo -e "${GREEN} ✓ Downloaded $count font files${NC}" + echo "" +} + +# Download fonts +download_font "roboto" "https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;700&display=swap" "Roboto" +download_font "noto-sans" "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&display=swap" "Noto Sans" +download_font "fira-sans" "https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&display=swap" "Fira Sans" + +echo -e "${GREEN}╔════════════════════════════════════════════╗${NC}" +echo -e "${GREEN}║ ✓ All fonts downloaded successfully! ║${NC}" +echo -e "${GREEN}╚════════════════════════════════════════════╝${NC}" +echo "" +echo -e "Font files saved to: ${BLUE}$(pwd)${NC}" +echo "" +echo "Next steps:" +echo "1. Verify font files are present" +echo "2. Update templateDetails.xml font options (if needed)" +echo "3. Remove Google Fonts CDN preconnect links from PHP templates" diff --git a/src/administrator/language/en-GB/index.html b/src/administrator/language/en-GB/index.html deleted file mode 100644 index 480348d..0000000 --- a/src/administrator/language/en-GB/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - Redirecting… - - - - - - - - - - - - - - - - - - - -
Redirecting to the site root… If you are not redirected, click here.
- - diff --git a/src/administrator/language/en-US/index.html b/src/administrator/language/en-US/index.html deleted file mode 100644 index 480348d..0000000 --- a/src/administrator/language/en-US/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - Redirecting… - - - - - - - - - - - - - - - - - - - -
Redirecting to the site root… If you are not redirected, click here.
- - diff --git a/src/administrator/language/index.html b/src/administrator/language/index.html deleted file mode 100644 index 480348d..0000000 --- a/src/administrator/language/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - Redirecting… - - - - - - - - - - - - - - - - - - - -
Redirecting to the site root… If you are not redirected, click here.
- - diff --git a/src/component.php b/src/component.php new file mode 100644 index 0000000..efb20be --- /dev/null +++ b/src/component.php @@ -0,0 +1,184 @@ + + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia + REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia + PATH: ./templates/mokocassiopeia/component.php + VERSION: 03.06.02 + BRIEF: Main template index file for MokoCassiopeia rendering site layout + */ + + +defined('_JEXEC') or die; + +use Joomla\CMS\Factory; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Component\ComponentHelper; + +/** @var Joomla\CMS\Document\HtmlDocument $this */ + +$app = Factory::getApplication(); +$input = $app->getInput(); +$document = $app->getDocument(); +$wa = $document->getWebAssetManager(); + +// Template params - Component uses minimal configuration +$params_googletagmanager = $this->params->get('googletagmanager', false); +$params_googletagmanagerid = $this->params->get('googletagmanagerid', null); +$params_googleanalytics = $this->params->get('googleanalytics', false); +$params_googleanalyticsid = $this->params->get('googleanalyticsid', null); + +// Detecting Active Variables +$option = $input->getCmd('option', ''); +$view = $input->getCmd('view', ''); +$layout = $input->getCmd('layout', ''); +$task = $input->getCmd('task', ''); +$itemid = $input->getCmd('Itemid', ''); +$sitenameR = $app->get('sitename'); // raw for title composition +$sitename = htmlspecialchars($sitenameR, ENT_QUOTES, 'UTF-8'); +$menu = $app->getMenu()->getActive(); +$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : ''; + +// Respect “Site Name in Page Titles” (0:none, 1:before, 2:after) +$mode = (int) $app->get('sitename_pagetitles', 0); +$pageTitle = trim($this->getTitle()); +$final = $pageTitle !== '' + ? ($mode === 1 ? $sitenameR . ' - ' . $pageTitle + : ($mode === 2 ? $pageTitle . ' - ' . $sitenameR : $pageTitle)) + : $sitenameR; +$this->setTitle($final); + +// Template/Media path +$templatePath = 'media/templates/site/mokocassiopeia'; + +// Core template CSS +$wa->useStyle('template.base'); // css/template.css + +// Component always uses light theme only (no theme switching) +$wa->useStyle('template.light.standard'); // css/theme/light.standard.css + +// Load Osaka font for site title +$wa->useStyle('template.font.osaka'); + +// Brand: logo from params OR siteTitle +// ------------------------------------- +$brandHtml = ''; +$logoFile = (string) $this->params->get('logoFile'); + +if ($logoFile !== '') { + $brandHtml = HTMLHelper::_( + 'image', + Uri::root(false) . htmlspecialchars($logoFile, ENT_QUOTES, 'UTF-8'), + $sitename, + ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], + false, + 0 + ); +} else { + // If no logo file, show the title (defaults to "MokoCassiopeia" if not set) + $siteTitle = $this->params->get('siteTitle', 'MokoCassiopeia'); + $brandHtml = '' + . htmlspecialchars($siteTitle, ENT_COMPAT, 'UTF-8') + . ''; +} + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + params->get('brand', 1)) : ?> + + + + + + +
+ countModules('footer-menu', true)) : ?> + + + countModules('footer', true)) : ?> +
+ +
+ +
+ + + + diff --git a/src/templates/custom.php b/src/custom.php similarity index 100% rename from src/templates/custom.php rename to src/custom.php diff --git a/src/templates/error.php b/src/error.php similarity index 93% rename from src/templates/error.php rename to src/error.php index 2003598..7f85bbd 100644 --- a/src/templates/error.php +++ b/src/error.php @@ -29,9 +29,9 @@ $params = $this->params; $wa = $this->getWebAssetManager(); // Template params -$params_LightColorName = (string) $params->get('colorLightName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom +$params_LightColorName = (string) $params->get('colorLightName', 'standard'); // standard|custom -$params_DarkColorName = (string) $params->get('colorDarkName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom +$params_DarkColorName = (string) $params->get('colorDarkName', 'standard'); // standard|custom $params_googletagmanager = $params->get('googletagmanager', false); $params_googletagmanagerid = $params->get('googletagmanagerid', ''); @@ -60,30 +60,18 @@ $templatePath = 'media/templates/site/mokocassiopeia'; // Core template CSS $wa->useStyle('template.base'); // css/template.css -// Color theme (light + optional dark) -$colorLightKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_LightColorName)); -$colorDarkKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_DarkColorName)); -$lightKey = 'template.light.' . $colorLightKey; -$darkKey = 'template.dark.' . $colorDarkKey; -try { - $wa->useStyle('template.light.colors_standard'); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.light.colors_standard', $templatePath . '/css/colors/light/colors_standard.css'); +// Load theme palette stylesheets based on configuration +$wa->useStyle('template.light.standard'); // css/theme/light.standard.css +$wa->useStyle('template.dark.standard'); // css/theme/dark.standard.css + +// Load custom palettes only if selected in template configuration AND files exist +if ($params_LightColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/light.custom.css')) +{ + $wa->useStyle('template.light.custom'); } -try { - $wa->useStyle('template.dark.colors_standard'); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.dark.colors_standard', $templatePath . '/css/colors/dark/colors_standard.css'); -} -try { - $wa->useStyle($lightKey); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.light.dynamic', $templatePath . '/css/colors/light/' . $colorLightKey . '.css'); -} -try { - $wa->useStyle($darkKey); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.dark.dynamic', $templatePath . '/css/colors/dark/' . $colorDarkKey . '.css'); +if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/dark.custom.css')) +{ + $wa->useStyle('template.dark.custom'); } // Scripts @@ -137,8 +125,6 @@ if ($this->params->get('faKitCode')) { } } -$wa->useStyle('template.user'); // css/user.css - // ------------------ Context (logo, bootstrap needs) ------------------ $sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8'); @@ -170,6 +156,10 @@ $errorObj = isset($this->error) && is_object($this->error) ? $this->error : nul $errorCode = $errorObj ? (int) $errorObj->getCode() : 500; $errorMsg = $errorObj ? $errorObj->getMessage() : Text::_('JERROR_AN_ERROR_HAS_OCCURRED'); $debugOn = defined('JDEBUG') && JDEBUG; + +// Load user assets last (after all other styles and scripts) +$wa->useStyle('template.user'); // css/user.css +$wa->useScript('user.js'); // js/user.js ?> diff --git a/src/templates/html/com_comprofiler/index.html b/src/html/com_comprofiler/index.html similarity index 100% rename from src/templates/html/com_comprofiler/index.html rename to src/html/com_comprofiler/index.html diff --git a/src/templates/html/com_comprofiler/login/index.html b/src/html/com_comprofiler/login/index.html similarity index 100% rename from src/templates/html/com_comprofiler/login/index.html rename to src/html/com_comprofiler/login/index.html diff --git a/src/templates/html/com_comprofiler/login/default.php b/src/html/com_comprofiler/login/mobile.php similarity index 100% rename from src/templates/html/com_comprofiler/login/default.php rename to src/html/com_comprofiler/login/mobile.php diff --git a/src/templates/html/com_comprofiler/registers/index.html b/src/html/com_comprofiler/registers/index.html similarity index 100% rename from src/templates/html/com_comprofiler/registers/index.html rename to src/html/com_comprofiler/registers/index.html diff --git a/src/templates/html/com_comprofiler/registers/default.php b/src/html/com_comprofiler/registers/mobile.php similarity index 100% rename from src/templates/html/com_comprofiler/registers/default.php rename to src/html/com_comprofiler/registers/mobile.php diff --git a/src/templates/html/com_comprofiler/userprofile/index.html b/src/html/com_comprofiler/userprofile/index.html similarity index 100% rename from src/templates/html/com_comprofiler/userprofile/index.html rename to src/html/com_comprofiler/userprofile/index.html diff --git a/src/templates/html/com_comprofiler/userprofile/default.php b/src/html/com_comprofiler/userprofile/mobile.php similarity index 100% rename from src/templates/html/com_comprofiler/userprofile/default.php rename to src/html/com_comprofiler/userprofile/mobile.php diff --git a/src/templates/html/com_comprofiler/userslist/index.html b/src/html/com_comprofiler/userslist/index.html similarity index 100% rename from src/templates/html/com_comprofiler/userslist/index.html rename to src/html/com_comprofiler/userslist/index.html diff --git a/src/templates/html/com_comprofiler/userslist/default.php b/src/html/com_comprofiler/userslist/mobile.php similarity index 100% rename from src/templates/html/com_comprofiler/userslist/default.php rename to src/html/com_comprofiler/userslist/mobile.php diff --git a/src/templates/html/com_content/article/index.html b/src/html/com_content/article/index.html similarity index 100% rename from src/templates/html/com_content/article/index.html rename to src/html/com_content/article/index.html diff --git a/src/templates/html/com_content/article/toc-left.php b/src/html/com_content/article/toc-left.php similarity index 100% rename from src/templates/html/com_content/article/toc-left.php rename to src/html/com_content/article/toc-left.php diff --git a/src/templates/html/com_content/article/toc-right.php b/src/html/com_content/article/toc-right.php similarity index 100% rename from src/templates/html/com_content/article/toc-right.php rename to src/html/com_content/article/toc-right.php diff --git a/src/html/com_jem/calendar/index.html b/src/html/com_jem/calendar/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/src/html/com_jem/calendar/index.html @@ -0,0 +1 @@ + diff --git a/src/html/com_jem/calendar/mobile.php b/src/html/com_jem/calendar/mobile.php new file mode 100644 index 0000000..ec2c307 --- /dev/null +++ b/src/html/com_jem/calendar/mobile.php @@ -0,0 +1,167 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Mobile responsive override for JEM calendar view + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Language\Text; +use Joomla\CMS\Router\Route; +use Joomla\CMS\HTML\HTMLHelper; + +$events = $this->rows ?? []; +$date = $this->date ?? null; +$year = $this->year ?? date('Y'); +$month = $this->month ?? date('m'); +?> + +
+
+ + +
+

+ +

+
+ + +
+ + + + +

+ +

+ + + + +
+ + +
+ +
+ +
+ +
+ +
+ + +
+ +
+ dates) && date('Y-m-d', strtotime($event->dates)) == $currentDate) { + $hasEvents = true; + $dayEvents[] = $event; + } + } + } + + $isToday = ($currentDate == date('Y-m-d')); + $classes = 'jem-calendar__day'; + if ($hasEvents) { + $classes .= ' jem-calendar__day--has-events'; + } + if ($isToday) { + $classes .= ' jem-calendar__day--today'; + } + ?> +
+
+ +
+ +
+ + + +
+ +
+ +
+
+ + + +
+

+ +

+
+ +
+
+ dates)) : ?> + + +
+

+ slug)) : ?> + + escape($event->title); ?> + + + escape($event->title); ?> + +

+ venue)) : ?> +
+ 📍 escape($event->venue); ?> +
+ +
+ +
+
+ + +
+
diff --git a/src/html/com_jem/categories/index.html b/src/html/com_jem/categories/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/src/html/com_jem/categories/index.html @@ -0,0 +1 @@ + diff --git a/src/html/com_jem/categories/mobile.php b/src/html/com_jem/categories/mobile.php new file mode 100644 index 0000000..7c704a7 --- /dev/null +++ b/src/html/com_jem/categories/mobile.php @@ -0,0 +1,111 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Mobile responsive override for JEM categories view + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Language\Text; +use Joomla\CMS\Router\Route; + +$categories = $this->categories ?? []; +?> + +
+
+ + +
+

+ +

+
+ + +
+ +
+
+ + + image)) : ?> +
+ <?php echo $this->escape($category->catname); ?> +
+ + + +
+ + +

+ slug)) : ?> + + escape($category->catname); ?> + + + escape($category->catname); ?> + +

+ + + catdescription)) : ?> +
+ catdescription; ?> +
+ + + + eventcount)) : ?> +
+ + eventcount); ?> + +
+ + + + slug)) : ?> +
+ + + +
+ + +
+ +
+
+ +
+ + + pagination)) : ?> +
+ pagination->getPagesLinks(); ?> +
+ + + +
+

+ +

+
+ + +
+
diff --git a/src/html/com_jem/event/index.html b/src/html/com_jem/event/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/src/html/com_jem/event/index.html @@ -0,0 +1 @@ + diff --git a/src/html/com_jem/event/mobile.php b/src/html/com_jem/event/mobile.php new file mode 100644 index 0000000..43f90c8 --- /dev/null +++ b/src/html/com_jem/event/mobile.php @@ -0,0 +1,212 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Mobile responsive override for JEM event details view + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Language\Text; +use Joomla\CMS\Router\Route; +use Joomla\CMS\HTML\HTMLHelper; + +$item = $this->item ?? null; +$params = $this->params ?? null; + +if (!$item) { + return; +} +?> + +
+
+ + +
+

+ escape($item->title); ?> +

+
+ + + datimage)) : ?> +
+ <?php echo $this->escape($item->title); ?> +
+ + + +
+ + +
+ +
+ + : + + dates)) : ?> + + + + enddates) && $item->enddates != $item->dates) : ?> + - + + +
+
+ + + times)) : ?> +
+ +
+ + : + + + escape($item->times); ?> + endtimes)) : ?> + - escape($item->endtimes); ?> + + +
+
+ + + + venue)) : ?> +
+ +
+ + : + + venueslug)) : ?> + + escape($item->venue); ?> + + + + escape($item->venue); ?> + + + + street) || !empty($item->city)) : ?> +
+ street)) : ?> + + escape($item->street); ?> + + + city)) : ?> + + escape($item->city); ?> + + +
+ +
+
+ + + + categories)) : ?> +
+ +
+ + : + +
+ categories as $category) : ?> + + escape($category->catname); ?> + + +
+
+
+ + +
+ + + fulltext)) : ?> +
+

+ +

+
+ fulltext; ?> +
+
+ + + + registra) && $item->registra == 1) : ?> +
+

+ +

+ maxplaces)) : ?> +

+ : + maxplaces; ?> +

+ + waitinglist)) : ?> +

+ +

+ +
+ + + + contactname)) : ?> +
+

+ +

+

+ : + escape($item->contactname); ?> +

+ contactemail)) : ?> +

+ : + + escape($item->contactemail); ?> + +

+ +
+ + + +
+ + + +
+ +
+
diff --git a/src/html/com_jem/eventslist/index.html b/src/html/com_jem/eventslist/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/src/html/com_jem/eventslist/index.html @@ -0,0 +1 @@ + diff --git a/src/html/com_jem/eventslist/mobile.php b/src/html/com_jem/eventslist/mobile.php new file mode 100644 index 0000000..b7b6d65 --- /dev/null +++ b/src/html/com_jem/eventslist/mobile.php @@ -0,0 +1,147 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Mobile responsive override for JEM events list view + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Language\Text; +use Joomla\CMS\Router\Route; +use Joomla\CMS\HTML\HTMLHelper; + +// Load JEM helper if available +if (file_exists(JPATH_SITE . '/components/com_jem/helpers/helper.php')) { + require_once JPATH_SITE . '/components/com_jem/helpers/helper.php'; +} + +$items = $this->items ?? []; +$params = $this->params ?? null; +?> + +
+
+ + pageheading)) : ?> +
+

+ escape($this->pageheading); ?> +

+
+ + + +
+ +
+
+ + +
+ dates)) : ?> + + + + enddates) && $item->enddates != $item->dates) : ?> + - + + +
+ + +

+ slug)) : ?> + + escape($item->title); ?> + + + escape($item->title); ?> + +

+ + + venue)) : ?> +
+ + venueslug)) : ?> + + escape($item->venue); ?> + + + + escape($item->venue); ?> + + + + city)) : ?> + + , escape($item->city); ?> + + +
+ + + + introtext)) : ?> +
+ introtext; ?> +
+ + + + categories)) : ?> +
+ categories as $category) : ?> + + escape($category->catname); ?> + + +
+ + + + slug)) : ?> +
+ + + +
+ + +
+
+ +
+ + + pagination)) : ?> +
+ pagination->getPagesLinks(); ?> +
+ + + +
+

+ +

+
+ + +
+
diff --git a/src/html/com_jem/index.html b/src/html/com_jem/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/src/html/com_jem/index.html @@ -0,0 +1 @@ + diff --git a/src/html/com_jem/venue/index.html b/src/html/com_jem/venue/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/src/html/com_jem/venue/index.html @@ -0,0 +1 @@ + diff --git a/src/html/com_jem/venue/mobile.php b/src/html/com_jem/venue/mobile.php new file mode 100644 index 0000000..6c69804 --- /dev/null +++ b/src/html/com_jem/venue/mobile.php @@ -0,0 +1,188 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Mobile responsive override for JEM venue view + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Language\Text; +use Joomla\CMS\Router\Route; +use Joomla\CMS\HTML\HTMLHelper; + +$venue = $this->venue ?? null; +$events = $this->rows ?? []; + +if (!$venue) { + return; +} +?> + +
+
+ + +
+

+ escape($venue->venue); ?> +

+
+ + + locimage)) : ?> +
+ <?php echo $this->escape($venue->venue); ?> +
+ + + +
+ + + street) || !empty($venue->city) || !empty($venue->postalCode)) : ?> +
+ +
+ + : + +
+ street)) : ?> +
+ escape($venue->street); ?> +
+ + postalCode) || !empty($venue->city)) : ?> +
+ postalCode)) : ?> + + escape($venue->postalCode); ?> + + + city)) : ?> + + escape($venue->city); ?> + + +
+ + state)) : ?> +
+ escape($venue->state); ?> +
+ + country)) : ?> +
+ escape($venue->country); ?> +
+ +
+
+
+ + + + url)) : ?> +
+ + +
+ + + + locdescription)) : ?> +
+

+ +

+
+ locdescription; ?> +
+
+ + +
+ + + latitude) && !empty($venue->longitude)) : ?> +
+

+ +

+
+ +
+

+

+ + + +

+
+
+
+ + + + +
+

+ +

+
+ +
+
+ dates)) : ?> + + +
+

+ slug)) : ?> + + escape($event->title); ?> + + + escape($event->title); ?> + +

+
+ +
+
+ + + +
+ + + +
+ +
+
diff --git a/src/templates/html/com_kunena/category/index.html b/src/html/com_kunena/category/index.html similarity index 100% rename from src/templates/html/com_kunena/category/index.html rename to src/html/com_kunena/category/index.html diff --git a/src/templates/html/com_kunena/category/default.php b/src/html/com_kunena/category/mobile.php similarity index 100% rename from src/templates/html/com_kunena/category/default.php rename to src/html/com_kunena/category/mobile.php diff --git a/src/templates/html/com_kunena/topic/index.html b/src/html/com_kunena/topic/index.html similarity index 100% rename from src/templates/html/com_kunena/topic/index.html rename to src/html/com_kunena/topic/index.html diff --git a/src/templates/html/com_osmembership/plan/index.html b/src/html/com_osmembership/plan/index.html similarity index 100% rename from src/templates/html/com_osmembership/plan/index.html rename to src/html/com_osmembership/plan/index.html diff --git a/src/templates/html/com_osmembership/plans/index.html b/src/html/com_osmembership/plans/index.html similarity index 100% rename from src/templates/html/com_osmembership/plans/index.html rename to src/html/com_osmembership/plans/index.html diff --git a/src/templates/html/com_osmembership/plans/default.php b/src/html/com_osmembership/plans/mobile.php similarity index 100% rename from src/templates/html/com_osmembership/plans/default.php rename to src/html/com_osmembership/plans/mobile.php diff --git a/src/templates/html/mod_acymailing/index.html b/src/html/mod_acymailing/index.html similarity index 100% rename from src/templates/html/mod_acymailing/index.html rename to src/html/mod_acymailing/index.html diff --git a/src/templates/html/mod_acymailing/default.php b/src/html/mod_acymailing/mobile.php similarity index 100% rename from src/templates/html/mod_acymailing/default.php rename to src/html/mod_acymailing/mobile.php diff --git a/src/templates/html/mod_articles_latest/index.html b/src/html/mod_cblogin/index.html similarity index 100% rename from src/templates/html/mod_articles_latest/index.html rename to src/html/mod_cblogin/index.html diff --git a/src/templates/html/mod_cblogin/default.php b/src/html/mod_cblogin/mobile.php similarity index 97% rename from src/templates/html/mod_cblogin/default.php rename to src/html/mod_cblogin/mobile.php index 568ee74..4011014 100644 --- a/src/templates/html/mod_cblogin/default.php +++ b/src/html/mod_cblogin/mobile.php @@ -11,8 +11,13 @@ defined('_JEXEC') or die; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; +// Ensure module language file is loaded +$lang = Factory::getLanguage(); +$lang->load('mod_cblogin', JPATH_SITE); + $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); // Add responsive wrapper class diff --git a/src/templates/html/mod_breadcrumbs/index.html b/src/html/mod_comprofilerOnline/index.html similarity index 100% rename from src/templates/html/mod_breadcrumbs/index.html rename to src/html/mod_comprofilerOnline/index.html diff --git a/src/templates/html/mod_comprofilerOnline/default.php b/src/html/mod_comprofilerOnline/mobile.php similarity index 95% rename from src/templates/html/mod_comprofilerOnline/default.php rename to src/html/mod_comprofilerOnline/mobile.php index f595861..dac596b 100644 --- a/src/templates/html/mod_comprofilerOnline/default.php +++ b/src/html/mod_comprofilerOnline/mobile.php @@ -11,8 +11,13 @@ defined('_JEXEC') or die; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; +// Ensure module language file is loaded +$lang = Factory::getLanguage(); +$lang->load('mod_comprofilerOnline', JPATH_SITE); + $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); // Add responsive wrapper class diff --git a/src/templates/html/mod_cblogin/index.html b/src/html/mod_hikashop_cart/index.html similarity index 100% rename from src/templates/html/mod_cblogin/index.html rename to src/html/mod_hikashop_cart/index.html diff --git a/src/templates/html/mod_hikashop_cart/default.php b/src/html/mod_hikashop_cart/mobile.php similarity index 100% rename from src/templates/html/mod_hikashop_cart/default.php rename to src/html/mod_hikashop_cart/mobile.php diff --git a/src/templates/html/mod_comprofilerOnline/index.html b/src/html/mod_k2_content/index.html similarity index 100% rename from src/templates/html/mod_comprofilerOnline/index.html rename to src/html/mod_k2_content/index.html diff --git a/src/templates/html/mod_k2_content/default.php b/src/html/mod_k2_content/mobile.php similarity index 100% rename from src/templates/html/mod_k2_content/default.php rename to src/html/mod_k2_content/mobile.php diff --git a/src/templates/html/mod_hikashop_cart/index.html b/src/html/mod_kunenalatest/index.html similarity index 100% rename from src/templates/html/mod_hikashop_cart/index.html rename to src/html/mod_kunenalatest/index.html diff --git a/src/templates/html/mod_kunenalatest/default.php b/src/html/mod_kunenalatest/mobile.php similarity index 100% rename from src/templates/html/mod_kunenalatest/default.php rename to src/html/mod_kunenalatest/mobile.php diff --git a/src/templates/html/mod_k2_content/index.html b/src/html/mod_kunenalogin/index.html similarity index 100% rename from src/templates/html/mod_k2_content/index.html rename to src/html/mod_kunenalogin/index.html diff --git a/src/templates/html/mod_kunenalogin/default.php b/src/html/mod_kunenalogin/mobile.php similarity index 100% rename from src/templates/html/mod_kunenalogin/default.php rename to src/html/mod_kunenalogin/mobile.php diff --git a/src/templates/html/mod_kunenalatest/index.html b/src/html/mod_kunenasearch/index.html similarity index 100% rename from src/templates/html/mod_kunenalatest/index.html rename to src/html/mod_kunenasearch/index.html diff --git a/src/templates/html/mod_kunenasearch/default.php b/src/html/mod_kunenasearch/mobile.php similarity index 100% rename from src/templates/html/mod_kunenasearch/default.php rename to src/html/mod_kunenasearch/mobile.php diff --git a/src/templates/html/mod_kunenalogin/index.html b/src/html/mod_kunenastats/index.html similarity index 100% rename from src/templates/html/mod_kunenalogin/index.html rename to src/html/mod_kunenastats/index.html diff --git a/src/templates/html/mod_kunenastats/default.php b/src/html/mod_kunenastats/mobile.php similarity index 100% rename from src/templates/html/mod_kunenastats/default.php rename to src/html/mod_kunenastats/mobile.php diff --git a/src/html/mod_menu/index.html b/src/html/mod_menu/index.html new file mode 100644 index 0000000..a07609c --- /dev/null +++ b/src/html/mod_menu/index.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/html/mod_menu/mainmenu.php b/src/html/mod_menu/mainmenu.php new file mode 100644 index 0000000..0c43bdd --- /dev/null +++ b/src/html/mod_menu/mainmenu.php @@ -0,0 +1,104 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Main Menu - Mobile responsive collapsible dropdown menu override + * Bootstrap 5 responsive navbar with hamburger menu + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Helper\ModuleHelper; + +$id = ''; + +if ($tagId = $params->get('tag_id', '')) { + $id = ' id="' . $tagId . '"'; +} + +// Get module class suffix +$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); + +// The menu class is deprecated. Use mod-menu instead +?> + diff --git a/src/html/mod_menu/mainmenu_component.php b/src/html/mod_menu/mainmenu_component.php new file mode 100644 index 0000000..0707118 --- /dev/null +++ b/src/html/mod_menu/mainmenu_component.php @@ -0,0 +1,64 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Main Menu - Component item layout + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Filter\OutputFilter; +use Joomla\CMS\HTML\HTMLHelper; + +$attributes = []; + +if ($item->anchor_title) { + $attributes['title'] = $item->anchor_title; +} + +if ($item->anchor_css) { + $attributes['class'] = $item->anchor_css; +} + +if ($item->anchor_rel) { + $attributes['rel'] = $item->anchor_rel; +} + +$linktype = $item->title; + +if ($item->menu_icon) { + // The link is an icon + if ($itemParams->get('menu_text', 1)) { + // If the link text is to be displayed, the icon is added with aria-hidden + $linktype = '' . $item->title; + } else { + // If the icon itself is the link, it needs a visually hidden text + $linktype = '' . $item->title . ''; + } +} + +if ($item->browserNav == 1) { + $attributes['target'] = '_blank'; + $attributes['rel'] = 'noopener noreferrer'; +} elseif ($item->browserNav == 2) { + $options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open'); + + $attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;"; +} + +// Add dropdown toggle for items with children +$linkClass = 'nav-link mod-menu-main__link'; +if ($item->deeper) { + $linkClass .= ' dropdown-toggle'; + $attributes['data-bs-toggle'] = 'dropdown'; + $attributes['role'] = 'button'; + $attributes['aria-expanded'] = 'false'; +} + +$attributes['class'] = $linkClass; + +echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes); diff --git a/src/html/mod_menu/mainmenu_heading.php b/src/html/mod_menu/mainmenu_heading.php new file mode 100644 index 0000000..0b92a44 --- /dev/null +++ b/src/html/mod_menu/mainmenu_heading.php @@ -0,0 +1,37 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Main Menu - Heading item layout + */ + +defined('_JEXEC') or die; + +$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : ''; +$anchor_css = $item->anchor_css ?: ''; + +$linktype = $item->title; + +if ($item->menu_icon) { + // The link is an icon + if ($itemParams->get('menu_text', 1)) { + // If the link text is to be displayed, the icon is added with aria-hidden + $linktype = '' . $item->title; + } else { + // If the icon itself is the link, it needs a visually hidden text + $linktype = '' . $item->title . ''; + } +} + +// Add dropdown toggle for items with children +$headingClass = 'nav-link mod-menu-main__heading'; +if ($item->deeper) { + $headingClass .= ' dropdown-toggle'; +} + +?> +> diff --git a/src/html/mod_menu/mainmenu_separator.php b/src/html/mod_menu/mainmenu_separator.php new file mode 100644 index 0000000..2523962 --- /dev/null +++ b/src/html/mod_menu/mainmenu_separator.php @@ -0,0 +1,31 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Main Menu - Separator item layout + */ + +defined('_JEXEC') or die; + +$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : ''; +$anchor_css = $item->anchor_css ?: ''; + +$linktype = $item->title; + +if ($item->menu_icon) { + // The link is an icon + if ($itemParams->get('menu_text', 1)) { + // If the link text is to be displayed, the icon is added with aria-hidden + $linktype = '' . $item->title; + } else { + // If the icon itself is the link, it needs a visually hidden text + $linktype = '' . $item->title . ''; + } +} + +?> +> diff --git a/src/html/mod_menu/mainmenu_url.php b/src/html/mod_menu/mainmenu_url.php new file mode 100644 index 0000000..abad710 --- /dev/null +++ b/src/html/mod_menu/mainmenu_url.php @@ -0,0 +1,69 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * + * Main Menu - URL item layout + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Filter\OutputFilter; +use Joomla\CMS\HTML\HTMLHelper; + +$attributes = []; + +if ($item->anchor_title) { + $attributes['title'] = $item->anchor_title; +} + +if ($item->anchor_css) { + $attributes['class'] = $item->anchor_css; +} + +if ($item->anchor_rel) { + $attributes['rel'] = $item->anchor_rel; +} + +$linktype = $item->title; + +if ($item->menu_icon) { + // The link is an icon + if ($itemParams->get('menu_text', 1)) { + // If the link text is to be displayed, the icon is added with aria-hidden + $linktype = '' . $item->title; + } else { + // If the icon itself is the link, it needs a visually hidden text + $linktype = '' . $item->title . ''; + } +} + +if ($item->browserNav == 1) { + $attributes['target'] = '_blank'; + $attributes['rel'] = 'noopener noreferrer'; +} elseif ($item->browserNav == 2) { + $options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open'); + + $attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;"; +} + +// Add dropdown toggle for items with children +$linkClass = 'nav-link mod-menu-main__link'; +if ($item->deeper) { + $linkClass .= ' dropdown-toggle'; + $attributes['data-bs-toggle'] = 'dropdown'; + $attributes['role'] = 'button'; + $attributes['aria-expanded'] = 'false'; +} + +// Merge existing class with our class +if (isset($attributes['class'])) { + $attributes['class'] .= ' ' . $linkClass; +} else { + $attributes['class'] = $linkClass; +} + +echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes); diff --git a/src/templates/html/mod_kunenasearch/index.html b/src/html/mod_osmembership/index.html similarity index 100% rename from src/templates/html/mod_kunenasearch/index.html rename to src/html/mod_osmembership/index.html diff --git a/src/templates/html/mod_osmembership/default.php b/src/html/mod_osmembership/mobile.php similarity index 100% rename from src/templates/html/mod_osmembership/default.php rename to src/html/mod_osmembership/mobile.php diff --git a/src/templates/html/mod_kunenastats/index.html b/src/html/mod_virtuemart_cart/index.html similarity index 100% rename from src/templates/html/mod_kunenastats/index.html rename to src/html/mod_virtuemart_cart/index.html diff --git a/src/templates/html/mod_virtuemart_cart/default.php b/src/html/mod_virtuemart_cart/mobile.php similarity index 100% rename from src/templates/html/mod_virtuemart_cart/default.php rename to src/html/mod_virtuemart_cart/mobile.php diff --git a/src/templates/html/mod_login/index.html b/src/html/mod_virtuemart_category/index.html similarity index 100% rename from src/templates/html/mod_login/index.html rename to src/html/mod_virtuemart_category/index.html diff --git a/src/templates/html/mod_virtuemart_category/default.php b/src/html/mod_virtuemart_category/mobile.php similarity index 100% rename from src/templates/html/mod_virtuemart_category/default.php rename to src/html/mod_virtuemart_category/mobile.php diff --git a/src/templates/html/mod_menu/index.html b/src/html/mod_virtuemart_currencies/index.html similarity index 100% rename from src/templates/html/mod_menu/index.html rename to src/html/mod_virtuemart_currencies/index.html diff --git a/src/templates/html/mod_virtuemart_currencies/default.php b/src/html/mod_virtuemart_currencies/mobile.php similarity index 100% rename from src/templates/html/mod_virtuemart_currencies/default.php rename to src/html/mod_virtuemart_currencies/mobile.php diff --git a/src/templates/html/mod_osmembership/index.html b/src/html/mod_virtuemart_manufacturer/index.html similarity index 100% rename from src/templates/html/mod_osmembership/index.html rename to src/html/mod_virtuemart_manufacturer/index.html diff --git a/src/templates/html/mod_virtuemart_manufacturer/default.php b/src/html/mod_virtuemart_manufacturer/mobile.php similarity index 100% rename from src/templates/html/mod_virtuemart_manufacturer/default.php rename to src/html/mod_virtuemart_manufacturer/mobile.php diff --git a/src/templates/html/mod_search/index.html b/src/html/mod_virtuemart_product/index.html similarity index 100% rename from src/templates/html/mod_search/index.html rename to src/html/mod_virtuemart_product/index.html diff --git a/src/templates/html/mod_virtuemart_product/default.php b/src/html/mod_virtuemart_product/mobile.php similarity index 100% rename from src/templates/html/mod_virtuemart_product/default.php rename to src/html/mod_virtuemart_product/mobile.php diff --git a/src/templates/index.html b/src/index.html similarity index 100% rename from src/templates/index.html rename to src/index.html diff --git a/src/templates/index.php b/src/index.php similarity index 93% rename from src/templates/index.php rename to src/index.php index 795669a..e50086d 100644 --- a/src/templates/index.php +++ b/src/index.php @@ -45,9 +45,9 @@ $document = $app->getDocument(); $wa = $document->getWebAssetManager(); // Template params -$params_LightColorName = (string) $this->params->get('colorLightName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom +$params_LightColorName = (string) $this->params->get('colorLightName', 'standard'); // standard|custom -$params_DarkColorName = (string) $this->params->get('colorDarkName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom +$params_DarkColorName = (string) $this->params->get('colorDarkName', 'standard'); // standard|custom $params_googletagmanager = $this->params->get('googletagmanager', false); $params_googletagmanagerid = $this->params->get('googletagmanagerid', null); @@ -88,36 +88,6 @@ $templatePath = 'media/templates/site/mokocassiopeia'; // Core template CSS $wa->useStyle('template.base'); // css/template.css -// Color theme (light + optional dark) -$colorLightKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_LightColorName)); -$colorDarkKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_DarkColorName)); -$lightKey = 'template.light.' . $colorLightKey; -$darkKey = 'template.dark.' . $colorDarkKey; - -try { - $wa->useStyle('template.light.colors_standard'); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.light.colors_standard', $templatePath . '/css/colors/light/colors_standard.css'); -} - -try { - $wa->useStyle('template.dark.colors_standard'); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.dark.colors_standard', $templatePath . '/css/colors/dark/colors_standard.css'); -} - -try { - $wa->useStyle($lightKey); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.light.dynamic', $templatePath . '/css/colors/light/' . $colorLightKey . '.css'); -} - -try { - $wa->useStyle($darkKey); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.dark.dynamic', $templatePath . '/css/colors/dark/' . $colorDarkKey . '.css'); -} - // Scripts $wa->useScript('template.js'); @@ -149,8 +119,6 @@ $fontStyles = ''; if ($params_FontScheme) { if (stripos($params_FontScheme, 'https://') === 0) { - $this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']); - $this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']); $this->getPreloadManager()->preload($params_FontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']); $wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, [], [ 'media' => 'print', @@ -259,7 +227,23 @@ if ($this->params->get('fA6KitCode')) { $params_leftIcon = htmlspecialchars($this->params->get('drawerLeftIcon', 'fa-solid fa-chevron-left'), ENT_COMPAT, 'UTF-8'); $params_rightIcon = htmlspecialchars($this->params->get('drawerRightIcon', 'fa-solid fa-chevron-right'), ENT_COMPAT, 'UTF-8'); +// Load theme palette stylesheets based on configuration +$wa->useStyle('template.light.standard'); // css/theme/light.standard.css +$wa->useStyle('template.dark.standard'); // css/theme/dark.standard.css + +// Load custom palettes only if selected in template configuration AND files exist +if ($params_LightColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/light.custom.css')) +{ + $wa->useStyle('template.light.custom'); +} +if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/dark.custom.css')) +{ + $wa->useStyle('template.dark.custom'); +} + +// Load user assets last (after all other styles and scripts) $wa->useStyle('template.user'); // css/user.css +$wa->useScript('user.js'); // js/user.js ?> diff --git a/src/templates/joomla.asset.json b/src/joomla.asset.json similarity index 81% rename from src/templates/joomla.asset.json rename to src/joomla.asset.json index a63c0a5..a305b51 100644 --- a/src/templates/joomla.asset.json +++ b/src/joomla.asset.json @@ -46,6 +46,18 @@ "uri": "media/templates/site/mokocassiopeia/css/user.min.css", "attributes": {"media": "all"} }, + { + "name": "user.js", + "type": "script", + "uri": "media/templates/site/mokocassiopeia/js/user.js", + "attributes": {"defer": true} + }, + { + "name": "user.js.min", + "type": "script", + "uri": "media/templates/site/mokocassiopeia/js/user.min.js", + "attributes": {"defer": true} + }, { "name": "template.font.osaka", "type": "style", @@ -65,62 +77,51 @@ "attributes": {"media": "all"} }, { - "name": "template.light.colors_standard", + "name": "template.light.standard", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_standard.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/light.standard.css", "attributes": {"media": "all"} }, { - "name": "template.light.colors_standard.min", + "name": "template.light.standard.min", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_standard.min.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/light.standard.min.css", "attributes": {"media": "all"} }, { - "name": "template.light.colors_custom", + "name": "template.light.custom", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/light.custom.css", "attributes": {"media": "all"} }, { - "name": "template.light.colors_custom.min", + "name": "template.light.custom.min", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/light/colors_custom.min.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/light.custom.min.css", "attributes": {"media": "all"} }, { - "name": "template.dark.colors_standard", + "name": "template.dark.standard", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_standard.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/dark.standard.css", "attributes": {"media": "all"} }, { - "name": "template.dark.colors_standard.min", + "name": "template.dark.standard.min", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_standard.min.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/dark.standard.min.css", "attributes": {"media": "all"} }, { - "name": "template.dark.colors_alternative", + "name": "template.dark.custom", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_alternative.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/dark.custom.css", "attributes": {"media": "all"} }, { - "name": "template.dark.colors_alternative.min", + "name": "template.dark.custom.min", "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_alternative.min.css" - }, - { - "name": "template.dark.colors_custom", - "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css", - "attributes": {"media": "all"} - }, - { - "name": "template.dark.colors_custom.min", - "type": "style", - "uri": "media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.min.css", + "uri": "media/templates/site/mokocassiopeia/css/theme/dark.custom.min.css", "attributes": {"media": "all"} }, { diff --git a/src/language/en-GB/tpl_mokocassiopeia.ini b/src/language/en-GB/tpl_mokocassiopeia.ini index 0eb9c00..d3ae6ce 100644 --- a/src/language/en-GB/tpl_mokocassiopeia.ini +++ b/src/language/en-GB/tpl_mokocassiopeia.ini @@ -11,9 +11,7 @@ ; VERSION: 03.06.02 ; BRIEF: English (GB) language strings for the MokoCassiopeia Joomla template ; -; ===== Template meta ===== -MOKOCASSIOPEIA="MokoCassiopeia Site template" -TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="

MokoCassiopeia Template Description

MokoCassiopeia 3.0 continues Joomla’s tradition of space-themed default templates— building on the legacy of Solarflare (Joomla 1.0), Milkyway (Joomla 1.5), and Protostar (Joomla 3.0).

This template is a customized fork of the Cassiopeia template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting.

Code Attribution

This template is based on the original Cassiopeia template developed by the Joomla! Project and released under the GNU General Public License.

Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.

It includes integration with Bootstrap TOC, an open-source table of contents generator by A. Feld, licensed under the MIT License.

All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.

" +; Note: Template metadata strings (name, description) are in tpl_mokocassiopeia.sys.ini ; ===== System / layout ===== TPL_MOKOCASSIOPEIA_DEVELOPMENTMODE_LABEL="Development Mode" @@ -77,9 +75,9 @@ TPL_MOKOCASSIOPEIA_COLOR_NAME_STANDARD="Standard" TPL_MOKOCASSIOPEIA_COLOR_NAME_CUSTOM="Custom" ; New labels for Theme tab dropdowns TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_LABEL="Light colour palette" -TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a colour palette for light mode. Standard uses the default blue theme with comprehensive styling for all components. Custom allows you to create your own colour scheme - copy the template file from templates/colors_custom.css to media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css and customise the CSS variables to match your brand." +TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a colour palette for light mode. Standard uses the default blue theme with comprehensive styling for all components. Custom allows you to create your own colour scheme - copy the template file from templates/theme_custom_light.css to media/templates/site/mokocassiopeia/css/theme/light.custom.css and customise the CSS variables to match your brand." TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_LABEL="Dark colour palette" -TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a colour palette for dark mode. Standard uses the default blue theme optimised for dark backgrounds with proper contrast. Custom allows you to create your own colour scheme - copy the template file from templates/colors_custom.css to media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css and customise the CSS variables to match your brand." +TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a colour palette for dark mode. Standard uses the default blue theme optimised for dark backgrounds with proper contrast. Custom allows you to create your own colour scheme - copy the template file from templates/theme_custom_dark.css to media/templates/site/mokocassiopeia/css/theme/dark.custom.css and customise the CSS variables to match your brand." ; ===== Theme tab (core feature strings) ===== TPL_MOKO_THEME_FIELDSET="Theme" diff --git a/src/administrator/language/en-GB/tpl_mokocassiopeia.sys.ini b/src/language/en-GB/tpl_mokocassiopeia.sys.ini similarity index 62% rename from src/administrator/language/en-GB/tpl_mokocassiopeia.sys.ini rename to src/language/en-GB/tpl_mokocassiopeia.sys.ini index 069405c..17019a0 100644 --- a/src/administrator/language/en-GB/tpl_mokocassiopeia.sys.ini +++ b/src/language/en-GB/tpl_mokocassiopeia.sys.ini @@ -34,4 +34,4 @@ TPL_MOKOCASSIOPEIA_POSITION_TOP_B="Top-b" TPL_MOKOCASSIOPEIA_POSITION_TOPBAR="Top Bar" TPL_MOKOCASSIOPEIA_POSITION_DRAWER_LEFT="Drawer-Left" TPL_MOKOCASSIOPEIA_POSITION_DRAWER_RIGHT="Drawer-Right" -TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="

MokoCassiopeia Template Description

MokoCassiopeia 3.0 continues Joomla’s tradition of space-themed default templates— building on the legacy of Solarflare (Joomla 1.0), Milkyway (Joomla 1.5), and Protostar (Joomla 3.0).

This template is a customized fork of the Cassiopeia template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting.

Custom Colour Themes

To create a custom colour scheme, copy the template file templates/colors_custom.css to either media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css or media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css. Customise the CSS variables to match your brand, then activate it in System → Site Templates → MokoCassiopeia → Theme tab by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see docs/CSS_VARIABLES.md.

Code Attribution

This template is based on the original Cassiopeia template developed by the Joomla! Project and released under the GNU General Public License.

Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.

It includes integration with Bootstrap TOC, an open-source table of contents generator by A. Feld, licensed under the MIT License.

All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.

" +TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="

MokoCassiopeia Template Description

MokoCassiopeia 3.0 continues Joomla’s tradition of space-themed default templates— building on the legacy of Solarflare (Joomla 1.0), Milkyway (Joomla 1.5), and Protostar (Joomla 3.0).

This template is a customized fork of the Cassiopeia template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting.

Custom Colour Themes

To create a custom colour scheme, copy the template file templates/theme_custom_light.css to media/templates/site/mokocassiopeia/css/theme/light.custom.css or media/templates/site/mokocassiopeia/css/theme/dark.custom.css. Customise the CSS variables to match your brand, then activate it in System → Site Templates → MokoCassiopeia → Theme tab by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see docs/CSS_VARIABLES.md.

Code Attribution

This template is based on the original Cassiopeia template developed by the Joomla! Project and released under the GNU General Public License.

Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.

It includes integration with Bootstrap TOC, an open-source table of contents generator by A. Feld, licensed under the MIT License.

All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.

" diff --git a/src/language/en-US/tpl_mokocassiopeia.ini b/src/language/en-US/tpl_mokocassiopeia.ini index 4c12993..82aa2bb 100644 --- a/src/language/en-US/tpl_mokocassiopeia.ini +++ b/src/language/en-US/tpl_mokocassiopeia.ini @@ -11,9 +11,7 @@ ; VERSION: 03.06.02 ; BRIEF: English (US) language strings for the MokoCassiopeia Joomla template ; -; ===== Template meta ===== -MOKOCASSIOPEIA="MokoCassiopeia Site template" -TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="

MokoCassiopeia Template Description

MokoCassiopeia 3.0 continues Joomla’s tradition of space-themed default templates— building on the legacy of Solarflare (Joomla 1.0), Milkyway (Joomla 1.5), and Protostar (Joomla 3.0).

This template is a customized fork of the Cassiopeia template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting.

Code Attribution

This template is based on the original Cassiopeia template developed by the Joomla! Project and released under the GNU General Public License.

Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.

It includes integration with Bootstrap TOC, an open-source table of contents generator by A. Feld, licensed under the MIT License.

All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.

" +; Note: Template metadata strings (name, description) are in tpl_mokocassiopeia.sys.ini ; ===== System / layout ===== TPL_MOKOCASSIOPEIA_DEVELOPMENTMODE_LABEL="Development Mode" @@ -77,9 +75,9 @@ TPL_MOKOCASSIOPEIA_COLOR_NAME_STANDARD="Standard" TPL_MOKOCASSIOPEIA_COLOR_NAME_CUSTOM="Custom" ; New labels for Theme tab dropdowns TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_LABEL="Light color palette" -TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a color palette for light mode. Standard uses the default blue theme with comprehensive styling for all components. Custom allows you to create your own color scheme - copy the template file from templates/colors_custom.css to media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css and customize the CSS variables to match your brand." +TPL_MOKOCASSIOPEIA_COLOR_LIGHT_NAME_DESC="Select a color palette for light mode. Standard uses the default blue theme with comprehensive styling for all components. Custom allows you to create your own color scheme - copy the template file from templates/theme_custom_light.css to media/templates/site/mokocassiopeia/css/theme/light.custom.css and customize the CSS variables to match your brand." TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_LABEL="Dark color palette" -TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a color palette for dark mode. Standard uses the default blue theme optimized for dark backgrounds with proper contrast. Custom allows you to create your own color scheme - copy the template file from templates/colors_custom.css to media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css and customize the CSS variables to match your brand." +TPL_MOKOCASSIOPEIA_COLOR_DARK_NAME_DESC="Select a color palette for dark mode. Standard uses the default blue theme optimized for dark backgrounds with proper contrast. Custom allows you to create your own color scheme - copy the template file from templates/theme_custom_dark.css to media/templates/site/mokocassiopeia/css/theme/dark.custom.css and customize the CSS variables to match your brand." ; ===== Theme tab (core feature strings) ===== TPL_MOKO_THEME_FIELDSET="Theme" diff --git a/src/administrator/language/en-US/tpl_mokocassiopeia.sys.ini b/src/language/en-US/tpl_mokocassiopeia.sys.ini similarity index 62% rename from src/administrator/language/en-US/tpl_mokocassiopeia.sys.ini rename to src/language/en-US/tpl_mokocassiopeia.sys.ini index 2942d9b..af98009 100644 --- a/src/administrator/language/en-US/tpl_mokocassiopeia.sys.ini +++ b/src/language/en-US/tpl_mokocassiopeia.sys.ini @@ -34,4 +34,4 @@ TPL_MOKOCASSIOPEIA_POSITION_TOP_B="Top-b" TPL_MOKOCASSIOPEIA_POSITION_TOPBAR="Top Bar" TPL_MOKOCASSIOPEIA_POSITION_DRAWER_LEFT="Drawer-Left" TPL_MOKOCASSIOPEIA_POSITION_DRAWER_RIGHT="Drawer-Right" -TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="

MokoCassiopeia Template Description

MokoCassiopeia 3.0 continues Joomla’s tradition of space-themed default templates— building on the legacy of Solarflare (Joomla 1.0), Milkyway (Joomla 1.5), and Protostar (Joomla 3.0).

This template is a customized fork of the Cassiopeia template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting.

Custom Color Themes

To create a custom color scheme, copy the template file templates/colors_custom.css to either media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css or media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css. Customize the CSS variables to match your brand, then activate it in System → Site Templates → MokoCassiopeia → Theme tab by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see docs/CSS_VARIABLES.md.

Code Attribution

This template is based on the original Cassiopeia template developed by the Joomla! Project and released under the GNU General Public License.

Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.

It includes integration with Bootstrap TOC, an open-source table of contents generator by A. Feld, licensed under the MIT License.

All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.

" +TPL_MOKOCASSIOPEIA_XML_DESCRIPTION="

MokoCassiopeia Template Description

MokoCassiopeia 3.0 continues Joomla’s tradition of space-themed default templates— building on the legacy of Solarflare (Joomla 1.0), Milkyway (Joomla 1.5), and Protostar (Joomla 3.0).

This template is a customized fork of the Cassiopeia template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting.

Custom Color Themes

To create a custom color scheme, copy the template file templates/theme_custom_light.css to media/templates/site/mokocassiopeia/css/theme/light.custom.css or media/templates/site/mokocassiopeia/css/theme/dark.custom.css. Customize the CSS variables to match your brand, then activate it in System → Site Templates → MokoCassiopeia → Theme tab by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see docs/CSS_VARIABLES.md.

Code Attribution

This template is based on the original Cassiopeia template developed by the Joomla! Project and released under the GNU General Public License.

Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.

It includes integration with Bootstrap TOC, an open-source table of contents generator by A. Feld, licensed under the MIT License.

All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.

" diff --git a/src/media/css/colors/dark/index.html b/src/media/css/colors/dark/index.html deleted file mode 100644 index 480348d..0000000 --- a/src/media/css/colors/dark/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - Redirecting… - - - - - - - - - - - - - - - - - - - -
Redirecting to the site root… If you are not redirected, click here.
- - diff --git a/src/media/css/colors/index.html b/src/media/css/colors/index.html deleted file mode 100644 index 480348d..0000000 --- a/src/media/css/colors/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - Redirecting… - - - - - - - - - - - - - - - - - - - -
Redirecting to the site root… If you are not redirected, click here.
- - diff --git a/src/media/css/colors/light/index.html b/src/media/css/colors/light/index.html deleted file mode 100644 index 480348d..0000000 --- a/src/media/css/colors/light/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - Redirecting… - - - - - - - - - - - - - - - - - - - -
Redirecting to the site root… If you are not redirected, click here.
- - diff --git a/src/media/css/fonts/fira-sans.css b/src/media/css/fonts/fira-sans.css new file mode 100644 index 0000000..1c17706 --- /dev/null +++ b/src/media/css/fonts/fira-sans.css @@ -0,0 +1,64 @@ +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Styles + PATH: ./media/templates/site/mokocassiopeia/css/fonts/fira-sans.css + VERSION: 03.08.04 + BRIEF: Fira Sans font family definitions (self-hosted) + */ + +/* + * IMPORTANT: Font files must be downloaded separately + * + * This CSS file references Fira Sans font files that must be manually downloaded + * and placed in the fonts directory. See GOOGLE_FONTS_README.md in the fonts + * directory for download instructions. + * + * Required files: + * - fira-sans-v17-latin-100.woff2 + * - fira-sans-v17-latin-300.woff2 + * - fira-sans-v17-latin-regular.woff2 + * - fira-sans-v17-latin-700.woff2 + */ + +/* Fira Sans Thin (100) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-100.woff2') format('woff2'); +} + +/* Fira Sans Light (300) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-300.woff2') format('woff2'); +} + +/* Fira Sans Regular (400) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-regular.woff2') format('woff2'); +} + +/* Fira Sans Bold (700) */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../../fonts/fira-sans-v17-latin-700.woff2') format('woff2'); +} diff --git a/src/media/css/fonts/noto-sans.css b/src/media/css/fonts/noto-sans.css new file mode 100644 index 0000000..c011dd1 --- /dev/null +++ b/src/media/css/fonts/noto-sans.css @@ -0,0 +1,64 @@ +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Styles + PATH: ./media/templates/site/mokocassiopeia/css/fonts/noto-sans.css + VERSION: 03.08.04 + BRIEF: Noto Sans font family definitions (self-hosted) + */ + +/* + * IMPORTANT: Font files must be downloaded separately + * + * This CSS file references Noto Sans font files that must be manually downloaded + * and placed in the fonts directory. See GOOGLE_FONTS_README.md in the fonts + * directory for download instructions. + * + * Required files: + * - noto-sans-v36-latin-100.woff2 + * - noto-sans-v36-latin-300.woff2 + * - noto-sans-v36-latin-regular.woff2 + * - noto-sans-v36-latin-700.woff2 + */ + +/* Noto Sans Thin (100) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-100.woff2') format('woff2'); +} + +/* Noto Sans Light (300) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-300.woff2') format('woff2'); +} + +/* Noto Sans Regular (400) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-regular.woff2') format('woff2'); +} + +/* Noto Sans Bold (700) */ +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../../fonts/noto-sans-v36-latin-700.woff2') format('woff2'); +} diff --git a/src/media/css/fonts/roboto.css b/src/media/css/fonts/roboto.css new file mode 100644 index 0000000..bf68f47 --- /dev/null +++ b/src/media/css/fonts/roboto.css @@ -0,0 +1,64 @@ +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Styles + PATH: ./media/templates/site/mokocassiopeia/css/fonts/roboto.css + VERSION: 03.08.04 + BRIEF: Roboto font family definitions (self-hosted) + */ + +/* + * IMPORTANT: Font files must be downloaded separately + * + * This CSS file references Roboto font files that must be manually downloaded + * and placed in the fonts directory. See GOOGLE_FONTS_README.md in the fonts + * directory for download instructions. + * + * Required files: + * - roboto-v30-latin-100.woff2 + * - roboto-v30-latin-300.woff2 + * - roboto-v30-latin-regular.woff2 + * - roboto-v30-latin-700.woff2 + */ + +/* Roboto Thin (100) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-100.woff2') format('woff2'); +} + +/* Roboto Light (300) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-300.woff2') format('woff2'); +} + +/* Roboto Regular (400) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-regular.woff2') format('woff2'); +} + +/* Roboto Bold (700) */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../../fonts/roboto-v30-latin-700.woff2') format('woff2'); +} diff --git a/src/media/css/template.css b/src/media/css/template.css index 1eb55d3..4667039 100644 --- a/src/media/css/template.css +++ b/src/media/css/template.css @@ -2336,11 +2336,11 @@ progress { --table-border-color: var(--border-color); --table-accent-bg: transparent; --table-striped-color: var(--body-color); - --table-striped-bg: rgba(0, 0, 0, 0.05); + --table-striped-bg: rgba(var(--black-rgb), var(--opacity-5)); --table-active-color: var(--body-color); - --table-active-bg: rgba(0, 0, 0, 0.1); + --table-active-bg: rgba(var(--black-rgb), var(--opacity-10)); --table-active-color: var(--body-color); - --table-active-bg: rgba(0, 0, 0, 0.075); + --table-active-bg: rgba(var(--black-rgb), 0.075); width: 100%; margin-bottom: 1rem; color: var(--table-color); @@ -2729,11 +2729,11 @@ progress { } .form-control:active:not(:disabled):not([readonly])::-webkit-file-upload-button { - background-color: #dee1e4; + background-color: var(--input-file-button-active-bg); } .form-control:active:not(:disabled):not([readonly])::file-selector-button { - background-color: #dee1e4; + background-color: var(--input-file-button-active-bg); } .form-control-plaintext { @@ -2878,7 +2878,7 @@ textarea.form-control-lg { .form-select:focus, .custom-select:focus { - border-color: #8894aa; + border-color: var(--input-focus-border-color); outline: 0; -webkit-box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); @@ -2974,7 +2974,7 @@ textarea.form-control-lg { } .form-check-input:focus { - border-color: #8894aa; + border-color: var(--input-focus-border-color); outline: 0; -webkit-box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); @@ -3123,7 +3123,7 @@ textarea.form-control-lg { } .form-range::-webkit-slider-thumb:active { - background-color: #b8bfcc; + background-color: var(--form-range-thumb-active-bg); } .form-range::-webkit-slider-runnable-track { @@ -3156,7 +3156,7 @@ textarea.form-control-lg { } .form-range::-moz-range-thumb:active { - background-color: #b8bfcc; + background-color: var(--form-range-thumb-active-bg); } .form-range::-moz-range-track { @@ -3422,7 +3422,7 @@ textarea.form-control-lg { } .input-group> :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { - margin-left: -1px; + margin-left: -0.0625rem; border-top-left-radius: 0; border-bottom-left-radius: 0; } @@ -3882,7 +3882,7 @@ fieldset:disabled .btn { --dropdown-inner-border-radius: calc(0.25rem - 1px); --dropdown-divider-bg: var(--border-color-translucent); --dropdown-divider-margin-y: 0.5rem; - --dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --dropdown-box-shadow: 0 0.5rem 1rem var(--shadow-color-light); --dropdown-link-color: hsl(210, 11%, 15%); --dropdown-link-active-color: #1f2226; --dropdown-link-active-bg: hsl(210, 16%, 93%); @@ -4249,7 +4249,7 @@ fieldset:disabled .btn { .btn-group> :not(.btn-check:first-child)+.btn, .btn-group>.btn-group:not(:first-child) { - margin-left: -1px; + margin-left: -0.0625rem; } .btn-group>.btn:not(:last-child):not(.dropdown-toggle), @@ -4313,7 +4313,7 @@ fieldset:disabled .btn { .btn-group-vertical>.btn:not(:first-child), .btn-group-vertical>.btn-group:not(:first-child) { - margin-top: -1px; + margin-top: -0.0625rem; } .btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle), @@ -5278,7 +5278,7 @@ fieldset:disabled .btn { --accordion-btn-icon-transform: rotate(-180deg); --accordion-btn-icon-transition: transform 0.2s ease-in-out; --accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230f244d'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - --accordion-btn-focus-border-color: #8894aa; + --accordion-btn-focus-border-color: var(--input-focus-border-color); --accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); --accordion-body-padding-x: 1.25rem; --accordion-body-padding-y: 1rem; @@ -5554,7 +5554,7 @@ fieldset:disabled .btn { } .page-item:not(:first-child) .page-link { - margin-left: -1px; + margin-left: -0.0625rem; } .page-item:first-child .page-link { @@ -5654,7 +5654,7 @@ fieldset:disabled .btn { } .alert-primary .alert-link { - color: #01012a; + color: var(--alert-primary-link-color); } .alert-secondary { @@ -5664,7 +5664,7 @@ fieldset:disabled .btn { } .alert-secondary .alert-link { - color: #34383d; + color: var(--alert-secondary-link-color); } .alert-success { @@ -5674,7 +5674,7 @@ fieldset:disabled .btn { } .alert-success .alert-link { - color: #213f21; + color: var(--alert-success-link-color); } .alert-info { @@ -5684,7 +5684,7 @@ fieldset:disabled .btn { } .alert-info .alert-link { - color: #172f44; + color: var(--alert-info-link-color); } .alert-warning { @@ -5694,7 +5694,7 @@ fieldset:disabled .btn { } .alert-warning .alert-link { - color: #532f00; + color: var(--alert-warning-link-color); } .alert-danger { @@ -5704,7 +5704,7 @@ fieldset:disabled .btn { } .alert-danger .alert-link { - color: #4f0f0b; + color: var(--alert-danger-link-color); } .alert-light { @@ -5714,7 +5714,7 @@ fieldset:disabled .btn { } .alert-light .alert-link { - color: #505050; + color: var(--alert-light-link-color); } .alert-dark { @@ -5724,7 +5724,7 @@ fieldset:disabled .btn { } .alert-dark .alert-link { - color: #1a1c1f; + color: var(--alert-dark-link-color); } @-webkit-keyframes progress-bar-stripes { @@ -5744,7 +5744,7 @@ fieldset:disabled .btn { --progress-font-size: 0.75rem; --progress-bg: hsl(210, 16%, 93%); --progress-border-radius: 0.25rem; - --progress-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); + --progress-box-shadow: inset 0 1px 2px rgba(var(--black-rgb), 0.075); --progress-bar-color: var(--body-color); --progress-bar-bg: hsl(240, 98%, 17%); --progress-bar-transition: width 0.6s ease; @@ -5808,7 +5808,7 @@ fieldset:disabled .btn { .list-group { --list-group-color: hsl(210, 11%, 15%); --list-group-bg: var(--body-color); - --list-group-border-color: rgba(0, 0, 0, 0.125); + --list-group-border-color: rgba(var(--black-rgb), 0.125); --list-group-border-width: 1px; --list-group-border-radius: 0.25rem; --list-group-item-padding-x: 1rem; @@ -6116,139 +6116,139 @@ fieldset:disabled .btn { } .list-group-item-primary { - color: #010134; - background-color: #ccccdd; + color: var(--list-group-item-primary-color); + background-color: var(--list-group-item-primary-bg); } .list-group-item-primary.list-group-item-action:active, .list-group-item-primary.list-group-item-action:focus { - color: #010134; - background-color: #b8b8c7; + color: var(--list-group-item-primary-color); + background-color: var(--list-group-item-primary-active-bg); } .list-group-item-primary.list-group-item-action.active { color: var(--body-color); - background-color: #010134; - border-color: #010134; + background-color: var(--list-group-item-primary-color); + border-color: var(--list-group-item-primary-color); } .list-group-item-secondary { - color: #41464c; - background-color: #e2e3e5; + color: var(--list-group-item-secondary-color); + background-color: var(--list-group-item-secondary-bg); } .list-group-item-secondary.list-group-item-action:active, .list-group-item-secondary.list-group-item-action:focus { - color: #41464c; - background-color: #cbccce; + color: var(--list-group-item-secondary-color); + background-color: var(--list-group-item-secondary-active-bg); } .list-group-item-secondary.list-group-item-action.active { color: var(--body-color); - background-color: #41464c; - border-color: #41464c; + background-color: var(--list-group-item-secondary-color); + border-color: var(--list-group-item-secondary-color); } .list-group-item-success { - color: #294f29; - background-color: #dae6da; + color: var(--list-group-item-success-color); + background-color: var(--list-group-item-success-bg); } .list-group-item-success.list-group-item-action:active, .list-group-item-success.list-group-item-action:focus { - color: #294f29; - background-color: #c4cfc4; + color: var(--list-group-item-success-color); + background-color: var(--list-group-item-success-active-bg); } .list-group-item-success.list-group-item-action.active { color: var(--body-color); - background-color: #294f29; - border-color: #294f29; + background-color: var(--list-group-item-success-color); + border-color: var(--list-group-item-success-color); } .list-group-item-info { - color: #1d3b55; - background-color: #d6e0e8; + color: var(--list-group-item-info-color); + background-color: var(--list-group-item-info-bg); } .list-group-item-info.list-group-item-action:active, .list-group-item-info.list-group-item-action:focus { - color: #1d3b55; - background-color: #c1cad1; + color: var(--list-group-item-info-color); + background-color: var(--list-group-item-info-active-bg); } .list-group-item-info.list-group-item-action.active { color: var(--body-color); - background-color: #1d3b55; - border-color: #1d3b55; + background-color: var(--list-group-item-info-color); + border-color: var(--list-group-item-info-color); } .list-group-item-warning { - color: #683b00; - background-color: #efe0cc; + color: var(--list-group-item-warning-color); + background-color: var(--list-group-item-warning-bg); } .list-group-item-warning.list-group-item-action:active, .list-group-item-warning.list-group-item-action:focus { - color: #683b00; - background-color: #d7cab8; + color: var(--list-group-item-warning-color); + background-color: var(--list-group-item-warning-active-bg); } .list-group-item-warning.list-group-item-action.active { color: var(--body-color); - background-color: #683b00; - border-color: #683b00; + background-color: var(--list-group-item-warning-color); + border-color: var(--list-group-item-warning-color); } .list-group-item-danger { - color: #63130e; - background-color: #edd2d1; + color: var(--list-group-item-danger-color); + background-color: var(--list-group-item-danger-bg); } .list-group-item-danger.list-group-item-action:active, .list-group-item-danger.list-group-item-action:focus { - color: #63130e; - background-color: #d5bdbc; + color: var(--list-group-item-danger-color); + background-color: var(--list-group-item-danger-active-bg); } .list-group-item-danger.list-group-item-action.active { color: var(--body-color); - background-color: #63130e; - border-color: #63130e; + background-color: var(--list-group-item-danger-color); + border-color: var(--list-group-item-danger-color); } .list-group-item-light { - color: #646464; - background-color: #fefefe; + color: var(--list-group-item-light-color); + background-color: var(--list-group-item-light-bg); } .list-group-item-light.list-group-item-action:active, .list-group-item-light.list-group-item-action:focus { - color: #646464; - background-color: #e5e5e5; + color: var(--list-group-item-light-color); + background-color: var(--list-group-item-light-active-bg); } .list-group-item-light.list-group-item-action.active { color: var(--body-color); - background-color: #646464; - border-color: #646464; + background-color: var(--list-group-item-light-color); + border-color: var(--list-group-item-light-color); } .list-group-item-dark { - color: #202327; - background-color: #d7d8d9; + color: var(--list-group-item-dark-color); + background-color: var(--list-group-item-dark-bg); } .list-group-item-dark.list-group-item-action:active, .list-group-item-dark.list-group-item-action:focus { - color: #202327; - background-color: #c2c2c3; + color: var(--list-group-item-dark-color); + background-color: var(--list-group-item-dark-active-bg); } .list-group-item-dark.list-group-item-action.active { color: var(--body-color); - background-color: #202327; - border-color: #202327; + background-color: var(--list-group-item-dark-color); + border-color: var(--list-group-item-dark-color); } .btn-close { @@ -6304,10 +6304,10 @@ fieldset:disabled .btn { --toast-border-width: 1px; --toast-border-color: var(--border-color-translucent); --toast-border-radius: 0.25rem; - --toast-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --toast-box-shadow: 0 0.5rem 1rem var(--shadow-color-light); --toast-header-color: hsl(210, 7%, 46%); - --toast-header-bg: rgba(255, 255, 255, 0.85); - --toast-header-border-color: rgba(0, 0, 0, 0.05); + --toast-header-bg: rgba(var(--white-rgb), 0.85); + --toast-header-border-color: rgba(var(--black-rgb), var(--opacity-5)); width: var(--toast-max-width); max-width: 100%; font-size: var(--toast-font-size); @@ -7258,8 +7258,8 @@ fieldset:disabled .btn { width: 30px; height: 3px; padding: 0; - margin-right: 3px; - margin-left: 3px; + margin-right: 0.1875rem; + margin-left: 0.1875rem; text-indent: -999px; cursor: pointer; background-color: var(--body-color); @@ -8290,75 +8290,75 @@ fieldset:disabled .btn { } .link-primary { - color: hsl(240, 98%, 17%) ; + color: var(--link-primary-color); } .link-primary:active, .link-primary:focus { - color: #010145 ; + color: var(--link-primary-hover-color); } .link-secondary { - color: hsl(210, 7%, 46%) ; + color: var(--link-secondary-color); } .link-secondary:active, .link-secondary:focus { - color: #575e65 ; + color: var(--link-secondary-hover-color); } .link-success { - color: hsl(120, 32%, 39%) ; + color: var(--link-success-color); } .link-success:active, .link-success:focus { - color: #366936 ; + color: var(--link-success-hover-color); } .link-info { - color: hsl(207, 49%, 37%) ; + color: var(--link-info-color); } .link-info:active, .link-info:focus { - color: #264f71 ; + color: var(--link-info-hover-color); } .link-warning { - color: hsl(34, 100%, 34%) ; + color: var(--link-warning-color); } .link-warning:active, .link-warning:focus { - color: #8a4e00 ; + color: var(--link-warning-hover-color); } .link-danger { - color: hsl(3, 75%, 37%) ; + color: var(--link-danger-color); } .link-danger:active, .link-danger:focus { - color: #841913 ; + color: var(--link-danger-hover-color); } .link-light { - color: hsl(210, 17%, 98%) ; + color: var(--link-light-color); } .link-light:active, .link-light:focus { - color: #fafbfc ; + color: var(--link-light-hover-color); } .link-dark { - color: hsl(210, 10%, 23%) ; + color: var(--link-dark-color); } .link-dark:active, .link-dark:focus { - color: #2a2f34 ; + color: var(--link-dark-hover-color); } .ratio { @@ -8531,7 +8531,7 @@ fieldset:disabled .btn { width: 1px ; height: 1px ; padding: 0 ; - margin: -1px ; + margin: -0.0625rem ; overflow: hidden ; clip: rect(0, 0, 0, 0) ; white-space: nowrap ; @@ -14222,7 +14222,7 @@ td .form-control { } .checkboxes { - padding-top: 5px; + padding-top: 0.3125rem; } .checkboxes .checkbox input { @@ -14367,7 +14367,7 @@ fieldset>* { } .container-header nav { - padding: 0; + padding: 0 2rem; } .container-header .site-description { @@ -14598,7 +14598,7 @@ li.current a { .container-header .mod-finder a:active, .container-header .mod-finder a:focus { - color: #e6e6e6; + color: var(--mod-finder-link-hover); } .container-header .mod-finder .awesomplete { @@ -14620,7 +14620,7 @@ li.current a { } .tbody-icon { - padding: 0 3px; + padding: 0 0.1875rem; text-align: center; background-color: transparent; border: 0; @@ -14674,8 +14674,8 @@ li.current a { } .plg_system_webauthn_login_button svg { - -webkit-margin-end: 2px; - margin-inline-end: 2px; + -webkit-margin-end: 0.125rem; + margin-inline-end: 0.125rem; max-height: 25px; width: auto; } @@ -14912,9 +14912,9 @@ iframe { width: 100%; padding: 1vw 2vw; margin-bottom: 1rem; - color: #495057; + color: var(--form-legend-color); background-color: var(--body-color); - border: 1px solid #b2bfcd; + border: 1px solid var(--border-gray); } .options-form>legend { @@ -14922,7 +14922,7 @@ iframe { width: auto; padding: 0 0.5rem; font-weight: 700; - color: #495057; + color: var(--form-legend-color); background-color: var(--body-color); } @@ -14941,7 +14941,7 @@ iframe { } .modal-header { - padding: 0 15px; + padding: 0 0.9375rem; } .modal-title { @@ -14950,11 +14950,11 @@ iframe { } .contentpane { - padding: 15px; + padding: 0.9375rem; } .contentpane .main-card { - margin: -10px; + margin: -0.625rem; -webkit-box-shadow: none; box-shadow: none; } @@ -15093,12 +15093,12 @@ iframe { } .boxed .blog-item .item-content { - padding: 25px; + padding: 1.5625rem; } .blog-item .item-image { - margin-top: 3px; - margin-bottom: 15px; + margin-top: 0.1875rem; + margin-bottom: 0.9375rem; overflow: hidden; max-height: 500px; } @@ -15116,18 +15116,18 @@ iframe { } .image-bottom .blog-item .item-image { - margin-top: -15px; + margin-top: -0.9375rem; -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .image-left .blog-item .item-content { - padding-left: 25px; + padding-left: 1.5625rem; } .image-right .blog-item .item-content { - padding-right: 25px; + padding-right: 1.5625rem; } .image-left .blog-item, @@ -15270,7 +15270,7 @@ ul.tags { .image-alternate.image-left .blog-item:nth-of-type(2n+1) .item-image { margin-right: 0; - margin-left: 25px; + margin-left: 1.5625rem; -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; @@ -15363,7 +15363,7 @@ joomla-alert { } .editor-xtd-buttons .btn { - margin-bottom: 5px; + margin-bottom: 0.3125rem; } .subhead { @@ -15375,10 +15375,10 @@ joomla-alert { width: auto; min-height: 43px; padding: 0.25rem; - color: #495057; + color: var(--subhead-color); background: var(--body-color); - -webkit-box-shadow: -3px -2px 22px #ddd; - box-shadow: -3px -2px 22px #ddd; + -webkit-box-shadow: -3px -2px 22px var(--box-shadow-gray); + box-shadow: -3px -2px 22px var(--box-shadow-gray); } .subhead .row { @@ -15412,12 +15412,12 @@ joomla-alert { } .subhead .btn { - --subhead-btn-accent: #495057; + --subhead-btn-accent: var(--subhead-color); padding: 0 1rem; - margin: 5px 0; + margin: 0.3125rem 0; font-size: 1rem; line-height: 2.45rem; - color: #495057; + color: var(--subhead-color); background: var(--body-color); border-color: hsl(210, 11%, 71%); } @@ -15846,7 +15846,7 @@ body:not(.has-sidebar-right) .site-grid .container-component { .form-select:focus, .custom-select:focus { - border-color: #000; + border-color: var(--black); -webkit-box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); } @@ -15954,7 +15954,7 @@ body:not(.has-sidebar-right) .site-grid .container-component { } .list-unstyled .list-unstyled { - padding-left: 20px; + padding-left: 1.25rem; } .jviewport-height10 { @@ -16119,7 +16119,7 @@ body:not(.has-sidebar-right) .site-grid .container-component { } .nav-tabs+.tab-content { - padding: 15px; + padding: 0.9375rem; background: var(--body-color); border: 1px solid; border-color: hsl(210, 14%, 89%); @@ -16181,7 +16181,7 @@ body:not(.has-sidebar-right) .site-grid .container-component { } .chosen-container.chosen-container-single .chosen-single:focus { - border-color: #8894aa; + border-color: var(--input-focus-border-color); outline: none; } @@ -16217,7 +16217,7 @@ body:not(.has-sidebar-right) .site-grid .container-component { } .chosen-container.chosen-container-multi .chosen-choices li.search-choice { - padding: 5px 33px 5px 10px; + padding: 0.3125rem 2.0625rem 0.3125rem 0.625rem; color: var(--body-color); background: var(--primary); border: 0; @@ -16770,7 +16770,7 @@ body:not(.has-sidebar-right) .site-grid .container-component { .btn.show, .btn:first-child:active, :not(.btn-check)+.btn:active { - color: #A0A0A0; + color: var(--btn-active-text-gray); } .form-control, @@ -17112,7 +17112,7 @@ button#mokoThemeSwitch { } html.component body{ - padding-top: 50px; + padding-top: 3.125rem; } code { @@ -17121,13 +17121,13 @@ code { #view_gabble { background-color: var(--gab-blue); - padding: 6px; + padding: 0.375rem; border-radius: 6px; } #mod_gabble { background-color: var(--gab-blue); - padding: 3px; + padding: 0.1875rem; border-radius: 6px; } @@ -17136,35 +17136,35 @@ code { height: 100%; border: 4px solid var(--gab-red); background-color: var(--gab-green); - padding: 4px; + padding: 0.25rem; border-radius: 6px; } #select_list { - margin-left: 0px; + margin-left: 0; width: 100%; - padding: 4px; + padding: 0.25rem; border-radius: 6px 6px 0px 0px; } #options_list { width: 100%; - padding: 4px; + padding: 0.25rem; } #frame_list { width: 100%; height: 484px; - padding: 4px; + padding: 0.25rem; border-radius: 0px 0px 6px 6px; } #windows_list { - margin-left: 0px; + margin-left: 0; width: 100%; border: 4px solid var(--gab-red); background-color: var(--gab-green); - padding: 4px; + padding: 0.25rem; border-radius: 6px; } @@ -17181,7 +17181,7 @@ code { height: 34px; cursor: pointer; border: 3px solid var(--gab-gray3); - background-color: #FFF; + background-color: var(--white); border-radius: 17px; } @@ -17198,7 +17198,7 @@ code { right: 15px; width: 35px; height: 35px; - padding: 2px; + padding: 0.125rem; z-index: 1; border-radius: 10px; } @@ -17206,16 +17206,16 @@ code { .openai_logo_sm { width: 22px; height: 22px; - background-color: #FFF; - border: 3px solid #FFF; + background-color: var(--white); + border: 3px solid var(--white); border-radius: 11px; } .openai_logo_md { width: 34px; height: 34px; - background-color: #FFF; - border: 4px solid #FFF; + background-color: var(--white); + border: 4px solid var(--white); border-radius: 17px; } @@ -17225,7 +17225,7 @@ code { left: -2px; width: 12px; height: 12px; - background-color: #448344; + background-color: var(--indicator-success-bg); border-radius: 6px; } @@ -17235,7 +17235,7 @@ code { left: 0px; width: 12px; height: 12px; - background-color: #448344; + background-color: var(--indicator-success-bg); border-radius: 6px; } @@ -17244,7 +17244,7 @@ code { width:100%; outline: none; background-color: var(--gab-gray1); - padding: 6px; + padding: 0.375rem; border-radius: 6px; } @@ -17257,22 +17257,22 @@ code { width: 100%; outline: none; cursor: pointer; - color: #FFF; + color: var(--white); background-color: var(--gab-red); - padding: 6px; + padding: 0.375rem; border-radius: 6px; } .window_list { position: relative; - margin: 4px; + margin: 0.25rem; width: 100%; border: none; outline: none; cursor: pointer; text-align: left; background-color: var(--gab-gray1); - padding: 6px; + padding: 0.375rem; border-radius: 6px; } @@ -17282,15 +17282,15 @@ code { .window_list_s { position: relative; - margin: 4px; + margin: 0.25rem; width: 100%; border: none; outline: none; cursor: pointer; text-align: left; - color: #FFF; + color: var(--white); background-color: var(--gab-red); - padding: 6px; + padding: 0.375rem; border-radius: 6px; } @@ -17298,10 +17298,10 @@ code { position: absolute; right: 4px; top: 10px; - padding-left: 1px; + padding-left: 0.0625rem; width: 16px; height: 16px; - color: #000; + color: var(--black); font-size: 10px; text-align: center; background-color: var(--gab-gray2); @@ -17315,7 +17315,7 @@ code { .iframe_list { width: 100%; height: 100%; - background-color: #FFF; + background-color: var(--white); border: 4px solid var(--gab-red); border-radius: 6px; } @@ -17323,7 +17323,7 @@ code { .iframe_messages { width: 100%; height: 100%; - background-color: #FFF; + background-color: var(--white); border: 4px solid var(--gab-red); border-radius: 6px; } @@ -17348,8 +17348,8 @@ code { display: inline-block; float: left; cursor: pointer; - padding: 2px; - background-color: #FFF; + padding: 0.125rem; + background-color: var(--white); } .emoji:hover { @@ -17368,23 +17368,23 @@ code { } .msg-button-on { - margin-left: 5px; + margin-left: 0.3125rem; width: 30px; height: 30px; font-size: 20px; text-align: center; - color: #FFF; + color: var(--white); background-color: var(--gab-orange); border-radius: 15px; } .msg-button-off { - margin-left: 5px; + margin-left: 0.3125rem; width: 30px; height: 30px; font-size: 20px; text-align: center; - color: #FFF; + color: var(--white); background-color: var(--gab-gray2); border-radius: 15px; } @@ -17394,8 +17394,8 @@ code { } .msg-input { - padding-left: 10px; - padding-right: 26px; + padding-left: 0.625rem; + padding-right: 1.625rem; width: calc(100% - 35px); height: 30px; border-radius: 15px; @@ -17403,7 +17403,7 @@ code { .main-windows { position: fixed; - margin-bottom: 10px; + margin-bottom: 0.625rem; bottom: 0px; right: 90px; z-index: 901; @@ -17414,15 +17414,15 @@ code { bottom: 0px; right: 0px; width: 50px; - margin-bottom: 20px; - margin-right: 20px; + margin-bottom: 1.25rem; + margin-right: 1.25rem; z-index: 901; } .item-list { display: inline-block; - color: #F5F5F5; - margin-top: 5px; + color: var(--item-list-color); + margin-top: 0.3125rem; width: 50px; height: 50px; font-size: 30px; @@ -17451,11 +17451,11 @@ code { right: -2px; width: 18px; height: 18px; - color: #FFF; + color: var(--white); font-size: 11px; font-weight: bold; text-align: center; - background-color: #a51f18; + background-color: var(--notification-badge-bg); border-radius: 9px; } @@ -17465,46 +17465,46 @@ code { right: -2px; width: 18px; height: 18px; - color: #FFF; + color: var(--white); font-size: 11px; font-weight: bold; text-align: center; - background-color: #a51f18; + background-color: var(--notification-badge-bg); border-radius: 9px; } .window { display: inline-block; - margin-left: 8px; + margin-left: 0.5rem; width: 280px; height: 420px; } .window-com { - margin-top: 6px; + margin-top: 0.375rem; width: 100%; height: 480px; } .window-title { - margin-left: 5px; + margin-left: 0.3125rem; display: inline-block; - color: #FFF; + color: var(--white); } .window-title-com { - margin-left: 5px; + margin-left: 0.3125rem; display: inline-block; - color: #000; + color: var(--black); } .window-icon { display: inline-block; - color: #FFF; + color: var(--white); } .window-header { - padding: 6px; + padding: 0.375rem; width: 100%; height: 40px; background-color: var(--gab-blue); @@ -17512,7 +17512,7 @@ code { } .window-header-com { - padding: 4px; + padding: 0.25rem; width: 100%; height: 35px; background-color: var(--gab-red); @@ -17524,26 +17524,26 @@ code { display: block; width: 100%; height: calc(100% - 80px); - background-color: #DDD; + background-color: var(--content-bg-gray); } .content-footer { position: relative; - padding: 5px; + padding: 0.3125rem; width: 100%; height: 40px; - background-color: #DDD; + background-color: var(--content-bg-gray); border-radius: 0px 0px 8px 8px; } .taba-btn { text-align: center; display: inline-block; - margin-left: 5px; + margin-left: 0.3125rem; float: right; width: 24px; height: 24px; - background-color: #DDD; + background-color: var(--content-bg-gray); border-radius: 12px; } @@ -17557,49 +17557,49 @@ code { } .taba-self { - border: 1px solid #FFF; - background-color: #7ac143; - padding: 6px; - padding-top: 9px; + border: 1px solid var(--white); + background-color: var(--taba-btn-green); + padding: 0.375rem; + padding-top: 0.5625rem; border-radius: 10px; } .taba-others { - border: 1px solid #FFF; - background-color: #5091cd; - padding: 6px; - padding-top: 9px; + border: 1px solid var(--white); + background-color: var(--taba-btn-blue); + padding: 0.375rem; + padding-top: 0.5625rem; border-radius: 10px; } .taba-bot { - border: 1px solid #FFF; + border: 1px solid var(--white); background-color: var(--gab-gray3); - padding: 6px; - padding-top: 9px; + padding: 0.375rem; + padding-top: 0.5625rem; border-radius: 10px; } .taba-dice { - border: 1px solid #FFF; - background-color: #f44321; - padding: 6px; + border: 1px solid var(--white); + background-color: var(--taba-btn-red); + padding: 0.375rem; border-radius: 10px; } .taba-emoji { - border: 1px solid #FFF; - background-color: #5091cd; - padding: 6px; + border: 1px solid var(--white); + background-color: var(--taba-btn-blue); + padding: 0.375rem; border-radius: 10px; } .taba-user { - border: 1px solid #FFF; - background-color: #FFF; - padding: 6px; + border: 1px solid var(--white); + background-color: var(--white); + padding: 0.375rem; border-radius: 6px; word-wrap: break-word; } @@ -17607,83 +17607,83 @@ code { .taba-user-on { border: 1px solid #FFF; background-color: var(--gab-green); - padding: 6px; + padding: 0.375rem; border-radius: 8px; } .taba-feed { border: 1px solid #FFF; background-color: var(--gab-blue); - padding: 6px; + padding: 0.375rem; border-radius: 8px; } .openai_error { border: 1px solid #FFF; background-color: var(--gab-red); - padding: 6px; + padding: 0.375rem; border-radius: 8px; } .taba-msgsystem { - border: 1px solid #FFF; - background-color: #AAA; - padding: 6px; + border: 1px solid var(--white); + background-color: var(--taba-btn-gray); + padding: 0.375rem; border-radius: 10px; } .taba-msghead { - background-color: #f5f5f5; - padding: 4px; - padding-left: 10px; - padding-right: 6px; + background-color: var(--taba-msg-bg); + padding: 0.25rem; + padding-left: 0.625rem; + padding-right: 0.375rem; border-radius: 6px 6px 0px 0px; } .taba-msg { - background-color: #f5f5f5; - padding: 8px; + background-color: var(--taba-msg-bg); + padding: 0.5rem; border-radius: 0px 8px 8px 8px; word-wrap: break-word; } nav[data-toggle=toc] .nav>li>a{ display:block; - padding:4px 20px; + padding:0.25rem 1.25rem; font-size:13px; font-weight:500; - color:#767676; + color: var(--toc-link-color); } nav[data-toggle=toc] .nav>li>a:focus,nav[data-toggle=toc] .nav>li>a:hover{ - padding-left:19px; - color:#563d7c; + padding-left:1.1875rem; + color: var(--toc-link-active-color); text-decoration:none; background-color:transparent; - border-left:1px solid #563d7c; + border-left:1px solid var(--toc-link-active-color); } nav[data-toggle=toc] .nav-link.active,nav[data-toggle=toc] .nav-link.active:focus,nav[data-toggle=toc] .nav-link.active:hover{ - padding-left:18px; + padding-left:1.125rem; font-weight:700; - color:#563d7c; + color: var(--toc-link-active-color); background-color:transparent; - border-left:2px solid #563d7c; + border-left:2px solid var(--toc-link-active-color); } nav[data-toggle=toc] .nav-link+ul{ display:none; - padding-bottom:10px; + padding-bottom:0.625rem; } nav[data-toggle=toc] .nav .nav>li>a{ - padding-top:1px; - padding-bottom:1px; - padding-left:30px; + padding-top:0.0625rem; + padding-bottom:0.0625rem; + padding-left:1.875rem; font-size:12px; font-weight:400; } nav[data-toggle=toc] .nav .nav>li>a:focus,nav[data-toggle=toc] .nav .nav>li>a:hover{ - padding-left:29px; + padding-left:1.8125rem; } nav[data-toggle=toc] .nav .nav>li>.active,nav[data-toggle=toc] .nav .nav>li>.active:focus,nav[data-toggle=toc] .nav .nav>li>.active:hover{ - padding-left:28px; + padding-left:1.75rem; font-weight:500; } nav[data-toggle=toc] .nav-link.active+ul{ @@ -17697,7 +17697,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ .choices { position: relative; overflow: hidden; - margin-bottom: 24px; + margin-bottom: 1.5rem; font-size: 16px; } .choices:focus { @@ -17711,7 +17711,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ } .choices.is-disabled .choices__inner, .choices.is-disabled .choices__input { - background-color: #eaeaea; + background-color: var(--choices-disabled-bg); cursor: not-allowed; -webkit-user-select: none; -moz-user-select: none; @@ -17729,14 +17729,14 @@ nav[data-toggle=toc] .nav-link.active+ul{ cursor: pointer; } .choices[data-type*=select-one] .choices__inner { - padding-bottom: 7.5px; + padding-bottom: 0.46875rem; } .choices[data-type*=select-one] .choices__input { display: block; width: 100%; - padding: 10px; - border-bottom: 1px solid #ddd; - background-color: #fff; + padding: 0.625rem; + border-bottom: 1px solid var(--choices-border-light); + background-color: var(--choices-input-bg); margin: 0; } .choices[data-type*=select-one] .choices__button { @@ -17746,8 +17746,8 @@ nav[data-toggle=toc] .nav-link.active+ul{ position: absolute; top: 50%; right: 0; - margin-top: -10px; - margin-right: 25px; + margin-top: -0.625rem; + margin-right: 1.5625rem; height: 20px; width: 20px; border-radius: 10em; @@ -17768,17 +17768,17 @@ nav[data-toggle=toc] .nav-link.active+ul{ height: 0; width: 0; border-style: solid; - border-color: #333 transparent transparent transparent; + border-color: var(--choices-arrow-color) transparent transparent transparent; border-width: 5px; position: absolute; right: 11.5px; top: 50%; - margin-top: -2.5px; + margin-top: -0.15625rem; pointer-events: none; } .choices[data-type*=select-one].is-open::after { - border-color: transparent transparent #333 transparent; - margin-top: -7.5px; + border-color: transparent transparent var(--choices-arrow-color) transparent; + margin-top: -0.46875rem; } .choices[data-type*=select-one][dir=rtl]::after { left: 11.5px; @@ -17787,7 +17787,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ .choices[data-type*=select-one][dir=rtl] .choices__button { right: auto; left: 0; - margin-left: 25px; + margin-left: 1.5625rem; margin-right: 0; } @@ -17800,10 +17800,10 @@ nav[data-toggle=toc] .nav-link.active+ul{ position: relative; display: inline-block; margin-top: 0; - margin-right: -4px; + margin-right: -0.25rem; margin-bottom: 0; - margin-left: 8px; - padding-left: 16px; + margin-left: 0.5rem; + padding-left: 1rem; border-left: 1px solid #008fa1; background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg=="); background-size: 8px; @@ -17822,16 +17822,16 @@ nav[data-toggle=toc] .nav-link.active+ul{ display: inline-block; vertical-align: top; width: 100%; - background-color: #f9f9f9; - padding: 7.5px 7.5px 3.75px; - border: 1px solid #ddd; + background-color: var(--choices-inner-bg); + padding: 0.46875rem 0.46875rem 0.234375rem; + border: 1px solid var(--choices-border-light); border-radius: 2.5px; font-size: 14px; min-height: 44px; overflow: hidden; } .is-focused .choices__inner, .is-open .choices__inner { - border-color: #b7b7b7; + border-color: var(--choices-focused-border); } .is-open .choices__inner { border-radius: 2.5px 2.5px 0 0; @@ -17848,12 +17848,12 @@ nav[data-toggle=toc] .nav-link.active+ul{ .choices__list--single { display: inline-block; - padding: 4px 16px 4px 4px; + padding: 0.25rem 1rem 0.25rem 0.25rem; width: 100%; } [dir=rtl] .choices__list--single { - padding-right: 4px; - padding-left: 16px; + padding-right: 0.25rem; + padding-left: 1rem; } .choices__list--single .choices__item { width: 100%; @@ -17866,32 +17866,32 @@ nav[data-toggle=toc] .nav-link.active+ul{ display: inline-block; vertical-align: middle; border-radius: 20px; - padding: 4px 10px; + padding: 0.25rem 0.625rem; font-size: 12px; font-weight: 500; - margin-right: 3.75px; - margin-bottom: 3.75px; - background-color: #00bcd4; - border: 1px solid #00a5bb; - color: #fff; + margin-right: 0.234375rem; + margin-bottom: 0.234375rem; + background-color: var(--choices-item-bg); + border: 1px solid var(--choices-item-border); + color: var(--white); word-break: break-all; -webkit-box-sizing: border-box; box-sizing: border-box; } .choices__list--multiple .choices__item[data-deletable] { - padding-right: 5px; + padding-right: 0.3125rem; } [dir=rtl] .choices__list--multiple .choices__item { margin-right: 0; - margin-left: 3.75px; + margin-left: 0.234375rem; } .choices__list--multiple .choices__item.is-highlighted { - background-color: #00a5bb; - border: 1px solid #008fa1; + background-color: var(--choices-item-hover-bg); + border: 1px solid var(--choices-item-hover-border); } .is-disabled .choices__list--multiple .choices__item { - background-color: #aaaaaa; - border: 1px solid #919191; + background-color: var(--choices-item-disabled-bg); + border: 1px solid var(--choices-item-disabled-border); } .choices__list--dropdown { @@ -17899,10 +17899,10 @@ nav[data-toggle=toc] .nav-link.active+ul{ z-index: 1; position: absolute; width: 100%; - background-color: #fff; - border: 1px solid #ddd; + background-color: var(--choices-dropdown-bg); + border: 1px solid var(--choices-border-light); top: 100%; - margin-top: -1px; + margin-top: -0.0625rem; border-bottom-left-radius: 2.5px; border-bottom-right-radius: 2.5px; overflow: hidden; @@ -17913,13 +17913,13 @@ nav[data-toggle=toc] .nav-link.active+ul{ visibility: visible; } .is-open .choices__list--dropdown { - border-color: #b7b7b7; + border-color: var(--choices-focused-border); } .is-flipped .choices__list--dropdown { top: auto; bottom: 100%; margin-top: 0; - margin-bottom: -1px; + margin-bottom: -0.0625rem; border-radius: 0.25rem 0.25rem 0 0; } .choices__list--dropdown .choices__list { @@ -17931,7 +17931,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ } .choices__list--dropdown .choices__item { position: relative; - padding: 10px; + padding: 0.625rem; font-size: 14px; } [dir=rtl] .choices__list--dropdown .choices__item { @@ -17939,7 +17939,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ } @media (min-width: 640px) { .choices__list--dropdown .choices__item--selectable { - padding-right: 100px; + padding-right: 6.25rem; } .choices__list--dropdown .choices__item--selectable::after { content: attr(data-select-text); @@ -17953,8 +17953,8 @@ nav[data-toggle=toc] .nav-link.active+ul{ } [dir=rtl] .choices__list--dropdown .choices__item--selectable { text-align: right; - padding-left: 100px; - padding-right: 10px; + padding-left: 6.25rem; + padding-right: 0.625rem; } [dir=rtl] .choices__list--dropdown .choices__item--selectable::after { right: auto; @@ -17962,7 +17962,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ } } .choices__list--dropdown .choices__item--selectable.is-highlighted { - background-color: #f2f2f2; + background-color: var(--choices-item-highlighted); } .choices__list--dropdown .choices__item--selectable.is-highlighted::after { opacity: 0.5; @@ -17988,7 +17988,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ .choices__heading { font-weight: 600; font-size: 12px; - padding: 10px; + padding: 0.625rem; border-bottom: 1px solid #f7f7f7; color: gray; } @@ -18011,19 +18011,19 @@ nav[data-toggle=toc] .nav-link.active+ul{ .choices__input { display: inline-block; vertical-align: baseline; - background-color: #f9f9f9; + background-color: var(--choices-input-inner-bg); font-size: 14px; - margin-bottom: 5px; + margin-bottom: 0.3125rem; border: 0; border-radius: 0; max-width: 100%; - padding: 4px 0 4px 2px; + padding: 0.25rem 0 0.25rem 0.125rem; } .choices__input:focus { outline: 0; } [dir=rtl] .choices__input { - padding-right: 2px; + padding-right: 0.125rem; padding-left: 0; } @@ -18037,7 +18037,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ border-radius: 0.25rem; } .choices.is-focused { - border-color: #8894aa; + border-color: var(--input-focus-border-color); -webkit-box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); box-shadow: 0 0 0 0.25rem rgba(1, 1, 86, 0.25); } @@ -18083,10 +18083,10 @@ nav[data-toggle=toc] .nav-link.active+ul{ .choices__list--multiple .choices__item { position: relative; - margin: 2px; + margin: 0.125rem; background-color: var(--color-primary); - -webkit-margin-end: 2px; - margin-inline-end: 2px; + -webkit-margin-end: 0.125rem; + margin-inline-end: 0.125rem; border: 0; border-radius: 0.25rem; } @@ -18096,8 +18096,8 @@ nav[data-toggle=toc] .nav-link.active+ul{ } .choices .choices__list--dropdown .choices__item { - -webkit-padding-end: 10px; - padding-inline-end: 10px; + -webkit-padding-end: 0.625rem; + padding-inline-end: 0.625rem; } .choices .choices__list--dropdown .choices__item--selectable::after { display: none; @@ -18105,7 +18105,7 @@ nav[data-toggle=toc] .nav-link.active+ul{ .choices__button_joomla { position: relative; - padding: 0 10px; + padding: 0 0.625rem; color: inherit; text-indent: -9999px; cursor: pointer; @@ -18163,10 +18163,10 @@ nav[data-toggle=toc] .nav-link.active+ul{ width: 20px; height: 20px; padding: 0; - -webkit-margin-before: -10px; - margin-block-start: -10px; - -webkit-margin-end: 50px; - margin-inline-end: 50px; + -webkit-margin-before: -0.625rem; + margin-block-start: -0.625rem; + -webkit-margin-end: 3.125rem; + margin-inline-end: 3.125rem; border-radius: 10em; opacity: 0.5; } @@ -19362,6 +19362,177 @@ nav[data-toggle=toc] .nav-link.active+ul{ font-weight: 600; } +/* === Main Menu - Collapsible Dropdown Bootstrap Responsive === */ +.mod-menu-main { + background-color: var(--body-bg); + padding: 0.5rem 0; +} + +.mod-menu-main .navbar-toggler { + border-color: var(--border-color); + padding: 0.5rem 0.75rem; + font-size: 1.25rem; + min-height: 48px; /* WCAG 2.1 touch target */ +} + +.mod-menu-main .navbar-toggler:focus { + box-shadow: 0 0 0 0.25rem rgba(var(--link-color-rgb), 0.25); + outline: 0; +} + +.mod-menu-main .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.75)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} + +.mod-menu-main__list { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.mod-menu-main__item { + position: relative; +} + +.mod-menu-main__link, +.mod-menu-main__heading { + display: block; + padding: 0.75rem 1rem; + color: var(--link-color); + text-decoration: none; + transition: background-color 0.2s ease, color 0.2s ease; + min-height: 48px; /* WCAG 2.1 touch target on mobile */ + display: flex; + align-items: center; + border-radius: var(--border-radius); +} + +.mod-menu-main__link:hover, +.mod-menu-main__link:focus { + background-color: var(--secondary-bg); + color: var(--link-hover-color); + text-decoration: none; +} + +.mod-menu-main__item.active > .mod-menu-main__link, +.mod-menu-main__item.current > .mod-menu-main__link { + background-color: var(--primary-bg); + color: var(--white); + font-weight: 600; +} + +/* Dropdown menu styles */ +.mod-menu-main__dropdown { + list-style: none; + padding: 0.5rem 0; + margin: 0; + background-color: var(--body-bg); + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + display: none; +} + +.mod-menu-main__item.dropdown.show > .mod-menu-main__dropdown { + display: block; +} + +.mod-menu-main__dropdown .mod-menu-main__item { + padding: 0; +} + +.mod-menu-main__dropdown .mod-menu-main__link { + padding: 0.5rem 1.5rem; + min-height: 44px; /* Slightly smaller for nested items */ +} + +.mod-menu-main__dropdown .mod-menu-main__link:hover, +.mod-menu-main__dropdown .mod-menu-main__link:focus { + background-color: var(--secondary-bg); +} + +.mod-menu-main__separator { + border-top: 1px solid var(--border-color); + margin: 0.5rem 0; + padding: 0; +} + +/* Dropdown toggle arrow */ +.mod-menu-main__link.dropdown-toggle::after, +.mod-menu-main__heading.dropdown-toggle::after { + content: ""; + display: inline-block; + margin-left: auto; + padding-left: 0.5rem; + vertical-align: middle; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} + +/* Desktop styles (≥768px) */ +@media (min-width: 768px) { + .mod-menu-main__list { + flex-direction: row; + flex-wrap: wrap; + gap: 0; + } + + .mod-menu-main__link, + .mod-menu-main__heading { + min-height: 44px; /* WCAG 2.1 touch target on desktop */ + padding: 0.5rem 1rem; + } + + .mod-menu-main__item.dropdown { + position: relative; + } + + .mod-menu-main__dropdown { + position: absolute; + top: 100%; + left: 0; + min-width: 200px; + z-index: 1000; + margin-top: 0.125rem; + } + + /* Hover dropdown on desktop */ + .mod-menu-main__item.dropdown:hover > .mod-menu-main__dropdown { + display: block; + } + + /* Nested dropdowns */ + .mod-menu-main__dropdown .mod-menu-main__dropdown { + top: 0; + left: 100%; + margin-top: 0; + margin-left: 0.125rem; + } +} + +/* Large desktop styles (≥992px) */ +@media (min-width: 992px) { + .mod-menu-main { + padding: 1rem 0; + } + + .mod-menu-main__list { + gap: 0.25rem; + } +} + /* === mod_breadcrumbs === */ .mod-breadcrumbs-responsive { width: 100%; @@ -21682,3 +21853,997 @@ height: 120px; padding: 1.5rem; } } + +/* + JEM (JOOMLA EVENT MANAGER) COMPONENT STYLES + Mobile-responsive overrides for JEM event management component + Includes: Events List, Event Details, Calendar, Venue, Categories +*/ + +/* =========================== + JEM Events List Styles + =========================== */ + +.jem-eventslist-responsive { +width: 100%; +max-width: 100%; +} + +.jem-eventslist__container { +padding: 1rem; +} + +.jem-eventslist__header { +margin-bottom: 1.5rem; +} + +.jem-eventslist__title { +font-size: 1.75rem; +font-weight: 700; +margin: 0; +color: var(--body-color); +} + +.jem-eventslist__list { +display: flex; +flex-direction: column; +gap: 1.5rem; +} + +.jem-eventslist__item { +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +overflow: hidden; +transition: box-shadow 0.3s ease; +} + +.jem-eventslist__item:hover { +box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +.jem-eventslist__item-inner { +padding: 1.25rem; +} + +.jem-eventslist__date { +font-size: 0.875rem; +color: var(--secondary-color, #6c757d); +margin-bottom: 0.5rem; +display: flex; +align-items: center; +flex-wrap: wrap; +gap: 0.25rem; +} + +.jem-eventslist__datetime { +font-weight: 500; +} + +.jem-eventslist__date-separator { +margin: 0 0.25rem; +} + +.jem-eventslist__event-title { +font-size: 1.25rem; +font-weight: 600; +margin: 0.5rem 0; +} + +.jem-eventslist__link { +color: var(--link-color); +text-decoration: none; +transition: color 0.2s ease; +} + +.jem-eventslist__link:hover { +color: var(--link-hover-color); +text-decoration: underline; +} + +.jem-eventslist__venue { +display: flex; +align-items: center; +gap: 0.5rem; +margin: 0.75rem 0; +font-size: 0.9375rem; +color: var(--body-color); +} + +.jem-eventslist__venue-icon { +font-size: 1rem; +} + +.jem-eventslist__venue-link { +color: var(--link-color); +text-decoration: none; +} + +.jem-eventslist__venue-link:hover { +text-decoration: underline; +} + +.jem-eventslist__description { +margin: 1rem 0; +color: var(--body-color); +line-height: 1.6; +} + +.jem-eventslist__categories { +display: flex; +flex-wrap: wrap; +gap: 0.5rem; +margin: 1rem 0; +} + +.jem-eventslist__category-badge { +display: inline-block; +padding: 0.25rem 0.75rem; +background: var(--primary-color, #007bff); +color: var(--white); +border-radius: 1rem; +font-size: 0.8125rem; +font-weight: 500; +} + +.jem-eventslist__actions { +margin-top: 1rem; +} + +.jem-eventslist__button { +display: inline-block; +padding: 0.625rem 1.25rem; +min-height: 44px; +background: var(--btn-primary-bg, #007bff); +color: var(--white); +border: none; +border-radius: var(--border-radius, 0.375rem); +text-decoration: none; +font-weight: 500; +text-align: center; +transition: background-color 0.2s ease; +cursor: pointer; +} + +.jem-eventslist__button:hover { +background: var(--btn-primary-hover-bg, #0056b3); +color: var(--white); +text-decoration: none; +} + +.jem-eventslist__pagination { +margin-top: 2rem; +text-align: center; +} + +.jem-eventslist__empty { +padding: 3rem 1rem; +text-align: center; +} + +.jem-eventslist__empty-message { +font-size: 1.125rem; +color: var(--secondary-color, #6c757d); +} + +/* =========================== + JEM Event Details Styles + =========================== */ + +.jem-event-responsive { +width: 100%; +max-width: 100%; +} + +.jem-event__container { +padding: 1rem; +} + +.jem-event__header { +margin-bottom: 1.5rem; +} + +.jem-event__title { +font-size: 2rem; +font-weight: 700; +margin: 0; +color: var(--body-color); +} + +.jem-event__image-wrapper { +margin: 1.5rem 0; +border-radius: var(--border-radius, 0.375rem); +overflow: hidden; +} + +.jem-event__image { +width: 100%; +height: auto; +display: block; +} + +.jem-event__meta { +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +padding: 1.5rem; +margin: 1.5rem 0; +} + +.jem-event__meta-item { +display: flex; +align-items: flex-start; +gap: 0.75rem; +margin-bottom: 1rem; +} + +.jem-event__meta-item:last-child { +margin-bottom: 0; +} + +.jem-event__meta-icon { +font-size: 1.25rem; +flex-shrink: 0; +margin-top: 0.125rem; +} + +.jem-event__meta-content { +flex: 1; +} + +.jem-event__meta-label { +display: block; +margin-bottom: 0.25rem; +color: var(--body-color); +} + +.jem-event__datetime, +.jem-event__time-value, +.jem-event__venue-name { +color: var(--body-color); +} + +.jem-event__venue-link { +color: var(--link-color); +text-decoration: none; +font-weight: 500; +} + +.jem-event__venue-link:hover { +color: var(--link-hover-color); +text-decoration: underline; +} + +.jem-event__address { +margin-top: 0.5rem; +font-size: 0.9375rem; +color: var(--secondary-color, #6c757d); +} + +.jem-event__street, +.jem-event__city { +display: block; +} + +.jem-event__category-list { +display: flex; +flex-wrap: wrap; +gap: 0.5rem; +margin-top: 0.5rem; +} + +.jem-event__category-badge { +display: inline-block; +padding: 0.25rem 0.75rem; +background: var(--primary-color, #007bff); +color: var(--white); +border-radius: 1rem; +font-size: 0.8125rem; +font-weight: 500; +} + +.jem-event__description { +margin: 2rem 0; +} + +.jem-event__description-title { +font-size: 1.5rem; +font-weight: 600; +margin-bottom: 1rem; +color: var(--body-color); +} + +.jem-event__description-content { +line-height: 1.8; +color: var(--body-color); +} + +.jem-event__registration, +.jem-event__contact { +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +padding: 1.5rem; +margin: 1.5rem 0; +} + +.jem-event__registration-title, +.jem-event__contact-title { +font-size: 1.25rem; +font-weight: 600; +margin-bottom: 1rem; +color: var(--body-color); +} + +.jem-event__contact-link { +color: var(--link-color); +text-decoration: none; +} + +.jem-event__contact-link:hover { +text-decoration: underline; +} + +.jem-event__actions { +margin-top: 2rem; +} + +.jem-event__button { +display: inline-block; +padding: 0.625rem 1.25rem; +min-height: 44px; +background: var(--btn-secondary-bg, #6c757d); +color: var(--white); +border: none; +border-radius: var(--border-radius, 0.375rem); +text-decoration: none; +font-weight: 500; +text-align: center; +transition: background-color 0.2s ease; +cursor: pointer; +} + +.jem-event__button:hover { +background: var(--btn-secondary-hover-bg, #5a6268); +color: var(--white); +text-decoration: none; +} + +/* =========================== + JEM Calendar Styles + =========================== */ + +.jem-calendar-responsive { +width: 100%; +max-width: 100%; +} + +.jem-calendar__container { +padding: 1rem; +} + +.jem-calendar__header { +margin-bottom: 1.5rem; +} + +.jem-calendar__title { +font-size: 1.75rem; +font-weight: 700; +margin: 0; +color: var(--body-color); +} + +.jem-calendar__navigation { +display: flex; +justify-content: space-between; +align-items: center; +margin-bottom: 1.5rem; +padding: 1rem; +background: var(--secondary-bg, #f8f9fa); +border-radius: var(--border-radius, 0.375rem); +} + +.jem-calendar__nav-button { +display: flex; +align-items: center; +justify-content: center; +width: 44px; +height: 44px; +background: var(--btn-primary-bg, #007bff); +color: var(--white); +border: none; +border-radius: 50%; +text-decoration: none; +font-size: 1.5rem; +transition: background-color 0.2s ease; +} + +.jem-calendar__nav-button:hover { +background: var(--btn-primary-hover-bg, #0056b3); +color: var(--white); +} + +.jem-calendar__current-month { +font-size: 1.25rem; +font-weight: 600; +margin: 0; +color: var(--body-color); +} + +.jem-calendar__grid { +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +padding: 1rem; +margin-bottom: 2rem; +} + +.jem-calendar__weekdays { +display: grid; +grid-template-columns: repeat(7, 1fr); +gap: 0.5rem; +margin-bottom: 0.5rem; +} + +.jem-calendar__weekday { +text-align: center; +font-weight: 600; +font-size: 0.875rem; +color: var(--body-color); +padding: 0.5rem 0; +} + +.jem-calendar__days { +display: grid; +grid-template-columns: repeat(7, 1fr); +gap: 0.5rem; +} + +.jem-calendar__day { +aspect-ratio: 1; +display: flex; +flex-direction: column; +align-items: center; +justify-content: center; +padding: 0.5rem; +background: var(--white); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +cursor: pointer; +transition: background-color 0.2s ease; +} + +.jem-calendar__day:hover { +background: var(--hover-bg, #e9ecef); +} + +.jem-calendar__day--empty { +background: transparent; +border: none; +cursor: default; +} + +.jem-calendar__day--has-events { +background: var(--primary-light, #cfe2ff); +border-color: var(--primary-color, #007bff); +} + +.jem-calendar__day--today { +border: 2px solid var(--primary-color, #007bff); +font-weight: 700; +} + +.jem-calendar__day-number { +font-size: 0.9375rem; +color: var(--body-color); +} + +.jem-calendar__event-indicator { +display: inline-flex; +align-items: center; +justify-content: center; +min-width: 1.25rem; +height: 1.25rem; +background: var(--primary-color, #007bff); +color: var(--white); +border-radius: 50%; +font-size: 0.6875rem; +font-weight: 600; +margin-top: 0.25rem; +} + +.jem-calendar__events-list { +margin-top: 2rem; +} + +.jem-calendar__events-title { +font-size: 1.5rem; +font-weight: 600; +margin-bottom: 1rem; +color: var(--body-color); +} + +.jem-calendar__events { +display: flex; +flex-direction: column; +gap: 1rem; +} + +.jem-calendar__event-item { +padding: 1rem; +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +} + +.jem-calendar__event-date { +font-size: 0.875rem; +color: var(--secondary-color, #6c757d); +margin-bottom: 0.5rem; +} + +.jem-calendar__event-title { +font-size: 1.125rem; +font-weight: 600; +margin: 0.5rem 0; +} + +.jem-calendar__event-link { +color: var(--link-color); +text-decoration: none; +} + +.jem-calendar__event-link:hover { +color: var(--link-hover-color); +text-decoration: underline; +} + +.jem-calendar__event-venue { +font-size: 0.9375rem; +color: var(--body-color); +margin-top: 0.5rem; +} + +/* =========================== + JEM Venue Styles + =========================== */ + +.jem-venue-responsive { +width: 100%; +max-width: 100%; +} + +.jem-venue__container { +padding: 1rem; +} + +.jem-venue__header { +margin-bottom: 1.5rem; +} + +.jem-venue__title { +font-size: 2rem; +font-weight: 700; +margin: 0; +color: var(--body-color); +} + +.jem-venue__image-wrapper { +margin: 1.5rem 0; +border-radius: var(--border-radius, 0.375rem); +overflow: hidden; +} + +.jem-venue__image { +width: 100%; +height: auto; +display: block; +} + +.jem-venue__info { +margin: 2rem 0; +} + +.jem-venue__info-item { +display: flex; +align-items: flex-start; +gap: 0.75rem; +margin-bottom: 1.5rem; +padding: 1.25rem; +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +} + +.jem-venue__info-item:last-child { +margin-bottom: 0; +} + +.jem-venue__info-icon { +font-size: 1.25rem; +flex-shrink: 0; +margin-top: 0.125rem; +} + +.jem-venue__info-content { +flex: 1; +} + +.jem-venue__info-label { +display: block; +margin-bottom: 0.5rem; +color: var(--body-color); +} + +.jem-venue__address-content { +font-style: normal; +color: var(--body-color); +} + +.jem-venue__street, +.jem-venue__city-line, +.jem-venue__state, +.jem-venue__country { +display: block; +margin-bottom: 0.25rem; +} + +.jem-venue__link { +color: var(--link-color); +text-decoration: none; +word-break: break-all; +} + +.jem-venue__link:hover { +text-decoration: underline; +} + +.jem-venue__description { +margin: 2rem 0; +} + +.jem-venue__description-title { +font-size: 1.5rem; +font-weight: 600; +margin-bottom: 1rem; +color: var(--body-color); +} + +.jem-venue__description-content { +line-height: 1.8; +color: var(--body-color); +} + +.jem-venue__map { +margin: 2rem 0; +} + +.jem-venue__map-title { +font-size: 1.5rem; +font-weight: 600; +margin-bottom: 1rem; +color: var(--body-color); +} + +.jem-venue__map-container { +border-radius: var(--border-radius, 0.375rem); +overflow: hidden; +} + +.jem-venue__map-placeholder { +padding: 3rem 1rem; +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +text-align: center; +} + +.jem-venue__map-link { +display: inline-block; +padding: 0.625rem 1.25rem; +min-height: 44px; +background: var(--btn-primary-bg, #007bff); +color: var(--white); +border: none; +border-radius: var(--border-radius, 0.375rem); +text-decoration: none; +font-weight: 500; +margin-top: 1rem; +transition: background-color 0.2s ease; +} + +.jem-venue__map-link:hover { +background: var(--btn-primary-hover-bg, #0056b3); +color: var(--white); +text-decoration: none; +} + +.jem-venue__events { +margin: 2rem 0; +} + +.jem-venue__events-title { +font-size: 1.5rem; +font-weight: 600; +margin-bottom: 1rem; +color: var(--body-color); +} + +.jem-venue__events-list { +display: flex; +flex-direction: column; +gap: 1rem; +} + +.jem-venue__event-item { +padding: 1rem; +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +} + +.jem-venue__event-date { +font-size: 0.875rem; +color: var(--secondary-color, #6c757d); +margin-bottom: 0.5rem; +} + +.jem-venue__event-title { +font-size: 1.125rem; +font-weight: 600; +margin: 0.5rem 0; +} + +.jem-venue__event-link { +color: var(--link-color); +text-decoration: none; +} + +.jem-venue__event-link:hover { +color: var(--link-hover-color); +text-decoration: underline; +} + +.jem-venue__actions { +margin-top: 2rem; +} + +.jem-venue__button { +display: inline-block; +padding: 0.625rem 1.25rem; +min-height: 44px; +background: var(--btn-secondary-bg, #6c757d); +color: var(--white); +border: none; +border-radius: var(--border-radius, 0.375rem); +text-decoration: none; +font-weight: 500; +text-align: center; +transition: background-color 0.2s ease; +cursor: pointer; +} + +.jem-venue__button:hover { +background: var(--btn-secondary-hover-bg, #5a6268); +color: var(--white); +text-decoration: none; +} + +/* =========================== + JEM Categories Styles + =========================== */ + +.jem-categories-responsive { +width: 100%; +max-width: 100%; +} + +.jem-categories__container { +padding: 1rem; +} + +.jem-categories__header { +margin-bottom: 1.5rem; +} + +.jem-categories__title { +font-size: 1.75rem; +font-weight: 700; +margin: 0; +color: var(--body-color); +} + +.jem-categories__list { +display: flex; +flex-direction: column; +gap: 1.5rem; +} + +.jem-categories__item { +background: var(--secondary-bg, #f8f9fa); +border: 1px solid var(--border-color, #dee2e6); +border-radius: var(--border-radius, 0.375rem); +overflow: hidden; +transition: box-shadow 0.3s ease; +} + +.jem-categories__item:hover { +box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +.jem-categories__item-inner { +padding: 1.25rem; +} + +.jem-categories__image-wrapper { +margin-bottom: 1rem; +border-radius: var(--border-radius, 0.375rem); +overflow: hidden; +} + +.jem-categories__image { +width: 100%; +height: auto; +display: block; +} + +.jem-categories__category-title { +font-size: 1.25rem; +font-weight: 600; +margin: 0.5rem 0; +} + +.jem-categories__link { +color: var(--link-color); +text-decoration: none; +transition: color 0.2s ease; +} + +.jem-categories__link:hover { +color: var(--link-hover-color); +text-decoration: underline; +} + +.jem-categories__description { +margin: 1rem 0; +color: var(--body-color); +line-height: 1.6; +} + +.jem-categories__meta { +margin: 0.75rem 0; +font-size: 0.875rem; +color: var(--secondary-color, #6c757d); +} + +.jem-categories__event-count { +font-weight: 500; +} + +.jem-categories__actions { +margin-top: 1rem; +} + +.jem-categories__button { +display: inline-block; +padding: 0.625rem 1.25rem; +min-height: 44px; +background: var(--btn-primary-bg, #007bff); +color: var(--white); +border: none; +border-radius: var(--border-radius, 0.375rem); +text-decoration: none; +font-weight: 500; +text-align: center; +transition: background-color 0.2s ease; +cursor: pointer; +} + +.jem-categories__button:hover { +background: var(--btn-primary-hover-bg, #0056b3); +color: var(--white); +text-decoration: none; +} + +.jem-categories__pagination { +margin-top: 2rem; +text-align: center; +} + +.jem-categories__empty { +padding: 3rem 1rem; +text-align: center; +} + +.jem-categories__empty-message { +font-size: 1.125rem; +color: var(--secondary-color, #6c757d); +} + +/* =========================== + JEM Responsive Styles + =========================== */ + +@media (min-width: 768px) { +.jem-eventslist__list, +.jem-categories__list { +display: grid; +grid-template-columns: repeat(2, 1fr); +gap: 1.5rem; +} + +.jem-calendar__day-number { +font-size: 1rem; +} + +.jem-event__meta { +padding: 2rem; +} + +.jem-venue__info-item { +padding: 1.5rem; +} +} + +@media (min-width: 992px) { +.jem-eventslist__container, +.jem-event__container, +.jem-calendar__container, +.jem-venue__container, +.jem-categories__container { +padding: 2rem; +} + +.jem-eventslist__title, +.jem-calendar__title, +.jem-categories__title { +font-size: 2rem; +} + +.jem-event__title, +.jem-venue__title { +font-size: 2.5rem; +} + +.jem-calendar__grid { +padding: 1.5rem; +} +} + +@media (max-width: 575.98px) { +.jem-eventslist__button, +.jem-event__button, +.jem-calendar__nav-button, +.jem-venue__button, +.jem-venue__map-link, +.jem-categories__button { +min-height: 48px; +} + +.jem-eventslist__item-inner, +.jem-event__meta, +.jem-venue__info-item, +.jem-categories__item-inner { +padding: 1rem; +} + +.jem-calendar__navigation { +padding: 0.75rem; +} + +.jem-calendar__current-month { +font-size: 1rem; +} + +.jem-calendar__weekday { +font-size: 0.75rem; +padding: 0.25rem 0; +} + +.jem-calendar__day { +padding: 0.25rem; +} + +.jem-calendar__day-number { +font-size: 0.8125rem; +} +} diff --git a/src/media/css/colors/dark/colors_standard.css b/src/media/css/theme/dark.standard.css similarity index 58% rename from src/media/css/colors/dark/colors_standard.css rename to src/media/css/theme/dark.standard.css index 0ce1e0f..f9e03e6 100644 --- a/src/media/css/colors/dark/colors_standard.css +++ b/src/media/css/theme/dark.standard.css @@ -167,6 +167,94 @@ color-scheme: dark; --light-border-subtle: #222831; --dark-border-subtle: #2b323b; +/* ===== ALERT LINK COLORS ===== */ +--alert-primary-link-color: #b3c1ff; +--alert-secondary-link-color: #9fa6ad; +--alert-success-link-color: #a0e5b3; +--alert-info-link-color: #8eccf2; +--alert-warning-link-color: #ffe4a0; +--alert-danger-link-color: #ffa8a3; +--alert-light-link-color: #f0f4f8; +--alert-dark-link-color: #9fa6ad; + +/* ===== LIST GROUP ITEM COLORS ===== */ +--list-group-item-primary-color: #8ca3ff; +--list-group-item-primary-bg: #1a2550; +--list-group-item-primary-active-bg: #223066; +--list-group-item-secondary-color: #9fa6ad; +--list-group-item-secondary-bg: #2b323b; +--list-group-item-secondary-active-bg: #363d47; +--list-group-item-success-color: #a0e5b3; +--list-group-item-success-bg: #1e3d2d; +--list-group-item-success-active-bg: #275538; +--list-group-item-info-color: #8eccf2; +--list-group-item-info-bg: #1a3448; +--list-group-item-info-active-bg: #234459; +--list-group-item-warning-color: #ffe4a0; +--list-group-item-warning-bg: #4a3410; +--list-group-item-warning-active-bg: #5c4216; +--list-group-item-danger-color: #ffa8a3; +--list-group-item-danger-bg: #4a1e1c; +--list-group-item-danger-active-bg: #5c2823; +--list-group-item-light-color: #e9ecef; +--list-group-item-light-bg: #1e2430; +--list-group-item-light-active-bg: #282f3d; +--list-group-item-dark-color: #48525d; +--list-group-item-dark-bg: #0e1318; +--list-group-item-dark-active-bg: #161b22; + +/* ===== LINK UTILITY COLORS ===== */ +--link-primary-color: hsl(240, 98%, 50%); +--link-primary-hover-color: hsl(240, 98%, 45%); +--link-secondary-color: hsl(210, 15%, 70%); +--link-secondary-hover-color: hsl(210, 15%, 65%); +--link-success-color: hsl(120, 40%, 60%); +--link-success-hover-color: hsl(120, 40%, 55%); +--link-info-color: hsl(207, 60%, 65%); +--link-info-hover-color: hsl(207, 60%, 60%); +--link-warning-color: hsl(38, 100%, 65%); +--link-warning-hover-color: hsl(38, 100%, 60%); +--link-danger-color: hsl(3, 85%, 65%); +--link-danger-hover-color: hsl(3, 85%, 60%); +--link-light-color: hsl(210, 20%, 90%); +--link-light-hover-color: hsl(210, 20%, 85%); +--link-dark-color: hsl(210, 10%, 35%); +--link-dark-hover-color: hsl(210, 10%, 30%); + +/* ===== COMPONENT-SPECIFIC COLORS ===== */ +--mod-finder-link-hover: #5a6470; +--form-legend-color: #9fa6ad; +--border-gray: #3a4250; +--subhead-color: #9fa6ad; +--box-shadow-gray: #1a2027; +--btn-active-text-gray: #7a8490; +--indicator-success-bg: var(--success); +--item-list-color: #2a2f34; +--notification-badge-bg: var(--danger); +--content-bg-gray: #2b323b; +--taba-btn-green: #5a9c2f; +--taba-btn-blue: #3d75a8; +--taba-btn-red: #c43620; +--taba-btn-gray: #6a7080; +--taba-msg-bg: #1e2430; +--toc-link-color: #9fa6ad; +--toc-link-active-color: #91a4ff; +--choices-disabled-bg: #2b323b; +--choices-input-bg: var(--body-bg); +--choices-border-light: #48525d; +--choices-arrow-color: #9fa6ad; +--choices-inner-bg: #1a2027; +--choices-focused-border: #5472ff; +--choices-dropdown-bg: var(--body-bg); +--choices-item-bg: #1a5f75; +--choices-item-border: #1a748f; +--choices-item-hover-bg: #1a748f; +--choices-item-hover-border: #1a8aa8; +--choices-item-disabled-bg: #48525d; +--choices-item-disabled-border: #36404a; +--choices-item-highlighted: #2b323b; +--choices-input-inner-bg: #1a2027; + /* ===== STANDARD COLORS ===== */ --blue: #91a4ff; --indigo: #b19cff; @@ -194,6 +282,25 @@ color-scheme: dark; --white-rgb: 255, 255, 255; --black-rgb: 0, 0, 0; +/* ===== OPACITY UTILITIES ===== */ +--opacity-0: 0; +--opacity-5: 0.05; +--opacity-10: 0.1; +--opacity-15: 0.15; +--opacity-20: 0.2; +--opacity-25: 0.25; +--opacity-30: 0.3; +--opacity-50: 0.5; +--opacity-75: 0.75; +--opacity-100: 1; + +/* ===== COMMON SHADOW COLORS ===== */ +--shadow-color-light: rgba(var(--black-rgb), var(--opacity-30)); +--shadow-color-medium: rgba(var(--black-rgb), var(--opacity-50)); +--shadow-color-dark: rgba(var(--black-rgb), var(--opacity-75)); +--border-color-translucent: rgba(var(--white-rgb), var(--opacity-10)); +--highlight-translucent: rgba(var(--white-rgb), var(--opacity-5)); + /* ===== HEADER BACKGROUND ===== */ --header-background-image: url('../../../../../../media/templates/site/mokocassiopeia/images/bg.svg'); --header-background-attachment: fixed; @@ -296,6 +403,8 @@ color-scheme: dark; --input-placeholder-color: #8894aa; --input-disabled-bg: #0f1318; --input-disabled-border-color: #2b323b; +--input-file-button-active-bg: #2b3441; +--form-range-thumb-active-bg: #4a5766; --form-valid-color: #78d694; --form-valid-border-color: #78d694; --form-invalid-color: #ff8e86; @@ -481,6 +590,210 @@ color-scheme: dark; --btn-active-border-color: #12203f; } +.btn-success { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: hsl(120, 35%, 45%); + --btn-border-color: hsl(120, 35%, 45%); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: hsl(120, 35%, 40%); + --btn-hover-border-color: hsl(120, 35%, 38%); + --btn-focus-shadow-rgb: 96, 180, 96; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: hsl(120, 35%, 38%); + --btn-active-border-color: hsl(120, 35%, 36%); + --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, 35%, 45%); + --btn-disabled-border-color: hsl(120, 35%, 45%); +} + +.btn-info { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: hsl(207, 55%, 55%); + --btn-border-color: hsl(207, 55%, 55%); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: hsl(207, 55%, 50%); + --btn-hover-border-color: hsl(207, 55%, 48%); + --btn-focus-shadow-rgb: 100, 160, 210); + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: hsl(207, 55%, 48%); + --btn-active-border-color: hsl(207, 55%, 46%); + --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, 55%, 55%); + --btn-disabled-border-color: hsl(207, 55%, 55%); +} + +.btn-warning { + --btn-color: hsl(0, 0%, 0%); + --btn-bg: hsl(38, 100%, 50%); + --btn-border-color: hsl(38, 100%, 50%); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: hsl(38, 100%, 45%); + --btn-hover-border-color: hsl(38, 100%, 43%); + --btn-focus-shadow-rgb: 220, 170, 40; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: hsl(38, 100%, 43%); + --btn-active-border-color: hsl(38, 100%, 41%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 0%); + --btn-disabled-bg: hsl(38, 100%, 50%); + --btn-disabled-border-color: hsl(38, 100%, 50%); +} + +.btn-danger { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: hsl(3, 82%, 50%); + --btn-border-color: hsl(3, 82%, 50%); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: hsl(3, 82%, 45%); + --btn-hover-border-color: hsl(3, 82%, 43%); + --btn-focus-shadow-rgb: 220, 80, 80; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: hsl(3, 82%, 43%); + --btn-active-border-color: hsl(3, 82%, 41%); + --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, 82%, 50%); + --btn-disabled-border-color: hsl(3, 82%, 50%); +} + +.btn-light { + --btn-color: hsl(0, 0%, 0%); + --btn-bg: hsl(210, 17%, 85%); + --btn-border-color: hsl(210, 17%, 85%); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: hsl(210, 17%, 80%); + --btn-hover-border-color: hsl(210, 17%, 78%); + --btn-focus-shadow-rgb: 200, 205, 210; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: hsl(210, 17%, 78%); + --btn-active-border-color: hsl(210, 17%, 76%); + --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%, 85%); + --btn-disabled-border-color: hsl(210, 17%, 85%); +} + +.btn-dark { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: hsl(210, 10%, 20%); + --btn-border-color: hsl(210, 10%, 20%); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: hsl(210, 10%, 18%); + --btn-hover-border-color: hsl(210, 10%, 16%); + --btn-focus-shadow-rgb: 60, 65, 70; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: hsl(210, 10%, 16%); + --btn-active-border-color: hsl(210, 10%, 14%); + --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%, 20%); + --btn-disabled-border-color: hsl(210, 10%, 20%); +} + +.btn-outline-primary { + --btn-color: hsl(240, 98%, 40%); + --btn-border-color: hsl(240, 98%, 40%); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: hsl(240, 98%, 40%); + --btn-hover-border-color: hsl(240, 98%, 40%); + --btn-focus-shadow-rgb: 80, 80, 180; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: hsl(240, 98%, 40%); + --btn-active-border-color: hsl(240, 98%, 40%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(240, 98%, 40%); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: hsl(240, 98%, 40%); + --gradient: none; +} + +.btn-outline-secondary { + --btn-color: hsl(210, 20%, 60%); + --btn-border-color: hsl(210, 20%, 60%); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: hsl(210, 20%, 60%); + --btn-hover-border-color: hsl(210, 20%, 60%); + --btn-focus-shadow-rgb: 120, 140, 160; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: hsl(210, 20%, 60%); + --btn-active-border-color: hsl(210, 20%, 60%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(210, 20%, 60%); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: hsl(210, 20%, 60%); + --gradient: none; +} + +.btn-outline-success { + --btn-color: hsl(120, 35%, 55%); + --btn-border-color: hsl(120, 35%, 55%); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: hsl(120, 35%, 55%); + --btn-hover-border-color: hsl(120, 35%, 55%); + --btn-focus-shadow-rgb: 100, 190, 100; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: hsl(120, 35%, 55%); + --btn-active-border-color: hsl(120, 35%, 55%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(120, 35%, 55%); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: hsl(120, 35%, 55%); + --gradient: none; +} + +.btn-outline-info { + --btn-color: hsl(207, 55%, 65%); + --btn-border-color: hsl(207, 55%, 65%); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: hsl(207, 55%, 65%); + --btn-hover-border-color: hsl(207, 55%, 65%); + --btn-focus-shadow-rgb: 110, 170, 220; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: hsl(207, 55%, 65%); + --btn-active-border-color: hsl(207, 55%, 65%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(207, 55%, 65%); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: hsl(207, 55%, 65%); + --gradient: none; +} + +.btn-outline-warning { + --btn-color: hsl(38, 100%, 60%); + --btn-border-color: hsl(38, 100%, 60%); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: hsl(38, 100%, 60%); + --btn-hover-border-color: hsl(38, 100%, 60%); + --btn-focus-shadow-rgb: 240, 190, 70; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: hsl(38, 100%, 60%); + --btn-active-border-color: hsl(38, 100%, 60%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(38, 100%, 60%); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: hsl(38, 100%, 60%); + --gradient: none; +} + +.btn-outline-danger { + --btn-color: hsl(3, 82%, 60%); + --btn-border-color: hsl(3, 82%, 60%); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: hsl(3, 82%, 60%); + --btn-hover-border-color: hsl(3, 82%, 60%); + --btn-focus-shadow-rgb: 240, 100, 100; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: hsl(3, 82%, 60%); + --btn-active-border-color: hsl(3, 82%, 60%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(3, 82%, 60%); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: hsl(3, 82%, 60%); + --gradient: none; +} + /* Outline buttons on dark: keep readable borders */ .btn-outline-light { --btn-color: #e6ebf1; @@ -494,6 +807,23 @@ color-scheme: dark; --gradient: none; } +.btn-outline-dark { + --btn-color: hsl(210, 10%, 30%); + --btn-border-color: hsl(210, 10%, 30%); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: hsl(210, 10%, 30%); + --btn-hover-border-color: hsl(210, 10%, 30%); + --btn-focus-shadow-rgb: 70, 75, 80; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: hsl(210, 10%, 30%); + --btn-active-border-color: hsl(210, 10%, 30%); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(210, 10%, 30%); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: hsl(210, 10%, 30%); + --gradient: none; +} + /* Links as buttons */ .btn-link { --btn-font-weight: 400; @@ -510,8 +840,3 @@ color-scheme: dark; --btn-focus-shadow-rgb: 84, 114, 255; text-decoration: underline; } - -.btn-secondary { - --btn-color: var(--color-hover); - --btn-bg: var(--nav-bg-color); -} diff --git a/src/media/css/theme/index.html b/src/media/css/theme/index.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/media/css/theme/index.html @@ -0,0 +1 @@ + diff --git a/src/media/css/colors/light/colors_standard.css b/src/media/css/theme/light.standard.css similarity index 86% rename from src/media/css/colors/light/colors_standard.css rename to src/media/css/theme/light.standard.css index 87e4472..4c71b15 100644 --- a/src/media/css/colors/light/colors_standard.css +++ b/src/media/css/theme/light.standard.css @@ -166,6 +166,94 @@ color-scheme: light; --light-border-subtle: #eaedf0; --dark-border-subtle: #adb5bd; +/* ===== ALERT LINK COLORS ===== */ +--alert-primary-link-color: #01012a; +--alert-secondary-link-color: #34383d; +--alert-success-link-color: #213f21; +--alert-info-link-color: #172f44; +--alert-warning-link-color: #532f00; +--alert-danger-link-color: #4f0f0b; +--alert-light-link-color: #505050; +--alert-dark-link-color: #1a1c1f; + +/* ===== LIST GROUP ITEM COLORS ===== */ +--list-group-item-primary-color: #010134; +--list-group-item-primary-bg: #ccccdd; +--list-group-item-primary-active-bg: #b8b8c7; +--list-group-item-secondary-color: #41464c; +--list-group-item-secondary-bg: #e2e3e5; +--list-group-item-secondary-active-bg: #cbccce; +--list-group-item-success-color: #294f29; +--list-group-item-success-bg: #dae6da; +--list-group-item-success-active-bg: #c4cfc4; +--list-group-item-info-color: #1d3b55; +--list-group-item-info-bg: #d6e0e8; +--list-group-item-info-active-bg: #c1cad1; +--list-group-item-warning-color: #683b00; +--list-group-item-warning-bg: #efe0cc; +--list-group-item-warning-active-bg: #d7cab8; +--list-group-item-danger-color: #63130e; +--list-group-item-danger-bg: #edd2d1; +--list-group-item-danger-active-bg: #d5bdbc; +--list-group-item-light-color: #646464; +--list-group-item-light-bg: #fefefe; +--list-group-item-light-active-bg: #e5e5e5; +--list-group-item-dark-color: #202327; +--list-group-item-dark-bg: #d7d8d9; +--list-group-item-dark-active-bg: #c2c2c3; + +/* ===== LINK UTILITY COLORS ===== */ +--link-primary-color: hsl(240, 98%, 17%); +--link-primary-hover-color: #010145; +--link-secondary-color: hsl(210, 7%, 46%); +--link-secondary-hover-color: #575e65; +--link-success-color: hsl(120, 32%, 39%); +--link-success-hover-color: #366936; +--link-info-color: hsl(207, 49%, 37%); +--link-info-hover-color: #264f71; +--link-warning-color: hsl(34, 100%, 34%); +--link-warning-hover-color: #8a4e00; +--link-danger-color: hsl(3, 75%, 37%); +--link-danger-hover-color: #841913; +--link-light-color: hsl(210, 17%, 98%); +--link-light-hover-color: #fafbfc; +--link-dark-color: hsl(210, 10%, 23%); +--link-dark-hover-color: #2a2f34; + +/* ===== COMPONENT-SPECIFIC COLORS ===== */ +--mod-finder-link-hover: #e6e6e6; +--form-legend-color: #495057; +--border-gray: #b2bfcd; +--subhead-color: #495057; +--box-shadow-gray: #ddd; +--btn-active-text-gray: #A0A0A0; +--indicator-success-bg: var(--success); +--item-list-color: #F5F5F5; +--notification-badge-bg: var(--danger); +--content-bg-gray: #DDD; +--taba-btn-green: #7ac143; +--taba-btn-blue: #5091cd; +--taba-btn-red: #f44321; +--taba-btn-gray: #AAA; +--taba-msg-bg: #f5f5f5; +--toc-link-color: #767676; +--toc-link-active-color: #563d7c; +--choices-disabled-bg: #eaeaea; +--choices-input-bg: var(--white); +--choices-border-light: #ddd; +--choices-arrow-color: #333; +--choices-inner-bg: #f9f9f9; +--choices-focused-border: #b7b7b7; +--choices-dropdown-bg: var(--white); +--choices-item-bg: #00bcd4; +--choices-item-border: #00a5bb; +--choices-item-hover-bg: #00a5bb; +--choices-item-hover-border: #008fa1; +--choices-item-disabled-bg: #aaaaaa; +--choices-item-disabled-border: #919191; +--choices-item-highlighted: #f2f2f2; +--choices-input-inner-bg: #f9f9f9; + /* ===== STANDARD COLORS ===== */ --blue: #010156; --indigo: #6812f3; @@ -193,6 +281,25 @@ color-scheme: light; --white-rgb: 255, 255, 255; --black-rgb: 0, 0, 0; +/* ===== OPACITY UTILITIES ===== */ +--opacity-0: 0; +--opacity-5: 0.05; +--opacity-10: 0.1; +--opacity-15: 0.15; +--opacity-20: 0.2; +--opacity-25: 0.25; +--opacity-30: 0.3; +--opacity-50: 0.5; +--opacity-75: 0.75; +--opacity-100: 1; + +/* ===== COMMON SHADOW COLORS ===== */ +--shadow-color-light: rgba(var(--black-rgb), var(--opacity-15)); +--shadow-color-medium: rgba(var(--black-rgb), var(--opacity-25)); +--shadow-color-dark: rgba(var(--black-rgb), var(--opacity-30)); +--border-color-translucent: rgba(var(--black-rgb), var(--opacity-10)); +--highlight-translucent: rgba(var(--white-rgb), var(--opacity-15)); + /* ===== HEADER BACKGROUND ===== */ --header-background-image: url('../../../../../../media/templates/site/mokocassiopeia/images/bg.svg'); --header-background-attachment: fixed; @@ -295,6 +402,8 @@ color-scheme: light; --input-placeholder-color: hsl(210, 7%, 46%); --input-disabled-bg: hsl(210, 16%, 93%); --input-disabled-border-color: hsl(210, 14%, 83%); +--input-file-button-active-bg: #dee1e4; +--form-range-thumb-active-bg: #b8bfcc; --form-valid-color: #448344; --form-valid-border-color: #448344; --form-invalid-color: #a51f18; diff --git a/src/media/css/user.css b/src/media/css/user.css deleted file mode 100644 index 740330f..0000000 --- a/src/media/css/user.css +++ /dev/null @@ -1,18 +0,0 @@ -@charset "UTF-8"; -/* Copyright (C) 2025 Moko Consulting - - This file is part of a Moko Consulting project. - - SPDX-License-Identifier: GPL-3.0-or-later - - - - # FILE INFORMATION - DEFGROUP: Joomla.Template.Site - INGROUP: MokoCassiopeia - PATH: ./media/templates/site/moko-cassiopeia/css/user.css - VERSION: 03.06.01 - BRIEF: User custom styles for MokoCassiopeia template - add your custom CSS here - */ - -/* Add your custom CSS here */ diff --git a/src/media/fonts/GOOGLE_FONTS_README.md b/src/media/fonts/GOOGLE_FONTS_README.md new file mode 100644 index 0000000..ddb0464 --- /dev/null +++ b/src/media/fonts/GOOGLE_FONTS_README.md @@ -0,0 +1,131 @@ + + +# Google Fonts - Download Instructions + +This directory should contain self-hosted Google Font files to eliminate CDN dependencies. + +## ⚠️ Manual Download Required + +The Google Font `.woff2` files are **NOT included** in the repository and must be downloaded manually before using non-default font schemes. + +**Currently Available:** +- ✅ Osaka font (local TTF file, included) + +**Requires Manual Download:** +- ❌ Roboto fonts (4 weight variants) +- ❌ Noto Sans fonts (4 weight variants) +- ❌ Fira Sans fonts (4 weight variants) + +## Required Font Files + +Download the following `.woff2` font files and place them in this directory: + +### Roboto Font Files +- `roboto-v30-latin-100.woff2` (Thin) +- `roboto-v30-latin-300.woff2` (Light) +- `roboto-v30-latin-regular.woff2` (Regular) +- `roboto-v30-latin-700.woff2` (Bold) + +### Noto Sans Font Files +- `noto-sans-v36-latin-100.woff2` (Thin) +- `noto-sans-v36-latin-300.woff2` (Light) +- `noto-sans-v36-latin-regular.woff2` (Regular) +- `noto-sans-v36-latin-700.woff2` (Bold) + +### Fira Sans Font Files +- `fira-sans-v17-latin-100.woff2` (Thin) +- `fira-sans-v17-latin-300.woff2` (Light) +- `fira-sans-v17-latin-regular.woff2` (Regular) +- `fira-sans-v17-latin-700.woff2` (Bold) + +## How to Download + +### Option 1: Using google-webfonts-helper (Recommended) + +1. Visit https://gwfh.mranftl.com/ +2. Search for each font (Roboto, Noto Sans, Fira Sans) +3. Select character sets: **latin** (or add latin-ext if needed) +4. Select styles: + - ☑ 100 (thin) + - ☑ 300 (light) + - ☑ 400 (regular) + - ☑ 700 (bold) +5. In step 3, ensure **Modern Browsers** is selected (woff2 format) +6. In step 4, click **Download files** +7. Extract the `.woff2` files to this directory + +### Option 2: Using google-font-installer (Node.js) + +```bash +npm install -g google-font-installer +cd src/media/fonts/ + +# Download Roboto +google-font-installer Roboto:100,300,400,700 + +# Download Noto Sans +google-font-installer "Noto Sans:100,300,400,700" + +# Download Fira Sans +google-font-installer "Fira Sans:100,300,400,700" +``` + +### Option 3: Manual Download Script (Linux/macOS) + +```bash +#!/bin/bash +# Run this from src/media/fonts/ directory + +download_font() { + local font_url="$1" + local output_dir="." + + # Download CSS + css=$(curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" "$font_url") + + # Extract and download woff2 files + echo "$css" | grep -oP 'https://fonts\.gstatic\.com[^\)]*\.woff2' | while read url; do + filename=$(basename "$url") + echo "Downloading $filename..." + curl -s "$url" -o "$output_dir/$filename" + done +} + +download_font "https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;700&display=swap" +download_font "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@100;300;400;700&display=swap" +download_font "https://fonts.googleapis.com/css2?family=Fira+Sans:wght@100;300;400;700&display=swap" +``` + +## Font CSS Files + +The corresponding CSS files with `@font-face` declarations are located in: +- `../css/fonts/roboto.css` +- `../css/fonts/noto-sans.css` +- `../css/fonts/fira-sans.css` + +These CSS files reference the `.woff2` files in this directory. + +## License + +All Google Fonts are open source and licensed under the SIL Open Font License (OFL). +- Roboto: Apache License 2.0 +- Noto Sans: SIL Open Font License 1.1 +- Fira Sans: SIL Open Font License 1.1 + +## References + +- Google Fonts: https://fonts.google.com/ +- google-webfonts-helper: https://gwfh.mranftl.com/ +- Font Licensing: https://fonts.google.com/attribution diff --git a/src/templates/offline.php b/src/offline.php similarity index 65% rename from src/templates/offline.php rename to src/offline.php index f2cef85..0a2f458 100644 --- a/src/templates/offline.php +++ b/src/offline.php @@ -40,22 +40,44 @@ $params = $this->params ?: $app->getTemplate(true)->params; $direction = $this->direction ?: 'ltr'; /* ----------------------- - Load ONLY template.css + colors_*.css (with min toggle) + Load ONLY template.css + theme palettes (with min toggle) ------------------------ */ $useMin = !((int) $params->get('development_mode', 0) === 1); $assetSuffix = $useMin ? '.min' : ''; $base = rtrim(Uri::root(true), '/') . '/templates/' . $this->template . '/css/'; +$jsBase = rtrim(Uri::root(true), '/') . '/templates/' . $this->template . '/js/'; $doc->addStyleSheet($base . 'template' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-template']); -/* 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']); + +/* Load theme palettes */ +$doc->addStyleSheet($base . 'theme/light.standard' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-light-standard']); +$doc->addStyleSheet($base . 'theme/dark.standard' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-dark-standard']); + +/* Load custom palettes only if selected in template configuration AND files exist */ +$params_LightColorName = (string) $params->get('colorLightName', 'standard'); +$params_DarkColorName = (string) $params->get('colorDarkName', 'standard'); +if ($params_LightColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/light.custom.css')) +{ + $doc->addStyleSheet($base . 'theme/light.custom' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-light-custom']); +} +if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/dark.custom.css')) +{ + $doc->addStyleSheet($base . 'theme/dark.custom' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-dark-custom']); +} + +/* Load user assets last (after all other styles and scripts) */ +$doc->addStyleSheet($base . 'user' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-user']); /* Bootstrap CSS/JS for accordion behavior; safe to keep. */ HTMLHelper::_('bootstrap.loadCss', true, $doc); HTMLHelper::_('bootstrap.framework'); +/* Load template.js for theme switcher and other functionality */ +$doc->addScript($jsBase . 'template' . $assetSuffix . '.js', ['version' => 'auto', 'defer' => true], ['id' => 'moko-template-js']); + +/* Load user.js last for custom user scripts */ +$doc->addScript($jsBase . 'user' . $assetSuffix . '.js', ['version' => 'auto', 'defer' => true], ['id' => 'moko-user-js']); + /* ----------------------- Title + Meta (Include Site Name in Page Titles) ------------------------ */ @@ -79,45 +101,39 @@ $displayOfflineMessage = (int) $app->get('display_offline_message', 1); // 0|1|2 $offlineMessage = trim((string) $app->get('offline_message', '')); /* ----------------------- - Brand (mutually exclusive: logoFile OR siteTitle) + Brand: logo from params OR siteTitle (matches index.php) ------------------------ */ -if ($params->get('logoFile')) { - $logo = HTMLHelper::_( +$brandHtml = ''; +$logoFile = (string) $params->get('logoFile'); + +if ($logoFile !== '') { + $brandHtml = HTMLHelper::_( 'image', - Uri::root(false) . htmlspecialchars((string) $params->get('logoFile'), ENT_QUOTES, 'UTF-8'), + Uri::root(false) . htmlspecialchars($logoFile, ENT_QUOTES, 'UTF-8'), $sitename, - [ - 'class' => 'logo d-inline-block', - 'loading' => 'eager', - 'decoding' => 'async', - 'style' => 'max-height:64px;height:auto;width:auto;' - ], + ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], false, 0 ); -} elseif ($params->get('siteTitle')) { - $logo = '' - . htmlspecialchars((string) $params->get('siteTitle'), ENT_COMPAT, 'UTF-8') - . ''; } else { - $logo = HTMLHelper::_( - 'image', - 'full_logo.png', - $sitename, - [ - 'class' => 'logo d-inline-block', - 'loading' => 'eager', - 'decoding' => 'async', - 'style' => 'max-height:64px;height:auto;width:auto;' - ], - true, - 0 - ); + // If no logo file, show the title (defaults to "MokoCassiopeia" if not set) + $siteTitle = $params->get('siteTitle', 'MokoCassiopeia'); + $brandHtml = '' + . htmlspecialchars($siteTitle, ENT_COMPAT, 'UTF-8') + . ''; } $brandTagline = (string) ($params->get('brand_tagline') ?: $params->get('siteDescription') ?: ''); $showTagline = (int) $params->get('show_brand_tagline', 0); -$showSwitcher = (int) $params->get('show_theme_switcher', 1); + +// Theme params +$params_theme_enabled = (int) $params->get('theme_enabled', 1); + +// Analytics params +$params_googletagmanager = $params->get('googletagmanager', false); +$params_googletagmanagerid = $params->get('googletagmanagerid', null); +$params_googleanalytics = $params->get('googleanalytics', false); +$params_googleanalyticsid = $params->get('googleanalyticsid', null); /* ----------------------- Login routes & Users @@ -141,51 +157,21 @@ if (class_exists('\Joomla\Component\Users\Site\Helper\RouteHelper')) { - - + + + + + + + + + + + + + + + + + + +
@@ -206,38 +244,12 @@ if (class_exists('\Joomla\Component\Users\Site\Helper\RouteHelper')) { - + - - - - - - countModules('offline-header')) : ?>
diff --git a/src/templates/templateDetails.xml b/src/templateDetails.xml similarity index 77% rename from src/templates/templateDetails.xml rename to src/templateDetails.xml index 646857b..5b81628 100644 --- a/src/templates/templateDetails.xml +++ b/src/templateDetails.xml @@ -25,23 +25,23 @@ DEFGROUP: Joomla INGROUP: MokoCassiopeia PATH: templates/mokocassiopeia/templateDetails.xml - VERSION: 03.06.03 + VERSION: 03.08.04 BRIEF: Template manifest XML file for MokoCassiopeia ========================================================================= --> - https://mokoconsulting.tech/index.php?option=com_ars&view=update&task=stream&format=xml&id=1 + https://raw.githubusercontent.com/mokoconsulting-tech/MokoCassiopeia/main/updates.xml MokoCassiopeia - 03.06.03 - 2026-01-30 + 03.09.00 + 2026-03-08 Jonathan Miller || Moko Consulting hello@mokoconsulting.tech (C)GNU General Public License Version 3 - 2026 Moko Consulting - TPL_MOKOCASSIOPEIA_XML_DESCRIPTION + MokoCassiopeia Template Description

MokoCassiopeia continues Joomla's tradition of space-themed default templates— building on the legacy of Solarflare (Joomla 1.0), Milkyway (Joomla 1.5), and Protostar (Joomla 3.0).

This template is a customized fork of the Cassiopeia template introduced in Joomla 4, preserving its modern, accessible, and mobile-first foundation while introducing new stylistic enhancements and structural refinements specifically tailored for use by Moko Consulting.

Custom Colour Themes

To create a custom colour scheme, copy the template file templates/light.custom.css to media/templates/site/mokocassiopeia/css/theme/light.custom.css or templates/dark.custom.css to media/templates/site/mokocassiopeia/css/theme/dark.custom.css. Customise the CSS variables to match your brand, then activate it in System → Site Templates → MokoCassiopeia → Theme tab by selecting "Custom" for the Light or Dark Mode Palette. For comprehensive documentation on all available CSS variables, see docs/CSS_VARIABLES.md.

Code Attribution

This template is based on the original Cassiopeia template developed by the Joomla! Project and released under the GNU General Public License.

Modifications and enhancements have been made by Moko Consulting in accordance with open-source licensing standards.

It includes integration with Bootstrap TOC, an open-source table of contents generator by A. Feld, licensed under the MIT License.

All third-party libraries and assets remain the property of their respective authors and are credited within their source files where applicable.

]]>
1 component.php @@ -51,6 +51,7 @@ offline.php templateDetails.xml html + language media/templates/site/mokocassiopeia/css/editor.css @@ -86,14 +87,11 @@ drawer-left drawer-right - - en-GB/tpl_mokocassiopeia.ini - en-US/tpl_mokocassiopeia.ini - - - - en-GB/tpl_mokocassiopeia.sys.ini - en-US/tpl_mokocassiopeia.sys.ini + + language/en-GB/tpl_mokocassiopeia.ini + language/en-GB/tpl_mokocassiopeia.sys.ini + language/en-US/tpl_mokocassiopeia.ini + language/en-US/tpl_mokocassiopeia.sys.ini @@ -189,25 +187,23 @@ - - - + + + - - - + + + - + - - - - - + + + diff --git a/src/templates/component.php b/src/templates/component.php deleted file mode 100644 index 9eeb946..0000000 --- a/src/templates/component.php +++ /dev/null @@ -1,210 +0,0 @@ - - - This file is part of a Moko Consulting project. - - SPDX-License-Identifier: GPL-3.0-or-later - - - - # FILE INFORMATION - DEFGROUP: Joomla.Template.Site - INGROUP: MokoCassiopeia - REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia - PATH: ./templates/mokocassiopeia/component.php - VERSION: 03.06.02 - BRIEF: Main template index file for MokoCassiopeia rendering site layout - */ - - -defined('_JEXEC') or die; - -use Joomla\CMS\Factory; -use Joomla\CMS\HTML\HTMLHelper; -use Joomla\CMS\Language\Text; -use Joomla\CMS\Uri\Uri; -use Joomla\CMS\Component\ComponentHelper; - -/** @var Joomla\CMS\Document\HtmlDocument $this */ - -$app = Factory::getApplication(); -$input = $app->getInput(); -$document = $app->getDocument(); -$wa = $document->getWebAssetManager(); - -// Template params -$params_LightColorName = (string) $this->params->get('colorLightName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom - -$params_DarkColorName = (string) $this->params->get('colorDarkName', 'colors_standard'); // colors_standard|colors_alternative|colors_custom - -$params_googletagmanager = $this->params->get('googletagmanager', false); -$params_googletagmanagerid = $this->params->get('googletagmanagerid', null); -$params_googleanalytics = $this->params->get('googleanalytics', false); -$params_googleanalyticsid = $this->params->get('googleanalyticsid', null); -$params_custom_head_start = $this->params->get('custom_head_start', null); -$params_custom_head_end = $this->params->get('custom_head_end', null); -$params_developmentmode = $this->params->get('developmentmode', false); - -// Detecting Active Variables -$option = $input->getCmd('option', ''); -$view = $input->getCmd('view', ''); -$layout = $input->getCmd('layout', ''); -$task = $input->getCmd('task', ''); -$itemid = $input->getCmd('Itemid', ''); -$sitenameR = $app->get('sitename'); // raw for title composition -$sitename = htmlspecialchars($sitenameR, ENT_QUOTES, 'UTF-8'); -$menu = $app->getMenu()->getActive(); -$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : ''; - -// Respect “Site Name in Page Titles” (0:none, 1:before, 2:after) -$mode = (int) $app->get('sitename_pagetitles', 0); -$pageTitle = trim($this->getTitle()); -$final = $pageTitle !== '' - ? ($mode === 1 ? $sitenameR . ' - ' . $pageTitle - : ($mode === 2 ? $pageTitle . ' - ' . $sitenameR : $pageTitle)) - : $sitenameR; -$this->setTitle($final); - -// Template/Media path -$templatePath = 'media/templates/site/mokocassiopeia'; - -// Core template CSS -$wa->useStyle('template.base'); // css/template.css - -// Color theme (light + optional dark) -$colorLightKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_LightColorName)); -$colorDarkKey = strtolower(preg_replace('/[^a-z0-9_.-]/i', '', $params_DarkColorName)); -$lightKey = 'template.light.' . $colorLightKey; -$darkKey = 'template.dark.' . $colorDarkKey; -try { - $wa->useStyle('template.light.colors_standard'); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.light.colors_standard', $templatePath . '/css/colors/light/colors_standard.css'); -} -try { - $wa->useStyle('template.dark.colors_standard'); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.dark.colors_standard', $templatePath . '/css/colors/dark/colors_standard.css'); -} -try { - $wa->useStyle($lightKey); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.light.dynamic', $templatePath . '/css/colors/light/' . $colorLightKey . '.css'); -} -try { - $wa->useStyle($darkKey); -} catch (\Throwable $e) { - $wa->registerAndUseStyle('template.dark.dynamic', $templatePath . '/css/colors/dark/' . $colorDarkKey . '.css'); -} - -// Scripts -$wa->useScript('template.js'); - -// Load Osaka font for site title -$wa->useStyle('template.font.osaka'); - -/** - * VirtueMart detection: - * - Component must exist and be enabled - */ -$isVirtueMartActive = ComponentHelper::isEnabled('com_virtuemart', true); - -if ($isVirtueMartActive) { - /** - * Load a VirtueMart-specific stylesheet defined in your template manifest. - * This assumes you defined an asset named "template.virtuemart". - */ - $wa->useStyle('vendor.vm'); -} - -// Font scheme (external or local) + CSS custom properties -$params_FontScheme = $this->params->get('useFontScheme', false); -$fontStyles = ''; - -if ($params_FontScheme) { - if (stripos($params_FontScheme, 'https://') === 0) { - $this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']); - $this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']); - $this->getPreloadManager()->preload($params_FontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']); - $wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, [], [ - 'media' => 'print', - 'rel' => 'lazy-stylesheet', - 'onload' => 'this.media=\'all\'', - 'crossorigin' => 'anonymous' - ]); - - if (preg_match_all('/family=([^?:]*):/i', $params_FontScheme, $matches) > 0) { - $fontStyles = '--font-family-body: "' . str_replace('+', ' ', $matches[1][0]) . '", sans-serif;' . "\n"; - $fontStyles .= '--font-family-headings: "' . str_replace('+', ' ', isset($matches[1][1]) ? $matches[1][1] : $matches[1][0]) . '", sans-serif;' . "\n"; - $fontStyles .= '--font-weight-normal: 400;' . "\n"; - $fontStyles .= '--font-weight-headings: 700;'; - } - } else { - $wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, ['version' => 'auto'], [ - 'media' => 'print', - 'rel' => 'lazy-stylesheet', - 'onload' => 'this.media=\'all\'' - ]); - $this->getPreloadManager()->preload( - $wa->getAsset('style', 'fontscheme.current')->getUri() . '?' . $this->getMediaVersion(), - ['as' => 'style'] - ); - } -} - -// Meta -$this->setMetaData('viewport', 'width=device-width, initial-scale=1'); - -if ($this->params->get('faKitCode')) { - $faKit = "https://kit.fontawesome.com/" . $this->params->get('faKitCode') . ".js"; - HTMLHelper::_('script', $faKit, ['crossorigin' => 'anonymous']); -} else { - try { - if($params_developmentmode){ - $wa->useStyle('vendor.fa7free.all'); - $wa->useStyle('vendor.fa7free.brands'); - $wa->useStyle('vendor.fa7free.fontawesome'); - $wa->useStyle('vendor.fa7free.regular'); - $wa->useStyle('vendor.fa7free.solid'); - } else { - $wa->useStyle('vendor.fa7free.all.min'); - $wa->useStyle('vendor.fa7free.brands.min'); - $wa->useStyle('vendor.fa7free.fontawesome.min'); - $wa->useStyle('vendor.fa7free.regular.min'); - $wa->useStyle('vendor.fa7free.solid.min'); - } - } catch (\Throwable $e) { - if($params_developmentmode){ - $wa->registerAndUseStyle('vendor.fa7free.all.dynamic', $templatePath . '/vendor/fa7free/css/all.css'); - $wa->registerAndUseStyle('vendor.fa7free.brands.dynamic', $templatePath . '/vendor/fa7free/css/brands.css'); - $wa->registerAndUseStyle('vendor.fa7free.fontawesome.dynamic', $templatePath . '/vendor/fa7free/css/fontawesome.css'); - $wa->registerAndUseStyle('vendor.fa7free.regular.dynamic', $templatePath . '/vendor/fa7free/css/regular.css'); - $wa->registerAndUseStyle('vendor.fa7free.solid.dynamic', $templatePath . '/vendor/fa7free/css/solid.css'); - } else { - $wa->registerAndUseStyle('vendor.fa7free.all.min.dynamic', $templatePath . '/vendor/fa7free/css/all.min.css'); - $wa->registerAndUseStyle('vendor.fa7free.brands.min.dynamic', $templatePath . '/vendor/fa7free/css/brands.min.css'); - $wa->registerAndUseStyle('vendor.fa7free.fontawesome.min.dynamic', $templatePath . '/vendor/fa7free/css/fontawesome.min.css'); - $wa->registerAndUseStyle('vendor.fa7free.regular.min.dynamic', $templatePath . '/vendor/fa7free/css/regular.min.css'); - $wa->registerAndUseStyle('vendor.fa7free.solid.min.dynamic', $templatePath . '/vendor/fa7free/css/solid.min.css'); - } - - } -} -$params_leftIcon = htmlspecialchars($this->params->get('drawerLeftIcon', 'fa-solid fa-chevron-left'), ENT_COMPAT, 'UTF-8'); -$params_rightIcon = htmlspecialchars($this->params->get('drawerRightIcon', 'fa-solid fa-chevron-right'), ENT_COMPAT, 'UTF-8'); - -$wa->useStyle('template.user'); // css/user.css -?> - - - - - - - - - - - - - diff --git a/src/templates/html/INDUSTRY_MODULES_README.md b/src/templates/html/INDUSTRY_MODULES_README.md deleted file mode 100644 index fcb8452..0000000 --- a/src/templates/html/INDUSTRY_MODULES_README.md +++ /dev/null @@ -1,306 +0,0 @@ -# Industry Extension Module Mobile Responsive Overrides - -## Overview -This directory contains mobile-responsive overrides for popular industry Joomla extensions, designed specifically for the MokoCassiopeia template. - -## Industry Extension Modules - -### 1. mod_k2_content (K2) -K2 content display module featuring: -- Responsive article/content cards -- Optional images with hover effects -- Metadata display (author, date, category, hits) -- Introtext support -- Read more links -- Custom link support -- Touch-friendly interactions - -### 2. mod_acymailing (AcyMailing) -AcyMailing newsletter subscription module with: -- Mobile-responsive form inputs -- Touch-friendly form controls (48px on mobile) -- 16px input font (prevents iOS zoom) -- Intro and outro text support -- Custom form styling that overrides inline styles -- Accessible form structure - -### 3. mod_hikashop_cart (HikaShop) -HikaShop shopping cart module offering: -- Product list with images -- Cart summary with item count and total -- Touch-friendly remove buttons -- Mobile-optimized cart display -- Flexible action buttons layout -- Empty cart state - -### 4. mod_kunenalatest (Kunena Forum) -Kunena latest posts module with: -- User avatars -- Post metadata (author, date, category, hits, replies) -- Post excerpts -- Forum navigation links -- Responsive card layouts -- Touch-friendly post links - -### 5. mod_kunenalogin (Kunena Forum) -Kunena login module featuring: -- Login and logout states -- User profile with avatar -- Post count and karma display -- Profile and private messages links -- Touch-friendly form controls -- Password recovery links - -### 6. mod_kunenasearch (Kunena Forum) -Kunena forum search module with: -- Configurable button positions (top/right/bottom/left) -- Touch-friendly search input (48px on mobile) -- 16px input font (prevents iOS zoom) -- Icon-only or text button options -- Accessible search form - -### 7. mod_kunenastats (Kunena Forum) -Kunena statistics module offering: -- Member count with icon -- Latest member display -- Message and topic counts -- Today/yesterday topic counts -- Responsive grid layout (1-3 columns) -- Visual stat cards with icons - -### 8. mod_osmembership (OS Membership Pro) -Membership Pro plans module with: -- Responsive pricing cards -- Plan images and descriptions -- Feature lists with checkmarks -- Pricing display with periods -- Free plan highlighting -- Touch-friendly subscribe buttons -- Grid layout (1-3 columns) - -## Component Overrides - -### com_kunena (Kunena Forum) -- Category list view with responsive cards -- Mobile-optimized forum navigation -- Touch-friendly category links - -### com_osmembership (OS Membership Pro) -- Plans list with pricing table layout -- Featured plan highlighting -- Responsive grid (1-4 columns) -- Touch-friendly subscription buttons - -## Mobile Responsive Features - -### Touch Target Sizes (WCAG 2.1 Compliant) -- **Mobile (< 576px):** 48px minimum height -- **Desktop (≥ 768px):** 44px minimum height - -### Font Sizes (iOS Zoom Prevention) -- **Mobile:** 16px base font for inputs (prevents auto-zoom) -- **Desktop:** 1rem (16px typically) - -### Responsive Breakpoints -Using Bootstrap-aligned breakpoints: -- `< 576px` - Mobile (xs) -- `576px - 767px` - Tablet (sm-md) -- `768px+` - Desktop (md+) - -### Layout Adaptations - -#### Mobile (< 576px) -- Stacked content layouts -- Full-width images -- Vertical metadata lists -- Larger touch targets (48px) -- Stacked action buttons - -#### Desktop (≥ 768px) -- Horizontal layouts where appropriate -- Side-by-side image and content -- Inline metadata -- Enhanced hover effects -- Horizontal button groups - -## CSS Architecture - -### BEM Naming Convention -All modules use Block-Element-Modifier naming: - -```css -.mod-k2-content /* Block */ -.mod-k2-content__title /* Element */ -.mod-k2-content__item--featured /* Modifier */ -``` - -### CSS Variables Integration -Styles integrate with template's color system: - -```css ---body-color ---link-color ---color-primary ---secondary-bg ---border-color ---border-radius ---gray-600 ---success ---danger -``` - -## Accessibility Features - -All modules include: -- ✅ Semantic HTML5 elements -- ✅ ARIA labels and landmarks -- ✅ Proper heading hierarchy -- ✅ Keyboard navigation support -- ✅ Screen reader friendly -- ✅ Focus indicators -- ✅ Touch-optimized controls -- ✅ Alternative text for images - -## Browser Compatibility - -- ✅ Modern browsers (Chrome, Firefox, Safari, Edge) -- ✅ iOS Safari (no zoom on input focus) -- ✅ Android browsers -- ✅ Touch and mouse input -- ✅ All screen sizes (320px+) -- ✅ Portrait and landscape orientations - -## File Structure - -``` -src/templates/html/ -├── mod_k2_content/ -│ ├── default.php -│ └── index.html -├── mod_acymailing/ -│ ├── default.php -│ └── index.html -├── mod_hikashop_cart/ -│ ├── default.php -│ └── index.html -└── mod_kunenalatest/ - ├── default.php - └── index.html -``` - -## Usage - -These overrides are automatically used when: -1. The MokoCassiopeia template is active -2. The respective extensions are installed -3. The modules are published - -No additional configuration required beyond standard module settings. - -## Extension Parameters - -All standard extension module parameters are fully supported. Each override respects the module's configuration options. - -## Customization - -### Override CSS Variables -```css -:root { - --border-radius: 0.5rem; - --color-primary: #your-color; -} -``` - -### Add Custom Styles -```css -.mod-k2-content-responsive { - max-width: 800px; - margin: 0 auto; -} -``` - -### Modify Templates -Each PHP file can be modified to adjust HTML structure while maintaining mobile responsiveness. - -## Security - -- ✅ index.html security files in all directories -- ✅ Proper input escaping with `htmlspecialchars()` -- ✅ XSS prevention -- ✅ Joomla security best practices (`_JEXEC` check) -- ✅ No SQL injection vectors - -## Extension Compatibility - -### K2 -- Compatible with K2 2.x and 3.x -- Supports all K2 module parameters -- Image handling for various sizes -- BBCode/HTML content support - -### AcyMailing -- Compatible with AcyMailing 6.x+ -- Form styling overrides inline styles -- Supports custom form layouts -- Newsletter list integration - -### HikaShop -- Compatible with HikaShop 4.x and 5.x -- Product image display -- Price formatting support -- Tax calculations -- Cart operations via AJAX - -### Kunena -- Compatible with Kunena 5.x and 6.x -- Avatar integration -- BBCode parsing -- Forum routing support -- User profile links - -## Testing Checklist - -### General Testing -- [ ] Test on mobile device (< 576px) -- [ ] Test on tablet (576px - 767px) -- [ ] Test on desktop (≥ 768px) -- [ ] Verify touch targets are adequate -- [ ] Test with screen reader -- [ ] Check keyboard navigation -- [ ] Verify ARIA labels - -### Extension-Specific Testing -- [ ] K2: Test with/without images, various metadata options -- [ ] AcyMailing: Test form submission, validation -- [ ] HikaShop: Test add/remove items, cart update -- [ ] Kunena: Test avatar display, post links, forum navigation - -## Documentation - -Each module follows the same pattern established by: -- mod_search override -- VirtueMart module overrides -- Standard Joomla module overrides -- Mobile-first responsive design -- BEM naming convention - -## Related Documentation - -- `STANDARD_MODULES_README.md` - Standard Joomla module overrides -- `VIRTUEMART_MODULES_README.md` - VirtueMart module overrides -- `docs/CSS_VARIABLES.md` - Complete CSS variables reference -- `docs/ROADMAP.md` - Template development roadmap - -## License - -Copyright (C) 2025 Moko Consulting -Licensed under GNU General Public License version 2 or later - -## Support - -For issues or questions: -- Review extension-specific documentation -- Check CSS variables documentation -- Consult extension and Joomla documentation -- Verify module configuration in Joomla admin -- Check extension compatibility versions diff --git a/src/templates/html/STANDARD_MODULES_README.md b/src/templates/html/STANDARD_MODULES_README.md deleted file mode 100644 index 508c8ec..0000000 --- a/src/templates/html/STANDARD_MODULES_README.md +++ /dev/null @@ -1,253 +0,0 @@ -# Standard Joomla & Community Builder Module Mobile Responsive Overrides - -## Overview -This directory contains mobile-responsive overrides for standard Joomla and Community Builder modules, designed specifically for the MokoCassiopeia template. - -## Standard Joomla Modules - -### 1. mod_menu -Main navigation menu module with: -- Responsive navigation structure -- BEM naming for easy styling -- Support for all menu types -- Semantic HTML5 nav element -- Accessibility-friendly with ARIA labels - -### 2. mod_breadcrumbs -Breadcrumb navigation module featuring: -- Schema.org structured data -- Responsive breadcrumb trail -- Home icon support -- Active page highlighting -- Touch-friendly links - -### 3. mod_login -User login form module with: -- Login and logout states -- Two-factor authentication support -- Remember me functionality -- Password recovery links -- User registration links -- Touch-friendly form inputs (48px on mobile) -- 16px input font (prevents iOS zoom) - -### 4. mod_articles_latest -Latest articles display module offering: -- Responsive article cards -- Optional metadata display (author, date, category, hits) -- Schema.org Article markup -- Introtext support -- Read more links -- Touch-friendly interactions - -## Community Builder Modules - -### 5. mod_cblogin -Community Builder login module with: -- Avatar display in logged-in state -- Profile link button -- Touch-friendly form controls -- Remember me checkbox -- Password/username recovery links -- Registration link -- Pre/post text support - -### 6. mod_comprofilerOnline -Community Builder online users module featuring: -- Online user count display -- Members vs. guests breakdown -- User list with avatars -- Profile links -- Online status indicators -- Responsive card layouts - -## Mobile Responsive Features - -### Touch Target Sizes (WCAG 2.1 Compliant) -- **Mobile (< 576px):** 48px minimum height -- **Desktop (≥ 768px):** 44px minimum height - -### Font Sizes (iOS Zoom Prevention) -- **Mobile:** 16px base font for inputs (prevents auto-zoom) -- **Desktop:** 1rem (16px typically) - -### Responsive Breakpoints -Using Bootstrap-aligned breakpoints: -- `< 576px` - Mobile (xs) -- `576px - 767px` - Tablet (sm-md) -- `768px+` - Desktop (md+) - -### Layout Adaptations - -#### Mobile (< 576px) -- Stacked form layouts -- Full-width buttons -- Larger touch targets (48px) -- 16px input font size -- Vertical link lists - -#### Tablet & Desktop (≥ 768px) -- Inline button layouts where appropriate -- Horizontal action groups -- Enhanced hover effects -- Optimized spacing - -## CSS Architecture - -### BEM Naming Convention -All modules use Block-Element-Modifier naming: - -```css -.mod-login /* Block */ -.mod-login__input /* Element */ -.mod-login__btn--submit /* Modifier */ -``` - -### CSS Variables Integration -Styles integrate with template's color system: - -```css ---body-color ---link-color ---link-hover-color ---color-primary ---secondary-bg ---border-color ---border-radius ---gray-600 ---success -``` - -## Accessibility Features - -All modules include: -- ✅ Semantic HTML5 elements -- ✅ ARIA labels and landmarks -- ✅ Proper form labeling -- ✅ Keyboard navigation support -- ✅ Screen reader friendly -- ✅ Focus indicators -- ✅ Touch-optimized controls -- ✅ Schema.org structured data (where applicable) - -## Browser Compatibility - -- ✅ Modern browsers (Chrome, Firefox, Safari, Edge) -- ✅ iOS Safari (no zoom on input focus) -- ✅ Android browsers -- ✅ Touch and mouse input -- ✅ All screen sizes (320px+) -- ✅ Portrait and landscape orientations - -## File Structure - -``` -src/templates/html/ -├── mod_menu/ -│ ├── default.php -│ ├── default_url.php -│ ├── default_component.php -│ └── index.html -├── mod_breadcrumbs/ -│ ├── default.php -│ └── index.html -├── mod_login/ -│ ├── default.php -│ └── index.html -├── mod_articles_latest/ -│ ├── default.php -│ └── index.html -├── mod_cblogin/ -│ ├── default.php -│ └── index.html -└── mod_comprofilerOnline/ - ├── default.php - └── index.html -``` - -## Usage - -These overrides are automatically used when: -1. The MokoCassiopeia template is active -2. The respective modules are published -3. No additional configuration required beyond standard module settings - -## Module Parameters - -All standard Joomla and Community Builder module parameters are fully supported. Each override respects the module's configuration options. - -## Customization - -### Override CSS Variables -```css -:root { - --border-radius: 0.5rem; - --color-primary: #your-color; -} -``` - -### Add Custom Styles -```css -.mod-login-responsive { - max-width: 400px; - margin: 0 auto; -} -``` - -### Modify Templates -Each PHP file can be modified to adjust HTML structure while maintaining mobile responsiveness. - -## Security - -- ✅ index.html security files in all directories -- ✅ Proper input escaping with `htmlspecialchars()` -- ✅ XSS prevention -- ✅ Joomla security best practices (`_JEXEC` check) -- ✅ Form token validation - -## Testing Checklist - -### General Testing -- [ ] Test on mobile device (< 576px) -- [ ] Test on tablet (576px - 767px) -- [ ] Test on desktop (≥ 768px) -- [ ] Verify touch targets are adequate -- [ ] Test with screen reader -- [ ] Check keyboard navigation -- [ ] Verify ARIA labels - -### Module-Specific Testing -- [ ] mod_menu: Test menu types and levels -- [ ] mod_breadcrumbs: Verify breadcrumb trail accuracy -- [ ] mod_login: Test login/logout flows, 2FA -- [ ] mod_articles_latest: Check various parameter combinations -- [ ] mod_cblogin: Test CB login/logout with avatar -- [ ] mod_comprofilerOnline: Verify user list display - -## Documentation - -Each module follows the same pattern established by: -- mod_search override -- VirtueMart module overrides -- Comprehensive documentation -- BEM naming convention -- Mobile-first responsive design - -## Related Documentation - -- `VIRTUEMART_MODULES_README.md` - VirtueMart module overrides -- `docs/CSS_VARIABLES.md` - Complete CSS variables reference -- `docs/ROADMAP.md` - Template development roadmap - -## License - -Copyright (C) 2025 Moko Consulting -Licensed under GNU General Public License version 2 or later - -## Support - -For issues or questions: -- Review module-specific parameters -- Check CSS variables documentation -- Consult Joomla and Community Builder documentation -- Verify module configuration in Joomla admin diff --git a/src/templates/html/VIRTUEMART_MODULES_README.md b/src/templates/html/VIRTUEMART_MODULES_README.md deleted file mode 100644 index 5dbf40b..0000000 --- a/src/templates/html/VIRTUEMART_MODULES_README.md +++ /dev/null @@ -1,228 +0,0 @@ -# VirtueMart Module Mobile Responsive Overrides - -## Overview -This directory contains mobile-responsive overrides for VirtueMart e-commerce modules, designed specifically for the MokoCassiopeia template. - -## Modules Included - -### 1. mod_virtuemart_cart -Shopping cart display module with: -- Responsive product list with images -- Touch-friendly remove buttons -- Mobile-optimized cart summary -- Flexible action buttons layout - -### 2. mod_virtuemart_product -Product display module featuring: -- Grid/list layout options -- Responsive product cards -- Mobile-optimized images -- Touch-friendly action buttons - -### 3. mod_virtuemart_currencies -Currency selector module with: -- Custom styled select dropdown -- Mobile-friendly touch targets -- Accessible form controls -- Icon indicators - -### 4. mod_virtuemart_category -Category navigation module offering: -- Hierarchical category display -- Optional product counts -- Image support for categories -- Active state highlighting - -### 5. mod_virtuemart_manufacturer -Manufacturer display module with: -- Grid and list display modes -- Logo/image display -- Responsive card layouts -- Hover effects - -## Mobile Responsive Features - -### Touch Targets -- **Mobile (< 576px):** 48px minimum height -- **Desktop (≥ 768px):** 44px minimum height -- WCAG 2.1 AA compliant - -### Font Sizes -- **Mobile:** 16px base (prevents iOS auto-zoom) -- **Desktop:** 1rem (16px typically) - -### Responsive Breakpoints -Using Bootstrap-aligned breakpoints: -- `< 576px` - Mobile (xs) -- `576px` - Small (sm) -- `768px` - Medium (md) -- `992px` - Large (lg) -- `1200px` - Extra Large (xl) -- `1400px` - Extra Extra Large (xxl) - -### Layout Adaptations - -#### Mobile (< 576px) -- Single column layouts -- Stacked action buttons -- Full-width elements -- Larger touch targets (48px) - -#### Tablet (576px - 767px) -- 2-column grids for products/manufacturers -- Inline action buttons where appropriate -- 44px touch targets - -#### Desktop (≥ 768px) -- 3-4 column grids -- Horizontal button layouts -- Optimized spacing -- Enhanced hover effects - -## CSS Architecture - -### CSS Variables Integration -All styles integrate with template's VirtueMart CSS variables: - -```css -/* Surfaces & Colors */ ---vm-surface ---vm-surface-2 ---vm-text ---vm-text-strong ---vm-text-muted ---vm-border ---vm-price-color - -/* Layout */ ---vm-block-radius ---vm-block-shadow ---vm-section-gap - -/* Buttons */ ---vm-btn-primary-bg ---vm-btn-primary-text ---vm-btn-secondary-bg ---vm-btn-secondary-text -``` - -### BEM Naming Convention -All modules use Block-Element-Modifier naming: - -```css -.mod-vm-cart /* Block */ -.mod-vm-cart__header /* Element */ -.mod-vm-cart__item--active /* Modifier */ -``` - -## Accessibility Features - -All modules include: -- ✅ ARIA labels on interactive elements -- ✅ Semantic HTML5 structure -- ✅ Proper heading hierarchy -- ✅ Keyboard navigation support -- ✅ Screen reader friendly -- ✅ Focus indicators -- ✅ Touch-optimized controls - -## Browser Compatibility - -- ✅ Modern browsers with flexbox/grid support -- ✅ iOS Safari (no auto-zoom issues) -- ✅ Android browsers -- ✅ Chrome, Firefox, Safari, Edge -- ✅ Responsive on all device sizes -- ✅ Touch and mouse input - -## File Structure - -``` -src/templates/html/ -├── mod_virtuemart_cart/ -│ ├── default.php -│ ├── index.html -│ └── README.md -├── mod_virtuemart_product/ -│ ├── default.php -│ ├── index.html -│ └── README.md -├── mod_virtuemart_currencies/ -│ ├── default.php -│ ├── index.html -│ └── README.md -├── mod_virtuemart_category/ -│ ├── default.php -│ ├── index.html -│ └── README.md -└── mod_virtuemart_manufacturer/ - ├── default.php - ├── index.html - └── README.md -``` - -## Usage - -These overrides are automatically used when: -1. The MokoCassiopeia template is active -2. VirtueMart is installed and configured -3. The respective modules are published - -No additional configuration is required beyond standard VirtueMart module settings. - -## Customization - -To customize the appearance, you can: - -1. **Override CSS variables** in `user.css`: -```css -:root { - --vm-btn-primary-bg: #your-color; - --vm-block-radius: 0.5rem; -} -``` - -2. **Add custom styles** targeting module classes: -```css -.mod-vm-cart-responsive { - max-width: 400px; -} -``` - -3. **Modify PHP templates** in the respective module directories - -## Testing - -All overrides have been designed to work across: -- Mobile devices (320px+) -- Tablets (768px+) -- Desktop screens (1200px+) -- Touch and click interactions -- Portrait and landscape orientations - -## Security - -- ✅ index.html security files included -- ✅ Proper input escaping in PHP -- ✅ XSS prevention -- ✅ Follows Joomla security best practices - -## Documentation - -Each module directory contains a detailed README.md with: -- Module-specific features -- Configuration options -- Customization examples -- Usage guidelines - -## License - -Copyright (C) 2025 Moko Consulting -Licensed under GNU General Public License version 2 or later - -## Support - -For issues or questions: -- Check individual module README files -- Review CSS_VARIABLES.md for available CSS variables -- Consult VirtueMart and Joomla documentation diff --git a/src/templates/html/mod_articles_latest/default.php b/src/templates/html/mod_articles_latest/default.php deleted file mode 100644 index a570677..0000000 --- a/src/templates/html/mod_articles_latest/default.php +++ /dev/null @@ -1,100 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - * - * Mobile responsive override for mod_articles_latest module - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\HTML\HTMLHelper; -use Joomla\CMS\Language\Text; - -$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); - -// Add responsive wrapper class -$wrapperClass = 'mod-articles-latest mod-articles-latest-responsive ' . $moduleclass_sfx; -?> - -
- -
    - -
  • - get('show_introtext', 0) && !empty($item->introtext)) : ?> -
    - get('item_heading', 4); ?> class="mod-articles-latest__title" itemprop="headline"> - get('link_titles', 1)) : ?> - - - title, ENT_COMPAT, 'UTF-8'); ?> - - get('item_heading', 4); ?>> - - get('show_author', 0) || $params->get('show_date', 0) || $params->get('show_category', 0) || $params->get('show_hits', 0)) : ?> -
    - get('show_author', 0)) : ?> - - - - get('show_date', 0)) : ?> - - - - - - - get('show_category', 0)) : ?> - - - displayCategoryTitle; ?> - - - - get('show_hits', 0)) : ?> - - - displayHits; ?> - - -
    - - -
    - introtext; ?> -
    - - get('readmore', 0)) : ?> - - -
    - - - -
  • - -
- -
-

-
- -
diff --git a/src/templates/html/mod_breadcrumbs/default.php b/src/templates/html/mod_breadcrumbs/default.php deleted file mode 100644 index 413df37..0000000 --- a/src/templates/html/mod_breadcrumbs/default.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - * - * Mobile responsive override for mod_breadcrumbs module - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Language\Text; - -$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); - -// Add responsive wrapper class -$wrapperClass = 'mod-breadcrumbs mod-breadcrumbs-responsive ' . $moduleclass_sfx; -?> - - diff --git a/src/templates/html/mod_login/default.php b/src/templates/html/mod_login/default.php deleted file mode 100644 index 29f855c..0000000 --- a/src/templates/html/mod_login/default.php +++ /dev/null @@ -1,168 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - * - * Mobile responsive override for mod_login module - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\HTML\HTMLHelper; -use Joomla\CMS\Language\Text; -use Joomla\CMS\Router\Route; - -HTMLHelper::_('behavior.keepalive'); -HTMLHelper::_('bootstrap.tooltip', '.hasTooltip'); - -$usersConfig = ComponentHelper::getParams('com_users'); -$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); - -// Add responsive wrapper class -$wrapperClass = 'mod-login mod-login-responsive ' . $moduleclass_sfx; -?> - -
- - - - - -
diff --git a/src/templates/html/mod_menu/default.php b/src/templates/html/mod_menu/default.php deleted file mode 100644 index 92e1df9..0000000 --- a/src/templates/html/mod_menu/default.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - * - * Mobile responsive override for mod_menu module - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Helper\ModuleHelper; - -$id = ''; - -if ($tagId = $params->get('tag_id', '')) { - $id = ' id="' . $tagId . '"'; -} - -// The menu class is deprecated. Use mod-menu instead -$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); - -// Add responsive wrapper class -$wrapperClass = 'mod-menu mod-menu-responsive ' . $moduleclass_sfx; - -if ($params->get('layout', 'default') === 'default') { - $wrapperClass .= ' mod-menu--default'; -} -?> - diff --git a/src/templates/html/mod_menu/default_component.php b/src/templates/html/mod_menu/default_component.php deleted file mode 100644 index 68ca54e..0000000 --- a/src/templates/html/mod_menu/default_component.php +++ /dev/null @@ -1,14 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - * - * Mobile responsive component for mod_menu - */ - -defined('_JEXEC') or die; -?> -title; ?> diff --git a/src/templates/html/mod_menu/default_url.php b/src/templates/html/mod_menu/default_url.php deleted file mode 100644 index 43cc450..0000000 --- a/src/templates/html/mod_menu/default_url.php +++ /dev/null @@ -1,52 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - * - * Mobile responsive menu list for mod_menu - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\HTML\HTMLHelper; - -$attributes = []; - -if ($item->anchor_title) { - $attributes['title'] = $item->anchor_title; -} - -if ($item->anchor_css) { - $attributes['class'] = $item->anchor_css; -} - -if ($item->anchor_rel) { - $attributes['rel'] = $item->anchor_rel; -} - -$linktype = $item->title; - -if ($item->menu_image) { - if ($item->menu_image_css) { - $image_attributes['class'] = $item->menu_image_css; - $linktype = HTMLHelper::_('image', $item->menu_image, $item->title, $image_attributes); - } else { - $linktype = HTMLHelper::_('image', $item->menu_image, $item->title); - } - - if ($item->params->get('menu_text', 1)) { - $linktype .= '' . $item->title . ''; - } -} - -if ($item->browserNav == 1) { - $attributes['target'] = '_blank'; -} elseif ($item->browserNav == 2) { - $options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes'; - $attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;"; -} - -echo HTMLHelper::_('link', $item->flink, $linktype, $attributes); diff --git a/src/templates/html/mod_search/README.md b/src/templates/html/mod_search/README.md deleted file mode 100644 index fa44f24..0000000 --- a/src/templates/html/mod_search/README.md +++ /dev/null @@ -1,126 +0,0 @@ -# mod_search Mobile Responsive Override - -## Overview -This directory contains a mobile-responsive override for Joomla's `mod_search` module, designed specifically for the MokoCassiopeia template. - -## Features - -### Mobile Responsiveness -- **Flexible Layout**: Adapts to different screen sizes automatically -- **Touch-Friendly**: Minimum 44px touch targets (48px on mobile) -- **Readable Text**: 16px font size on mobile to prevent auto-zoom on iOS -- **Proper Spacing**: Adequate padding and gaps for easy interaction - -### Responsive Breakpoints -- **Mobile (< 576px)**: Stacked layout, full-width buttons, larger touch targets -- **Tablet (576px - 767px)**: Inline search field and button -- **Desktop (≥ 768px)**: Optimized horizontal layout - -### Button Position Support -The override supports all standard mod_search button positions: -- **Left**: Search button appears to the left of input field -- **Right**: Search button appears to the right of input field (default) -- **Top**: Search button appears above input field -- **Bottom**: Search button appears below input field - -### Icon Button Support -Supports both text and icon-only search buttons: -- Text buttons display customizable button text -- Icon buttons show search icon (icon-search) - -## Files - -### default.php -The main template override file that renders the search module with responsive HTML structure. - -**Key Classes:** -- `.mod-search-responsive`: Main wrapper class -- `.mod-search__form`: Form container with flex layout -- `.mod-search__input-wrapper`: Input field wrapper -- `.mod-search__input`: Search input field -- `.mod-search__button`: Search button -- `.mod-search__button--icon`: Icon-only button variant - -## CSS Styling - -The mobile-responsive styles are defined in `/src/media/css/template.css` under the section: -``` -/* ===== MOD_SEARCH MOBILE RESPONSIVE STYLES ===== */ -``` - -### Key CSS Features: -1. **Flexbox Layout**: Uses modern flexbox for flexible, responsive layouts -2. **CSS Variables**: Integrates with template's color scheme system -3. **Mobile-First**: Base styles target mobile, with progressive enhancement -4. **Accessible**: Proper focus states and ARIA labels -5. **Touch-Optimized**: Appropriate sizing for touch interaction - -## Usage - -This override is automatically used when: -1. The MokoCassiopeia template is active -2. A mod_search module is published on the site - -No additional configuration is required beyond standard mod_search module settings. - -## Module Parameters - -All standard mod_search parameters are supported: -- **Width**: Input field width (in characters) - note: overridden by responsive CSS -- **Button Text**: Custom text for the search button -- **Button Position**: left, right, top, or bottom -- **Image Button**: Use icon instead of text button -- **Max Length**: Maximum search query length -- **Menu Item**: Target search results page - -## Accessibility Features - -- Hidden label for screen readers -- ARIA labels on input and button -- Proper focus indicators -- Semantic HTML structure -- Keyboard navigation support - -## Browser Support - -- Modern browsers with flexbox support -- Responsive on all device sizes -- Works with iOS Safari (no auto-zoom on input focus) -- Compatible with touch and mouse input - -## Customization - -To customize the appearance, you can: -1. Override CSS variables in `user.css` -2. Modify classes in `default.php` -3. Add custom styles targeting `.mod-search-responsive` - -Example custom CSS: -```css -.mod-search-responsive { - max-width: 600px; - margin: 0 auto; -} - -.mod-search__input { - border-radius: 25px; -} - -.mod-search__button { - border-radius: 25px; -} -``` - -## Testing - -The override has been designed to work across: -- Mobile devices (320px+) -- Tablets (768px+) -- Desktop screens (1200px+) -- Touch and click interactions -- Portrait and landscape orientations - -## License - -Copyright (C) 2025 Moko Consulting -Licensed under GNU General Public License version 2 or later diff --git a/src/templates/html/mod_search/default.php b/src/templates/html/mod_search/default.php deleted file mode 100644 index 5ad1836..0000000 --- a/src/templates/html/mod_search/default.php +++ /dev/null @@ -1,94 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - * - * Mobile responsive override for mod_search module - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Language\Text; - -// Get module parameters -$width = (int) $params->get('width', 20); -$maxlength = (int) $params->get('maxlength', 200); -$button_text = $params->get('button_text', ''); -$button_pos = $params->get('button_pos', 'right'); -$imagebutton = $params->get('imagebutton', 0); -$set_itemid = (int) $params->get('set_itemid', 0); -$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8'); - -// Add responsive wrapper class -$wrapperClass = 'mod-search mod-search-responsive ' . $moduleclass_sfx; -$inputClass = 'mod-search__input form-control'; -$buttonClass = 'mod-search__button btn btn-primary'; - -// Build the search button -if ($imagebutton) { - $buttonHtml = ''; -} else { - $button_text = $button_text ?: Text::_('JSEARCH_FILTER_SUBMIT'); - $buttonHtml = ''; -} - -$output = ''; - -// Menuitem option -$mitemid = $set_itemid > 0 ? $set_itemid : $app->input->getInt('Itemid'); -?> - -
-
- -
- -
- - -
- -
- -
- - - - - - -
- -
- -
- - -
- -
- - - - - -
-
diff --git a/src/templates/html/mod_virtuemart_cart/README.md b/src/templates/html/mod_virtuemart_cart/README.md deleted file mode 100644 index 5d49ef2..0000000 --- a/src/templates/html/mod_virtuemart_cart/README.md +++ /dev/null @@ -1,205 +0,0 @@ -# mod_virtuemart_cart Mobile Responsive Override - -## Overview -Mobile-responsive override for VirtueMart's shopping cart module (`mod_virtuemart_cart`), designed for the MokoCassiopeia template. - -## Features - -### Cart Display -- **Cart Summary Header**: Shows item count and total price -- **Product List**: Displays cart items with images, names, quantities, and prices -- **Remove Buttons**: Touch-friendly delete buttons for each item -- **Action Buttons**: View cart and checkout buttons -- **Empty State**: Friendly message when cart is empty - -### Mobile Responsiveness -- **Touch Targets**: 48px on mobile, 44px on desktop (WCAG compliant) -- **Flexible Layout**: Adapts to different screen sizes -- **Stacked Layout**: Products stack vertically on mobile -- **Full-Width Actions**: Buttons expand to full width on small screens - -### Responsive Breakpoints - -#### Mobile (< 576px) -- Vertical product layout -- Full-width product images (max 200px centered) -- Stacked action buttons -- 48px minimum touch targets -- Increased padding for comfortable touch - -#### Tablet (576px - 767px) -- Side-by-side product details -- Inline action buttons begin to appear -- 44px touch targets - -#### Desktop (≥ 768px) -- Horizontal action button layout -- Optimized spacing and alignment -- Enhanced hover effects - -## Module Parameters - -All standard mod_virtuemart_cart parameters are supported: - -- **show_price**: Display product prices (default: Yes) -- **show_product_list**: Display list of products in cart (default: Yes) -- **moduleclass_sfx**: Custom CSS class suffix - -## HTML Structure - -``` -.mod-vm-cart-responsive - ├── .mod-vm-cart__header (if items in cart) - │ ├── .mod-vm-cart__icon - │ └── .mod-vm-cart__summary - │ ├── .mod-vm-cart__count - │ └── .mod-vm-cart__total - ├── .mod-vm-cart__products (if show_product_list) - │ └── .mod-vm-cart__product (foreach product) - │ ├── .mod-vm-cart__product-image - │ ├── .mod-vm-cart__product-details - │ │ ├── .mod-vm-cart__product-name - │ │ ├── .mod-vm-cart__product-quantity - │ │ └── .mod-vm-cart__product-price - │ └── .mod-vm-cart__product-remove - └── .mod-vm-cart__actions - ├── .mod-vm-cart__btn--view - └── .mod-vm-cart__btn--checkout -``` - -## CSS Classes - -### Main Container -- `.mod-vm-cart-responsive` - Main wrapper with responsive styles - -### Header Section -- `.mod-vm-cart__header` - Cart summary container -- `.mod-vm-cart__icon` - Shopping basket icon -- `.mod-vm-cart__summary` - Summary information wrapper -- `.mod-vm-cart__count` - Number of items -- `.mod-vm-cart__total` - Total price display - -### Product List -- `.mod-vm-cart__products` - Products container -- `.mod-vm-cart__product` - Individual product card -- `.mod-vm-cart__product-image` - Product image container -- `.mod-vm-cart__product-details` - Product information -- `.mod-vm-cart__product-name` - Product title -- `.mod-vm-cart__product-quantity` - Quantity display -- `.mod-vm-cart__product-price` - Price display -- `.mod-vm-cart__product-remove` - Remove button container -- `.mod-vm-cart__remove-btn` - Delete button - -### Actions -- `.mod-vm-cart__actions` - Action buttons container -- `.mod-vm-cart__btn` - Base button class -- `.mod-vm-cart__btn--view` - View cart button -- `.mod-vm-cart__btn--checkout` - Checkout button - -### Empty State -- `.mod-vm-cart__empty` - Empty cart container -- `.mod-vm-cart__empty-icon` - Empty state icon -- `.mod-vm-cart__empty-text` - Empty state message - -## CSS Variables Used - -```css ---vm-surface /* Background colors */ ---vm-surface-2 /* Alternative background */ ---vm-text /* Main text color */ ---vm-text-strong /* Strong emphasis text */ ---vm-text-muted /* Muted/secondary text */ ---vm-border /* Border colors */ ---vm-price-color /* Price display color */ ---vm-block-radius /* Border radius */ ---vm-block-shadow /* Box shadow */ ---vm-btn-primary-bg /* Primary button background */ ---vm-btn-primary-text /* Primary button text */ ---vm-btn-padding-y /* Button vertical padding */ ---vm-btn-padding-x /* Button horizontal padding */ ---vm-btn-radius /* Button border radius */ ---danger /* Delete button color */ -``` - -## Accessibility Features - -- ✅ ARIA label on remove buttons with product name -- ✅ Proper semantic HTML structure -- ✅ Icon elements marked with `aria-hidden="true"` -- ✅ Keyboard navigation support -- ✅ Focus indicators on interactive elements -- ✅ Touch-friendly target sizes -- ✅ Color contrast compliance - -## Customization Examples - -### Adjust Cart Width -```css -.mod-vm-cart-responsive { - max-width: 400px; - margin: 0 auto; -} -``` - -### Customize Product Card Spacing -```css -.mod-vm-cart__products { - gap: 1.5rem; -} -``` - -### Change Button Layout -```css -@media (min-width: 768px) { - .mod-vm-cart__actions { - flex-direction: column; - gap: 1rem; - } -} -``` - -### Style Empty State -```css -.mod-vm-cart__empty { - padding: 3rem 1.5rem; - background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); -} -``` - -## Integration with VirtueMart - -This override works seamlessly with: -- VirtueMart 3.x and 4.x -- Standard VirtueMart cart functionality -- AJAX cart updates (if configured) -- Multiple currency support -- Tax calculations - -## Browser Compatibility - -- ✅ Modern browsers (Chrome, Firefox, Safari, Edge) -- ✅ iOS Safari (no zoom on input/button touch) -- ✅ Android Chrome -- ✅ Touch and mouse input -- ✅ All screen sizes from 320px+ - -## Testing Checklist - -- [ ] Add products to cart -- [ ] Verify item count updates -- [ ] Test remove button functionality -- [ ] Check price calculations -- [ ] Verify cart view link works -- [ ] Test checkout button redirect -- [ ] Check empty cart state -- [ ] Test on mobile device (< 576px) -- [ ] Test on tablet (576px - 767px) -- [ ] Test on desktop (≥ 768px) -- [ ] Verify touch targets are adequate -- [ ] Test with screen reader -- [ ] Check keyboard navigation - -## License - -Copyright (C) 2025 Moko Consulting -Licensed under GNU General Public License version 2 or later diff --git a/src/templates/html/mod_virtuemart_cart/index.html b/src/templates/html/mod_virtuemart_cart/index.html deleted file mode 100644 index 09b7ab1..0000000 --- a/src/templates/html/mod_virtuemart_cart/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/templates/html/mod_virtuemart_category/README.md b/src/templates/html/mod_virtuemart_category/README.md deleted file mode 100644 index 04682eb..0000000 --- a/src/templates/html/mod_virtuemart_category/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# mod_virtuemart_category Mobile Responsive Override - -## Overview -Mobile-responsive category navigation with hierarchical structure, optional images, product counts, and active state highlighting. - -## Key Features -- Hierarchical category/subcategory display -- Optional category images (40x40px) -- Product count badges -- Active page highlighting -- Touch-friendly links (48px mobile, 44px desktop) -- Collapsible subcategory lists - -## Responsive Features -- Full-width category links on mobile -- Indented subcategory lists -- Active state styling -- Hover effects - -## Module Parameters Supported -- `show_images` - Display category images -- `show_description` - Show category descriptions -- `show_product_count` - Display product counts -- `moduleclass_sfx` - Custom CSS suffix - -## CSS Classes -- `.mod-vm-category-responsive` - Main container -- `.mod-vm-category__nav` - Navigation element -- `.mod-vm-category__list` - Main category list -- `.mod-vm-category__item` - Category item -- `.mod-vm-category__link` - Category link -- `.mod-vm-category__link--active` - Active category -- `.mod-vm-category__sublist` - Subcategory list -- `.mod-vm-category__sublink` - Subcategory link - -## Customization Example -```css -.mod-vm-category__link { - border-radius: 10px; - padding: 1rem; -} - -.mod-vm-category__image { - width: 50px; - height: 50px; -} -``` - -## Accessibility -- Semantic navigation element -- `aria-current="page"` on active items -- ARIA labels for navigation -- Keyboard navigation support - -## License -Copyright (C) 2025 Moko Consulting -GNU General Public License version 2 or later diff --git a/src/templates/html/mod_virtuemart_category/index.html b/src/templates/html/mod_virtuemart_category/index.html deleted file mode 100644 index 09b7ab1..0000000 --- a/src/templates/html/mod_virtuemart_category/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/templates/html/mod_virtuemart_currencies/README.md b/src/templates/html/mod_virtuemart_currencies/README.md deleted file mode 100644 index 00f8ef4..0000000 --- a/src/templates/html/mod_virtuemart_currencies/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# mod_virtuemart_currencies Mobile Responsive Override - -## Overview -Mobile-responsive currency selector with custom-styled dropdown, touch-friendly controls, and automatic form submission on change. - -## Key Features -- Custom styled select dropdown with icon -- 16px font size on mobile (prevents iOS zoom) -- Auto-submit on currency change (JavaScript) -- Fallback submit button for no-JS users -- Full keyboard accessibility - -## Responsive Features - -| Screen Size | Input Height | Font Size | -|------------|--------------|-----------| -| Mobile (< 576px) | 48px | 16px | -| Desktop (≥ 768px) | 44px | 1rem | - -## Module Parameters Supported -- `text_before` - Text displayed before selector -- `text_after` - Text displayed after selector -- `moduleclass_sfx` - Custom CSS suffix - -## CSS Classes -- `.mod-vm-currencies-responsive` - Main container -- `.mod-vm-currencies__form` - Form element -- `.mod-vm-currencies__label` - Label text -- `.mod-vm-currencies__select-wrapper` - Select container -- `.mod-vm-currencies__select` - Dropdown element -- `.mod-vm-currencies__icon` - Chevron icon -- `.mod-vm-currencies__submit` - Submit button (no-JS) - -## Customization Example -```css -.mod-vm-currencies__select { - border-radius: 25px; - padding: 0.75rem 3rem 0.75rem 1.5rem; -} -``` - -## Accessibility -- Proper label association -- ARIA labels for screen readers -- Keyboard navigation support -- Focus indicators - -## License -Copyright (C) 2025 Moko Consulting -GNU General Public License version 2 or later diff --git a/src/templates/html/mod_virtuemart_currencies/index.html b/src/templates/html/mod_virtuemart_currencies/index.html deleted file mode 100644 index 09b7ab1..0000000 --- a/src/templates/html/mod_virtuemart_currencies/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/templates/html/mod_virtuemart_manufacturer/README.md b/src/templates/html/mod_virtuemart_manufacturer/README.md deleted file mode 100644 index 045860f..0000000 --- a/src/templates/html/mod_virtuemart_manufacturer/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# mod_virtuemart_manufacturer Mobile Responsive Override - -## Overview -Mobile-responsive manufacturer display with grid/list layouts, logo images, and responsive card designs. - -## Key Features -- Grid or list display modes -- Responsive manufacturer cards -- Logo/image display with aspect ratio control -- Manufacturer descriptions -- Hover effects and transitions - -## Responsive Layouts - -| Screen Size | Grid Mode | List Mode | -|------------|-----------|-----------| -| Mobile (< 576px) | 1 column | 1 column | -| Tablet (576px - 767px) | 2 columns | 1 column | -| Desktop (768px - 991px) | 3 columns | 1 column | -| Large Desktop (≥ 992px) | 4 columns | 1 column | - -## Module Parameters Supported -- `show_images` - Display manufacturer logos -- `display_style` - Layout mode (list/grid) -- `moduleclass_sfx` - Custom CSS suffix - -## CSS Classes -- `.mod-vm-manufacturer-responsive` - Main container -- `.mod-vm-manufacturer__container` - Grid/list container -- `.mod-vm-manufacturer__container--list` - List layout -- `.mod-vm-manufacturer__container--grid` - Grid layout -- `.mod-vm-manufacturer__item` - Manufacturer card -- `.mod-vm-manufacturer__link` - Clickable link -- `.mod-vm-manufacturer__image` - Logo container -- `.mod-vm-manufacturer__name` - Manufacturer name -- `.mod-vm-manufacturer__description` - Description text - -## Customization Example -```css -.mod-vm-manufacturer__image { - aspect-ratio: 1/1; - border-radius: 50%; -} - -.mod-vm-manufacturer__container--grid { - gap: 2rem; -} -``` - -## Accessibility -- Proper link structure -- Title attributes on links -- Semantic HTML -- Keyboard navigation -- Focus indicators - -## License -Copyright (C) 2025 Moko Consulting -GNU General Public License version 2 or later diff --git a/src/templates/html/mod_virtuemart_manufacturer/index.html b/src/templates/html/mod_virtuemart_manufacturer/index.html deleted file mode 100644 index 09b7ab1..0000000 --- a/src/templates/html/mod_virtuemart_manufacturer/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/templates/html/mod_virtuemart_product/README.md b/src/templates/html/mod_virtuemart_product/README.md deleted file mode 100644 index b6ad18e..0000000 --- a/src/templates/html/mod_virtuemart_product/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# mod_virtuemart_product Mobile Responsive Override - -## Overview -Mobile-responsive override for VirtueMart's product display module featuring grid/list layouts, responsive product cards, and touch-friendly controls. - -## Key Features -- Responsive grid layout (1-4 columns based on screen size) -- Product card with image, title, description, price -- Touch-friendly action buttons (48px mobile, 44px desktop) -- Availability badges -- Add to cart functionality - -## Responsive Layouts - -| Screen Size | Grid Columns | -|------------|--------------| -| Mobile (< 576px) | 1 column | -| Tablet (576px - 767px) | 2 columns | -| Desktop (768px - 991px) | 3 columns | -| Large Desktop (≥ 992px) | 4 columns | - -## Module Parameters Supported -- `headerText` - Header text above products -- `display_style` - Layout style (div, list) -- `moduleclass_sfx` - Custom CSS suffix - -## CSS Classes -- `.mod-vm-product-responsive` - Main container -- `.mod-vm-product__list` - Products grid -- `.mod-vm-product__item` - Product card -- `.mod-vm-product__image` - Product image -- `.mod-vm-product__title` - Product name -- `.mod-vm-product__description` - Short description -- `.mod-vm-product__price` - Price display -- `.mod-vm-product__actions` - Action buttons - -## Customization Example -```css -.mod-vm-product__list { - gap: 2rem; -} - -.mod-vm-product__item { - border-radius: 1rem; -} -``` - -## License -Copyright (C) 2025 Moko Consulting -GNU General Public License version 2 or later diff --git a/src/templates/html/mod_virtuemart_product/index.html b/src/templates/html/mod_virtuemart_product/index.html deleted file mode 100644 index 09b7ab1..0000000 --- a/src/templates/html/mod_virtuemart_product/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/templates/CLIENT_FORK_README_TEMPLATE.md b/templates/CLIENT_FORK_README_TEMPLATE.md deleted file mode 100644 index 4b2d497..0000000 --- a/templates/CLIENT_FORK_README_TEMPLATE.md +++ /dev/null @@ -1,57 +0,0 @@ - - -# [CLIENT NAME] - MokoCassiopeia Custom - -Custom Joomla template fork for **[CLIENT NAME]**. - ---- - -## 🎨 Custom Branding - -**Brand Colors**: -- Primary: `[COLOR]` -- Accent: `[COLOR]` -- Background: `[COLOR]` - -**Custom Files**: -- Light mode colors: `src/media/css/colors/light/colors_custom.css` -- Dark mode colors: `src/media/css/colors/dark/colors_custom.css` -- Custom PHP code: `src/templates/custom.php` - ---- - -## 🔄 Syncing with Upstream - -```bash -# Add upstream remote (first time only) -git remote add upstream https://github.com/mokoconsulting-tech/MokoCassiopeia.git - -# Sync with upstream -git fetch upstream -git merge upstream/main -``` - ---- - -## 📚 Documentation - -- **Full Client Fork Guide**: [CLIENT_FORK_README.md](../CLIENT_FORK_README.md) -- **MokoCassiopeia Docs**: https://github.com/mokoconsulting-tech/MokoCassiopeia -- **CSS Variables**: [docs/CSS_VARIABLES.md](../docs/CSS_VARIABLES.md) - ---- - -## 📝 Quick Notes - -[Add your client-specific notes here] - ---- - -**Fork of**: [MokoCassiopeia](https://github.com/mokoconsulting-tech/MokoCassiopeia) v03.06.03 -**Last Synced**: [DATE] -**Contact**: [CONTACT INFO] diff --git a/templates/README.md b/templates/README.md index b5b78e3..0ca8b74 100644 --- a/templates/README.md +++ b/templates/README.md @@ -5,77 +5,113 @@ BRIEF: Template files directory README --> -# MokoCassiopeia Template Files +# MokoCassiopeia Templates Directory -This directory contains template files for client customizations and custom code forks. +This directory contains template files for custom color schemes that can be copied to your template installation. ---- +## Custom Theme Palette Templates -## 📁 Available Templates +Template files are provided for both light and dark themes with complete Bootstrap button definitions: -### Custom Color Scheme Template +### Available Templates -**File**: `colors_custom.css` +| File | Theme | Description | +|------|-------|-------------| +| `light.custom.css` | Light | Custom light theme with all Bootstrap button variants | +| `dark.custom.css` | Dark | Custom dark theme with all Bootstrap button variants | -A comprehensive template for creating custom color schemes. This template includes all CSS variables used by MokoCassiopeia for both light and dark modes. +### Using Custom Theme Templates -**Usage**: -1. Copy this file to either: - - `src/media/css/colors/light/colors_custom.css` (for light mode) - - `src/media/css/colors/dark/colors_custom.css` (for dark mode) -2. Customize the CSS variables to match your brand colors -3. Enable in Joomla: System → Site Templates → MokoCassiopeia → Theme tab -4. Set the appropriate palette to "Custom" +1. **Copy** the template file to your template's CSS theme directory: + ```bash + # For light theme + cp templates/light.custom.css src/media/css/theme/light.custom.css + + # For dark theme + cp templates/dark.custom.css src/media/css/theme/dark.custom.css + ``` -**Reference**: See [CSS Variables Documentation](../docs/CSS_VARIABLES.md) for complete variable reference. +2. **Customize** the CSS variables in your copied file: + - Modify `--color-primary`, `--accent-color-primary`, etc. to match your brand + - Adjust Bootstrap state colors (`--success`, `--info`, `--warning`, `--danger`) + - Update button variants if needed ---- +3. **Register** in `src/joomla.asset.json`: + - Ensure `template.light.custom` and `template.dark.custom` assets are defined + - Already configured by default in the asset manifest -### Client Fork README Template +4. **Activate** via Joomla admin: + - Go to System → Site Templates → MokoCassiopeia + - Select "Custom" in the Theme Palette dropdown + - Save and check your site -**File**: `CLIENT_FORK_README_TEMPLATE.md` +### Bootstrap Button Variants Included -A simplified README template for client-specific forks. Use this as a starting point for documenting your customizations. +All template files include complete definitions for: -**Usage**: -1. Copy this file to the root of your fork repository as `README.md` -2. Replace `[CLIENT NAME]` with your client's name -3. Fill in brand colors and contact information -4. Add client-specific notes and configurations +**Solid Buttons:** +- `.btn-primary`, `.btn-secondary`, `.btn-success`, `.btn-info`, `.btn-warning`, `.btn-danger`, `.btn-light`, `.btn-dark` -**For Comprehensive Fork Setup**: See [CLIENT_FORK_README.md](../CLIENT_FORK_README.md) for the complete client fork guide. +**Outline Buttons:** +- `.btn-outline-primary`, `.btn-outline-secondary`, `.btn-outline-success`, `.btn-outline-info`, `.btn-outline-warning`, `.btn-outline-danger`, `.btn-outline-light`, `.btn-outline-dark` ---- +Each button variant includes hover, active, focus, and disabled states using CSS variables. -## 🎯 When to Use These Templates +## Theme System Features -### Creating a Client Fork +### CSS Variable Structure -If you're creating a custom fork of MokoCassiopeia for a specific client: +Colors are defined as CSS variables allowing easy customization: -1. **Start with the full guide**: Read [CLIENT_FORK_README.md](../CLIENT_FORK_README.md) -2. **Set up custom colors**: Use `colors_custom.css` as your starting point -3. **Document your fork**: Copy `CLIENT_FORK_README_TEMPLATE.md` to your fork +```css +:root[data-bs-theme="light"] { + --color-primary: #0066cc; + --accent-color-primary: #3399ff; + --success: #28a745; + --danger: #dc3545; + /* ...and many more */ +} +``` -### Custom Colors Only +### Opacity Utilities -If you just need custom colors without forking: +Template includes opacity utility variables for creating translucent colors: -1. Use the `colors_custom.css` template -2. Follow the instructions in the [main README](../README.md#custom-color-palettes) -3. Enable custom palette in Joomla template settings +```css +--opacity-5: 0.05; +--opacity-10: 0.1; +--opacity-15: 0.15; +--opacity-25: 0.25; +--opacity-50: 0.5; +--opacity-75: 0.75; +--opacity-100: 1; +``` + +Use with rgba(): +```css +background-color: rgba(var(--black-rgb), var(--opacity-10)); +``` + +### Shadow Color Utilities + +Pre-defined shadow color variables: + +```css +--shadow-color-light: rgba(var(--black-rgb), var(--opacity-15)); +--shadow-color-medium: rgba(var(--black-rgb), var(--opacity-25)); +--shadow-color-dark: rgba(var(--black-rgb), var(--opacity-30)); +``` --- ## 📚 Additional Resources - **[Main README](../README.md)** - MokoCassiopeia features and installation -- **[Client Fork Guide](../CLIENT_FORK_README.md)** - Complete guide for client forks - **[CSS Variables Reference](../docs/CSS_VARIABLES.md)** - All available CSS variables - **[Development Guide](../docs/JOOMLA_DEVELOPMENT.md)** - Development workflows --- **Template Directory**: `/templates/` -**Version**: 03.06.03 +**Version**: 03.08.04 **Maintained by**: Moko Consulting diff --git a/templates/colors_custom.css b/templates/colors_custom.css deleted file mode 100644 index 1ebc90a..0000000 --- a/templates/colors_custom.css +++ /dev/null @@ -1,424 +0,0 @@ -@charset "UTF-8"; -/* Copyright (C) 2025 Moko Consulting - - This file is part of a Moko Consulting project. - - SPDX-License-Identifier: GPL-3.0-or-later - - # FILE INFORMATION - DEFGROUP: Joomla.Template.Site - INGROUP: MokoCassiopeia.Templates - PATH: ./templates/colors_custom_dark.css - VERSION: 03.06.03 - BRIEF: Template for custom dark mode color definitions - - # USAGE INSTRUCTIONS - 1. Copy this file to: - `media/templates/site/mokocassiopeia/css/colors/dark/colors_custom.css` - or - `media/templates/site/mokocassiopeia/css/colors/light/colors_custom.css` ` - 2. Customize the CSS variables below to match your brand colors for dark mode - 3. In Joomla admin, go to System → Site Templates → MokoCassiopeia - 4. Under Theme tab, set "Dark Mode Palette" to "Custom" - 5. Save and view your site in dark mode to see the custom colors - - NOTE: This file is excluded from version control (.gitignore) to prevent - fork-specific customizations from being committed to the repository. - */ - -/* ----------------------------------------------- - * CUSTOM DARK THEME - * --------------------------------------------- */ - -:root[data-bs-theme='dark']{ -color-scheme: dark; - -/* ===== BRAND & THEME COLORS ===== */ ---color-primary: #112855; ---accent-color-primary: #3f8ff0; ---accent-color-secondary: #6fb3ff; - -/* ===== NAVIGATION ===== */ ---mainmenu-nav-link-color: #fff; ---nav-text-color: gray; ---nav-bg-color: var(--color-primary); - -/* ===== LINKS ===== */ ---color-link: white; ---color-hover: gray; ---color-active: var(--mainmenu-nav-link-color); ---link-color: #8ab4f8; ---link-color-rgb: 138, 180, 248; ---link-decoration: underline; ---link-hover-color: #c3d6ff; ---link-hover-color-rgb: 195, 214, 255; ---link-active-color: var(--link-color); - -/* ===== OFFCANVAS ===== */ ---offcanvas-color: var(--body-color); ---offcanvas-padding-x: 1rem; ---offcanvas-padding-y: 1rem; - -/* ===== NAVBAR ===== */ ---navbar-padding-x: 1rem; ---navbar-padding-y: 0.5rem; ---navbar-color: var(--nav-text-color); ---navbar-active-color: var(--mainmenu-nav-link-color); ---navbar-disabled-color: #6c757d; ---navbar-brand-padding-y: 0.3125rem; ---navbar-brand-margin-end: 1rem; ---navbar-brand-font-size: 1.25rem; ---navbar-brand-color: var(--nav-text-color); ---navbar-brand-active-color: var(--mainmenu-nav-link-color); ---navbar-nav-link-padding-x: 0.5rem; ---navbar-toggler-padding-y: 0.25rem; ---navbar-toggler-padding-x: 0.75rem; ---navbar-toggler-font-size: 1.25rem; ---navbar-toggler-border-color: rgba(255, 255, 255, 0.1); ---navbar-toggler-border-radius: 0.25rem; ---navbar-toggler-focus-width: 0.25rem; ---navbar-toggler-transition: box-shadow 0.15s ease-in-out; ---nav-link-padding-x: 1rem; ---nav-link-padding-y: 0.5rem; ---nav-link-font-weight: 400; ---nav-link-color: var(--nav-text-color); ---nav-link-active-color: var(--mainmenu-nav-link-color); ---nav-link-disabled-color: #6c757d; - -/* ===== TYPOGRAPHY & BODY ===== */ ---font-sans-serif: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; ---font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; ---body-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif; ---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; ---heading-color: #f1f5f9; ---emphasis-color: #fff; ---emphasis-color-rgb: 255, 255, 255; ---secondary-color: #e6ebf1bf; ---secondary-color-rgb: 230, 235, 241; ---tertiary-color: #e6ebf180; ---tertiary-color-rgb: 230, 235, 241; ---muted-color: #6d757e; ---code-color: #ff7abd; ---code-color-ink: var(--code-color, #e93f8e); ---highlight-color: #111; ---highlight-bg: #ffe28a1a; - -/* ===== LAYOUT & SPACING ===== */ ---padding-x: 0.15rem; ---padding-y: 0.15rem; ---bg-opacity: 1; ---nav-toggle-size: 3rem; ---gradient: linear-gradient(180deg, #ffffff26, #fff0); ---secondary-bg: #151b22; ---secondary-bg-rgb: 21, 27, 34; ---tertiary-bg: #10151b; ---tertiary-bg-rgb: 16, 21, 27; ---hr-color: var(--border-color, #dfe3e7); ---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); ---border: 5px; - -/* ===== BREAKPOINTS ===== */ ---bp-xs: 0; ---bp-sm: 576px; ---bp-md: 768px; ---bp-lg: 992px; ---bp-xl: 1200px; - -/* ===== BOOTSTRAP PALETTE ===== */ ---primary: #010156; ---secondary: #48525d; ---success: #4aa664; ---info: #4f7aa0; ---warning: #c77a00; ---danger: #c23a31; ---light: #1b2027; ---dark: #0f1318; ---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; ---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; - -/* ===== STANDARD COLORS ===== */ ---blue: #91a4ff; ---indigo: #b19cff; ---purple: #c0a5ff; ---pink: #ff8fc0; ---red: #ff7a73; ---orange: #ff9c4d; ---yellow: #ffd166; ---green: #78d694; ---teal: #76e3ff; ---cyan: #6fb7ff; ---black: #000; ---white: #fff; - -/* ===== GRAY SCALE ===== */ ---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; ---white-rgb: 255, 255, 255; ---black-rgb: 0, 0, 0; - -/* ===== HEADER BACKGROUND ===== */ ---header-background-image: url('../../../../../../media/templates/site/mokocassiopeia/images/bg.svg'); ---header-background-attachment: fixed; ---header-background-repeat: repeat; ---header-background-size: auto; - -/* ===== CONTAINER BACKGROUNDS ===== */ -/* Below Topbar Container */ ---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: ; - -/* Top A Container */ ---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: ; - -/* Top B Container */ ---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: ; - -/* TOC Container */ ---container-toc-bg: ; ---container-toc-color: #dbe3ff; - -/* Sidebar Container */ ---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: ; - -/* Bottom A Container */ ---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: ; - -/* Bottom B Container */ ---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: ; - -/* ===== BORDERS ===== */ ---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-pill: 50rem; - -/* ===== SHADOWS ===== */ ---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 & FORMS ===== */ ---focus-ring-width: .25rem; ---focus-ring-opacity: .6; ---focus-ring-color: #5472ff66; ---input-color: #e6ebf1; ---input-bg: #1a2332; ---input-border-color: #3a4250; ---input-focus-border-color: #5472ff; ---input-focus-box-shadow: 0 0 0 0.25rem rgba(84, 114, 255, 0.25); ---input-placeholder-color: #8894aa; ---input-disabled-bg: #0f1318; ---input-disabled-border-color: #2b323b; ---form-valid-color: #78d694; ---form-valid-border-color: #78d694; ---form-invalid-color: #ff8e86; ---form-invalid-border-color: #ff8e86; - -/* ===== BUTTONS ===== */ ---btn-border-radius: var(--border-radius); ---btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 1px 1px rgba(0, 0, 0, 0.3); - -/* ===== CARDS ===== */ ---card-spacer-y: 1rem; ---card-spacer-x: 1rem; ---card-title-spacer-y: 0.5rem; ---card-border-width: 1px; ---card-border-color: var(--border-color); ---card-border-radius: var(--border-radius); ---card-box-shadow: none; ---card-inner-border-radius: calc(var(--border-radius) - 1px); ---card-cap-padding-y: 0.5rem; ---card-cap-padding-x: 1rem; ---card-cap-bg: rgba(255, 255, 255, 0.03); ---card-cap-color: var(--body-color); ---card-height: auto; ---card-color: var(--body-color); ---card-bg: var(--secondary-bg); ---card-img-overlay-padding: 1rem; ---card-group-margin: 0.75rem; - -/* ===== VIRTUEMART (VM) ===== */ -/* VM Surfaces */ ---vm-surface: var(--secondary-bg); ---vm-surface-2: var(--tertiary-bg); ---vm-text: var(--body-color); ---vm-text-strong: #ffffff; ---vm-text-muted: var(--gray-700); ---vm-border: var(--border-color); ---vm-price-color: var(--success); - -/* VM Layout and Density */ ---vm-container-max-width: 1200px; ---vm-section-gap: 2rem; ---vm-block-radius: var(--border-radius); ---vm-block-shadow: var(--box-shadow-sm); - -/* VM Typography */ ---vm-category-title-size: 2rem; ---vm-subcategory-title-size: 1.5rem; ---vm-page-title-size: 1.75rem; ---vm-products-type-title-size: 1.25rem; ---vm-product-title-size: 1.125rem; ---vm-product-title-weight: 500; ---vm-products-type-title-weight: 600; ---vm-price-size: 1.5rem; ---vm-price-detail-size: 1.125rem; ---vm-price-desc-size: 0.875rem; - -/* VM Controls */ ---vm-input-radius: var(--border-radius); ---vm-input-shadow: var(--box-shadow-sm); ---vm-qty-width: 80px; ---vm-cart-dropdown-min-width: 300px; - -/* VM Alerts */ ---vm-alert-radius: var(--border-radius); ---vm-alert-shadow: var(--box-shadow-sm); ---vm-availability-bg: var(--success-bg-subtle); ---vm-availability-text: var(--success); - -/* VM Buttons */ ---vm-btn-padding-x: 1rem; ---vm-btn-padding-y: 0.5rem; ---vm-btn-radius: var(--border-radius); ---vm-btn-shadow: var(--box-shadow-sm); ---vm-btn-primary-bg: var(--primary); ---vm-btn-primary-text: #ffffff; ---vm-btn-primary-border: var(--primary); ---vm-btn-secondary-bg: var(--secondary); ---vm-btn-secondary-text: #ffffff; ---vm-btn-secondary-border: var(--secondary); - -/* VM Image Overlay Controls */ ---vm-image-overlay-gap-x: 0.5rem; ---vm-image-overlay-gap-y: 0.5rem; ---vm-image-overlay-raise: 0.25rem; ---vm-image-overlay-btn-size: 2.5rem; ---vm-image-overlay-btn-radius: 50%; ---vm-image-overlay-btn-bg: rgba(0, 0, 0, 0.7); ---vm-image-overlay-btn-bg-hover: rgba(0, 0, 0, 0.85); ---vm-image-overlay-btn-border-color: rgba(255, 255, 255, 0.2); ---vm-image-overlay-btn-border-width: 1px; ---vm-image-overlay-btn-color: var(--body-color); ---vm-image-overlay-btn-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); - -/* VM Vendor Menu */ ---vm-vendor-menu-bg: var(--secondary-bg); ---vm-vendor-menu-border: var(--border-color); ---vm-vendor-menu-radius: var(--border-radius); ---vm-vendor-menu-shadow: var(--box-shadow-sm); ---vm-vendor-menu-item-gap: 0.25rem; ---vm-vendor-menu-item-padding-x: 1rem; ---vm-vendor-menu-item-padding-y: 0.5rem; ---vm-vendor-menu-pill-radius: 50rem; ---vm-vendor-menu-link: var(--link-color); ---vm-vendor-menu-link-hover: var(--link-hover-color); ---vm-vendor-menu-link-active: var(--primary); ---vm-vendor-menu-hover-bg: var(--tertiary-bg); - -/* ===== GABLE ===== */ ---gab-blue: #4d9fff; ---gab-green: #5cb85c; ---gab-red: #ff6b6b; ---gab-orange: #ff9f5a; ---gab-gray1: #868e96; ---gab-gray2: #adb5bd; ---gab-gray3: #ced4da; -} diff --git a/templates/dark.custom.css b/templates/dark.custom.css new file mode 100644 index 0000000..8739731 --- /dev/null +++ b/templates/dark.custom.css @@ -0,0 +1,327 @@ +@charset "UTF-8"; +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Templates + PATH: ./templates/dark.custom.css + VERSION: 03.08.04 + BRIEF: Custom dark theme color template with Bootstrap button definitions + */ + +/* ----------------------------------------------- + * CUSTOM DARK THEME TEMPLATE + * + * Copy this file to: + * src/media/css/theme/dark.custom.css + * + * Then register it in src/joomla.asset.json under + * template.dark.custom asset. + * --------------------------------------------- */ + +:root[data-bs-theme='dark'] { + /* ===== BRAND COLORS (Customize these) ===== */ + --color-primary: #3399ff; + --accent-color-primary: #66b3ff; + --accent-color-secondary: #99ccff; + + /* ===== LINKS ===== */ + --link-color: #6bb3ff; + --link-hover-color: #99ccff; + + /* ===== BODY & TYPOGRAPHY ===== */ + --body-color: #e9ecef; + --body-bg: #0e1318; + + /* ===== BOOTSTRAP STATE COLORS ===== */ + --success: #5cb85c; + --info: #5bc0de; + --warning: #ffc107; + --danger: #d9534f; + + /* ===== NAVIGATION ===== */ + --nav-bg-color: var(--color-primary); + --nav-text-color: #ffffff; +} + +/* ===== BOOTSTRAP BUTTON VARIANTS ===== */ + +.btn-primary { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--color-primary); + --btn-border-color: var(--color-primary); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #2680e6; + --btn-hover-border-color: #1f73d9; + --btn-focus-shadow-rgb: 82, 168, 255; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #1f73d9; + --btn-active-border-color: #1a66cc; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--color-primary); + --btn-disabled-border-color: var(--color-primary); +} + +.btn-secondary { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: #6c757d; + --btn-border-color: #6c757d; + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #5c636a; + --btn-hover-border-color: #565e64; + --btn-focus-shadow-rgb: 130, 138, 145; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #565e64; + --btn-active-border-color: #51585e; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: #6c757d; + --btn-disabled-border-color: #6c757d; +} + +.btn-success { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--success); + --btn-border-color: var(--success); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #4cae4c; + --btn-hover-border-color: #449d44; + --btn-focus-shadow-rgb: 113, 198, 113; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #449d44; + --btn-active-border-color: #398439; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--success); + --btn-disabled-border-color: var(--success); +} + +.btn-info { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--info); + --btn-border-color: var(--info); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #46b8da; + --btn-hover-border-color: #31b0d5; + --btn-focus-shadow-rgb: 116, 204, 233; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #31b0d5; + --btn-active-border-color: #269abc; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--info); + --btn-disabled-border-color: var(--info); +} + +.btn-warning { + --btn-color: hsl(0, 0%, 0%); + --btn-bg: var(--warning); + --btn-border-color: var(--warning); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: #edb100; + --btn-hover-border-color: #d39e00; + --btn-focus-shadow-rgb: 222, 170, 12; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: #d39e00; + --btn-active-border-color: #c69500; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 0%); + --btn-disabled-bg: var(--warning); + --btn-disabled-border-color: var(--warning); +} + +.btn-danger { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--danger); + --btn-border-color: var(--danger); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #d43f3a; + --btn-hover-border-color: #c9302c; + --btn-focus-shadow-rgb: 223, 109, 105; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #c9302c; + --btn-active-border-color: #ac2925; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--danger); + --btn-disabled-border-color: var(--danger); +} + +.btn-light { + --btn-color: hsl(0, 0%, 0%); + --btn-bg: #e9ecef; + --btn-border-color: #e9ecef; + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: #d3d6d9; + --btn-hover-border-color: #c8cbcf; + --btn-focus-shadow-rgb: 204, 207, 210; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: #c8cbcf; + --btn-active-border-color: #bdc1c5; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 0%); + --btn-disabled-bg: #e9ecef; + --btn-disabled-border-color: #e9ecef; +} + +.btn-dark { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: #2c3136; + --btn-border-color: #2c3136; + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #1e2124; + --btn-hover-border-color: #191c1f; + --btn-focus-shadow-rgb: 70, 75, 80; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #191c1f; + --btn-active-border-color: #14161a; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: #2c3136; + --btn-disabled-border-color: #2c3136; +} + +/* ===== OUTLINE BUTTON VARIANTS ===== */ + +.btn-outline-primary { + --btn-color: var(--color-primary); + --btn-border-color: var(--color-primary); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: var(--color-primary); + --btn-hover-border-color: var(--color-primary); + --btn-focus-shadow-rgb: 82, 168, 255; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: var(--color-primary); + --btn-active-border-color: var(--color-primary); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--color-primary); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--color-primary); + --gradient: none; +} + +.btn-outline-secondary { + --btn-color: #8c959f; + --btn-border-color: #8c959f; + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: #8c959f; + --btn-hover-border-color: #8c959f; + --btn-focus-shadow-rgb: 150, 158, 167; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: #8c959f; + --btn-active-border-color: #8c959f; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: #8c959f; + --btn-disabled-bg: transparent; + --btn-disabled-border-color: #8c959f; + --gradient: none; +} + +.btn-outline-success { + --btn-color: var(--success); + --btn-border-color: var(--success); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: var(--success); + --btn-hover-border-color: var(--success); + --btn-focus-shadow-rgb: 113, 198, 113; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: var(--success); + --btn-active-border-color: var(--success); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--success); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--success); + --gradient: none; +} + +.btn-outline-info { + --btn-color: var(--info); + --btn-border-color: var(--info); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: var(--info); + --btn-hover-border-color: var(--info); + --btn-focus-shadow-rgb: 116, 204, 233; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: var(--info); + --btn-active-border-color: var(--info); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--info); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--info); + --gradient: none; +} + +.btn-outline-warning { + --btn-color: var(--warning); + --btn-border-color: var(--warning); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: var(--warning); + --btn-hover-border-color: var(--warning); + --btn-focus-shadow-rgb: 222, 170, 12; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: var(--warning); + --btn-active-border-color: var(--warning); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--warning); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--warning); + --gradient: none; +} + +.btn-outline-danger { + --btn-color: var(--danger); + --btn-border-color: var(--danger); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: var(--danger); + --btn-hover-border-color: var(--danger); + --btn-focus-shadow-rgb: 223, 109, 105; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: var(--danger); + --btn-active-border-color: var(--danger); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--danger); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--danger); + --gradient: none; +} + +.btn-outline-light { + --btn-color: #e9ecef; + --btn-border-color: #e9ecef; + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: #e9ecef; + --btn-hover-border-color: #e9ecef; + --btn-focus-shadow-rgb: 204, 207, 210; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: #e9ecef; + --btn-active-border-color: #e9ecef; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: #e9ecef; + --btn-disabled-bg: transparent; + --btn-disabled-border-color: #e9ecef; + --gradient: none; +} + +.btn-outline-dark { + --btn-color: #4a5057; + --btn-border-color: #4a5057; + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #4a5057; + --btn-hover-border-color: #4a5057; + --btn-focus-shadow-rgb: 90, 95, 100; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #4a5057; + --btn-active-border-color: #4a5057; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: #4a5057; + --btn-disabled-bg: transparent; + --btn-disabled-border-color: #4a5057; + --gradient: none; +} diff --git a/templates/light.custom.css b/templates/light.custom.css new file mode 100644 index 0000000..098f7f5 --- /dev/null +++ b/templates/light.custom.css @@ -0,0 +1,327 @@ +@charset "UTF-8"; +/* Copyright (C) 2026 Moko Consulting + + This file is part of a Moko Consulting project. + + SPDX-License-Identifier: GPL-3.0-or-later + + + + # FILE INFORMATION + DEFGROUP: Joomla.Template.Site + INGROUP: MokoCassiopeia.Templates + PATH: ./templates/light.custom.css + VERSION: 03.08.04 + BRIEF: Custom light theme color template with Bootstrap button definitions + */ + +/* ----------------------------------------------- + * CUSTOM LIGHT THEME TEMPLATE + * + * Copy this file to: + * src/media/css/theme/light.custom.css + * + * Then register it in src/joomla.asset.json under + * template.light.custom asset. + * --------------------------------------------- */ + +:root[data-bs-theme="light"] { + /* ===== BRAND COLORS (Customize these) ===== */ + --color-primary: #0066cc; + --accent-color-primary: #3399ff; + --accent-color-secondary: #66b3ff; + + /* ===== LINKS ===== */ + --link-color: #0066cc; + --link-hover-color: #0052a3; + + /* ===== BODY & TYPOGRAPHY ===== */ + --body-color: #212529; + --body-bg: #ffffff; + + /* ===== BOOTSTRAP STATE COLORS ===== */ + --success: #28a745; + --info: #17a2b8; + --warning: #ffc107; + --danger: #dc3545; + + /* ===== NAVIGATION ===== */ + --nav-bg-color: var(--color-primary); + --nav-text-color: #ffffff; +} + +/* ===== BOOTSTRAP BUTTON VARIANTS ===== */ + +.btn-primary { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--color-primary); + --btn-border-color: var(--color-primary); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #0052a3; + --btn-hover-border-color: #004d99; + --btn-focus-shadow-rgb: 38, 128, 217; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #004d99; + --btn-active-border-color: #004788; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--color-primary); + --btn-disabled-border-color: var(--color-primary); +} + +.btn-secondary { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: #6c757d; + --btn-border-color: #6c757d; + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #5c636a; + --btn-hover-border-color: #565e64; + --btn-focus-shadow-rgb: 130, 138, 145; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #565e64; + --btn-active-border-color: #51585e; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: #6c757d; + --btn-disabled-border-color: #6c757d; +} + +.btn-success { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--success); + --btn-border-color: var(--success); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #218838; + --btn-hover-border-color: #1e7e34; + --btn-focus-shadow-rgb: 72, 180, 97; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #1e7e34; + --btn-active-border-color: #1c7430; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--success); + --btn-disabled-border-color: var(--success); +} + +.btn-info { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--info); + --btn-border-color: var(--info); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #138496; + --btn-hover-border-color: #117a8b; + --btn-focus-shadow-rgb: 58, 176, 195; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #117a8b; + --btn-active-border-color: #10707f; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--info); + --btn-disabled-border-color: var(--info); +} + +.btn-warning { + --btn-color: hsl(0, 0%, 0%); + --btn-bg: var(--warning); + --btn-border-color: var(--warning); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: #e0a800; + --btn-hover-border-color: #d39e00; + --btn-focus-shadow-rgb: 222, 170, 12; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: #d39e00; + --btn-active-border-color: #c69500; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 0%); + --btn-disabled-bg: var(--warning); + --btn-disabled-border-color: var(--warning); +} + +.btn-danger { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: var(--danger); + --btn-border-color: var(--danger); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #c82333; + --btn-hover-border-color: #bd2130; + --btn-focus-shadow-rgb: 225, 83, 97; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #bd2130; + --btn-active-border-color: #b21f2d; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: var(--danger); + --btn-disabled-border-color: var(--danger); +} + +.btn-light { + --btn-color: hsl(0, 0%, 0%); + --btn-bg: #f8f9fa; + --btn-border-color: #f8f9fa; + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: #e2e6ea; + --btn-hover-border-color: #dae0e5; + --btn-focus-shadow-rgb: 216, 217, 219; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: #dae0e5; + --btn-active-border-color: #d3d9df; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 0%); + --btn-disabled-bg: #f8f9fa; + --btn-disabled-border-color: #f8f9fa; +} + +.btn-dark { + --btn-color: hsl(0, 0%, 100%); + --btn-bg: #343a40; + --btn-border-color: #343a40; + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #23272b; + --btn-hover-border-color: #1d2124; + --btn-focus-shadow-rgb: 82, 88, 93; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #1d2124; + --btn-active-border-color: #171a1d; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: hsl(0, 0%, 100%); + --btn-disabled-bg: #343a40; + --btn-disabled-border-color: #343a40; +} + +/* ===== OUTLINE BUTTON VARIANTS ===== */ + +.btn-outline-primary { + --btn-color: var(--color-primary); + --btn-border-color: var(--color-primary); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: var(--color-primary); + --btn-hover-border-color: var(--color-primary); + --btn-focus-shadow-rgb: 38, 128, 217; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: var(--color-primary); + --btn-active-border-color: var(--color-primary); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--color-primary); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--color-primary); + --gradient: none; +} + +.btn-outline-secondary { + --btn-color: #6c757d; + --btn-border-color: #6c757d; + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #6c757d; + --btn-hover-border-color: #6c757d; + --btn-focus-shadow-rgb: 130, 138, 145; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #6c757d; + --btn-active-border-color: #6c757d; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: #6c757d; + --btn-disabled-bg: transparent; + --btn-disabled-border-color: #6c757d; + --gradient: none; +} + +.btn-outline-success { + --btn-color: var(--success); + --btn-border-color: var(--success); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: var(--success); + --btn-hover-border-color: var(--success); + --btn-focus-shadow-rgb: 72, 180, 97; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: var(--success); + --btn-active-border-color: var(--success); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--success); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--success); + --gradient: none; +} + +.btn-outline-info { + --btn-color: var(--info); + --btn-border-color: var(--info); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: var(--info); + --btn-hover-border-color: var(--info); + --btn-focus-shadow-rgb: 58, 176, 195; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: var(--info); + --btn-active-border-color: var(--info); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--info); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--info); + --gradient: none; +} + +.btn-outline-warning { + --btn-color: var(--warning); + --btn-border-color: var(--warning); + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: var(--warning); + --btn-hover-border-color: var(--warning); + --btn-focus-shadow-rgb: 222, 170, 12; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: var(--warning); + --btn-active-border-color: var(--warning); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--warning); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--warning); + --gradient: none; +} + +.btn-outline-danger { + --btn-color: var(--danger); + --btn-border-color: var(--danger); + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: var(--danger); + --btn-hover-border-color: var(--danger); + --btn-focus-shadow-rgb: 225, 83, 97; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: var(--danger); + --btn-active-border-color: var(--danger); + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: var(--danger); + --btn-disabled-bg: transparent; + --btn-disabled-border-color: var(--danger); + --gradient: none; +} + +.btn-outline-light { + --btn-color: #f8f9fa; + --btn-border-color: #f8f9fa; + --btn-hover-color: hsl(0, 0%, 0%); + --btn-hover-bg: #f8f9fa; + --btn-hover-border-color: #f8f9fa; + --btn-focus-shadow-rgb: 216, 217, 219; + --btn-active-color: hsl(0, 0%, 0%); + --btn-active-bg: #f8f9fa; + --btn-active-border-color: #f8f9fa; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: #f8f9fa; + --btn-disabled-bg: transparent; + --btn-disabled-border-color: #f8f9fa; + --gradient: none; +} + +.btn-outline-dark { + --btn-color: #343a40; + --btn-border-color: #343a40; + --btn-hover-color: hsl(0, 0%, 100%); + --btn-hover-bg: #343a40; + --btn-hover-border-color: #343a40; + --btn-focus-shadow-rgb: 82, 88, 93; + --btn-active-color: hsl(0, 0%, 100%); + --btn-active-bg: #343a40; + --btn-active-border-color: #343a40; + --btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --btn-disabled-color: #343a40; + --btn-disabled-bg: transparent; + --btn-disabled-border-color: #343a40; + --gradient: none; +} diff --git a/updates.xml b/updates.xml index 00db887..1b230b1 100644 --- a/updates.xml +++ b/updates.xml @@ -24,7 +24,7 @@ INGROUP: MokoCassiopeia REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia PATH: ./updates.xml - VERSION: 03.06.03 + VERSION: 03.08.03 BRIEF: Update manifest XML file for MokoCassiopeia --> @@ -36,17 +36,16 @@ template site - 03.06.03 - 2025-12-12 + 03.08.03 + 2026-02-27 Jonathan Miller || Moko Consulting hello@mokoconsulting.tech - (C)GNU General Public License Version 3 - 2025 Moko Consulting + (C)GNU General Public License Version 3 - 2026 Moko Consulting https://github.com/mokoconsulting-tech/MokoCassiopeia - https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/03.01.00/mokocassiopeia-src-03.01.00.zip - sha256:858dd1a9a0aceecfe844a22d2a3557aea68687ae02363e04ff4c80bae0f29480 + https://github.com/mokoconsulting-tech/MokoCassiopeia/releases/download/03.08.03/mokocassiopeia-src-03.08.03.zip