feat(openclaw,infra): optimize token usage with GLM-5.3-Flash and add Garmin MCP integration

- Migrate OpenClaw primary model to z-ai/glm-5.3-flash across conductor, heartbeat, subagents, and vision
- Configure deepseek-v4.1-flash and qwen3.8-flash as fallback models; retire claude-3.7-sonnet and deepseek-v4-pro
- Decouple heartbeat target to prevent active session context amplification and token bleed
- Add Garmin Connect MCP integration, secret unpacking, and Elite Strength Coach SOUL protocol
- Add ADR 0001 documenting hybrid tool search and subagent architecture
- Update Authentik configuration, theme styles, and Terraform state
- Add Grafana dashboard for Taupi fan monitoring and update Velero secrets
- Bump knowledge-wiki submodule pointer
This commit is contained in:
Moritz Graf
2026-09-13 22:21:17 +02:00
parent 02ad8f0050
commit ea6fa7344d
14 changed files with 648 additions and 196 deletions
+6 -1
View File
@@ -56,7 +56,12 @@ This repository is divided into distinct domains, each with its own `AGENTS.md`
4. Move the task to `## ✅ Completed Tasks` with completion details and commit info. 4. Move the task to `## ✅ Completed Tasks` with completion details and commit info.
5. Push back: `git -C knowledge-wiki commit -am "chore(tasks): complete <task>" && git -C knowledge-wiki push origin main`. 5. Push back: `git -C knowledge-wiki commit -am "chore(tasks): complete <task>" && git -C knowledge-wiki push origin main`.
- When Antigravity needs knowledge about family, home, servers, or setup: - When Antigravity needs knowledge about family, home, servers, or setup:
- Read notes in `knowledge-wiki/concepts/` and `knowledge-wiki/entities/`. ### 6. Architecture Decision Records (`docs/adr/`)
* **Purpose**: Formal record of architectural decisions, technical trade-offs, and design standards across the monorepo.
* **Format**: [MADR](https://adr.github.io/madr/) (Markdown Architectural Decision Records).
* **Consulting ADRs**: AI agents MUST consult `docs/adr/` before designing or altering system architecture, agent topologies, or tool integration patterns.
* **Key Records**:
* [ADR 0001: Hybrid MCP Tool Search and Subagent Delegation for AI Agents](docs/adr/0001-hybrid-mcp-tool-search-and-subagents.md)
## Global Constraints ## Global Constraints
* **Secrets**: `git-crypt` is used extensively. Ensure you have the unlock key before editing `*.secret` files. * **Secrets**: `git-crypt` is used extensively. Ensure you have the unlock key before editing `*.secret` files.
@@ -0,0 +1,125 @@
---
status: "accepted"
date: 2026-09-12
decision-makers: ["Moritz Graf", "Antigravity"]
consulted: []
informed: []
---
# ADR 0001: Hybrid MCP Tool Search and Subagent Delegation for AI Agents
## Context and Problem Statement
OpenClaw operates as the personal AI concierge for the Graf family, communicating primarily via Telegram and web interfaces. It integrates external systems via the Model Context Protocol (MCP) (e.g., Home Assistant, Prometheus, Spotify, weather, shopping).
When integrating comprehensive domain services like **Garmin Connect** via [`Taxuspt/garmin_mcp`](https://github.com/Taxuspt/garmin_mcp), the server exposes **148 distinct tools** spanning activity analysis, workout builders, physiological trends, sleep, stress, HRV, and gear tracking.
In standard MCP implementations, all tool schemas are transmitted in the LLM's `tools` array on *every single request turn*. For 148 tools, this imposes a **~25,000–30,000 token tax per turn** before a single word of user prompt is evaluated. This creates severe issues:
1. **Severe Token & Cost Bloat**: Inflates inference costs on OpenRouter across thousands of daily family turns.
2. **Turn Latency & Degradation**: Slows down response times on mobile Telegram and impairs the reasoning accuracy of fast conductor models (e.g. `deepseek-v4.1-flash`) due to tool schema noise.
3. **Imbalance for Simple Checks**: A simple query like *"Wie war mein Schlaf?"* should not require dragging 148 tool definitions into context or, conversely, incurring the multi-second startup latency of a full subagent session.
How do we grant OpenClaw full access to large, complex MCP tool catalogs without polluting everyday conversational context?
---
## Decision Drivers
* **Token Economics**: Minimize idle token overhead on routine conversational turns.
* **Low Latency**: Provide instant answers for routine, single-step lookups.
* **Complex Multi-Step Capabilities**: Enable autonomous, deep reasoning for tasks like workout generation, periodization, and multi-source research without cluttering the primary conversation transcript.
* **Protocol Standards**: Adhere to upstream MCP standards rather than writing fragile, non-standard CLI wrappers for every API.
* **Architectural Consistency**: Establish an extensible pattern that can later be applied to refactor other domains (e.g. Supermarket shopping, Jellyfin media, and Regensburg Stadtrat local news research).
---
## Considered Options
1. **Option 1: Global Eager MCP Registration**
* Register all 148 tools directly under `mcp.servers`.
* *Drawback*: Unacceptable ~30k token tax on every message; high cost and latency.
2. **Option 2: Pure CLI / Script Wrapper Skill**
* Avoid MCP entirely; write custom Python CLI scripts in `mop-skills` executed via `bash`.
* *Drawback*: Re-invents the wheel, ignores the 1,150-star community MCP server, requires maintaining hundreds of lines of bespoke CLI parsing code.
3. **Option 3: Subagent Delegation Only**
* Hide all domain tools from the main agent and mandate that *every* query spawns a subagent via `sessions_spawn`.
* *Drawback*: Adds unnecessary latency (2–4 seconds) and session overhead for trivial questions like *"Wie hoch ist meine Body Battery?"*.
4. **Option 4: Hybrid Tool Search + Subagent Delegation (Selected)**
* Enable OpenClaw's native **Tool Search** (`tools.toolSearch.mode: "directory"`) for the main agent so large tool catalogs are deferred behind lightweight search/describe/call operations (~600 tokens).
* Empower the main conductor to dynamically decide:
* Execute directly via Tool Search for fast, single-step queries.
* Delegate to an isolated subagent (`sessions_spawn`) for deep, multi-step, stateful reasoning.
---
## Decision Outcome
Chosen Option: **Option 4: Hybrid Tool Search + Subagent Delegation**.
### 1. Dual-Path Architecture
```
User Query (Telegram)
│
▼
┌────────────────────────────────────────┐
│ OpenClaw Main Conductor │
│ (DeepSeek v4.1 Flash) │
└───────────────────┬────────────────────┘
│
Is this a deep/multi-step task?
┌────────────┴────────────┐
│ NO │ YES
▼ ▼
┌───────────────┐ ┌─────────────────────────┐
│ Direct Tool │ │ Subagent Delegation │
│ Search │ │ (sessions_spawn) │
├───────────────┤ ├─────────────────────────┤
│ • tool_search │ │ • Dedicated Context │
│ • tool_call │ │ • Full Tool Access │
│ • Single Turn │ │ • Multi-Step Reasoning │
└───────┬───────┘ └────────────┬────────────┘
│ │
└──────────────┬──────────────┘
▼
┌─────────────────────────────────┐
│ Taxuspt/garmin_mcp (148 Tools)│
│ Garmin Connect Cloud API │
└─────────────────────────────────┘
```
### 2. Main Conductor Routing Heuristic
The main conductor is guided by explicit system prompt rules:
| Query Type | Routing Path | Examples |
| :--- | :--- | :--- |
| **Simple Vitals & Lookups** | **Direct Tool Search** | • *"Wie war mein Schlaf letzte Nacht?"*<br>• *"Wie ist meine Body Battery?"*<br>• *"Was habe ich gestern trainiert?"* |
| **Deep Analysis & Creation** | **Subagent Delegation (`sessions_spawn`)** | • *"Erstelle mir ein 45-minütiges Oberkörper-Superset-Workout für heute auf meiner Uhr."*<br>• *"Analysiere mein Krafttraining der letzten 3 Wochen auf Progressive Overload und plane die nächste Woche."*<br>• *"Erstelle ein Periodisierungskonzept für den nächsten Monat."* |
---
## Consequences
### Positive
* **98% Token Reduction on Idle Turns**: The tool catalog is deferred behind OpenClaw's native Tool Search, dropping tool schema overhead from ~30,000 tokens to ~600 tokens.
* **Instant Answers for Vitals**: Quick checks are answered in a single turn without waiting for subagent spin-up.
* **Isolated Deep Reasoning**: Heavy multi-turn planning and JSON compilation occur inside temporary subagents, keeping the main Telegram conversation transcript lightweight and readable.
* **Standard-Compliant**: Uses standard upstream MCP (`Taxuspt/garmin_mcp`) and standard OpenClaw features (`tools.toolSearch`, `sessions_spawn`).
### Negative & Mitigations
* **Two-Step Tool Search Latency**: For the first direct lookup of a tool, OpenClaw performs a search step before calling the tool.
* *Mitigation*: OpenClaw's `directory` mode caches known tool descriptors and allows direct calls when the exact tool name is known.
* **Model Prompt Instruction**: Requires clear guidelines in the system prompt so the conductor consistently knows when to delegate vs. query directly.
---
## Future Roadmap: Monorepo Refactoring Blueprint
This Hybrid MCP architecture serves as the official template for future refactorings in `infrapuzzle`:
1. **Shopping & Supermarket Deals**: Migrate current static MCP tools behind Tool Search; delegate multi-store price comparisons and recipe cart generation to a shopping subagent.
2. **Jellyfin & Media Management**: Keep playback/resume queries direct; delegate complex media recommendations and library reorganizations to a media subagent.
3. **Local News & Stadtrat Research**: Provide direct search for council dates; delegate deep legislative research, PDF document extraction, and meeting summarization to an isolated Stadtrat research subagent.
+39
View File
@@ -0,0 +1,39 @@
# Architecture Decision Records (ADRs)
This directory documents the key architectural decisions made within the **Infrapuzzle** monorepo and its associated workloads (Kubernetes, OpenClaw AI agent, networking, DNS, and smart home systems).
We follow the [Markdown Architectural Decision Records (MADR)](https://adr.github.io/madr/) format to capture intentional technical decisions, their context, considered options, trade-offs, and consequences.
---
## 📋 Record Index
| ADR | Title | Status | Date | Area |
| :--- | :--- | :---: | :---: | :--- |
| [**0001**](0001-hybrid-mcp-tool-search-and-subagents.md) | **Hybrid MCP Tool Search and Subagent Delegation for AI Agents** | `accepted` | 2026-09-12 | OpenClaw / AI / MCP |
---
## ✍️ How to Create a New ADR
1. Copy the template structure into a new numbered markdown file:
```bash
docs/adr/000X-short-title-in-kebab-case.md
```
2. Include the YAML frontmatter:
```yaml
---
status: "proposed | accepted | superseded | deprecated"
date: YYYY-MM-DD
decision-makers: ["Moritz Graf", "Antigravity"]
consulted: []
informed: []
---
```
3. Clearly define:
- **Context & Problem Statement** (Why was this decision needed?)
- **Decision Drivers** (Constraints, costs, token limits, latency, maintainability)
- **Considered Options** (Alternatives evaluated)
- **Decision Outcome** (Chosen path with justification)
- **Consequences** (Positive effects, negative trade-offs, follow-up actions)
4. Add the new record to the table in this `README.md`.
+1 -1
View File
@@ -138,7 +138,7 @@ A manual backup may be created executing the following command. **Note: Keep bac
```sh ```sh
DATE=$( date +%Y%m%d ) DATE=$( date +%Y%m%d )
velero backup create $DATE --include-namespaces coder,home-assistant,n8n,influxdb --wait velero backup create $DATE --include-namespaces coder,home-assistant,n8n,influxdb,development,nextcloud,openclaw,auth,zigbee --wait
``` ```
### Backup Retention Policy ### Backup Retention Policy
+4 -2
View File
@@ -14,6 +14,8 @@ global:
secretKeyRef: secretKeyRef:
name: authentik-db-app name: authentik-db-app
key: password key: password
- name: AUTHENTIK_SESSION__DURATION
value: "days=30"
authentik: authentik:
# Secret key for cookie signing and session encryption # Secret key for cookie signing and session encryption
@@ -27,9 +29,9 @@ server:
resources: resources:
requests: requests:
cpu: 100m cpu: 100m
memory: 384Mi memory: 512Mi
limits: limits:
memory: 768Mi memory: 1536Mi
ingress: ingress:
enabled: true enabled: true
@@ -15,7 +15,7 @@ data:
"tags": ["climate", "fan", "cellar", "taupi", "prometheus"], "tags": ["climate", "fan", "cellar", "taupi", "prometheus"],
"timezone": "browser", "timezone": "browser",
"schemaVersion": 41, "schemaVersion": 41,
"version": 5, "version": 6,
"refresh": "30s", "refresh": "30s",
"editable": false, "editable": false,
"graphTooltip": 2, "graphTooltip": 2,
@@ -24,20 +24,7 @@ data:
"to": "now" "to": "now"
}, },
"templating": { "templating": {
"list": [ "list": []
{
"name": "datasource",
"type": "datasource",
"pluginId": "prometheus",
"includeAll": false,
"label": "Prometheus",
"current": {
"selected": true,
"text": "prometheus",
"value": "prometheus"
}
}
]
}, },
"panels": [ "panels": [
{ {
@@ -50,7 +37,7 @@ data:
"id": 1, "id": 1,
"title": "Fan Power Relay", "title": "Fan Power Relay",
"type": "stat", "type": "stat",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 4, "w": 4, "x": 0, "y": 1}, "gridPos": {"h": 4, "w": 4, "x": 0, "y": 1},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -75,7 +62,7 @@ data:
"title": "Drying Quality Score", "title": "Drying Quality Score",
"description": "Calculated 0-100 score based on Dewpoint Spread. Higher score allows longer continuous ventilation runtime.", "description": "Calculated 0-100 score based on Dewpoint Spread. Higher score allows longer continuous ventilation runtime.",
"type": "stat", "type": "stat",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 4, "w": 4, "x": 4, "y": 1}, "gridPos": {"h": 4, "w": 4, "x": 4, "y": 1},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -109,7 +96,7 @@ data:
"title": "Dewpoint Drying Spread", "title": "Dewpoint Drying Spread",
"description": "Indoor Dewpoint − Outdoor Dewpoint. Must be > 2.0°C for drying.", "description": "Indoor Dewpoint − Outdoor Dewpoint. Must be > 2.0°C for drying.",
"type": "stat", "type": "stat",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 4, "w": 4, "x": 8, "y": 1}, "gridPos": {"h": 4, "w": 4, "x": 8, "y": 1},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -141,7 +128,7 @@ data:
"title": "Thermal Governor State", "title": "Thermal Governor State",
"description": "Thermal operating regime (Warm Cooling, Comfort 14-20°C, Cold Restricted, Frost Floor)", "description": "Thermal operating regime (Warm Cooling, Comfort 14-20°C, Cold Restricted, Frost Floor)",
"type": "stat", "type": "stat",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 4, "w": 4, "x": 12, "y": 1}, "gridPos": {"h": 4, "w": 4, "x": 12, "y": 1},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -165,7 +152,7 @@ data:
"title": "Dynamic Max Burst Runtime", "title": "Dynamic Max Burst Runtime",
"description": "Dynamic max continuous runtime allowed based on drying quality", "description": "Dynamic max continuous runtime allowed based on drying quality",
"type": "stat", "type": "stat",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 4, "w": 4, "x": 16, "y": 1}, "gridPos": {"h": 4, "w": 4, "x": 16, "y": 1},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -197,7 +184,7 @@ data:
"id": 6, "id": 6,
"title": "Controller Connectivity", "title": "Controller Connectivity",
"type": "stat", "type": "stat",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 4, "w": 4, "x": 20, "y": 1}, "gridPos": {"h": 4, "w": 4, "x": 20, "y": 1},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -228,7 +215,7 @@ data:
"title": "🎯 Primary Goal: Humidity High ➔ Fan Runs ➔ Humidity Drops", "title": "🎯 Primary Goal: Humidity High ➔ Fan Runs ➔ Humidity Drops",
"description": "Visual validation of cellar drying: When Indoor Humidity rises above target, the orange Fan Active band engages until Indoor Humidity drops back down.", "description": "Visual validation of cellar drying: When Indoor Humidity rises above target, the orange Fan Active band engages until Indoor Humidity drops back down.",
"type": "timeseries", "type": "timeseries",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 12, "w": 24, "x": 0, "y": 6}, "gridPos": {"h": 12, "w": 24, "x": 0, "y": 6},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -318,7 +305,7 @@ data:
"title": "📊 Full Telemetry Overview (Temperatures, Dewpoints, Humidity & Fan)", "title": "📊 Full Telemetry Overview (Temperatures, Dewpoints, Humidity & Fan)",
"description": "Comprehensive correlation: Left axis (°C) = Temperatures & Dewpoints. Right axis (%) = Humidity, Setpoint & Mold Limit. Orange shaded band = Fan Relay ON.", "description": "Comprehensive correlation: Left axis (°C) = Temperatures & Dewpoints. Right axis (%) = Humidity, Setpoint & Mold Limit. Orange shaded band = Fan Relay ON.",
"type": "timeseries", "type": "timeseries",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 13, "w": 24, "x": 0, "y": 19}, "gridPos": {"h": 13, "w": 24, "x": 0, "y": 19},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -451,7 +438,7 @@ data:
"title": "💧 Dew Point Spread (Indoor − Outdoor) — Physical Drying Potential", "title": "💧 Dew Point Spread (Indoor − Outdoor) — Physical Drying Potential",
"description": "Calculates physical moisture removal capacity. When Spread > 2.0°C (Green zone), outside air is dry enough to absorb moisture from the cellar.", "description": "Calculates physical moisture removal capacity. When Spread > 2.0°C (Green zone), outside air is dry enough to absorb moisture from the cellar.",
"type": "timeseries", "type": "timeseries",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 33}, "gridPos": {"h": 8, "w": 12, "x": 0, "y": 33},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -487,7 +474,7 @@ data:
"title": "🌡️ Temperature Delta (Indoor − Outdoor) & Heating Prevention", "title": "🌡️ Temperature Delta (Indoor − Outdoor) & Heating Prevention",
"description": "Positive = cellar warmer than outside. Summer heating rule: Fan blocked if Outdoor Temp > 20°C (or > Indoor Temp).", "description": "Positive = cellar warmer than outside. Summer heating rule: Fan blocked if Outdoor Temp > 20°C (or > Indoor Temp).",
"type": "timeseries", "type": "timeseries",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 33}, "gridPos": {"h": 8, "w": 12, "x": 12, "y": 33},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -529,7 +516,7 @@ data:
"id": 11, "id": 11,
"title": "🔋 BLU Sensor Batteries", "title": "🔋 BLU Sensor Batteries",
"type": "gauge", "type": "gauge",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 7, "w": 12, "x": 0, "y": 42}, "gridPos": {"h": 7, "w": 12, "x": 0, "y": 42},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
@@ -560,7 +547,7 @@ data:
"id": 12, "id": 12,
"title": "⏱️ Duty Cycle & Staleness Timers", "title": "⏱️ Duty Cycle & Staleness Timers",
"type": "timeseries", "type": "timeseries",
"datasource": {"type": "prometheus", "uid": "${datasource}"}, "datasource": {"type": "prometheus", "uid": "prometheus"},
"gridPos": {"h": 7, "w": 12, "x": 12, "y": 42}, "gridPos": {"h": 7, "w": 12, "x": 12, "y": 42},
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
Binary file not shown.
Binary file not shown.
Binary file not shown.
+22 -1
View File
@@ -130,7 +130,28 @@ resource "authentik_stage_user_write" "haumdaucher_enrollment_write" {
# 5. User Login Stage (starts the user session) # 5. User Login Stage (starts the user session)
resource "authentik_stage_user_login" "haumdaucher_enrollment_login" { resource "authentik_stage_user_login" "haumdaucher_enrollment_login" {
name = "haumdaucher-enrollment-login" name = "haumdaucher-enrollment-login"
session_duration = "seconds=0" session_duration = "days=30"
}
# Master Flow: Default User Login Stage (30-day persistent browser session)
import {
to = authentik_stage_user_login.default_authentication_login
id = "49749dd0-3c0d-41e2-9f10-e6c66d719901"
}
resource "authentik_stage_user_login" "default_authentication_login" {
name = "default-authentication-login"
session_duration = "days=30"
}
import {
to = authentik_stage_user_login.default_source_authentication_login
id = "7ff5a23d-6f78-4539-b40f-d7fb24af0ae7"
}
resource "authentik_stage_user_login" "default_source_authentication_login" {
name = "default-source-authentication-login"
session_duration = "days=30"
} }
# 6. Redirect Stage (redirects user to haumdaucher.de after successful registration) # 6. Redirect Stage (redirects user to haumdaucher.de after successful registration)
+328 -157
View File
@@ -1,95 +1,313 @@
/* ========================================================================== /* ==========================================================================
HAUMDAUCHER THEME FOR AUTHENTIK HAUMDAUCHER THEME FOR AUTHENTIK
Wurst und Spezialitäten n.e.V. Wurst und Spezialitäten n.e.V.
Core Principle: Black on White / White on Black (High Contrast & Consistency)
========================================================================== */ ========================================================================== */
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800;900&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800;900&display=swap');
/* --- Global Brand Font (Safe for all pages) --- */ /* ==========================================================================
1. GLOBAL FOUNDATION & TYPOGRAPHY
========================================================================== */
:root { :root {
--hd-font: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; --hd-font: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
--pf-global--FontFamily--sans-serif: var(--hd-font); --pf-global--FontFamily--sans-serif: var(--hd-font);
--pf-v5-global--FontFamily--sans-serif: var(--hd-font); --pf-v5-global--FontFamily--sans-serif: var(--hd-font);
/* PatternFly Button Variables (Light Mode / Default) */
--pf-c-button--m-primary--BackgroundColor: #000000;
--pf-c-button--m-primary--hover--BackgroundColor: #262626;
--pf-c-button--m-primary--focus--BackgroundColor: #262626;
--pf-c-button--m-primary--active--BackgroundColor: #000000;
--pf-c-button--m-primary--Color: #ffffff;
--pf-c-button--m-primary--hover--Color: #ffffff;
--pf-c-button--m-primary--focus--Color: #ffffff;
--pf-c-button--m-primary--active--Color: #ffffff;
--pf-c-button--m-secondary--BackgroundColor: #ffffff;
--pf-c-button--m-secondary--hover--BackgroundColor: #000000;
--pf-c-button--m-secondary--focus--BackgroundColor: #f4f5f8;
--pf-c-button--m-secondary--active--BackgroundColor: #000000;
--pf-c-button--m-secondary--Color: #000000;
--pf-c-button--m-secondary--hover--Color: #ffffff;
--pf-c-button--m-secondary--focus--Color: #000000;
--pf-c-button--m-secondary--active--Color: #ffffff;
--pf-c-button--m-secondary--BorderColor: #000000;
--pf-c-button--m-secondary--hover--BorderColor: #000000;
--pf-c-button--m-control--Color: #000000;
--pf-c-button--m-control--BackgroundColor: transparent;
--pf-c-button--m-plain--Color: #000000;
--pf-c-button--m-tertiary--Color: #000000;
}
/* Dark Mode Button Variables */
[data-theme='dark'] {
--pf-c-button--m-primary--BackgroundColor: #ffffff;
--pf-c-button--m-primary--hover--BackgroundColor: #e4e4e7;
--pf-c-button--m-primary--focus--BackgroundColor: #e4e4e7;
--pf-c-button--m-primary--active--BackgroundColor: #ffffff;
--pf-c-button--m-primary--Color: #000000;
--pf-c-button--m-primary--hover--Color: #000000;
--pf-c-button--m-primary--focus--Color: #000000;
--pf-c-button--m-primary--active--Color: #000000;
--pf-c-button--m-secondary--BackgroundColor: transparent;
--pf-c-button--m-secondary--hover--BackgroundColor: #ffffff;
--pf-c-button--m-secondary--focus--BackgroundColor: #27272a;
--pf-c-button--m-secondary--active--BackgroundColor: #ffffff;
--pf-c-button--m-secondary--Color: #ffffff;
--pf-c-button--m-secondary--hover--Color: #000000;
--pf-c-button--m-secondary--focus--Color: #ffffff;
--pf-c-button--m-secondary--active--Color: #000000;
--pf-c-button--m-secondary--BorderColor: #ffffff;
--pf-c-button--m-secondary--hover--BorderColor: #ffffff;
--pf-c-button--m-control--Color: #ffffff;
--pf-c-button--m-control--BackgroundColor: transparent;
--pf-c-button--m-plain--Color: #ffffff;
--pf-c-button--m-tertiary--Color: #ffffff;
} }
/* ========================================================================== /* ==========================================================================
AUTHENTICATED INTERFACE POLISH (User Dashboard & Admin Console) 2. UNIVERSAL BUTTON CONTRAST ENFORCEMENT
Ensure brand logo is well proportioned and high-contrast in masthead Guarantees that button text is NEVER the same color as the button background
in ANY state (normal, hover, focus, active, disabled).
========================================================================== */ ========================================================================== */
ak-interface-user .pf-c-brand img,
ak-interface-admin .pf-c-brand img, /* Ensure all inner elements (spans, icons, text) inherit button text color */
.pf-c-page__header-brand img, .pf-c-button *,
.pf-v5-c-page__header-brand img { .pf-v5-c-button *,
max-height: 38px !important; button * {
width: auto !important; color: inherit !important;
} }
[data-theme='dark'] ak-interface-user .pf-c-brand img, /* --- Primary Buttons (Light Mode / Default: Solid Black with Solid White Text) --- */
[data-theme='dark'] ak-interface-admin .pf-c-brand img, .pf-c-button.pf-m-primary,
[data-theme='dark'] .pf-c-page__header-brand img, .pf-v5-c-button.pf-m-primary,
[data-theme='dark'] .pf-v5-c-page__header-brand img { button[type="submit"] {
filter: invert(1) hue-rotate(180deg); background-color: #000000 !important;
color: #ffffff !important;
border: 1px solid #000000 !important;
font-family: var(--hd-font) !important;
font-weight: 700 !important;
border-radius: 12px !important;
transition: all 0.2s ease-in-out !important;
}
.pf-c-button.pf-m-primary:hover,
.pf-v5-c-button.pf-m-primary:hover,
button[type="submit"]:hover {
background-color: #262626 !important;
color: #ffffff !important;
border-color: #262626 !important;
}
.pf-c-button.pf-m-primary:focus,
.pf-v5-c-button.pf-m-primary:focus,
button[type="submit"]:focus {
background-color: #262626 !important;
color: #ffffff !important;
outline: 2px solid #000000 !important;
outline-offset: 2px !important;
}
.pf-c-button.pf-m-primary:active,
.pf-v5-c-button.pf-m-primary:active,
button[type="submit"]:active {
background-color: #000000 !important;
color: #ffffff !important;
}
.pf-c-button.pf-m-primary:disabled,
.pf-c-button.pf-m-primary.pf-m-disabled,
.pf-v5-c-button.pf-m-primary:disabled,
.pf-v5-c-button.pf-m-primary.pf-m-disabled,
button[type="submit"]:disabled {
background-color: #e5e7eb !important;
color: #6b7280 !important;
border-color: #d1d5db !important;
cursor: not-allowed !important;
opacity: 0.8 !important;
}
/* --- Primary Buttons (Dark Mode: Solid White with Solid Black Text) --- */
[data-theme='dark'] .pf-c-button.pf-m-primary:not(ak-flow-executor *),
[data-theme='dark'] .pf-v5-c-button.pf-m-primary:not(ak-flow-executor *),
[data-theme='dark'] .pf-c-page button[type="submit"] {
background-color: #ffffff !important;
color: #000000 !important;
border: 1px solid #ffffff !important;
}
[data-theme='dark'] .pf-c-button.pf-m-primary:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-v5-c-button.pf-m-primary:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-c-page button[type="submit"]:hover {
background-color: #e4e4e7 !important;
color: #000000 !important;
border-color: #e4e4e7 !important;
}
[data-theme='dark'] .pf-c-button.pf-m-primary:not(ak-flow-executor *):focus,
[data-theme='dark'] .pf-v5-c-button.pf-m-primary:not(ak-flow-executor *):focus,
[data-theme='dark'] .pf-c-page button[type="submit"]:focus {
background-color: #e4e4e7 !important;
color: #000000 !important;
outline: 2px solid #ffffff !important;
outline-offset: 2px !important;
}
[data-theme='dark'] .pf-c-button.pf-m-primary:not(ak-flow-executor *):disabled,
[data-theme='dark'] .pf-v5-c-button.pf-m-primary:not(ak-flow-executor *):disabled,
[data-theme='dark'] .pf-c-page button[type="submit"]:disabled {
background-color: #27272a !important;
color: #71717a !important;
border-color: #3f3f46 !important;
}
/* --- Secondary Buttons (Light Mode / Default: Solid White with Black Border & Text) --- */
.pf-c-button.pf-m-secondary,
.pf-v5-c-button.pf-m-secondary {
background-color: #ffffff !important;
color: #000000 !important;
border: 1px solid #000000 !important;
font-family: var(--hd-font) !important;
font-weight: 600 !important;
border-radius: 12px !important;
transition: all 0.2s ease-in-out !important;
}
.pf-c-button.pf-m-secondary:hover,
.pf-v5-c-button.pf-m-secondary:hover {
background-color: #000000 !important;
color: #ffffff !important;
border-color: #000000 !important;
}
.pf-c-button.pf-m-secondary:focus,
.pf-v5-c-button.pf-m-secondary:focus {
background-color: #f4f5f8 !important;
color: #000000 !important;
outline: 2px solid #000000 !important;
outline-offset: 2px !important;
}
.pf-c-button.pf-m-secondary:active,
.pf-v5-c-button.pf-m-secondary:active {
background-color: #000000 !important;
color: #ffffff !important;
}
.pf-c-button.pf-m-secondary:disabled,
.pf-c-button.pf-m-secondary.pf-m-disabled,
.pf-v5-c-button.pf-m-secondary:disabled,
.pf-v5-c-button.pf-m-secondary.pf-m-disabled {
background-color: #f9fafb !important;
color: #9ca3af !important;
border-color: #e5e7eb !important;
cursor: not-allowed !important;
}
/* --- Secondary Buttons (Dark Mode) --- */
[data-theme='dark'] .pf-c-button.pf-m-secondary:not(ak-flow-executor *),
[data-theme='dark'] .pf-v5-c-button.pf-m-secondary:not(ak-flow-executor *) {
background-color: transparent !important;
color: #ffffff !important;
border: 1px solid #ffffff !important;
}
[data-theme='dark'] .pf-c-button.pf-m-secondary:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-v5-c-button.pf-m-secondary:not(ak-flow-executor *):hover {
background-color: #ffffff !important;
color: #000000 !important;
border-color: #ffffff !important;
}
[data-theme='dark'] .pf-c-button.pf-m-secondary:not(ak-flow-executor *):focus,
[data-theme='dark'] .pf-v5-c-button.pf-m-secondary:not(ak-flow-executor *):focus {
background-color: #27272a !important;
color: #ffffff !important;
outline: 2px solid #ffffff !important;
outline-offset: 2px !important;
}
[data-theme='dark'] .pf-c-button.pf-m-secondary:not(ak-flow-executor *):disabled,
[data-theme='dark'] .pf-v5-c-button.pf-m-secondary:not(ak-flow-executor *):disabled {
background-color: transparent !important;
color: #52525b !important;
border-color: #27272a !important;
}
/* --- Control / Plain / Tertiary Buttons (e.g. eye toggle on password fields) --- */
.pf-c-button.pf-m-control,
.pf-v5-c-button.pf-m-control,
.pf-c-button.pf-m-plain,
.pf-v5-c-button.pf-m-plain,
.pf-c-button.pf-m-tertiary,
.pf-v5-c-button.pf-m-tertiary {
color: #000000 !important;
background-color: transparent !important;
}
.pf-c-button.pf-m-control:hover,
.pf-v5-c-button.pf-m-control:hover,
.pf-c-button.pf-m-plain:hover,
.pf-v5-c-button.pf-m-plain:hover,
.pf-c-button.pf-m-tertiary:hover,
.pf-v5-c-button.pf-m-tertiary:hover {
color: #000000 !important;
background-color: rgba(0, 0, 0, 0.08) !important;
}
[data-theme='dark'] .pf-c-button.pf-m-control:not(ak-flow-executor *),
[data-theme='dark'] .pf-v5-c-button.pf-m-control:not(ak-flow-executor *),
[data-theme='dark'] .pf-c-button.pf-m-plain:not(ak-flow-executor *),
[data-theme='dark'] .pf-v5-c-button.pf-m-plain:not(ak-flow-executor *),
[data-theme='dark'] .pf-c-button.pf-m-tertiary:not(ak-flow-executor *),
[data-theme='dark'] .pf-v5-c-button.pf-m-tertiary:not(ak-flow-executor *) {
color: #ffffff !important;
background-color: transparent !important;
}
[data-theme='dark'] .pf-c-button.pf-m-control:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-v5-c-button.pf-m-control:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-c-button.pf-m-plain:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-v5-c-button.pf-m-plain:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-c-button.pf-m-tertiary:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-v5-c-button.pf-m-tertiary:not(ak-flow-executor *):hover {
color: #ffffff !important;
background-color: rgba(255, 255, 255, 0.12) !important;
}
/* --- Link Buttons --- */
.pf-c-button.pf-m-link,
.pf-v5-c-button.pf-m-link {
color: #000000 !important;
text-decoration: underline !important;
background-color: transparent !important;
}
.pf-c-button.pf-m-link:hover,
.pf-v5-c-button.pf-m-link:hover {
color: #333333 !important;
}
[data-theme='dark'] .pf-c-button.pf-m-link:not(ak-flow-executor *),
[data-theme='dark'] .pf-v5-c-button.pf-m-link:not(ak-flow-executor *) {
color: #ffffff !important;
text-decoration: underline !important;
}
[data-theme='dark'] .pf-c-button.pf-m-link:not(ak-flow-executor *):hover,
[data-theme='dark'] .pf-v5-c-button.pf-m-link:not(ak-flow-executor *):hover {
color: #d4d4d8 !important;
} }
/* ========================================================================== /* ==========================================================================
LOGIN & AUTHENTICATION FLOW SCOPE 3. LOGIN & AUTHENTICATION FLOW SCOPE (Classic White Card & Black Elements)
All custom card styling, colors, and layout rules are strictly scoped
to ak-flow-executor and .pf-c-login to avoid leaking into the dashboard!
========================================================================== */ ========================================================================== */
/* --- Flow Executor Variables & Overrides --- */ /* Page Viewport Centering & Soft Minimal Backdrop */
ak-flow-executor,
.pf-c-login,
.pf-v5-c-login,
ak-stage,
.ak-stage {
--hd-bg: #f4f5f8;
--hd-card-bg: #ffffff;
--hd-card-border: rgba(0, 0, 0, 0.08);
--hd-text-main: #111111;
--hd-text-muted: #555555;
--hd-input-bg: #f9f9fb;
--hd-input-border: #d0d5dd;
--hd-btn-bg: #000000;
--hd-btn-text: #ffffff;
--hd-radius: 12px;
--hd-card-radius: 22px;
--hd-transition: all 0.2s ease-in-out;
/* Force PatternFly flow text & inputs to crisp black on the white card */
--pf-global--FontFamily--sans-serif: var(--hd-font) !important;
--pf-v5-global--FontFamily--sans-serif: var(--hd-font) !important;
--pf-global--Color--100: #111111 !important;
--pf-v5-global--Color--100: #111111 !important;
--pf-global--Color--200: #222222 !important;
--pf-v5-global--Color--200: #222222 !important;
--pf-global--Color--300: #444444 !important;
--pf-v5-global--Color--300: #444444 !important;
--pf-global--Color--dark-100: #111111 !important;
--pf-v5-global--Color--dark-100: #111111 !important;
--pf-global--Color--light-100: #111111 !important;
--pf-v5-global--Color--light-100: #111111 !important;
--pf-global--primary-color--100: #000000 !important;
--pf-v5-global--primary-color--100: #000000 !important;
/* Form & Label Variables */
--pf-c-form__label--Color: #111111 !important;
--pf-v5-c-form__label--Color: #111111 !important;
--pf-c-form__label-text--Color: #111111 !important;
--pf-v5-c-form__label-text--Color: #111111 !important;
--pf-c-form-control--Color: #111111 !important;
--pf-v5-c-form-control--Color: #111111 !important;
--pf-c-form-control--placeholder--Color: #666666 !important;
--pf-v5-c-form-control--placeholder--Color: #666666 !important;
--pf-c-form-control--BackgroundColor: #f9f9fb !important;
--pf-v5-c-form-control--BackgroundColor: #f9f9fb !important;
--pf-c-form-control--BorderColor: #d0d5dd !important;
--pf-v5-c-form-control--BorderColor: #d0d5dd !important;
--pf-c-form__helper-text--Color: #555555 !important;
--pf-v5-c-form__helper-text--Color: #555555 !important;
}
/* --- Flow Executor Viewport Centering & Background --- */
ak-flow-executor, ak-flow-executor,
.pf-c-login, .pf-c-login,
.pf-v5-c-login { .pf-v5-c-login {
@@ -110,7 +328,7 @@ ak-flow-executor,
color: #111111 !important; color: #111111 !important;
} }
/* --- Centered Login Container --- */ /* Centered Login Container */
ak-flow-executor .pf-c-login__container, ak-flow-executor .pf-c-login__container,
.pf-c-login .pf-c-login__container, .pf-c-login .pf-c-login__container,
.pf-v5-c-login .pf-v5-c-login__container { .pf-v5-c-login .pf-v5-c-login__container {
@@ -125,7 +343,7 @@ ak-flow-executor .pf-c-login__container,
box-sizing: border-box !important; box-sizing: border-box !important;
} }
/* --- Top Header & Logo Layout --- */ /* Header & Logo */
ak-flow-executor .pf-c-login__header, ak-flow-executor .pf-c-login__header,
.pf-c-login .pf-c-login__header, .pf-c-login .pf-c-login__header,
.pf-v5-c-login .pf-v5-c-login__header { .pf-v5-c-login .pf-v5-c-login__header {
@@ -154,7 +372,7 @@ ak-flow-executor .pf-c-login__header img,
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
} }
/* --- Classic White Card --- */ /* The White Card */
ak-flow-executor .pf-c-login__main, ak-flow-executor .pf-c-login__main,
.pf-c-login .pf-c-login__main, .pf-c-login .pf-c-login__main,
.pf-v5-c-login .pf-v5-c-login__main, .pf-v5-c-login .pf-v5-c-login__main,
@@ -162,7 +380,7 @@ ak-flow-executor ak-stage,
ak-flow-executor .ak-stage { ak-flow-executor .ak-stage {
background: #ffffff !important; background: #ffffff !important;
border: 1px solid rgba(0, 0, 0, 0.08) !important; border: 1px solid rgba(0, 0, 0, 0.08) !important;
border-radius: 22px !important; border-radius: 20px !important;
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.04) !important; box-shadow: 0 16px 48px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.04) !important;
padding: 36px 32px 32px 32px !important; padding: 36px 32px 32px 32px !important;
width: 100% !important; width: 100% !important;
@@ -170,7 +388,7 @@ ak-flow-executor .ak-stage {
color: #111111 !important; color: #111111 !important;
} }
/* --- Fully Hide Duplicate / Generic Flow Title --- */ /* Hide Redundant / Generic Flow Title */
ak-flow-executor .pf-c-login__main-header-title, ak-flow-executor .pf-c-login__main-header-title,
ak-flow-executor .pf-v5-c-login__main-header-title, ak-flow-executor .pf-v5-c-login__main-header-title,
ak-flow-executor .pf-c-title, ak-flow-executor .pf-c-title,
@@ -205,18 +423,17 @@ ak-flow-executor .pf-c-login__main-header-desc b,
.pf-c-login .pf-c-login__main-header-desc b, .pf-c-login .pf-c-login__main-header-desc b,
.pf-v5-c-login .pf-v5-c-login__main-header-desc strong, .pf-v5-c-login .pf-v5-c-login__main-header-desc strong,
.pf-v5-c-login .pf-v5-c-login__main-header-desc b { .pf-v5-c-login .pf-v5-c-login__main-header-desc b {
color: #111111 !important; color: #000000 !important;
font-weight: 700 !important; font-weight: 700 !important;
} }
/* --- Form Field Groups --- */ /* Form Groups & Labels */
ak-flow-executor .pf-c-form__group, ak-flow-executor .pf-c-form__group,
.pf-c-login .pf-c-form__group, .pf-c-login .pf-c-form__group,
.pf-v5-c-login .pf-v5-c-form__group { .pf-v5-c-login .pf-v5-c-form__group {
margin-bottom: 20px !important; margin-bottom: 20px !important;
} }
/* --- LABELS & LABEL TEXT (High-Contrast Black inside login flow) --- */
ak-flow-executor .pf-c-form__label, ak-flow-executor .pf-c-form__label,
ak-flow-executor .pf-v5-c-form__label, ak-flow-executor .pf-v5-c-form__label,
ak-flow-executor .pf-c-form__label-text, ak-flow-executor .pf-c-form__label-text,
@@ -236,7 +453,7 @@ ak-flow-executor label *,
font-family: var(--hd-font) !important; font-family: var(--hd-font) !important;
font-weight: 600 !important; font-weight: 600 !important;
font-size: 0.9rem !important; font-size: 0.9rem !important;
color: #111111 !important; color: #000000 !important;
margin-bottom: 6px !important; margin-bottom: 6px !important;
display: inline-block !important; display: inline-block !important;
opacity: 1 !important; opacity: 1 !important;
@@ -252,7 +469,7 @@ ak-flow-executor .pf-v5-c-form__label-required,
font-weight: 700 !important; font-weight: 700 !important;
} }
/* --- INPUT FIELDS & TEXT (inside login flow) --- */ /* Inputs */
ak-flow-executor .pf-c-form-control, ak-flow-executor .pf-c-form-control,
ak-flow-executor .pf-v5-c-form-control, ak-flow-executor .pf-v5-c-form-control,
ak-flow-executor input[type="text"], ak-flow-executor input[type="text"],
@@ -269,13 +486,12 @@ ak-flow-executor input,
padding: 12px 14px !important; padding: 12px 14px !important;
background-color: #f9f9fb !important; background-color: #f9f9fb !important;
border: 1px solid #d0d5dd !important; border: 1px solid #d0d5dd !important;
color: #111111 !important; color: #000000 !important;
transition: all 0.2s ease-in-out !important; transition: all 0.2s ease-in-out !important;
width: 100% !important; width: 100% !important;
box-sizing: border-box !important; box-sizing: border-box !important;
} }
/* Input Placeholder */
ak-flow-executor input::placeholder, ak-flow-executor input::placeholder,
.pf-c-login input::placeholder, .pf-c-login input::placeholder,
.pf-v5-c-login input::placeholder { .pf-v5-c-login input::placeholder {
@@ -284,7 +500,6 @@ ak-flow-executor input::placeholder,
opacity: 1 !important; opacity: 1 !important;
} }
/* Focus State */
ak-flow-executor input:focus, ak-flow-executor input:focus,
.pf-c-login input:focus, .pf-c-login input:focus,
.pf-v5-c-login input:focus { .pf-v5-c-login input:focus {
@@ -292,42 +507,27 @@ ak-flow-executor input:focus,
border-color: #000000 !important; border-color: #000000 !important;
box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.12) !important; box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.12) !important;
background-color: #ffffff !important; background-color: #ffffff !important;
color: #111111 !important; color: #000000 !important;
} }
/* Browser Autofill Fix (Prevent White on White) */ /* Autofill Fix */
ak-flow-executor input:-webkit-autofill, ak-flow-executor input:-webkit-autofill,
ak-flow-executor input:-webkit-autofill:hover, ak-flow-executor input:-webkit-autofill:hover,
ak-flow-executor input:-webkit-autofill:focus, ak-flow-executor input:-webkit-autofill:focus,
.pf-c-login input:-webkit-autofill, .pf-c-login input:-webkit-autofill,
.pf-v5-c-login input:-webkit-autofill { .pf-v5-c-login input:-webkit-autofill {
-webkit-text-fill-color: #111111 !important; -webkit-text-fill-color: #000000 !important;
-webkit-box-shadow: 0 0 0 1000px #f9f9fb inset !important; -webkit-box-shadow: 0 0 0 1000px #f9f9fb inset !important;
box-shadow: 0 0 0 1000px #f9f9fb inset !important; box-shadow: 0 0 0 1000px #f9f9fb inset !important;
transition: background-color 5000s ease-in-out 0s !important; transition: background-color 5000s ease-in-out 0s !important;
} }
/* --- Solid Black Submit Button (inside login flow) --- */ /* Flow Submit Button Spacing */
ak-flow-executor button[type="submit"], ak-flow-executor button[type="submit"],
ak-flow-executor .pf-c-button.pf-m-primary,
ak-flow-executor .pf-v5-c-button.pf-m-primary,
.pf-c-login button[type="submit"], .pf-c-login button[type="submit"],
.pf-c-login .pf-c-button.pf-m-primary, .pf-v5-c-login button[type="submit"] {
.pf-v5-c-login button[type="submit"],
.pf-v5-c-login .pf-v5-c-button.pf-m-primary {
font-family: var(--hd-font) !important;
font-size: 1rem !important;
font-weight: 700 !important;
letter-spacing: 0.3px !important;
border-radius: 12px !important;
padding: 13px 20px !important;
border: none !important;
cursor: pointer !important;
background: #000000 !important;
color: #ffffff !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
transition: all 0.2s ease-in-out !important;
width: 100% !important; width: 100% !important;
padding: 13px 20px !important;
margin-top: 16px !important; margin-top: 16px !important;
margin-bottom: 4px !important; margin-bottom: 4px !important;
display: flex !important; display: flex !important;
@@ -335,53 +535,7 @@ ak-flow-executor .pf-v5-c-button.pf-m-primary,
justify-content: center !important; justify-content: center !important;
} }
ak-flow-executor button[type="submit"]:hover, /* Language Selector at Bottom Right */
.pf-c-login button[type="submit"]:hover,
.pf-v5-c-login button[type="submit"]:hover {
background: #222222 !important;
color: #ffffff !important;
transform: translateY(-1px) !important;
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2) !important;
}
ak-flow-executor button[type="submit"]:active,
.pf-c-login button[type="submit"]:active,
.pf-v5-c-login button[type="submit"]:active {
transform: translateY(0) !important;
}
/* Secondary Buttons (inside login flow) */
ak-flow-executor .pf-c-button.pf-m-secondary,
ak-flow-executor .pf-v5-c-button.pf-m-secondary,
.pf-c-login .pf-c-button.pf-m-secondary,
.pf-v5-c-login .pf-v5-c-button.pf-m-secondary {
font-family: var(--hd-font) !important;
font-weight: 600 !important;
border-radius: 12px !important;
padding: 11px 18px !important;
border: 1px solid #d0d5dd !important;
background: #ffffff !important;
color: #111111 !important;
transition: all 0.2s ease-in-out !important;
}
ak-flow-executor .pf-c-button.pf-m-secondary:hover,
.pf-c-login .pf-c-button.pf-m-secondary:hover,
.pf-v5-c-login .pf-v5-c-button.pf-m-secondary:hover {
background: #f4f5f7 !important;
border-color: #000000 !important;
}
/* --- Alerts & Messages (inside login flow) --- */
ak-flow-executor .pf-c-alert,
ak-flow-executor .pf-v5-c-alert,
.pf-c-login .pf-c-alert,
.pf-v5-c-login .pf-v5-c-alert {
border-radius: 12px !important;
margin-bottom: 16px !important;
}
/* --- LANGUAGE BUTTON AT BOTTOM (inside login flow only) --- */
ak-flow-executor ak-locale-select, ak-flow-executor ak-locale-select,
ak-flow-executor [part="locale-select"], ak-flow-executor [part="locale-select"],
ak-flow-executor::part(locale-select), ak-flow-executor::part(locale-select),
@@ -407,18 +561,18 @@ ak-flow-executor ak-locale-select:hover,
ak-flow-executor ak-locale-select select, ak-flow-executor ak-locale-select select,
.pf-c-login ak-locale-select select { .pf-c-login ak-locale-select select {
color: #111111 !important; color: #000000 !important;
background: transparent !important; background: transparent !important;
cursor: pointer !important; cursor: pointer !important;
} }
ak-flow-executor ak-locale-select label, ak-flow-executor ak-locale-select label,
.pf-c-login ak-locale-select label { .pf-c-login ak-locale-select label {
color: #111111 !important; color: #000000 !important;
cursor: pointer !important; cursor: pointer !important;
} }
/* --- Footer & Copyright (inside login flow) --- */ /* Footer & Watermark */
ak-flow-executor ak-brand-links, ak-flow-executor ak-brand-links,
ak-flow-executor .pf-c-login__footer, ak-flow-executor .pf-c-login__footer,
ak-flow-executor .pf-v5-c-login__footer, ak-flow-executor .pf-v5-c-login__footer,
@@ -435,7 +589,7 @@ ak-flow-executor ak-brand-links a,
ak-flow-executor .pf-c-login__footer a, ak-flow-executor .pf-c-login__footer a,
.pf-c-login .pf-c-login__footer a, .pf-c-login .pf-c-login__footer a,
.pf-v5-c-login .pf-v5-c-login__footer a { .pf-v5-c-login .pf-v5-c-login__footer a {
color: #111111 !important; color: #000000 !important;
text-decoration: none !important; text-decoration: none !important;
font-weight: 600 !important; font-weight: 600 !important;
} }
@@ -447,7 +601,6 @@ ak-flow-executor .pf-c-login__footer a:hover,
text-decoration: underline !important; text-decoration: underline !important;
} }
/* --- Watermark (inside login flow container) --- */
ak-flow-executor .pf-c-login__container::after, ak-flow-executor .pf-c-login__container::after,
.pf-c-login .pf-c-login__container::after, .pf-c-login .pf-c-login__container::after,
.pf-v5-c-login .pf-v5-c-login__container::after { .pf-v5-c-login .pf-v5-c-login__container::after {
@@ -463,7 +616,7 @@ ak-flow-executor .pf-c-login__container::after,
text-align: center; text-align: center;
} }
/* --- Mobile Responsiveness (inside login flow) --- */ /* Mobile Responsiveness */
@media (max-width: 480px) { @media (max-width: 480px) {
ak-flow-executor, ak-flow-executor,
.pf-c-login, .pf-c-login,
@@ -512,3 +665,21 @@ ak-flow-executor .pf-c-login__container::after,
right: 12px !important; right: 12px !important;
} }
} }
/* ==========================================================================
4. AUTHENTICATED DASHBOARD (User & Admin Interface)
========================================================================== */
ak-interface-user .pf-c-brand img,
ak-interface-admin .pf-c-brand img,
.pf-c-page__header-brand img,
.pf-v5-c-page__header-brand img {
max-height: 36px !important;
width: auto !important;
}
[data-theme='dark'] ak-interface-user .pf-c-brand img,
[data-theme='dark'] ak-interface-admin .pf-c-brand img,
[data-theme='dark'] .pf-c-page__header-brand img,
[data-theme='dark'] .pf-v5-c-page__header-brand img {
filter: invert(1) hue-rotate(180deg);
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long