Compare commits
70 Commits
mai/knuth/
...
mai/hermes
| Author | SHA1 | Date | |
|---|---|---|---|
| 59833b5d6d | |||
| 098a7ad99a | |||
| 7d731e8bcf | |||
| e4797aa532 | |||
| f85f4b4e7f | |||
| a5777ff65d | |||
| a4e37735f8 | |||
|
|
dadfa0df7c | ||
|
|
1caf12d801 | ||
|
|
f6c9eddfe4 | ||
|
|
4315f4c2c0 | ||
|
|
8f615fd3d1 | ||
|
|
6f2f150cb6 | ||
|
|
3d457d6b42 | ||
|
|
d8e145a49d | ||
|
|
8fc605c851 | ||
|
|
66166d979c | ||
|
|
b12b8e9068 | ||
|
|
5a2416f3a6 | ||
|
|
5454f0fc27 | ||
|
|
ab4003fb15 | ||
|
|
7d56e6a2fd | ||
|
|
866d30476d | ||
|
|
5240244a14 | ||
|
|
057fbf5434 | ||
|
|
52758c94a8 | ||
|
|
e2fc469957 | ||
|
|
4a7aa31dc1 | ||
|
|
3c324d4103 | ||
|
|
9d6debecbd | ||
|
|
21f22dc90d | ||
|
|
98fd237298 | ||
|
|
ffeed4998c | ||
|
|
fc4986b805 | ||
|
|
1576ac892b | ||
|
|
08739c6294 | ||
|
|
075be054e9 | ||
|
|
6480e72472 | ||
|
|
6dc338ddc2 | ||
|
|
2c4b693ac8 | ||
|
|
fc50219740 | ||
|
|
89a0f992e0 | ||
|
|
5fe3132e34 | ||
|
|
4dfae76862 | ||
|
|
2ffb1b4192 | ||
|
|
40f07304de | ||
|
|
d022ef209e | ||
|
|
208004f450 | ||
|
|
0b2b718410 | ||
|
|
68552cac15 | ||
|
|
8af8d3d35f | ||
|
|
596ccac889 | ||
|
|
d3efd8231f | ||
|
|
e6d397a77b | ||
|
|
c9f97eb43f | ||
|
|
8992f6775f | ||
|
|
7702963902 | ||
|
|
536e693b18 | ||
|
|
6596ac14fa | ||
|
|
cfa491c47e | ||
|
|
f7b5439387 | ||
|
|
327e1fcd43 | ||
|
|
6aa3d79d20 | ||
|
|
3d4dd8c49a | ||
|
|
5173611b46 | ||
|
|
069a2a3b4a | ||
|
|
882179d533 | ||
|
|
b4d2ef7991 | ||
|
|
9a92d9651f | ||
|
|
883904318e |
79
.claude/CLAUDE.md
Normal file
79
.claude/CLAUDE.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# onepager Project Instructions
|
||||
|
||||
## Project Overview
|
||||
|
||||
Mono-repo for 57+ vanity domain onepager sites. Single Caddy container with bash template system and host-based routing. Most domains are creative AI/KI wordplay (kAInco, kIlemma, orAKIl, etc.).
|
||||
|
||||
**Deploy:** Push to main -> Dokploy auto-deploys. All domains must be configured in Dokploy.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
sites/<domain>/ # One folder per domain
|
||||
site.yaml # Config: domain, template, vars
|
||||
index.html # Content (rendered or hand-crafted for custom)
|
||||
assets/ # Optional images, fonts
|
||||
templates/ # 6 HTML templates + base.html
|
||||
base.html # Shared skeleton (CSS includes, meta tags)
|
||||
person-dark.html # Professional profile, dark theme
|
||||
person-light.html # Professional profile, light/cream theme
|
||||
product-dark.html # Product/service landing, dark
|
||||
editorial.html # Long-form manifesto/editorial
|
||||
fun.html # Playful/personal pages
|
||||
minimal.html # Bare-bones single section
|
||||
shared/
|
||||
css/ # variables.css, responsive.css, animations.css, noise.css
|
||||
fonts.html # Google Fonts includes
|
||||
impressum.js # Shared impressum overlay
|
||||
build/ # Generated output (gitignored)
|
||||
Caddyfile # Generated by generate-caddyfile.sh (committed)
|
||||
```
|
||||
|
||||
### Build Pipeline
|
||||
|
||||
1. `generate-caddyfile.sh` reads all `sites/*/site.yaml` -> generates Caddyfile with host matchers
|
||||
2. `build.sh` orchestrates: generates Caddyfile, renders all sites, copies shared assets to `build/`
|
||||
3. `render.sh` takes `site.yaml` + template -> outputs rendered HTML (bash/yq/awk templating)
|
||||
4. Docker: Alpine builder runs `build.sh`, then Caddy serves from `/srv/`
|
||||
|
||||
### Template System
|
||||
|
||||
Templates use `{{placeholder}}` markers. `render.sh` reads vars from `site.yaml` and substitutes. Templates define CSS between `{{template_css_start}}`/`{{template_css_end}}` and body between `{{template_body_start}}`/`{{template_body_end}}`. Base template assembles shared CSS + template CSS + body.
|
||||
|
||||
Available vars: `title`, `description`, `lang`, `name`, `role`, `initials`, `tagline`, `accent`, `accent_light`, `font_primary`, `font_secondary`, `emoji`, `cta_text`, `cta_href`, `tags_html`, `sections_html`, `content_html`, `domain`, `year`.
|
||||
|
||||
### Custom Sites
|
||||
|
||||
Sites with `template: custom` skip rendering entirely -- their `index.html` is copied as-is. Many sites use custom for complex interactive content (e.g., orakil.de oracle, ichbinotto.de agent profile).
|
||||
|
||||
## Code Style & Conventions
|
||||
|
||||
- **Shell scripts**: bash, `set -euo pipefail`, use yq for YAML parsing
|
||||
- **HTML/CSS**: Inline styles in templates. Shared CSS via variables.css. Dark themes predominant.
|
||||
- **Commit messages**: `feat:` for new sites, `fix:` for corrections, `refactor:` for restructuring
|
||||
- **Site naming**: domain name = folder name under `sites/`
|
||||
- **Language**: Default `de` (German). Sites are primarily German-language.
|
||||
|
||||
## Adding a New Site
|
||||
|
||||
```bash
|
||||
# Templated
|
||||
./add-site.sh example.de --template person-dark --name "Max Mustermann"
|
||||
|
||||
# Custom
|
||||
./add-site.sh example.de --template custom
|
||||
# Then edit sites/example.de/index.html
|
||||
```
|
||||
|
||||
After adding: build locally with `./build.sh` to verify, commit, push.
|
||||
|
||||
## Deploy Trigger
|
||||
|
||||
A `.deploy-trigger` file exists -- changing its content forces Dokploy rebuild even without code changes.
|
||||
|
||||
## Git Strategy
|
||||
|
||||
- **main** = production, auto-deploys via Dokploy
|
||||
- Feature branches for multi-site changes or infrastructure work
|
||||
- Direct commits to main OK for single-site additions/fixes (this is a content repo)
|
||||
- Gitea repo: m/onepager
|
||||
14
.claude/agents/coder.md
Normal file
14
.claude/agents/coder.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Coder Agent
|
||||
|
||||
Implementation-focused agent for writing and refactoring code.
|
||||
|
||||
## Instructions
|
||||
|
||||
- Follow existing patterns in the codebase
|
||||
- Write minimal, focused code
|
||||
- Run tests after changes
|
||||
- Commit incrementally with descriptive messages
|
||||
|
||||
## Tools
|
||||
|
||||
All tools available.
|
||||
14
.claude/agents/researcher.md
Normal file
14
.claude/agents/researcher.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Researcher Agent
|
||||
|
||||
Exploration and information gathering agent.
|
||||
|
||||
## Instructions
|
||||
|
||||
- Search broadly, then narrow down
|
||||
- Document findings in structured format
|
||||
- Cite sources and file paths
|
||||
- Summarize key insights, don't dump raw data
|
||||
|
||||
## Tools
|
||||
|
||||
Read-only tools preferred. Use Bash only for non-destructive commands.
|
||||
14
.claude/agents/reviewer.md
Normal file
14
.claude/agents/reviewer.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Reviewer Agent
|
||||
|
||||
Code review agent for checking quality and correctness.
|
||||
|
||||
## Instructions
|
||||
|
||||
- Check for bugs, security issues, and style violations
|
||||
- Verify test coverage for changes
|
||||
- Suggest improvements concisely
|
||||
- Focus on correctness over style preferences
|
||||
|
||||
## Tools
|
||||
|
||||
Read-only tools. No file modifications.
|
||||
1
.claude/skills/mai-clone
Symbolic link
1
.claude/skills/mai-clone
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-clone
|
||||
1
.claude/skills/mai-coder
Symbolic link
1
.claude/skills/mai-coder
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-coder
|
||||
1
.claude/skills/mai-commit
Symbolic link
1
.claude/skills/mai-commit
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-commit
|
||||
1
.claude/skills/mai-consultant
Symbolic link
1
.claude/skills/mai-consultant
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-consultant
|
||||
1
.claude/skills/mai-daily
Symbolic link
1
.claude/skills/mai-daily
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-daily
|
||||
1
.claude/skills/mai-debrief
Symbolic link
1
.claude/skills/mai-debrief
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-debrief
|
||||
1
.claude/skills/mai-enemy
Symbolic link
1
.claude/skills/mai-enemy
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-enemy
|
||||
1
.claude/skills/mai-excalidraw
Symbolic link
1
.claude/skills/mai-excalidraw
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-excalidraw
|
||||
1
.claude/skills/mai-fixer
Symbolic link
1
.claude/skills/mai-fixer
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-fixer
|
||||
1
.claude/skills/mai-gitster
Symbolic link
1
.claude/skills/mai-gitster
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-gitster
|
||||
1
.claude/skills/mai-head
Symbolic link
1
.claude/skills/mai-head
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-head
|
||||
1
.claude/skills/mai-init
Symbolic link
1
.claude/skills/mai-init
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-init
|
||||
1
.claude/skills/mai-inventor
Symbolic link
1
.claude/skills/mai-inventor
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-inventor
|
||||
1
.claude/skills/mai-lead
Symbolic link
1
.claude/skills/mai-lead
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-lead
|
||||
1
.claude/skills/mai-maister
Symbolic link
1
.claude/skills/mai-maister
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-maister
|
||||
1
.claude/skills/mai-member
Symbolic link
1
.claude/skills/mai-member
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-member
|
||||
1
.claude/skills/mai-researcher
Symbolic link
1
.claude/skills/mai-researcher
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-researcher
|
||||
1
.claude/skills/mai-think
Symbolic link
1
.claude/skills/mai-think
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-think
|
||||
1
.claude/skills/mai-web
Symbolic link
1
.claude/skills/mai-web
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-web
|
||||
4
.m/.gitignore
vendored
Normal file
4
.m/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
workers.json
|
||||
spawn.lock
|
||||
session.yaml
|
||||
config.reference.yaml
|
||||
171
.m/config.yaml
Normal file
171
.m/config.yaml
Normal file
@@ -0,0 +1,171 @@
|
||||
# Project-specific mai configuration
|
||||
# Auto-generated by 'mai init' — run 'mai setup' to customize
|
||||
|
||||
provider: claude
|
||||
providers:
|
||||
claude:
|
||||
api_key: ""
|
||||
model: claude-sonnet-4-20250514
|
||||
base_url: https://api.anthropic.com/v1
|
||||
ollama:
|
||||
host: http://localhost:11434
|
||||
model: llama3.2
|
||||
memory:
|
||||
enabled: true
|
||||
backend: ""
|
||||
path: ""
|
||||
url: postgres://mai_memory.your-tenant-id:maiMem6034supa@100.99.98.201:6543/postgres?sslmode=disable
|
||||
group_id: onepager
|
||||
cache_ttl: 5m0s
|
||||
auto_load: true
|
||||
embedding_url: ""
|
||||
embedding_model: ""
|
||||
gitea:
|
||||
url: https://mgit.msbls.de
|
||||
repo: m/onepager
|
||||
token: ""
|
||||
sync:
|
||||
enabled: false
|
||||
interval: 0s
|
||||
repos: []
|
||||
auto_queue: false
|
||||
api:
|
||||
api_key: ""
|
||||
basic_auth:
|
||||
username: ""
|
||||
password: ""
|
||||
public_endpoints:
|
||||
- /api/health
|
||||
ui:
|
||||
theme: default
|
||||
show_sidebar: true
|
||||
animation: true
|
||||
persona: true
|
||||
avatar_pack: ""
|
||||
worker:
|
||||
names: []
|
||||
name_scheme: role
|
||||
default_level: standard
|
||||
auto_discard: false
|
||||
max_workers: 5
|
||||
persistent: true
|
||||
head:
|
||||
name: ""
|
||||
max_loops: 50
|
||||
infinity_mode: false
|
||||
capacity:
|
||||
global:
|
||||
max_workers: 5
|
||||
max_heads: 3
|
||||
per_worker:
|
||||
max_tasks_lifetime: 0
|
||||
max_concurrent: 1
|
||||
max_context_tokens: 0
|
||||
per_head:
|
||||
max_workers: 10
|
||||
resources:
|
||||
max_memory_mb: 0
|
||||
max_cpu_percent: 0
|
||||
queue:
|
||||
max_pending: 100
|
||||
stale_task_days: 30
|
||||
workforce:
|
||||
timeouts:
|
||||
task_default: 0s
|
||||
task_max: 0s
|
||||
idle_before_warn: 10m0s
|
||||
idle_before_kill: 30m0s
|
||||
quality_check: 2m0s
|
||||
context:
|
||||
max_tokens_per_worker: 0
|
||||
max_tokens_global: 0
|
||||
warn_threshold: 0.8
|
||||
truncate_strategy: oldest
|
||||
delegation:
|
||||
strategy: skill_match
|
||||
preferred_role: coder
|
||||
auto_delegate: false
|
||||
max_depth: 3
|
||||
allowed_roles:
|
||||
- coder
|
||||
- researcher
|
||||
- fixer
|
||||
peppy:
|
||||
enabled: false
|
||||
style: calm
|
||||
interval: 5m0s
|
||||
emoji: false
|
||||
nudges: true
|
||||
nudge_main: false
|
||||
custom_prompt: ""
|
||||
stall_threshold: 0s
|
||||
restart_enabled: false
|
||||
max_shifts: 0
|
||||
quality_gates:
|
||||
enabled: false
|
||||
checks: []
|
||||
preflight:
|
||||
enabled: false
|
||||
type: ""
|
||||
root: ""
|
||||
checks: []
|
||||
guardrails:
|
||||
enabled: false
|
||||
use_defaults: true
|
||||
output:
|
||||
coder_checks: []
|
||||
researcher_checks: []
|
||||
fixer_checks: []
|
||||
custom_checks: {}
|
||||
global_checks: []
|
||||
tools:
|
||||
role_rules: {}
|
||||
deny_patterns: []
|
||||
allow_patterns: []
|
||||
schemas:
|
||||
report_schemas: {}
|
||||
deliverable_schemas: {}
|
||||
modes:
|
||||
yolo: false
|
||||
self_improvement: true
|
||||
autonomous: false
|
||||
verbose: false
|
||||
improve_interval: 0s
|
||||
predict_interval: 0s
|
||||
layouts:
|
||||
head: ""
|
||||
worker: ""
|
||||
roles: {}
|
||||
dog:
|
||||
name: buddy
|
||||
supabase:
|
||||
url: ""
|
||||
role_key: ""
|
||||
anon_key: ""
|
||||
schema: mai
|
||||
storage:
|
||||
backend: ""
|
||||
postgres:
|
||||
url: ""
|
||||
max_conns: 0
|
||||
min_conns: 0
|
||||
max_conn_lifetime: 0s
|
||||
idle:
|
||||
behavior: wait
|
||||
auto_hire: false
|
||||
prompt: ""
|
||||
git:
|
||||
worktrees:
|
||||
enabled: true
|
||||
delete_branch: false
|
||||
dir: .worktrees
|
||||
phase:
|
||||
enabled: false
|
||||
current: ""
|
||||
allowed_roles: {}
|
||||
goal: "Mono-repo for 57+ vanity domain onepager sites — bash template system, Caddy routing, Dokploy deploy. Creative AI/KI-themed domains."
|
||||
skills: {}
|
||||
editor: nvim
|
||||
log_level: info
|
||||
project_detection: true
|
||||
tone: professional
|
||||
22
.mcp.json
Normal file
22
.mcp.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"supabase": {
|
||||
"type": "http",
|
||||
"url": "http://100.99.98.201:8000/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Basic ${SUPABASE_AUTH}"
|
||||
}
|
||||
},
|
||||
"mai-memory": {
|
||||
"command": "mai",
|
||||
"args": [
|
||||
"mcp",
|
||||
"memory"
|
||||
],
|
||||
"env": {
|
||||
"MAI_MEMORY_EMBEDDING_MODEL": "nomic-embed-text",
|
||||
"MAI_MEMORY_EMBEDDING_URL": "https://llm.x.msbls.de"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
.worktrees/knuth
Submodule
1
.worktrees/knuth
Submodule
Submodule .worktrees/knuth added at b49f1ae83e
15
Caddyfile
15
Caddyfile
@@ -9,6 +9,11 @@
|
||||
root * /srv
|
||||
file_server
|
||||
}
|
||||
@6034_de host 6034.de
|
||||
handle @6034_de {
|
||||
root * /srv/6034.de
|
||||
file_server
|
||||
}
|
||||
@allainallain_de host allainallain.de
|
||||
handle @allainallain_de {
|
||||
root * /srv/allainallain.de
|
||||
@@ -279,6 +284,11 @@
|
||||
root * /srv/sorgenfrai.de
|
||||
file_server
|
||||
}
|
||||
@traihard_de host traihard.de
|
||||
handle @traihard_de {
|
||||
root * /srv/traihard.de
|
||||
file_server
|
||||
}
|
||||
@vonschraitter_de host vonschraitter.de
|
||||
handle @vonschraitter_de {
|
||||
root * /srv/vonschraitter.de
|
||||
@@ -289,6 +299,11 @@
|
||||
root * /srv/wartebitte.de
|
||||
file_server
|
||||
}
|
||||
@zensiebels_de host zensiebels.de
|
||||
handle @zensiebels_de {
|
||||
root * /srv/zensiebels.de
|
||||
file_server
|
||||
}
|
||||
handle {
|
||||
respond "Not Found" 444
|
||||
}
|
||||
|
||||
@@ -1,45 +1,248 @@
|
||||
/**
|
||||
* Modulares Impressum für Onepager-Sites.
|
||||
* Modulares Impressum — Single Source of Truth für alle Onepager-Sites.
|
||||
*
|
||||
* Einbinden: <script src="/shared/impressum.js"></script>
|
||||
* Einbinden:
|
||||
* <script src="/shared/impressum.js"></script>
|
||||
* <script src="/shared/impressum.js" data-owner="flexsiebels"></script>
|
||||
* <script src="/shared/impressum.js" data-owner="flexsiebels" data-variant="full"></script>
|
||||
*
|
||||
* Konfiguration via data-Attribute am Script-Tag:
|
||||
* data-owner="msbls" (default) — Kurzform, msbls.de Satire-Impressum
|
||||
* data-owner="martinsiebels" — Volles Impressum Martin Siebels
|
||||
* data-style="minimal" (default) — Einzeiler
|
||||
* data-style="full" — Komplettes Impressum mit Adresse etc.
|
||||
* data-owner="msbls" (default) — Kurzverweis auf msbls.de
|
||||
* data-owner="flexsiebels" — Kurzverweis auf flexsiebels.de
|
||||
* data-owner="martinsiebels" — volles Impressum Martin Siebels (separate Person, Osnabrück)
|
||||
* data-variant="minimal" (default) — Einzeiler im Footer (inline)
|
||||
* data-variant="full" — kleiner Text-Trigger im Footer, voller § 5 TMG-Block im Overlay
|
||||
*
|
||||
* Legacy-Alias: data-style (gleiche Werte wie data-variant).
|
||||
*
|
||||
* Render-Ziel: Element mit id="impressum" falls vorhanden, sonst <footer>, sonst body.
|
||||
*
|
||||
* Theme: das Overlay liest --bg-card / --text / --accent / --border vom Host
|
||||
* (siehe shared/css/variables.css), mit neutralen Dark-Fallbacks für Sites
|
||||
* ohne diese Variablen.
|
||||
*/
|
||||
(function () {
|
||||
const script = document.currentScript;
|
||||
const owner = script?.getAttribute('data-owner') || 'msbls';
|
||||
const style = script?.getAttribute('data-style') || 'minimal';
|
||||
const variant = script?.getAttribute('data-variant')
|
||||
|| script?.getAttribute('data-style')
|
||||
|| 'minimal';
|
||||
|
||||
// Gemeinsamer Block für Matthias Siebels (m) — beide Domains, gleiche Anschrift.
|
||||
const matthiasAddress = 'Matthias Siebels<br>'
|
||||
+ 'c/o Online-Impressum.de #5892<br>'
|
||||
+ 'Europaring 90<br>'
|
||||
+ '53757 Sankt Augustin';
|
||||
|
||||
const owners = {
|
||||
msbls: {
|
||||
minimal: 'Ein Projekt von <a href="https://msbls.de" target="_blank" rel="noopener">msbls.de</a>',
|
||||
full: '<strong>Angaben gemäß § 5 TMG:</strong><br>msbls.de — Martin Siebels<br><a href="https://msbls.de/impressum" target="_blank" rel="noopener">Vollständiges Impressum</a>',
|
||||
full: '<strong>Angaben gemäß § 5 TMG:</strong><br>'
|
||||
+ matthiasAddress + '<br>'
|
||||
+ 'E-Mail: <a href="mailto:mail@msbls.de">mail@msbls.de</a>',
|
||||
},
|
||||
flexsiebels: {
|
||||
minimal: 'Ein Projekt von <a href="https://flexsiebels.de" target="_blank" rel="noopener">flexsiebels.de</a>',
|
||||
full: '<strong>Angaben gemäß § 5 TMG:</strong><br>'
|
||||
+ matthiasAddress + '<br>'
|
||||
+ 'E-Mail: <a href="mailto:mail@flexsiebels.de">mail@flexsiebels.de</a>',
|
||||
},
|
||||
martinsiebels: {
|
||||
minimal: 'Ein Projekt von <a href="https://martinsiebels.de" target="_blank" rel="noopener">Martin Siebels</a>',
|
||||
full: '<strong>Angaben gemäß § 5 TMG:</strong><br>'
|
||||
+ 'Martin Siebels<br>'
|
||||
+ 'Leyer Str. 38<br>'
|
||||
+ '49076 Osnabrück<br>'
|
||||
+ 'E-Mail: <a href="mailto:Martin_Siebels@web.de">Martin_Siebels@web.de</a>',
|
||||
},
|
||||
};
|
||||
|
||||
const config = owners[owner] || owners.msbls;
|
||||
const html = config[style] || config.minimal;
|
||||
|
||||
// Impressum-Element erstellen
|
||||
const el = document.createElement('div');
|
||||
el.className = 'onepager-impressum';
|
||||
el.innerHTML = html;
|
||||
const target = document.getElementById('impressum')
|
||||
|| document.querySelector('footer .container')
|
||||
|| document.querySelector('footer')
|
||||
|| document.body;
|
||||
|
||||
// Styling — erbt Farben vom footer/body, bleibt dezent
|
||||
el.style.cssText = 'text-align:center;font-size:0.7rem;opacity:0.5;padding:8px 0;margin-top:4px;';
|
||||
el.querySelector('a')?.style && Object.assign(el.querySelector('a').style, {
|
||||
color: 'inherit', textDecoration: 'none'
|
||||
});
|
||||
|
||||
// Einfügen: in <footer> falls vorhanden, sonst ans body-Ende
|
||||
const footer = document.querySelector('footer .container, footer');
|
||||
if (footer) {
|
||||
footer.appendChild(el);
|
||||
if (variant === 'full') {
|
||||
renderOverlay(config.full, target);
|
||||
} else {
|
||||
document.body.appendChild(el);
|
||||
renderInline(config.minimal, target);
|
||||
}
|
||||
|
||||
function renderInline(html, target) {
|
||||
const el = document.createElement('div');
|
||||
el.className = 'onepager-impressum';
|
||||
el.innerHTML = html;
|
||||
el.style.cssText = 'text-align:center;font-size:0.75rem;opacity:0.6;padding:12px 0;margin-top:4px;line-height:1.7;';
|
||||
el.querySelectorAll('a').forEach(a => {
|
||||
a.style.color = 'inherit';
|
||||
a.style.textDecoration = 'underline';
|
||||
a.style.textDecorationThickness = '1px';
|
||||
a.style.textUnderlineOffset = '2px';
|
||||
});
|
||||
target.appendChild(el);
|
||||
}
|
||||
|
||||
function renderOverlay(html, target) {
|
||||
// Trigger: kleiner Text-Link, layout-äquivalent zur inline-minimal-Variante,
|
||||
// damit Footer-Höhe sich nicht ändert.
|
||||
const wrap = document.createElement('div');
|
||||
wrap.className = 'onepager-impressum';
|
||||
wrap.style.cssText = 'text-align:center;font-size:0.75rem;opacity:0.6;padding:12px 0;margin-top:4px;line-height:1.7;';
|
||||
|
||||
const trigger = document.createElement('a');
|
||||
trigger.href = '#impressum';
|
||||
trigger.className = 'onepager-impressum-trigger';
|
||||
trigger.textContent = 'Impressum';
|
||||
trigger.style.cssText = [
|
||||
'color:inherit',
|
||||
'text-decoration:underline',
|
||||
'text-decoration-thickness:1px',
|
||||
'text-underline-offset:2px',
|
||||
'cursor:pointer',
|
||||
].join(';');
|
||||
|
||||
wrap.appendChild(trigger);
|
||||
target.appendChild(wrap);
|
||||
|
||||
let backdrop = null;
|
||||
let lastFocus = null;
|
||||
let prevBodyOverflow = '';
|
||||
|
||||
trigger.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
open();
|
||||
});
|
||||
|
||||
function open() {
|
||||
if (backdrop) return;
|
||||
lastFocus = document.activeElement;
|
||||
|
||||
backdrop = document.createElement('div');
|
||||
backdrop.className = 'onepager-impressum-backdrop';
|
||||
backdrop.style.cssText = [
|
||||
'position:fixed',
|
||||
'inset:0',
|
||||
'background:rgba(0,0,0,0.6)',
|
||||
'display:flex',
|
||||
'align-items:center',
|
||||
'justify-content:center',
|
||||
'padding:16px',
|
||||
'box-sizing:border-box',
|
||||
'overflow:auto',
|
||||
'z-index:99999',
|
||||
'opacity:0',
|
||||
'transition:opacity 0.18s ease',
|
||||
].join(';');
|
||||
|
||||
const card = document.createElement('div');
|
||||
card.className = 'onepager-impressum-card';
|
||||
card.setAttribute('role', 'dialog');
|
||||
card.setAttribute('aria-modal', 'true');
|
||||
card.setAttribute('aria-label', 'Impressum');
|
||||
// Theme-aware: nutzt CSS-Variablen vom Host, mit neutralen Dark-Fallbacks.
|
||||
// max-width via min(...) verhindert Frame-Sprengen auf schmalen Viewports.
|
||||
card.style.cssText = [
|
||||
'position:relative',
|
||||
'box-sizing:border-box',
|
||||
'max-width:min(420px, calc(100vw - 32px))',
|
||||
'width:100%',
|
||||
'background:var(--bg-card, #16161b)',
|
||||
'color:var(--text, #e8e8ed)',
|
||||
'padding:32px 24px 24px',
|
||||
'border:1px solid var(--border, rgba(255,255,255,0.08))',
|
||||
'border-radius:var(--radius, 8px)',
|
||||
'box-shadow:0 20px 60px rgba(0,0,0,0.5)',
|
||||
'font-family:var(--font-primary, Inter, -apple-system, BlinkMacSystemFont, sans-serif)',
|
||||
'font-size:0.9rem',
|
||||
'line-height:1.6',
|
||||
'overflow-wrap:break-word',
|
||||
'word-wrap:break-word',
|
||||
'transform:translateY(8px)',
|
||||
'transition:transform 0.18s ease',
|
||||
].join(';');
|
||||
|
||||
const close = document.createElement('button');
|
||||
close.type = 'button';
|
||||
close.setAttribute('aria-label', 'Schließen');
|
||||
close.innerHTML = '×';
|
||||
close.style.cssText = [
|
||||
'position:absolute',
|
||||
'top:4px',
|
||||
'right:8px',
|
||||
'background:none',
|
||||
'border:none',
|
||||
'font:inherit',
|
||||
'font-size:1.5rem',
|
||||
'line-height:1',
|
||||
'color:inherit',
|
||||
'opacity:0.5',
|
||||
'cursor:pointer',
|
||||
'padding:6px 10px',
|
||||
'border-radius:4px',
|
||||
'transition:opacity 0.15s ease',
|
||||
].join(';');
|
||||
close.addEventListener('mouseenter', () => { close.style.opacity = '1'; });
|
||||
close.addEventListener('mouseleave', () => { close.style.opacity = '0.5'; });
|
||||
close.addEventListener('focus', () => { close.style.opacity = '1'; });
|
||||
close.addEventListener('blur', () => { close.style.opacity = '0.5'; });
|
||||
close.addEventListener('click', dismiss);
|
||||
|
||||
const content = document.createElement('div');
|
||||
content.innerHTML = html;
|
||||
content.style.cssText = 'margin-top:4px;';
|
||||
content.querySelectorAll('a').forEach(a => {
|
||||
a.style.color = 'var(--accent, #c9a84c)';
|
||||
a.style.textDecoration = 'underline';
|
||||
});
|
||||
content.querySelectorAll('strong').forEach(s => {
|
||||
s.style.display = 'block';
|
||||
s.style.marginBottom = '10px';
|
||||
s.style.fontWeight = '600';
|
||||
});
|
||||
|
||||
card.appendChild(close);
|
||||
card.appendChild(content);
|
||||
backdrop.appendChild(card);
|
||||
document.body.appendChild(backdrop);
|
||||
|
||||
// Scroll-Lock auf body, damit Hintergrund nicht mitscrollt.
|
||||
prevBodyOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
backdrop.style.opacity = '1';
|
||||
card.style.transform = 'translateY(0)';
|
||||
});
|
||||
|
||||
backdrop.addEventListener('click', (e) => {
|
||||
if (e.target === backdrop) dismiss();
|
||||
});
|
||||
document.addEventListener('keydown', onKey);
|
||||
close.focus();
|
||||
}
|
||||
|
||||
function dismiss() {
|
||||
if (!backdrop) return;
|
||||
document.removeEventListener('keydown', onKey);
|
||||
const node = backdrop;
|
||||
backdrop = null;
|
||||
node.style.opacity = '0';
|
||||
document.body.style.overflow = prevBodyOverflow;
|
||||
setTimeout(() => {
|
||||
if (node.parentNode) node.parentNode.removeChild(node);
|
||||
if (lastFocus && typeof lastFocus.focus === 'function') {
|
||||
lastFocus.focus();
|
||||
}
|
||||
}, 180);
|
||||
}
|
||||
|
||||
function onKey(e) {
|
||||
if (e.key === 'Escape') {
|
||||
e.preventDefault();
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
110
sites/6034.de/index.html
Normal file
110
sites/6034.de/index.html
Normal file
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<meta name="theme-color" content="#0f1210">
|
||||
<title>6034.de</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0f1210;
|
||||
--bg-card: #1a1f1c;
|
||||
--border: #2d3630;
|
||||
--text: #e8ede9;
|
||||
--text-dim: #8a9b8e;
|
||||
--green: #4ade80;
|
||||
--green-dim: #22c55e;
|
||||
--font: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', monospace;
|
||||
}
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html, body {
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: var(--font);
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background-image: radial-gradient(circle at 20% 10%, rgba(74,222,128,0.06), transparent 40%),
|
||||
radial-gradient(circle at 80% 90%, rgba(74,222,128,0.04), transparent 40%);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
main {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
padding: 4rem 1.5rem;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.brand {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 4rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--green);
|
||||
line-height: 1;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
.brand-dot { color: var(--text-dim); }
|
||||
.links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.link {
|
||||
padding: 1rem 1.25rem;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
text-decoration: none;
|
||||
color: var(--text);
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
transition: border-color 0.15s ease, transform 0.15s ease;
|
||||
}
|
||||
.link:hover {
|
||||
border-color: var(--green-dim);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.link-arrow {
|
||||
color: var(--green);
|
||||
font-family: var(--font-mono);
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.15s ease, transform 0.15s ease;
|
||||
}
|
||||
.link:hover .link-arrow {
|
||||
opacity: 1;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.brand { font-size: 3rem; }
|
||||
main { padding: 3rem 1rem; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="brand">6034<span class="brand-dot">.de</span></div>
|
||||
<div class="links">
|
||||
<a class="link" href="https://grn.msbls.de" target="_blank" rel="noopener">
|
||||
<span>🌱 mGreen</span>
|
||||
<span class="link-arrow">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
4
sites/6034.de/site.yaml
Normal file
4
sites/6034.de/site.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
domain: 6034.de
|
||||
template: custom
|
||||
title: "6034 — Personal Project Space"
|
||||
description: "Eine Sammlung persönlicher Projekte von m."
|
||||
@@ -157,6 +157,91 @@
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
/* Rechner */
|
||||
.rechner {
|
||||
padding: 120px 0;
|
||||
}
|
||||
|
||||
.rechner h2 {
|
||||
font-size: clamp(2.5rem, 7vw, 4rem);
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.02em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.rechner h2 .dot { color: var(--red); }
|
||||
|
||||
.rechner-grid {
|
||||
display: flex;
|
||||
gap: 32px;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.rechner-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.rechner-input label {
|
||||
display: block;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-dim);
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.rechner-input input {
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
border: 1px solid var(--text-muted);
|
||||
color: var(--text);
|
||||
font-family: inherit;
|
||||
font-size: 2.4rem;
|
||||
font-weight: 700;
|
||||
padding: 12px 16px;
|
||||
text-align: center;
|
||||
outline: none;
|
||||
transition: border-color 0.3s;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
.rechner-input input::-webkit-inner-spin-button,
|
||||
.rechner-input input::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.rechner-input input:focus {
|
||||
border-color: var(--red);
|
||||
}
|
||||
|
||||
.rechner-result {
|
||||
font-size: clamp(1.3rem, 3vw, 1.8rem);
|
||||
font-weight: 300;
|
||||
color: var(--text-dim);
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.rechner-result .num {
|
||||
color: var(--red);
|
||||
font-weight: 700;
|
||||
font-size: 1.15em;
|
||||
}
|
||||
|
||||
.rechner-result .verdict {
|
||||
display: block;
|
||||
margin-top: 24px;
|
||||
font-size: clamp(1.5rem, 4vw, 2.2rem);
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.rechner { padding: 80px 0; }
|
||||
.rechner-grid { flex-direction: column; gap: 24px; }
|
||||
}
|
||||
|
||||
/* Silence */
|
||||
.silence {
|
||||
padding: 160px 0;
|
||||
@@ -171,6 +256,34 @@
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Rechnung */
|
||||
.rechnung {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.rechnung-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
font-size: clamp(1.1rem, 2.5vw, 1.5rem);
|
||||
font-weight: 300;
|
||||
color: var(--text-dim);
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.rechnung-row .label { text-align: left; }
|
||||
.rechnung-row .value { text-align: right; font-weight: 700; color: var(--red); }
|
||||
|
||||
.rechnung-divider {
|
||||
border: none;
|
||||
border-top: 1px solid var(--text-muted);
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.rechnung-total .label { font-weight: 600; color: var(--text); }
|
||||
.rechnung-total .value { font-size: 1.15em; }
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
padding: 40px 0;
|
||||
@@ -217,8 +330,9 @@
|
||||
<section class="numbers">
|
||||
<div class="wrap">
|
||||
<p class="reveal">
|
||||
<span class="num">2.400</span> Stunden pro Jahr.<br>
|
||||
<span class="num">6,5</span> Stunden pro Tag, die du „verkaufst“.<br>
|
||||
Eine Zahl bestimmt deinen Wert.<br>
|
||||
Nicht dein Ergebnis. Nicht dein Wissen.<br>
|
||||
<span class="num">Billable Hours</span> — der einzige KPI, der zählt.<br>
|
||||
Jede Minute dokumentiert.<br>
|
||||
Jede Pause ein Verlust.
|
||||
</p>
|
||||
@@ -230,26 +344,53 @@
|
||||
<section class="kritik">
|
||||
<div class="wrap">
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p>Du wirst nach Zeit bezahlt, <span class="dim">nicht nach Ergebnis.</span></p>
|
||||
</div>
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p>Effizienz wird bestraft. <span class="dim">Wer schneller arbeitet, verdient weniger.</span></p>
|
||||
</div>
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p>Der Mandant zahlt <span class="dim">für deine Lernkurve.</span></p>
|
||||
<p>Ineffizienz wird belohnt. <span class="dim">Länger brauchen heißt mehr verdienen.</span></p>
|
||||
</div>
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p><span class="num">8</span> Stunden Arbeit = <span class="num">6,5</span> billable. <span class="dim">Die restlichen 1,5? Dein Problem.</span></p>
|
||||
<p>Verkauft wird nur, was auf der Rechnung steht. <span class="dim">Der Rest deiner Arbeit existiert nicht.</span></p>
|
||||
</div>
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p>Partnertrack heißt: <span class="dim"><span class="num">10</span> Jahre beweisen, dass du leidensfähig bist.</span></p>
|
||||
<p>Und die anderen Stunden im Büro? <span class="dim">Egal.</span></p>
|
||||
</div>
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p>Die besten Ideen kommen nicht, <span class="dim">während die Stoppuhr läuft.</span></p>
|
||||
</div>
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p>Ein Leben im Sechs-Minuten-Takt <span class="dim">macht etwas mit deinem Bewusstsein.</span></p>
|
||||
</div>
|
||||
|
||||
<div class="kritik-item reveal">
|
||||
<p>Innovation ist ein Risiko. <span class="dim">Jedes Tool, das Zeit spart, bedroht den Umsatz.</span></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="line"></div>
|
||||
|
||||
<section class="rechner">
|
||||
<div class="wrap">
|
||||
<h2 class="reveal">Rechne selbst<span class="dot">.</span></h2>
|
||||
<div class="rechner-grid reveal">
|
||||
<div class="rechner-input">
|
||||
<label>Billable-Stunden / Jahr</label>
|
||||
<input type="number" id="hours" value="1800" min="0" max="5000">
|
||||
</div>
|
||||
<div class="rechner-input">
|
||||
<label>Urlaubstage</label>
|
||||
<input type="number" id="vacation" value="25" min="0" max="60">
|
||||
</div>
|
||||
</div>
|
||||
<div class="rechner-result reveal" id="result"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -277,6 +418,60 @@
|
||||
}, { threshold: 0.15 });
|
||||
|
||||
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
||||
|
||||
// Rechner
|
||||
function calculate() {
|
||||
const hours = parseInt(document.getElementById('hours').value) || 0;
|
||||
const vacation = parseInt(document.getElementById('vacation').value) || 0;
|
||||
const weekends = 104;
|
||||
const feiertage = 10;
|
||||
const workingDays = 365 - weekends - vacation - feiertage;
|
||||
const perDay = workingDays > 0 ? (hours / workingDays) : 0;
|
||||
const perDayStr = perDay.toFixed(1).replace('.', ',');
|
||||
|
||||
let verdict = '';
|
||||
if (perDay >= 7.96) {
|
||||
verdict = '<span class="verdict">Das ist nicht nur ein Job. <span class="dim">Das ist ein Lifestyle.</span></span>';
|
||||
} else if (perDay > 7) {
|
||||
verdict = '<span class="verdict">Das ist die Theorie. <span class="dim">In der Praxis bist du länger da.</span></span>';
|
||||
} else if (perDay > 6) {
|
||||
verdict = '<span class="verdict">Das sind nur die billable hours. <span class="dim">Dazu kommen Admin, Meetings, Mails — unbezahlt.</span></span>';
|
||||
}
|
||||
|
||||
var r = function(l, v) {
|
||||
return '<div class="rechnung-row"><span class="label">' + l + '</span><span class="value">' + v + '</span></div>';
|
||||
};
|
||||
|
||||
document.getElementById('result').innerHTML =
|
||||
'<div class="rechnung">' +
|
||||
r('Tage im Jahr', '365') +
|
||||
r('Wochenendtage (52 × 2)', '− 104') +
|
||||
r('Urlaubstage', '− ' + vacation) +
|
||||
r('Feiertage', '− ' + feiertage) +
|
||||
'<hr class="rechnung-divider">' +
|
||||
'<div class="rechnung-row rechnung-total">' +
|
||||
'<span class="label">Arbeitstage</span><span class="value">' + workingDays + '</span></div>' +
|
||||
'</div><br>' +
|
||||
'<span class="num">' + hours.toLocaleString('de-DE') + '</span> Stunden ÷ <span class="num">' + workingDays + '</span> Tage = ' +
|
||||
'<span class="num">' + perDayStr + '</span> Stunden billable pro Tag.' +
|
||||
verdict +
|
||||
'<span class="verdict" style="margin-top:32px;font-size:0.85em;font-weight:300;color:var(--text-dim);display:block;">' +
|
||||
(function() {
|
||||
var base = hours / workingDays * 60;
|
||||
var d1 = workingDays > 1 ? Math.round(hours / (workingDays - 1) * 60 - base) : 0;
|
||||
var d2 = workingDays > 2 ? Math.round(hours / (workingDays - 2) * 60 - base) : 0;
|
||||
var d5 = workingDays > 5 ? Math.round(hours / (workingDays - 5) * 60 - base) : 0;
|
||||
return 'Ein Tag krank? +<span class="num">' + d1 + '</span> Minuten mehr an jedem anderen Tag. Jeden.' +
|
||||
' Zwei Tage? +<span class="num">' + d2 + '</span>.' +
|
||||
' Eine Woche? +<span class="num">' + d5 + '</span>.' +
|
||||
'<br>Jeder verpasste Tag erhöht den Druck auf alle anderen.';
|
||||
})() +
|
||||
'</span>';
|
||||
}
|
||||
|
||||
document.getElementById('hours').addEventListener('input', calculate);
|
||||
document.getElementById('vacation').addEventListener('input', calculate);
|
||||
calculate();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -3,129 +3,34 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Clemens Plassmann</title>
|
||||
<title>Clemens Plassmann — Hogan Lovells</title>
|
||||
<meta name="description" content="Clemens Plassmann — Patent Litigation, Hogan Lovells.">
|
||||
<meta http-equiv="refresh" content="0; url=https://www.hoganlovells.com/en/clemens-plassmann">
|
||||
<link rel="canonical" href="https://www.hoganlovells.com/en/clemens-plassmann">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚖️</text></svg>">
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Georgia', 'Times New Roman', serif;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
background: #0a0a0a;
|
||||
color: #e8e6e3;
|
||||
color: #c9a96e;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: clamp(2.5rem, 6vw, 4rem);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.08em;
|
||||
margin-bottom: 0.5rem;
|
||||
background: linear-gradient(135deg, #c9a96e 0%, #f0d89d 50%, #c9a96e 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 60px;
|
||||
height: 1px;
|
||||
background: #c9a96e;
|
||||
margin: 1.5rem auto;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 400;
|
||||
color: #8a8580;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.firm {
|
||||
font-size: 1rem;
|
||||
color: #6a6560;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin-top: 3rem;
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.links a {
|
||||
color: #c9a96e;
|
||||
text-decoration: none;
|
||||
font-size: 0.85rem;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
padding: 0.6rem 1.5rem;
|
||||
border: 1px solid rgba(201, 169, 110, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.links a:hover {
|
||||
border-color: #c9a96e;
|
||||
background: rgba(201, 169, 110, 0.08);
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 4rem;
|
||||
font-size: 0.75rem;
|
||||
color: #3a3530;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #3a3530;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: #6a6560;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.container > * {
|
||||
animation: fadeIn 0.8s ease forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
.container > *:nth-child(1) { animation-delay: 0.1s; }
|
||||
.container > *:nth-child(2) { animation-delay: 0.3s; }
|
||||
.container > *:nth-child(3) { animation-delay: 0.5s; }
|
||||
.container > *:nth-child(4) { animation-delay: 0.7s; }
|
||||
.container > *:nth-child(5) { animation-delay: 0.9s; }
|
||||
.container > *:nth-child(6) { animation-delay: 1.1s; }
|
||||
a { color: #c9a96e; text-decoration: none; border-bottom: 1px solid rgba(201,169,110,0.4); }
|
||||
a:hover { border-bottom-color: #c9a96e; }
|
||||
p { letter-spacing: 0.06em; line-height: 1.8; }
|
||||
</style>
|
||||
<script>window.location.replace('https://www.hoganlovells.com/en/clemens-plassmann');</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="name">Clemens Plassmann</h1>
|
||||
<div class="divider"></div>
|
||||
<p class="title">Patent Litigation</p>
|
||||
<p class="firm">Hogan Lovells</p>
|
||||
<div class="links">
|
||||
<a href="https://www.hoganlovells.com/en/clemens-plassmann" target="_blank">Profile</a>
|
||||
<a href="https://www.linkedin.com/in/clemens-plassmann/" target="_blank">LinkedIn</a>
|
||||
</div>
|
||||
<p class="footer">Built by <a href="https://flexsiebels.de">Otto</a></p>
|
||||
<div>
|
||||
<p>Clemens Plassmann — Patent Litigation, Hogan Lovells.</p>
|
||||
<p>Weiter zu <a href="https://www.hoganlovells.com/en/clemens-plassmann">hoganlovells.com</a>.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -576,8 +576,9 @@
|
||||
<footer>
|
||||
<div class="footer-bear">🧸</div>
|
||||
<p class="footer-text">Hey Goldi! — Dein freundlicher KI-Begleiter.</p>
|
||||
<p class="footer-copy">© 2026 heygoldi.de — ein Projekt von <a href="https://msbls.de">msbls.de</a></p>
|
||||
<p class="footer-copy">© 2026 heygoldi.de</p>
|
||||
</footer>
|
||||
|
||||
<script src="/shared/impressum.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -440,5 +440,6 @@
|
||||
</footer>
|
||||
|
||||
<script src="/shared/i18n.js"></script>
|
||||
<script src="/shared/impressum.js" data-owner="flexsiebels" data-variant="full"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -550,5 +550,6 @@
|
||||
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
|
||||
</script>
|
||||
|
||||
<script src="/shared/impressum.js" data-owner="flexsiebels" data-variant="full"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -436,5 +436,6 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/shared/impressum.js" data-owner="flexsiebels" data-variant="full"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -392,5 +392,6 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/shared/impressum.js" data-owner="martinsiebels" data-variant="full"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -724,9 +724,10 @@
|
||||
<!-- FOOTER -->
|
||||
<footer>
|
||||
<p class="footer-brand">Paragraphen<span>rAI</span>ter</p>
|
||||
<p class="footer-credit">Ein Projekt von Matthias Flexsiebels</p>
|
||||
<p class="footer-legal">© 2026 · Recht. Aber schlauer.</p>
|
||||
</footer>
|
||||
|
||||
<script src="/shared/impressum.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -650,7 +650,7 @@
|
||||
<footer>
|
||||
<p class="footer-brand">Patentonkel</p>
|
||||
<p class="footer-tagline">Familiär. Kompetent. KI.</p>
|
||||
<p class="footer-legal">© 2026 · Ein Projekt von Matthias Flexsiebels · <a href="#" onclick="window.__impressum&&window.__impressum();return false;">Impressum</a></p>
|
||||
<p class="footer-legal">© 2026 · Familienkompatibel ausgedacht.</p>
|
||||
</footer>
|
||||
|
||||
<script src="/shared/impressum.js"></script>
|
||||
|
||||
BIN
sites/smartin3.de/img/flachkabel-halter.jpg
Normal file
BIN
sites/smartin3.de/img/flachkabel-halter.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
BIN
sites/smartin3.de/img/muenzhalter.jpg
Normal file
BIN
sites/smartin3.de/img/muenzhalter.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 243 KiB |
BIN
sites/smartin3.de/img/schaltanlage-panelhalter.jpg
Normal file
BIN
sites/smartin3.de/img/schaltanlage-panelhalter.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
BIN
sites/smartin3.de/img/sonnenblendenhalter.jpg
Normal file
BIN
sites/smartin3.de/img/sonnenblendenhalter.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
BIN
sites/smartin3.de/img/vw-golf-mk1-abdeckung.jpg
Normal file
BIN
sites/smartin3.de/img/vw-golf-mk1-abdeckung.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 308 KiB |
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>sMARTin 3D — Smart in 3D</title>
|
||||
<meta name="description" content="sMARTin 3D — Dein 3D-Druck-Shop. Individuelle Teile, Prototypen, Kleinserien. Smart gedacht, praezise gedruckt.">
|
||||
<meta name="description" content="sMARTin 3D — Dein 3D-Druck-Shop. Individuelle Teile, Prototypen, Kleinserien. Smart gedacht, präzise gedruckt.">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🧊</text></svg>">
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500&display=swap');
|
||||
@@ -26,7 +26,7 @@
|
||||
--blue-glow: rgba(56, 189, 248, 0.15);
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; }
|
||||
html { scroll-behavior: smooth; overflow-x: hidden; }
|
||||
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
@@ -37,39 +37,41 @@
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.03'/%3E%3C/svg%3E");
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.container { max-width: 860px; margin: 0 auto; padding: 0 24px; }
|
||||
|
||||
/* Nav */
|
||||
nav {
|
||||
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
|
||||
padding: 20px 0;
|
||||
padding: 20px 24px;
|
||||
background: rgba(10, 10, 12, 0.8);
|
||||
backdrop-filter: blur(20px);
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
max-width: 100vw; box-sizing: border-box;
|
||||
}
|
||||
nav .container { display: flex; justify-content: space-between; align-items: center; }
|
||||
.logo { font-family: 'Space Grotesk', sans-serif; font-size: 1.1rem; font-weight: 600; }
|
||||
.logo { font-family: 'Space Grotesk', sans-serif; font-size: 1.1rem; font-weight: 600; white-space: nowrap; }
|
||||
.logo .s { color: var(--text-dim); font-weight: 300; text-transform: lowercase; }
|
||||
.logo .martin { color: var(--orange); }
|
||||
.logo .three { color: var(--blue); font-weight: 700; }
|
||||
.logo .d { color: var(--text); }
|
||||
nav a { color: var(--text-dim); text-decoration: none; font-size: 0.85rem; transition: color 0.2s; }
|
||||
.nav-links { display: flex; gap: 16px; align-items: center; }
|
||||
nav a { color: var(--text-dim); text-decoration: none; font-size: 0.85rem; transition: color 0.2s; white-space: nowrap; }
|
||||
nav a:hover { color: var(--text); }
|
||||
.nav-toggle { display: none; background: none; border: none; color: var(--text-dim); font-size: 1.4rem; cursor: pointer; padding: 4px; }
|
||||
@media (max-width: 600px) {
|
||||
.nav-links { display: none; position: absolute; top: 100%; right: 24px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 0 0 12px 12px; flex-direction: column; padding: 16px 24px; gap: 14px; min-width: 160px; }
|
||||
.nav-links.open { display: flex; }
|
||||
.nav-toggle { display: block; }
|
||||
nav a { font-size: 0.9rem; }
|
||||
}
|
||||
|
||||
/* Hero */
|
||||
.hero {
|
||||
padding: 180px 0 120px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.hero::before {
|
||||
@@ -77,46 +79,80 @@
|
||||
position: absolute;
|
||||
top: 60px; left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 700px; height: 500px;
|
||||
width: 100vw; height: 400px;
|
||||
background:
|
||||
radial-gradient(ellipse at 40% 50%, var(--orange-glow) 0%, transparent 60%),
|
||||
radial-gradient(ellipse at 60% 40%, var(--blue-glow) 0%, transparent 60%);
|
||||
radial-gradient(ellipse at 40% 50%, var(--orange-glow) 0%, transparent 50%),
|
||||
radial-gradient(ellipse at 60% 40%, var(--blue-glow) 0%, transparent 50%);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* 3D cube animation */
|
||||
.cube-wrapper {
|
||||
perspective: 600px;
|
||||
width: 80px; height: 80px;
|
||||
/* 3D text animation */
|
||||
.text3d-wrapper {
|
||||
perspective: 800px;
|
||||
margin: 0 auto 40px;
|
||||
display: flex; justify-content: center;
|
||||
padding: 60px 40px;
|
||||
}
|
||||
|
||||
.cube {
|
||||
width: 80px; height: 80px;
|
||||
position: relative;
|
||||
.text3d {
|
||||
transform-style: preserve-3d;
|
||||
animation: rotateCube 12s linear infinite;
|
||||
animation: rotateText 10s ease-in-out infinite;
|
||||
transition: transform 0.1s ease-out;
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
font-size: clamp(3rem, 10vw, 5rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@keyframes rotateCube {
|
||||
from { transform: rotateX(-20deg) rotateY(0deg); }
|
||||
to { transform: rotateX(-20deg) rotateY(360deg); }
|
||||
.text3d-face {
|
||||
display: block;
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
.cube-face {
|
||||
position: absolute;
|
||||
width: 80px; height: 80px;
|
||||
border: 1px solid var(--orange);
|
||||
background: rgba(249, 115, 22, 0.04);
|
||||
opacity: 0.7;
|
||||
.text3d-depth {
|
||||
position: absolute; top: 0; left: 0;
|
||||
}
|
||||
|
||||
.cube-face:nth-child(1) { transform: translateZ(40px); }
|
||||
.cube-face:nth-child(2) { transform: rotateY(180deg) translateZ(40px); }
|
||||
.cube-face:nth-child(3) { transform: rotateY(90deg) translateZ(40px); }
|
||||
.cube-face:nth-child(4) { transform: rotateY(-90deg) translateZ(40px); }
|
||||
.cube-face:nth-child(5) { transform: rotateX(90deg) translateZ(40px); }
|
||||
.cube-face:nth-child(6) { transform: rotateX(-90deg) translateZ(40px); }
|
||||
.text3d-depth:nth-child(2) { transform: translateZ(-1px); color: rgb(249,115,22); }
|
||||
.text3d-depth:nth-child(3) { transform: translateZ(-2px); color: rgb(242,117,29); }
|
||||
.text3d-depth:nth-child(4) { transform: translateZ(-3px); color: rgb(235,120,37); }
|
||||
.text3d-depth:nth-child(5) { transform: translateZ(-4px); color: rgb(229,122,45); }
|
||||
.text3d-depth:nth-child(6) { transform: translateZ(-5px); color: rgb(222,125,53); }
|
||||
.text3d-depth:nth-child(7) { transform: translateZ(-6px); color: rgb(215,127,60); }
|
||||
.text3d-depth:nth-child(8) { transform: translateZ(-7px); color: rgb(209,130,68); }
|
||||
.text3d-depth:nth-child(9) { transform: translateZ(-8px); color: rgb(202,132,76); }
|
||||
.text3d-depth:nth-child(10) { transform: translateZ(-9px); color: rgb(195,135,84); }
|
||||
.text3d-depth:nth-child(11) { transform: translateZ(-10px); color: rgb(189,137,92); }
|
||||
.text3d-depth:nth-child(12) { transform: translateZ(-11px); color: rgb(182,140,99); }
|
||||
.text3d-depth:nth-child(13) { transform: translateZ(-12px); color: rgb(175,143,107); }
|
||||
.text3d-depth:nth-child(14) { transform: translateZ(-13px); color: rgb(169,145,115); }
|
||||
.text3d-depth:nth-child(15) { transform: translateZ(-14px); color: rgb(162,148,123); }
|
||||
.text3d-depth:nth-child(16) { transform: translateZ(-15px); color: rgb(155,150,131); }
|
||||
.text3d-depth:nth-child(17) { transform: translateZ(-16px); color: rgb(149,153,138); }
|
||||
.text3d-depth:nth-child(18) { transform: translateZ(-17px); color: rgb(142,155,146); }
|
||||
.text3d-depth:nth-child(19) { transform: translateZ(-18px); color: rgb(135,158,154); }
|
||||
.text3d-depth:nth-child(20) { transform: translateZ(-19px); color: rgb(129,160,162); }
|
||||
.text3d-depth:nth-child(21) { transform: translateZ(-20px); color: rgb(122,163,170); }
|
||||
.text3d-depth:nth-child(22) { transform: translateZ(-21px); color: rgb(115,166,177); }
|
||||
.text3d-depth:nth-child(23) { transform: translateZ(-22px); color: rgb(109,168,185); }
|
||||
.text3d-depth:nth-child(24) { transform: translateZ(-23px); color: rgb(102,171,193); }
|
||||
.text3d-depth:nth-child(25) { transform: translateZ(-24px); color: rgb(95,173,201); }
|
||||
.text3d-depth:nth-child(26) { transform: translateZ(-25px); color: rgb(89,176,209); }
|
||||
.text3d-depth:nth-child(27) { transform: translateZ(-26px); color: rgb(82,178,216); }
|
||||
.text3d-depth:nth-child(28) { transform: translateZ(-27px); color: rgb(75,181,224); }
|
||||
.text3d-depth:nth-child(29) { transform: translateZ(-28px); color: rgb(69,183,232); }
|
||||
.text3d-depth:nth-child(30) { transform: translateZ(-29px); color: rgb(62,186,240); }
|
||||
.text3d-depth:nth-child(31) { transform: translateZ(-30px); color: rgb(56,189,248); }
|
||||
|
||||
@keyframes rotateText {
|
||||
0% { transform: rotateX(-20deg) rotateY(-45deg); }
|
||||
50% { transform: rotateX(-20deg) rotateY(45deg); }
|
||||
100% { transform: rotateX(-20deg) rotateY(-45deg); }
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
@@ -201,6 +237,92 @@
|
||||
.service-card h3 { font-family: 'Space Grotesk', sans-serif; font-size: 0.95rem; font-weight: 600; margin-bottom: 8px; }
|
||||
.service-card p { color: var(--text-dim); font-size: 0.84rem; line-height: 1.6; font-weight: 300; }
|
||||
|
||||
/* Gallery */
|
||||
.gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.gallery-item {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
aspect-ratio: 4/3;
|
||||
border: 1px solid var(--border);
|
||||
transition: border-color 0.3s, transform 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.gallery-item:hover {
|
||||
border-color: var(--orange);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.gallery-item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.gallery-item figcaption {
|
||||
padding: 12px 14px;
|
||||
font-size: 0.78rem;
|
||||
color: var(--text-dim);
|
||||
line-height: 1.5;
|
||||
font-weight: 300;
|
||||
background: var(--bg-card);
|
||||
}
|
||||
|
||||
.gallery-item figcaption strong {
|
||||
color: var(--text);
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.gallery-item figure {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.gallery-item figure img {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.gallery-item.has-caption {
|
||||
aspect-ratio: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.gallery-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
|
||||
/* Lightbox */
|
||||
.lightbox {
|
||||
display: none; position: fixed; inset: 0; z-index: 200;
|
||||
background: rgba(0,0,0,0.9); backdrop-filter: blur(10px);
|
||||
justify-content: center; align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lightbox.active { display: flex; }
|
||||
.lightbox img {
|
||||
max-width: 90vw; max-height: 85vh;
|
||||
object-fit: contain; border-radius: 8px;
|
||||
}
|
||||
.lightbox-caption {
|
||||
position: fixed; bottom: 24px; left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: var(--text-dim); font-size: 0.9rem;
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
text-align: center; max-width: 80vw;
|
||||
}
|
||||
|
||||
/* Process */
|
||||
.process-steps {
|
||||
display: grid;
|
||||
@@ -266,31 +388,58 @@
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<div class="container">
|
||||
<div class="logo"><span class="s">s</span><span class="martin">MARTIN</span> <span class="three">3</span><span class="d">D</span></div>
|
||||
<a href="#kontakt">Anfrage</a>
|
||||
<div class="logo"><span class="s">s</span><span class="martin">MARTIN</span> <span class="three">3</span><span class="d">D</span></div>
|
||||
<button class="nav-toggle" onclick="document.querySelector('.nav-links').classList.toggle('open')" aria-label="Menu">☰</button>
|
||||
<div class="nav-links">
|
||||
<a href="https://www.instagram.com/smartin3d/" target="_blank" rel="noopener">Instagram</a>
|
||||
<a href="https://www.etsy.com/shop/Smartin3de" target="_blank" rel="noopener">Etsy Shop</a>
|
||||
<a href="#kontakt" onclick="document.querySelector('.nav-links').classList.remove('open')">Anfrage</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<div class="cube-wrapper">
|
||||
<div class="cube">
|
||||
<div class="cube-face"></div>
|
||||
<div class="cube-face"></div>
|
||||
<div class="cube-face"></div>
|
||||
<div class="cube-face"></div>
|
||||
<div class="cube-face"></div>
|
||||
<div class="cube-face"></div>
|
||||
<div class="text3d-wrapper">
|
||||
<div class="text3d">
|
||||
<span class="text3d-face">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
<span class="text3d-depth" aria-hidden="true">smart</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1><span class="s">s</span><span class="martin">MARTIN</span> <span class="three">3</span>D</h1>
|
||||
<div class="tagline">Smart in 3D</div>
|
||||
|
||||
<p class="hero-desc">
|
||||
<strong>3D-Druck</strong> fuer Ideen, die nicht warten koennen.
|
||||
Vom Prototyp bis zur Kleinserie — praezise, schnell und genau so,
|
||||
<strong>3D-Druck</strong> für Ideen, die nicht warten können.
|
||||
Vom Prototyp bis zur Kleinserie — präzise, schnell und genau so,
|
||||
wie du es brauchst.
|
||||
</p>
|
||||
|
||||
@@ -308,8 +457,8 @@
|
||||
<div class="section-label">Leistungen</div>
|
||||
<h2>Was wir drucken.</h2>
|
||||
<div class="section-desc">
|
||||
Egal ob Einzelstueck oder Serie — jedes Teil wird individuell
|
||||
fuer deinen Anwendungsfall optimiert.
|
||||
Egal ob Einzelstück oder Serie — jedes Teil wird individuell
|
||||
für deinen Anwendungsfall optimiert.
|
||||
</div>
|
||||
|
||||
<div class="services-grid">
|
||||
@@ -322,13 +471,13 @@
|
||||
<div class="service-card">
|
||||
<div class="service-icon">📦</div>
|
||||
<h3>Kleinserien</h3>
|
||||
<p>10 bis 500 Stueck. Ohne Werkzeugkosten, ohne Mindestmengen, ohne Wartezeit.</p>
|
||||
<p>10 bis 500 Stück. Ohne Werkzeugkosten, ohne Mindestmengen, ohne Wartezeit.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-card">
|
||||
<div class="service-icon">⚙️</div>
|
||||
<h3>Funktionsteile</h3>
|
||||
<p>Mechanisch belastbar, massgenau, einsatzbereit. Fuer Maschinen, Geraete, Anlagen.</p>
|
||||
<p>Mechanisch belastbar, maßgenau, einsatzbereit. Für Maschinen, Geräte, Anlagen.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-card">
|
||||
@@ -354,13 +503,69 @@
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<section id="galerie">
|
||||
<div class="container">
|
||||
<div class="section-label">Galerie</div>
|
||||
<h2>Unsere Drucke.</h2>
|
||||
<p style="color: var(--text-dim); font-size: 1rem; margin-bottom: 56px; font-weight: 300; line-height: 1.7;">
|
||||
Vom Prototyp bis zum fertigen Teil — ein paar Beispiele aus unserer Werkstatt.
|
||||
</p>
|
||||
|
||||
<div class="gallery-grid">
|
||||
<div class="gallery-item has-caption">
|
||||
<figure>
|
||||
<img src="img/vw-golf-mk1-abdeckung.jpg" alt="VW Golf MK1 Kofferraumklappe Abdeckung">
|
||||
<figcaption>
|
||||
<strong>VW Golf MK1 Kofferraumklappe</strong>
|
||||
Abdeckung für die offenen Löcher in der Kofferraumklappe des alten Golfs. Auf Wunsch auch mit Kunstleder oder anderen Folien lieferbar.
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="gallery-item has-caption">
|
||||
<figure>
|
||||
<img src="img/flachkabel-halter.jpg" alt="Flachkabelhalter für Wandmontage">
|
||||
<figcaption>
|
||||
<strong>Flachkabelhalter für die Wandmontage</strong>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="gallery-item has-caption">
|
||||
<figure>
|
||||
<img src="img/muenzhalter.jpg" alt="Münzhalter zum Reinigen von Sammlermünzen">
|
||||
<figcaption>
|
||||
<strong>Münzhalter zum Reinigen von Sammlermünzen</strong>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="gallery-item has-caption">
|
||||
<figure>
|
||||
<img src="img/schaltanlage-panelhalter.jpg" alt="Schaltanlage Panelhalter Abdeckungen">
|
||||
<figcaption>
|
||||
<strong>Schaltschrank Abdeckungshalter für alte Schaltschränke in der Industrie</strong>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="gallery-item has-caption">
|
||||
<figure>
|
||||
<img src="img/sonnenblendenhalter.jpg" alt="Sonnenblendenhalter für alte Opel Astra Modelle">
|
||||
<figcaption>
|
||||
<strong>Sonnenblendenhalter für alte Opel Astra Modelle</strong>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="section-label">Prozess</div>
|
||||
<h2>In 4 Schritten zum Teil.</h2>
|
||||
<div class="section-desc">
|
||||
Kein komplizierter Bestellprozess. Schick uns dein Modell oder deine Idee —
|
||||
wir kuemmern uns um den Rest.
|
||||
wir kümmern uns um den Rest.
|
||||
</div>
|
||||
|
||||
<div class="process-steps">
|
||||
@@ -377,7 +582,7 @@
|
||||
<div class="process-step">
|
||||
<div class="process-num">03</div>
|
||||
<h3>Druck</h3>
|
||||
<p>Produktion auf professionellen Druckern. Qualitaetskontrolle bei jedem Teil.</p>
|
||||
<p>Produktion auf professionellen Druckern. Qualitätskontrolle bei jedem Teil.</p>
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<div class="process-num">04</div>
|
||||
@@ -395,7 +600,7 @@
|
||||
<div class="section-label">Materialien</div>
|
||||
<h2>Was wir verarbeiten.</h2>
|
||||
<div class="section-desc">
|
||||
Verschiedene Materialien fuer verschiedene Anforderungen.
|
||||
Verschiedene Materialien für verschiedene Anforderungen.
|
||||
</div>
|
||||
|
||||
<div class="material-tags">
|
||||
@@ -404,7 +609,7 @@
|
||||
<span class="material-tag">ABS</span>
|
||||
<span class="material-tag">TPU (flexibel)</span>
|
||||
<span class="material-tag">Nylon</span>
|
||||
<span class="material-tag">ASA (UV-bestaendig)</span>
|
||||
<span class="material-tag">ASA (UV-beständig)</span>
|
||||
<span class="material-tag">Carbon-Verbund</span>
|
||||
<span class="material-tag">Holz-Filament</span>
|
||||
</div>
|
||||
@@ -422,27 +627,73 @@
|
||||
Wir melden uns innerhalb von 24 Stunden.
|
||||
</div>
|
||||
<a href="mailto:smartin3d@msbls.de" class="btn btn-primary">Projekt anfragen</a>
|
||||
<a href="https://www.etsy.com/shop/Smartin3de" target="_blank" rel="noopener" class="btn btn-ghost">🛒 Etsy Shop</a>
|
||||
<a href="https://www.instagram.com/smartin3d/" target="_blank" rel="noopener" class="btn btn-ghost">📸 Instagram</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p><span style="color:var(--text-dim)">s</span><span style="color:var(--orange)">MARTIN</span> <span style="color:var(--blue)">3</span>D — smartin3.de</p>
|
||||
<p style="margin-top: 24px; font-size: 0.65rem; color: var(--text-muted); line-height: 1.8;"><a href="#impressum" style="color: var(--text-muted); text-decoration: none;">Impressum</a></p>
|
||||
<p style="margin-top: 24px; font-size: 0.65rem; color: var(--text-muted); line-height: 1.8;"><a href="#impressum-section" style="color: var(--text-muted); text-decoration: none;">Impressum</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<section id="impressum" style="padding: 60px 0 80px; border-top: 1px solid var(--border);">
|
||||
<section id="impressum-section" style="padding: 60px 0 80px; border-top: 1px solid var(--border);">
|
||||
<div class="container" style="max-width: 540px;">
|
||||
<h2 style="font-size: 1.2rem; margin-bottom: 24px;">Impressum</h2>
|
||||
<p style="font-size: 0.85rem; color: var(--text-dim); line-height: 1.8; font-weight: 300;">
|
||||
Martin Siebels<br>
|
||||
Leyer Str. 38<br>
|
||||
49076 Osnabrück<br><br>
|
||||
E-Mail: <a href="mailto:Martin_Siebels@web.de" style="color: var(--orange); text-decoration: none;">Martin_Siebels@web.de</a>
|
||||
</p>
|
||||
<div id="impressum" style="font-size: 0.85rem; color: var(--text-dim); line-height: 1.8; font-weight: 300;"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script src="/shared/impressum.js" data-owner="martinsiebels" data-variant="full"></script>
|
||||
|
||||
<div class="lightbox" id="lightbox" onclick="this.classList.remove('active')">
|
||||
<img id="lightbox-img" src="" alt="">
|
||||
<div class="lightbox-caption" id="lightbox-cap"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.querySelectorAll('.gallery-item').forEach(function(item) {
|
||||
item.addEventListener('click', function() {
|
||||
var img = item.querySelector('img');
|
||||
var cap = item.querySelector('figcaption strong');
|
||||
document.getElementById('lightbox-img').src = img.src;
|
||||
document.getElementById('lightbox-cap').textContent = cap ? cap.textContent : '';
|
||||
document.getElementById('lightbox').classList.add('active');
|
||||
});
|
||||
});
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') document.getElementById('lightbox').classList.remove('active');
|
||||
});
|
||||
|
||||
// Interactive 3D text
|
||||
(function() {
|
||||
var hero = document.querySelector('.hero');
|
||||
var text = document.querySelector('.text3d');
|
||||
if (!hero || !text) return;
|
||||
|
||||
function handleMove(x, y) {
|
||||
var w = window.innerWidth;
|
||||
var cx = x / w - 0.5;
|
||||
var cy = y / (hero.getBoundingClientRect().bottom + 100) - 0.4;
|
||||
var rotY = cx * 90;
|
||||
var rotX = -cy * 30;
|
||||
text.style.animation = 'none';
|
||||
text.style.transform = 'rotateX(' + rotX + 'deg) rotateY(' + rotY + 'deg)';
|
||||
}
|
||||
|
||||
hero.addEventListener('mousemove', function(e) { handleMove(e.clientX, e.clientY); });
|
||||
hero.addEventListener('touchmove', function(e) {
|
||||
e.preventDefault();
|
||||
handleMove(e.touches[0].clientX, e.touches[0].clientY);
|
||||
}, {passive: false});
|
||||
hero.addEventListener('mouseleave', function() {
|
||||
text.style.animation = '';
|
||||
text.style.transform = '';
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
399
sites/traihard.de/comunio/index.html
Normal file
399
sites/traihard.de/comunio/index.html
Normal file
@@ -0,0 +1,399 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Comunio AI Assistant — Anleitung</title>
|
||||
<meta name="description" content="Schritt-für-Schritt-Anleitung: KI-Assistent für Comunio Fantasy Bundesliga mit Claude Code + Playwright">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg: #0a0b0d;
|
||||
--surface: #12141a;
|
||||
--surface-2: #1a1c24;
|
||||
--border: #1e2028;
|
||||
--text: #e8e8ec;
|
||||
--muted: #8888a0;
|
||||
--accent: #22c55e;
|
||||
--accent-dim: rgba(34, 197, 94, 0.12);
|
||||
--orange: #f97316;
|
||||
--orange-dim: rgba(249, 115, 22, 0.12);
|
||||
--blue: #3b82f6;
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.grain {
|
||||
position: fixed; inset: 0; z-index: 9999; pointer-events: none; opacity: 0.03;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.container { max-width: 760px; margin: 0 auto; padding: 0 24px; }
|
||||
|
||||
/* Header */
|
||||
header {
|
||||
padding: 60px 0 40px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
header .badge {
|
||||
display: inline-block;
|
||||
background: var(--accent-dim);
|
||||
color: var(--accent);
|
||||
padding: 6px 14px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(1.8rem, 5vw, 2.8rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
header p {
|
||||
color: var(--muted);
|
||||
font-size: 1.05rem;
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.content { padding: 48px 0 80px; }
|
||||
|
||||
h2 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin-top: 48px;
|
||||
margin-bottom: 16px;
|
||||
padding-top: 32px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
h2:first-child { border-top: none; padding-top: 0; margin-top: 0; }
|
||||
|
||||
h3 {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 12px;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
p { margin-bottom: 16px; color: var(--text); }
|
||||
|
||||
ul, ol {
|
||||
margin-bottom: 16px;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 8px;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
strong { color: var(--text); font-weight: 600; }
|
||||
|
||||
a { color: var(--accent); text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
|
||||
/* Code */
|
||||
code {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
background: var(--surface);
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 0.85rem;
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
pre {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.cmd { color: var(--text); }
|
||||
.comment { color: #555; }
|
||||
.highlight { color: var(--accent); }
|
||||
|
||||
/* Architecture diagram */
|
||||
.arch {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
padding: 28px;
|
||||
margin: 24px 0;
|
||||
text-align: center;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.9rem;
|
||||
line-height: 2;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.arch .you { color: var(--accent); font-weight: 600; }
|
||||
.arch .claude { color: var(--orange); font-weight: 600; }
|
||||
.arch .pw { color: var(--blue); font-weight: 600; }
|
||||
.arch .arrow { color: #444; }
|
||||
|
||||
/* Table */
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding: 12px 16px;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
font-weight: 600;
|
||||
font-size: 0.85rem;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 12px 16px;
|
||||
border: 1px solid var(--border);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.card h4 {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.card p { color: var(--muted); font-size: 0.9rem; margin-bottom: 0; }
|
||||
|
||||
/* Warning/Info boxes */
|
||||
.info {
|
||||
background: var(--accent-dim);
|
||||
border-left: 3px solid var(--accent);
|
||||
padding: 16px 20px;
|
||||
border-radius: 0 12px 12px 0;
|
||||
margin: 20px 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: var(--orange-dim);
|
||||
border-left: 3px solid var(--orange);
|
||||
padding: 16px 20px;
|
||||
border-radius: 0 12px 12px 0;
|
||||
margin: 20px 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.8rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
header { padding: 40px 0 30px; }
|
||||
.content { padding: 32px 0 60px; }
|
||||
pre { padding: 14px; }
|
||||
table { font-size: 0.8rem; }
|
||||
th, td { padding: 8px 10px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="grain"></div>
|
||||
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="badge">Anfänger-Guide</div>
|
||||
<h1>Comunio AI Assistant</h1>
|
||||
<p>Dein KI-Manager für die Fantasy Bundesliga. Claude Code + Playwright steuern dein Team im Browser.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<div class="container">
|
||||
|
||||
<h2>Was ist das?</h2>
|
||||
<p><a href="https://comunio.de">Comunio</a> ist Deutschlands ältester Fantasy-Fußball-Manager (seit 2000, 600.000+ Nutzer). Du managst ein virtuelles Bundesliga-Team — kaufst und verkaufst Spieler auf dem Transfermarkt, stellst dein Team für jeden Spieltag auf und sammelst Punkte.</p>
|
||||
<p>Diese Anleitung zeigt dir, wie du einen <strong>KI-Assistenten</strong> einrichtest, der dein Comunio-Team über den Browser steuert — automatisch, per Sprachbefehl.</p>
|
||||
|
||||
<h2>Was kann der Assistent?</h2>
|
||||
<ul>
|
||||
<li><strong>Aufstellung setzen</strong> vor jedem Spieltag</li>
|
||||
<li><strong>Gebote abgeben</strong> auf dem Transfermarkt (Deadline: täglich 3:00 Uhr)</li>
|
||||
<li><strong>Spielerwerte beobachten</strong> und Markttrends erkennen</li>
|
||||
<li><strong>Ergebnisse checken</strong> nach dem Spieltag</li>
|
||||
<li><strong>Kader analysieren</strong> und Schwachstellen finden</li>
|
||||
<li><strong>Tauschangebote</strong> annehmen oder ablehnen</li>
|
||||
</ul>
|
||||
|
||||
<h2>So funktioniert's</h2>
|
||||
<div class="arch">
|
||||
<span class="you">Du:</span> "Stell mein Team für den nächsten Spieltag auf"<br>
|
||||
<span class="arrow">↓</span><br>
|
||||
<span class="claude">Claude Code</span> (versteht was du willst, plant die Aktionen)<br>
|
||||
<span class="arrow">↓</span><br>
|
||||
<span class="pw">Playwright</span> (steuert den Browser — klickt, tippt, liest)<br>
|
||||
<span class="arrow">↓</span><br>
|
||||
comunio.de
|
||||
</div>
|
||||
|
||||
<h2>Einrichtung (10 Minuten)</h2>
|
||||
|
||||
<h3>1. Claude Code installieren</h3>
|
||||
<pre><code><span class="comment"># Im Terminal eingeben:</span>
|
||||
<span class="cmd">npm install -g @anthropic-ai/claude-code</span></code></pre>
|
||||
<p>Du brauchst einen <a href="https://claude.ai">Anthropic-Account</a>. Beim ersten Start wirst du zum Login aufgefordert.</p>
|
||||
|
||||
<h3>2. Projektordner erstellen</h3>
|
||||
<pre><code><span class="cmd">mkdir ~/comunio-assistant</span>
|
||||
<span class="cmd">cd ~/comunio-assistant</span></code></pre>
|
||||
|
||||
<h3>3. Playwright aktivieren</h3>
|
||||
<pre><code><span class="comment"># Claude Code starten:</span>
|
||||
<span class="cmd">claude</span>
|
||||
|
||||
<span class="comment"># Dann in Claude tippen:</span>
|
||||
<span class="cmd">/mcp</span>
|
||||
<span class="comment"># → "playwright" auswählen → Enable</span></code></pre>
|
||||
<p>Damit kann Claude einen Browser öffnen und Webseiten bedienen — genau wie du es manuell tun würdest.</p>
|
||||
|
||||
<h3>4. CLAUDE.md erstellen</h3>
|
||||
<p>Erstelle eine Datei namens <code>CLAUDE.md</code> in deinem Projektordner. Das ist die "Jobbeschreibung" für deinen Assistenten:</p>
|
||||
|
||||
<pre><code><span class="highlight"># Comunio Assistant</span>
|
||||
|
||||
Du managst mein Comunio Fantasy-Fußball-Team via Browser (Playwright).
|
||||
|
||||
<span class="highlight">## Zugang</span>
|
||||
- URL: https://classic.comunio.de (einfacher zu automatisieren)
|
||||
- Login: Frag mich nach den Zugangsdaten wenn nötig
|
||||
|
||||
<span class="highlight">## Punktesystem</span>
|
||||
- Note 1.0 = 12 Pkt, 1.5 = 10, 2.0 = 8, 2.5 = 6, 3.0 = 4
|
||||
- Tor-Bonus: TW +6, ABW +5, MF +4, ST +3
|
||||
- Gelb-Rot: -3, Rot: -6, Leerer Platz: -4 pro Spieltag
|
||||
|
||||
<span class="highlight">## Transfers</span>
|
||||
- Verdeckte Gebote — höchstes Gebot gewinnt
|
||||
- Berechnung täglich um 3:00 Uhr
|
||||
- IMMER fragen bevor du bietest!
|
||||
|
||||
<span class="highlight">## Regeln</span>
|
||||
- Vor jeder Aktion die Budget kosten zeigen
|
||||
- Screenshots machen bei wichtigen Aktionen
|
||||
- Nie ohne meine Bestätigung bieten oder tauschen</code></pre>
|
||||
|
||||
<h2>Benutzung</h2>
|
||||
<p>Starte Claude Code in deinem Projektordner:</p>
|
||||
<pre><code><span class="cmd">cd ~/comunio-assistant</span>
|
||||
<span class="cmd">claude</span></code></pre>
|
||||
<p>Dann sprich einfach mit Claude:</p>
|
||||
|
||||
<table>
|
||||
<tr><th>Du sagst</th><th>Claude macht</th></tr>
|
||||
<tr><td>"Log mich ein"</td><td>Öffnet Browser, navigiert zum Login, fragt nach Zugangsdaten</td></tr>
|
||||
<tr><td>"Zeig mir mein Team"</td><td>Geht zur Kaderseite, listet Spieler mit Werten</td></tr>
|
||||
<tr><td>"Stell das beste Team auf"</td><td>Prüft Verletzungen/Sperren, stellt optimale Formation auf</td></tr>
|
||||
<tr><td>"Was gibt's auf dem Transfermarkt?"</td><td>Listet verfügbare Spieler, zeigt gute Deals</td></tr>
|
||||
<tr><td>"Biete 3M auf Wirtz"</td><td>Gibt Gebot ab (nach deiner Bestätigung)</td></tr>
|
||||
<tr><td>"Wie lief der Spieltag?"</td><td>Zeigt deine Punkte, Einzelbewertungen, Ranking</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>Tipps</h2>
|
||||
|
||||
<div class="card">
|
||||
<h4>Nutze classic.comunio.de</h4>
|
||||
<p>Die Classic-Version ist einfacheres HTML (PHP-gerendert). Viel leichter für den Assistenten zu lesen als die moderne React-App.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h4>Transfer-Deadline beachten</h4>
|
||||
<p>Täglich um 3:00 Uhr werden Gebote ausgewertet. Frag abends: "Zeig mir Spieler unter 2M die gut bewertet wurden" — dann bieten.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h4>Spieltag-Routine</h4>
|
||||
<p>Vor dem Spieltag: "Ist jemand verletzt oder gesperrt?" → "Stell mein Team auf". Nach dem Spieltag: "Wie lief's?"</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h4>Screenshots</h4>
|
||||
<p>Lass Claude regelmäßig Screenshots machen. So siehst du immer, was gerade passiert — und hast einen Nachweis deiner Aktionen.</p>
|
||||
</div>
|
||||
|
||||
<div class="warning">
|
||||
<strong>Warum kein API?</strong> Comunio hat keine offizielle API. Alte Python-Wrapper sind längst kaputt. Browser-Automatisierung via Playwright ist der einzige zuverlässige Weg — und funktioniert mit jeder Comunio-Version.
|
||||
</div>
|
||||
|
||||
<h2>Häufige Fragen</h2>
|
||||
|
||||
<div class="card">
|
||||
<h4>Brauche ich Programmierkenntnisse?</h4>
|
||||
<p>Nein. Du musst nur ein Terminal öffnen und drei Befehle eintippen können. Den Rest macht Claude.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h4>Kostet das was?</h4>
|
||||
<p>Claude Code braucht einen Anthropic-Account (API-Kosten je nach Nutzung, ca. ein paar Euro/Monat bei normalem Gebrauch). Comunio selbst hat eine kostenlose Basic-Version.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h4>Ist das erlaubt?</h4>
|
||||
<p>Comunio hat keine öffentliche Policy gegen Browser-Automatisierung. Sei trotzdem fair: nicht im Sekundentakt Anfragen schicken, und spiel sportlich.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h4>Was wenn was schiefgeht?</h4>
|
||||
<p>Claude fragt vor jeder wichtigen Aktion (Gebote, Tausch, Aufstellung speichern). Du kannst jederzeit "Stop" sagen.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p><a href="https://traihard.de">traihard.de</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
435
sites/traihard.de/index.html
Normal file
435
sites/traihard.de/index.html
Normal file
@@ -0,0 +1,435 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>traihard.de — Marginal Gains. Maximum Effort.</title>
|
||||
<meta name="description" content="Trai Hard — Optimierungswahn in allen Lebensbereichen. Rennrad, Fantasy Football, Productivity, Fitness. Marginal Gains everywhere.">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&family=Orbitron:wght@700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg: #080808;
|
||||
--surface: #111114;
|
||||
--border: #1c1c22;
|
||||
--text: #f0f0f2;
|
||||
--muted: #777790;
|
||||
--accent: #ff3e00;
|
||||
--accent-glow: rgba(255, 62, 0, 0.12);
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.grain {
|
||||
position: fixed; inset: 0; z-index: 9999; pointer-events: none; opacity: 0.04;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.container { max-width: 960px; margin: 0 auto; padding: 0 24px; }
|
||||
|
||||
/* Hero */
|
||||
.hero {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hero::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -10%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 700px;
|
||||
height: 700px;
|
||||
background: radial-gradient(circle, var(--accent-glow) 0%, transparent 65%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.watts {
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.3em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
margin-bottom: 24px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: clamp(3.5rem, 12vw, 8rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.04em;
|
||||
line-height: 0.9;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.logo .ai { color: var(--accent); }
|
||||
|
||||
.tagline {
|
||||
font-size: clamp(1.1rem, 2.5vw, 1.4rem);
|
||||
color: var(--muted);
|
||||
margin-bottom: 48px;
|
||||
max-width: 600px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hr-line {
|
||||
width: 60px;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
margin: 0 auto 48px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* Manifesto */
|
||||
.manifesto {
|
||||
padding: 80px 0;
|
||||
}
|
||||
|
||||
.manifesto-text {
|
||||
max-width: 640px;
|
||||
margin: 0 auto;
|
||||
font-size: 1.15rem;
|
||||
line-height: 1.9;
|
||||
color: var(--muted);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.manifesto-text strong { color: var(--text); font-weight: 600; }
|
||||
.manifesto-text em { color: var(--accent); font-style: normal; }
|
||||
|
||||
/* Stats */
|
||||
.stats {
|
||||
padding: 40px 0 80px;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.stat {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
padding: 28px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.8rem;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
/* Domains */
|
||||
.domains {
|
||||
padding: 60px 0 80px;
|
||||
}
|
||||
|
||||
.domains h2 {
|
||||
text-align: center;
|
||||
font-size: 1.6rem;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.domains .subtitle {
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
margin-bottom: 40px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.domains-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.domain-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
padding: 28px;
|
||||
transition: border-color 0.2s, transform 0.2s;
|
||||
}
|
||||
|
||||
.domain-card:hover {
|
||||
border-color: var(--accent);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.domain-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.domain-card h3 {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.domain-card p {
|
||||
font-size: 0.85rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.domain-card a {
|
||||
display: inline-block;
|
||||
margin-top: 12px;
|
||||
color: var(--accent);
|
||||
font-size: 0.85rem;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.domain-card a:hover { text-decoration: underline; }
|
||||
|
||||
/* Gains */
|
||||
.gains {
|
||||
padding: 60px 0 80px;
|
||||
}
|
||||
|
||||
.gains h2 {
|
||||
text-align: center;
|
||||
font-size: 1.6rem;
|
||||
margin-bottom: 40px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.gains-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.gain-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
padding: 28px;
|
||||
transition: border-color 0.2s, transform 0.2s;
|
||||
}
|
||||
|
||||
.gain-card:hover {
|
||||
border-color: var(--accent);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.gain-num {
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
font-size: 0.7rem;
|
||||
color: var(--accent);
|
||||
letter-spacing: 0.2em;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.gain-card h3 {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.gain-card p {
|
||||
font-size: 0.85rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Quote */
|
||||
.quote-section {
|
||||
padding: 80px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quote {
|
||||
font-size: clamp(1.2rem, 3vw, 1.8rem);
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
max-width: 640px;
|
||||
margin: 0 auto 16px;
|
||||
}
|
||||
|
||||
.quote-attr {
|
||||
color: var(--muted);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.75rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.stats-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.gains-grid { grid-template-columns: 1fr; }
|
||||
.domains-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.hero { min-height: 80vh; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="grain"></div>
|
||||
|
||||
<section class="hero">
|
||||
<div class="watts">OPTIMIZE EVERYTHING</div>
|
||||
<div class="logo">tr<span class="ai">ai</span>hard</div>
|
||||
<p class="tagline">Marginal Gains. Maximum Effort.<br>In allem. Immer. Ohne Kompromisse.</p>
|
||||
</section>
|
||||
|
||||
<section class="manifesto">
|
||||
<div class="container">
|
||||
<div class="hr-line"></div>
|
||||
<div class="manifesto-text">
|
||||
Du wiegst dein <strong>Frühstück in Gramm ab</strong>, weil Haferflocken-Optimierung echte Gains bringt.
|
||||
Du fährst bei <em>3°C im Regen</em>, weil Ruhetage für Schwache sind.
|
||||
Du hast einen <strong>KI-Assistenten</strong>, der dein Fantasy-Team managed, weil manuelles Scouting ineffizient ist.
|
||||
Dein Strava-Profil ist sorgfältiger kuratiert als dein LinkedIn.
|
||||
Du trackst deinen <em>Schlaf</em>, dein <em>Wasser</em>, deine <em>Schritte</em> — und findest immer noch eine Metrik, die du optimieren kannst.
|
||||
Du hast <strong>Automationen</strong> für Dinge gebaut, die andere Leute nicht mal als Problem erkannt haben.
|
||||
<br><br>
|
||||
Du bist <em>Tryhard</em>. Und du bist nicht allein.
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="stats">
|
||||
<div class="container">
|
||||
<div class="stats-grid">
|
||||
<div class="stat">
|
||||
<div class="stat-value">4.2</div>
|
||||
<div class="stat-label">W/kg FTP</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-value">97</div>
|
||||
<div class="stat-label">Automationen</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-value">1.</div>
|
||||
<div class="stat-label">Comunio Liga</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-value">0</div>
|
||||
<div class="stat-label">Ruhetage</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="domains">
|
||||
<div class="container">
|
||||
<h2>Tryhard-Disziplinen</h2>
|
||||
<p class="subtitle">Wer nur in einem Bereich optimiert, hat das Prinzip nicht verstanden.</p>
|
||||
<div class="domains-grid">
|
||||
<div class="domain-card">
|
||||
<div class="domain-icon">🚴</div>
|
||||
<h3>Rennrad</h3>
|
||||
<p>Carbon-Rahmen. Titanschrauben. Aerosocken. Jedes Jedermannrennen wird behandelt wie eine Königsetappe. Beine rasiert — aus aerodynamischen Gründen, natürlich.</p>
|
||||
</div>
|
||||
<div class="domain-card">
|
||||
<div class="domain-icon">🤖</div>
|
||||
<h3>Comunio</h3>
|
||||
<p>Warum selbst scouten, wenn ein KI-Assistent den Transfermarkt per Browser automatisiert? Gebote um 2:59 Uhr, perfektes Lineup, Datenanalyse auf Knopfdruck.</p>
|
||||
<a href="/comunio">→ Comunio AI Guide</a>
|
||||
</div>
|
||||
<div class="domain-card">
|
||||
<div class="domain-icon">💪</div>
|
||||
<h3>Fitness</h3>
|
||||
<p>Periodisierung. Makros. Progressive Overload. HRV-Tracking. Supplements nach Peer-Review. Das Bier danach ist „Recovery Nutrition".</p>
|
||||
</div>
|
||||
<div class="domain-card">
|
||||
<div class="domain-icon">⚡</div>
|
||||
<h3>Productivity</h3>
|
||||
<p>Jeder Workflow hat eine Automation. Jede Automation hat ein Dashboard. Jedes Dashboard hat ein Alert. Und wenn alles grün ist, optimierst du das Dashboard.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="gains">
|
||||
<div class="container">
|
||||
<h2>The Marginal Gains Protocol</h2>
|
||||
<div class="gains-grid">
|
||||
<div class="gain-card">
|
||||
<div class="gain-num">GAIN 01</div>
|
||||
<h3>Messen</h3>
|
||||
<p>Wenn du es nicht misst, existiert es nicht. Watt, Kalorien, Schlaf, Screentime, Comunio-Punkteschnitt — alles wird getrackt.</p>
|
||||
</div>
|
||||
<div class="gain-card">
|
||||
<div class="gain-num">GAIN 02</div>
|
||||
<h3>Automatisieren</h3>
|
||||
<p>Alles was du zweimal machst, verdient ein Script. Alles was ein Script macht, verdient einen KI-Agenten. Alles was ein Agent macht, verdient ein Monitoring.</p>
|
||||
</div>
|
||||
<div class="gain-card">
|
||||
<div class="gain-num">GAIN 03</div>
|
||||
<h3>Iterieren</h3>
|
||||
<p>Version 1 ist nie gut genug. Version 47 ist ein guter Anfang. Der perfekte Prozess existiert nicht — aber die Annäherung macht süchtig.</p>
|
||||
</div>
|
||||
<div class="gain-card">
|
||||
<div class="gain-num">GAIN 04</div>
|
||||
<h3>Eliminieren</h3>
|
||||
<p>Gewicht am Rad. Unnötige Meetings. Schlechte Spieler im Kader. Alles was keinen Mehrwert bringt, fliegt raus. Gnadenlos.</p>
|
||||
</div>
|
||||
<div class="gain-card">
|
||||
<div class="gain-num">GAIN 05</div>
|
||||
<h3>Investieren</h3>
|
||||
<p>N+1 ist kein Meme, es ist eine Investitionsstrategie. Gilt für Räder, Tools, Subscriptions — und das Comunio-Pro-Upgrade.</p>
|
||||
</div>
|
||||
<div class="gain-card">
|
||||
<div class="gain-num">GAIN 06</div>
|
||||
<h3>Dominieren</h3>
|
||||
<p>Ob Jedermannrennen oder Fantasy-Liga — Zweiter ist Erster der Verlierer. Der Tryhard kennt nur ein Ziel: oben stehen.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="quote-section">
|
||||
<div class="container">
|
||||
<div class="quote">"Andere Leute haben Hobbys. Wir haben KPIs."</div>
|
||||
<div class="quote-attr">— Jeder Tryhard, immer</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p>traihard.de</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
4
sites/traihard.de/site.yaml
Normal file
4
sites/traihard.de/site.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
domain: traihard.de
|
||||
template: custom
|
||||
title: "traihard.de"
|
||||
description: "Trai Hard — AI-powered cycling routes"
|
||||
385
sites/zensiebels.de/index.html
Normal file
385
sites/zensiebels.de/index.html
Normal file
@@ -0,0 +1,385 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ZenSiebels — 静けさ</title>
|
||||
<meta name="description" content="ZenSiebels — Stille. Klarheit. Praxis.">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🪷</text></svg>">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@200;300;400;500;600&family=Inter:wght@200;300;400&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--stone: #1c1b1a;
|
||||
--stone-soft: #3a3835;
|
||||
--stone-faint: #6b6660;
|
||||
--stone-ghost: #a09a92;
|
||||
--washi: #f7f3ed;
|
||||
--washi-warm: #efe9df;
|
||||
--washi-dark: #e8e0d4;
|
||||
--sumi: #2c2a28;
|
||||
--matcha: #7a9a6a;
|
||||
--matcha-glow: rgba(122, 154, 106, 0.1);
|
||||
--sand: #c4b69c;
|
||||
--sand-glow: rgba(196, 182, 156, 0.12);
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, sans-serif;
|
||||
background: var(--washi);
|
||||
color: var(--stone);
|
||||
line-height: 1.7;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.jp { font-family: 'Noto Serif JP', serif; }
|
||||
|
||||
/* === HERO === */
|
||||
.hero {
|
||||
min-height: 100vh;
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
text-align: center;
|
||||
padding: 80px 32px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hero::before {
|
||||
content: '';
|
||||
position: absolute; inset: 0;
|
||||
background: radial-gradient(ellipse at 50% 35%, var(--sand-glow) 0%, transparent 55%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.enso {
|
||||
width: 180px; height: 180px;
|
||||
margin-bottom: 48px;
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
animation: fadeIn 2s ease-out 0.3s forwards;
|
||||
}
|
||||
|
||||
.enso svg {
|
||||
width: 100%; height: 100%;
|
||||
}
|
||||
|
||||
.enso-circle {
|
||||
fill: none;
|
||||
stroke: var(--stone);
|
||||
stroke-width: 2.5;
|
||||
stroke-linecap: round;
|
||||
stroke-dasharray: 580;
|
||||
stroke-dashoffset: 580;
|
||||
animation: drawEnso 3s ease-in-out 0.5s forwards;
|
||||
}
|
||||
|
||||
@keyframes drawEnso {
|
||||
to { stroke-dashoffset: 45; }
|
||||
}
|
||||
|
||||
.kanji {
|
||||
font-family: 'Noto Serif JP', serif;
|
||||
font-size: clamp(2.5rem, 6vw, 4rem);
|
||||
font-weight: 200;
|
||||
color: var(--stone-ghost);
|
||||
letter-spacing: 0.4em;
|
||||
margin-bottom: 32px;
|
||||
opacity: 0;
|
||||
animation: fadeIn 1.5s ease-out 1.5s forwards;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Noto Serif JP', serif;
|
||||
font-size: clamp(2rem, 5vw, 3.2rem);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.08em;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 24px;
|
||||
opacity: 0;
|
||||
animation: fadeIn 1.5s ease-out 2s forwards;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 0.95rem;
|
||||
color: var(--stone-faint);
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0;
|
||||
animation: fadeIn 1.5s ease-out 2.5s forwards;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(12px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* === DIVIDER === */
|
||||
.breath {
|
||||
padding: 80px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.breath-dot {
|
||||
width: 6px; height: 6px;
|
||||
background: var(--sand);
|
||||
border-radius: 50%;
|
||||
margin: 0 auto;
|
||||
animation: breathe 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes breathe {
|
||||
0%, 100% { transform: scale(1); opacity: 0.4; }
|
||||
50% { transform: scale(2.5); opacity: 1; }
|
||||
}
|
||||
|
||||
/* === WISDOM === */
|
||||
.wisdom {
|
||||
max-width: 640px;
|
||||
margin: 0 auto;
|
||||
padding: 0 32px 120px;
|
||||
}
|
||||
|
||||
.wisdom-item {
|
||||
padding: 64px 0;
|
||||
border-top: 1px solid var(--washi-dark);
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
transform: translateY(16px);
|
||||
transition: opacity 1s ease, transform 1s ease;
|
||||
}
|
||||
|
||||
.wisdom-item.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.wisdom-jp {
|
||||
font-family: 'Noto Serif JP', serif;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 300;
|
||||
color: var(--stone-ghost);
|
||||
margin-bottom: 16px;
|
||||
letter-spacing: 0.15em;
|
||||
}
|
||||
|
||||
.wisdom-text {
|
||||
font-family: 'Noto Serif JP', serif;
|
||||
font-size: clamp(1.2rem, 3vw, 1.6rem);
|
||||
font-weight: 400;
|
||||
color: var(--stone);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.wisdom-source {
|
||||
font-size: 0.8rem;
|
||||
color: var(--stone-faint);
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
/* === PRACTICE === */
|
||||
.practice {
|
||||
background: var(--washi-warm);
|
||||
padding: 100px 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.practice h2 {
|
||||
font-family: 'Noto Serif JP', serif;
|
||||
font-size: clamp(1.5rem, 4vw, 2.2rem);
|
||||
font-weight: 400;
|
||||
margin-bottom: 48px;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.practice-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 40px;
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.practice-card {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.practice-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 16px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.practice-name {
|
||||
font-family: 'Noto Serif JP', serif;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.practice-desc {
|
||||
font-size: 0.82rem;
|
||||
color: var(--stone-faint);
|
||||
font-weight: 300;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* === BREATHING === */
|
||||
.breathing {
|
||||
padding: 120px 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.breathing-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--stone-ghost);
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.breathing-circle {
|
||||
width: 100px; height: 100px;
|
||||
border: 1.5px solid var(--sand);
|
||||
border-radius: 50%;
|
||||
margin: 0 auto 32px;
|
||||
animation: breatheCircle 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes breatheCircle {
|
||||
0%, 100% { transform: scale(0.6); opacity: 0.3; }
|
||||
30% { transform: scale(1.2); opacity: 0.8; }
|
||||
50% { transform: scale(1.2); opacity: 0.8; }
|
||||
80% { transform: scale(0.6); opacity: 0.3; }
|
||||
}
|
||||
|
||||
.breathing-text {
|
||||
font-family: 'Noto Serif JP', serif;
|
||||
font-size: 0.9rem;
|
||||
color: var(--stone-faint);
|
||||
font-weight: 300;
|
||||
animation: breatheText 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes breatheText {
|
||||
0%, 100% { opacity: 0; }
|
||||
5% { opacity: 1; }
|
||||
25% { opacity: 1; }
|
||||
30% { opacity: 0; }
|
||||
50% { opacity: 0; }
|
||||
55% { opacity: 1; }
|
||||
75% { opacity: 1; }
|
||||
80% { opacity: 0; }
|
||||
}
|
||||
|
||||
/* === FOOTER === */
|
||||
footer {
|
||||
padding: 48px 32px;
|
||||
text-align: center;
|
||||
border-top: 1px solid var(--washi-dark);
|
||||
}
|
||||
|
||||
footer p {
|
||||
font-size: 0.75rem;
|
||||
color: var(--stone-ghost);
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
/* === RESPONSIVE === */
|
||||
@media (max-width: 640px) {
|
||||
.practice-grid { grid-template-columns: 1fr; gap: 32px; }
|
||||
.wisdom-item { padding: 48px 0; }
|
||||
.enso { width: 140px; height: 140px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section class="hero">
|
||||
<div class="enso">
|
||||
<svg viewBox="0 0 200 200">
|
||||
<circle class="enso-circle" cx="100" cy="100" r="88" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="kanji">禅</div>
|
||||
<h1>ZenSiebels</h1>
|
||||
<p class="subtitle">Stille · Klarheit · Praxis</p>
|
||||
</section>
|
||||
|
||||
<div class="breath">
|
||||
<div class="breath-dot"></div>
|
||||
</div>
|
||||
|
||||
<section class="wisdom">
|
||||
<div class="wisdom-item">
|
||||
<p class="wisdom-jp">初心</p>
|
||||
<p class="wisdom-text">Im Geist des Anfängers gibt es viele Möglichkeiten. Im Geist des Experten nur wenige.</p>
|
||||
<p class="wisdom-source">Shunryū Suzuki</p>
|
||||
</div>
|
||||
|
||||
<div class="wisdom-item">
|
||||
<p class="wisdom-jp">一期一会</p>
|
||||
<p class="wisdom-text">Jede Begegnung ist einmalig und kann nicht wiederholt werden.</p>
|
||||
<p class="wisdom-source">Teezeremonie-Weisheit</p>
|
||||
</div>
|
||||
|
||||
<div class="wisdom-item">
|
||||
<p class="wisdom-jp">無為</p>
|
||||
<p class="wisdom-text">Nicht Nichtstun. Sondern tun, ohne zu erzwingen.</p>
|
||||
<p class="wisdom-source">Laozi</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="practice">
|
||||
<h2 class="jp">三つの柱</h2>
|
||||
<div class="practice-grid">
|
||||
<div class="practice-card">
|
||||
<div class="practice-icon">🧘</div>
|
||||
<p class="practice-name">Zazen</p>
|
||||
<p class="practice-desc">Sitzen. Atmen. Loslassen. Die einfachste und schwierigste Übung zugleich.</p>
|
||||
</div>
|
||||
<div class="practice-card">
|
||||
<div class="practice-icon">🍵</div>
|
||||
<p class="practice-name">Chadō</p>
|
||||
<p class="practice-desc">Der Weg des Tees. Jede Bewegung bewusst. Jeder Moment vollständig.</p>
|
||||
</div>
|
||||
<div class="practice-card">
|
||||
<div class="practice-icon">✍️</div>
|
||||
<p class="practice-name">Shodō</p>
|
||||
<p class="practice-desc">Der Weg der Schrift. Ein Strich, unwiderruflich. Kontrolle durch Loslassen.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="breathing">
|
||||
<p class="breathing-label">Atme mit</p>
|
||||
<div class="breathing-circle"></div>
|
||||
<p class="breathing-text jp">吸う — 吐く</p>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>zensiebels.de — 2026</p>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) entry.target.classList.add('visible');
|
||||
});
|
||||
}, { threshold: 0.2 });
|
||||
document.querySelectorAll('.wisdom-item').forEach(el => observer.observe(el));
|
||||
</script>
|
||||
|
||||
<script src="/shared/impressum.js" data-owner="flexsiebels"></script>
|
||||
</body>
|
||||
</html>
|
||||
4
sites/zensiebels.de/site.yaml
Normal file
4
sites/zensiebels.de/site.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
domain: zensiebels.de
|
||||
template: custom
|
||||
title: "ZenSebels"
|
||||
description: "Stille. Klarheit. Praxis."
|
||||
Reference in New Issue
Block a user