Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76e179b077 | ||
|
|
b60e599dda | ||
|
|
791c265f42 | ||
|
|
78083fac6a | ||
|
|
b9740e6c1b |
No files matched your search
+11
-1
@@ -1,13 +1,23 @@
|
||||
# Projektstatus
|
||||
|
||||
## Fassung 1.39.1: SVG statt Schriftzeichen auf der Website, Luximmo-Immobilien (09.11.2026)
|
||||
|
||||
**Anlass:** Umut: „nur eigene SVGs nutzen“. Bildbetrachter, PDF-Betrachter, Nach-oben-Knopf, Video-Knopf, Menüpfeile, Brotkrumen, Weiterlesen, Blättern und Zitatsterne sind SVG (Masken in `site.css`, sonst eingebettet).
|
||||
|
||||
**Geprüft:** PHPUnit 692 grün (PHP 8.4), `npm test` 41, `test:editor`, `test:browser`, Twig-Lint; Symbole im Browser nachgemessen. Tag `v1.39.1`, Download stimmt mit der Prüfsumme überein.
|
||||
|
||||
**Offen:** Die Verwaltung enthält weiter Schriftzeichen (Editor-Symbole samt Plugin-Bausteinen, Pfeile auf Knöpfen). `var/luximmo-paket.zip` trägt Fassung 1.39.0 und hat die Immobilien-Seite. Im Menü von Luximmo bricht der fünfte Punkt zwischen etwa 1025 und 1130 px um. Immoscout-Plugin aktuell 1.5.2: Paket-Import ersetzt die Mediathek, der Abgleich holt die Bilder danach neu.
|
||||
|
||||
## Kern: Plugins mit PHP-Code; Plugin „ImmoScout-Abgleich“ für DEEG (09.11.2026)
|
||||
|
||||
**Anlass:** Umut: ImmoScout-Objekte im Takt abgleichen, kostenlos per URL, „100 % ein Plugin“, „wie WordPress“.
|
||||
|
||||
**Kern (ADR 127):** `plugin.php` mit `PluginApi`/`PluginRuntime`: Hooks, Aufgaben, Seiten, eigene Tabellen, Verwaltungsbildschirme, Fehler je Plugin eingegrenzt. `VERSION` steht im Arbeitsstand auf 1.39.0, nicht committet, kein Release.
|
||||
**Kern (ADR 127):** `plugin.php` mit `PluginApi`/`PluginRuntime`: Hooks, Aufgaben, Seiten, eigene Tabellen, Verwaltungsbildschirme, Fehler je Plugin eingegrenzt. **Release:** Tag `v1.39.0` auf `main`, Releaseeintrag mit Zip (3694 Dateien, 5,8 MB), `.sha256` und `install.php`, gebaut aus sauberem Stand ohne das ImmoScout-Plugin; anonymer Download stimmt mit der Prüfsumme überein.
|
||||
|
||||
**Geprüft:** PHPUnit 692 grün (PHP 8.4, neu `PluginServerTest`), `npm test` 41, `test:editor`, Twig-Lint, php-cs-fixer. Auf einer Kopie der DEEG-Installation in der Verwaltung: einschalten, einstellen, echter Abgleich (5 Objekte, Bilder, Exposés), Liste, Objektseite 1440 und 390 px ohne waagrechtes Scrollen, Sitemap, Anfrage mit Objektangabe gespeichert, verschwundenes Objekt beim zweiten Lauf inaktiv mit 410. Nicht geprüft: Hosting, MySQL, Mailversand, Lighthouse der Objektseiten; die Abweichung Angebotszahl/gelesene Objekte wurde nicht einzeln simuliert.
|
||||
|
||||
**Nächster Schritt:** DEEG auf 1.39.0 aktualisieren, `var/immoscout-plugin-1.4.0.zip` nach `plugins/` entpacken, einschalten, Portal-Adresse eintragen, abgleichen, Baustein auf `/angebote` setzen. Vorher Zustimmung von DEEG einholen.
|
||||
|
||||
**Plugin:** liegt in `plugins/immoscout` (lokal von Git ausgeschlossen, Auslieferung als ZIP), nicht Teil des Kerns. ImmoScouts `robots.txt` verbietet automatisches Abrufen; das hat Umut entschieden, der Kunde sollte zustimmen. Eine Sperre wird nicht umgangen.
|
||||
|
||||
## Kern: Unternehmensart, Standort und Logo in den strukturierten Daten (09.11.2026)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/* Symbole als SVG: Schriftzeichen macht ein Telefon zu Emoji. */
|
||||
const symbol = (p) => `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="${p}"/></svg>`;
|
||||
|
||||
/*
|
||||
* Der Bildbetrachter.
|
||||
*
|
||||
@@ -23,9 +26,9 @@
|
||||
<img class="zoom-image" alt="">
|
||||
<figcaption class="zoom-caption"></figcaption>
|
||||
</figure>
|
||||
<button class="zoom-close" type="button" aria-label="Schließen">×</button>
|
||||
<button class="zoom-prev" type="button" aria-label="Vorheriges Bild">‹</button>
|
||||
<button class="zoom-next" type="button" aria-label="Nächstes Bild">›</button>
|
||||
<button class="zoom-close" type="button" aria-label="Schließen">${symbol('M6 6l12 12M18 6 6 18')}</button>
|
||||
<button class="zoom-prev" type="button" aria-label="Vorheriges Bild">${symbol('M15 5.5 8.5 12l6.5 6.5')}</button>
|
||||
<button class="zoom-next" type="button" aria-label="Nächstes Bild">${symbol('m9 5.5 6.5 6.5L9 18.5')}</button>
|
||||
<p class="zoom-counter" aria-live="polite"></p>
|
||||
`;
|
||||
document.body.append(dialog);
|
||||
@@ -138,7 +141,7 @@
|
||||
<p class="pdf-title" id="pdf-dialog-title"></p>
|
||||
<a class="pdf-action pdf-download" download>Herunterladen</a>
|
||||
<a class="pdf-action pdf-open" target="_blank" rel="noopener">Im neuen Tab</a>
|
||||
<button class="pdf-close" type="button" aria-label="Schließen">×</button>
|
||||
<button class="pdf-close" type="button" aria-label="Schließen">${symbol('M6 6l12 12M18 6 6 18')}</button>
|
||||
</div>
|
||||
<iframe class="pdf-frame" title="PDF-Dokument"></iframe>
|
||||
`;
|
||||
|
||||
+17
-7
@@ -1,3 +1,5 @@
|
||||
/* Symbole als eingebettete SVG-Masken: Schriftzeichen macht ein Telefon zu Emoji. */
|
||||
:root{--kant-svg-unten:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");--kant-svg-oben:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 15 6-6 6 6'/%3E%3C/svg%3E");--kant-svg-rechts:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 5.5 6.5 6.5L9 18.5'/%3E%3C/svg%3E");--kant-svg-pfeil:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h15.5m-6.5-6.5 6.5 6.5-6.5 6.5'/%3E%3C/svg%3E");--kant-svg-pfeil-links:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 12H4.5M11 5.5 4.5 12 11 18.5'/%3E%3C/svg%3E");--kant-svg-pause:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 5v14m8-14v14'/%3E%3C/svg%3E");--kant-svg-play:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E")}
|
||||
@charset "UTF-8";
|
||||
/* Lange Wörter dürfen umbrechen, damit nichts aus der Spalte läuft. Getrennt wird nur im
|
||||
Fließtext: eine Überschrift mit Trennstrich („di-gitale") sieht nach Fehler aus. */
|
||||
@@ -19,14 +21,14 @@ p{hyphens:auto}
|
||||
.menu-list a:hover,.menu-list summary:hover{text-decoration:underline}
|
||||
.menu-list [aria-current=page]{font-weight:700;text-decoration:none}
|
||||
.menu-branch>summary{cursor:pointer;padding:6px 2px;list-style:none}
|
||||
.menu-branch>summary::after{content:' ▾'}
|
||||
.menu-branch[open]>summary::after{content:' ▴'}
|
||||
.menu-branch>summary::after{content:'';display:inline-block;width:.75em;height:.75em;background:currentColor;-webkit-mask:var(--kant-svg-unten) center/contain no-repeat;mask:var(--kant-svg-unten) center/contain no-repeat;margin-left:.3em;vertical-align:-.05em}
|
||||
.menu-branch[open]>summary::after{-webkit-mask-image:var(--kant-svg-oben);mask-image:var(--kant-svg-oben)}
|
||||
.menu-branch-body{display:grid;gap:2px;padding:6px 0 6px 14px}
|
||||
.menu-level-2{flex-direction:column;align-items:flex-start;gap:2px}
|
||||
|
||||
/* Posts */
|
||||
.post-list{list-style:none;margin:0;padding:0;display:grid;gap:26px}.post-list-karten{grid-template-columns:repeat(auto-fill,minmax(260px,1fr))}.post-list-liste{gap:18px}.post-list-liste .post-card{flex-direction:row;align-items:stretch}.post-list-liste .post-image{flex:0 0 34%;max-width:300px}.post-list-liste .post-image img{height:100%;aspect-ratio:auto;min-height:170px}.post-list-liste .post-body{flex:1 1 auto;align-content:center;padding:22px 26px}.post-list-wechsel{gap:0;counter-reset:beitrag}.post-list-wechsel .post-card{position:relative;counter-increment:beitrag;display:grid;grid-template-columns:1fr 1fr;align-items:center;gap:0 56px;padding:38px 0;background:transparent;border:0;border-radius:0;overflow:visible}.post-list-wechsel .post-card + .post-card{border-top:1px solid var(--line)}.post-list-wechsel .post-image{border-radius:20px;overflow:hidden;box-shadow:0 18px 46px -22px color-mix(in srgb,var(--ink) 55%,transparent)}.post-list-wechsel .post-image img{aspect-ratio:16/10;border-radius:20px}.post-list-wechsel .post-body{padding:0;display:grid;gap:12px;align-content:center}.post-list-wechsel .post-body::before{content:counter(beitrag,decimal-leading-zero);font-size:13px;font-weight:800;letter-spacing:2px;color:var(--accent)}.post-list-wechsel .post-card h3{font-size:28px;line-height:1.18;letter-spacing:-.5px}.post-list-wechsel .post-excerpt{margin:0;max-width:46ch}.post-list-wechsel .post-meta,.post-list-wechsel .post-terms{margin:0}.post-list-wechsel .post-more{display:inline-flex;align-items:center;gap:8px;margin-top:4px;font-size:15px;font-weight:700;color:var(--accent);text-decoration:none;width:fit-content}
|
||||
.post-more::after{content:'→';transition:transform .2s}
|
||||
.post-more::after{content:'';display:inline-block;width:1em;height:1em;background:currentColor;-webkit-mask:var(--kant-svg-pfeil) center/contain no-repeat;mask:var(--kant-svg-pfeil) center/contain no-repeat;vertical-align:-.12em;transition:transform .2s}
|
||||
.post-more:hover::after{transform:translateX(4px)}.post-list-wechsel .post-more::after{content:'\2192'}.post-list-wechsel .post-card:nth-child(even) .post-image{order:2}.post-list-wechsel .post-card:nth-child(even) .post-body{order:1}@media(max-width:767px){.post-list-wechsel .post-card{grid-template-columns:1fr;gap:18px;padding:26px 0}.post-list-wechsel .post-card:nth-child(even) .post-image{order:0}.post-list-wechsel .post-card:nth-child(even) .post-body{order:0}.post-list-wechsel .post-card h3{font-size:22px}}.post-list-kompakt{gap:0}.post-list-kompakt .post-card{flex-direction:row;align-items:baseline;justify-content:space-between;gap:18px;background:transparent;border:0;border-bottom:1px solid var(--line);border-radius:0;overflow:visible}.post-list-kompakt .post-body{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 18px;padding:16px 2px}.post-list-kompakt .post-meta,.post-list-kompakt .post-terms{margin:0}.post-list-kompakt .post-excerpt{flex:1 1 100%;margin:0}
|
||||
.post-card{display:flex;flex-direction:column;background:var(--paper);border:1px solid var(--line);border-radius:18px;overflow:hidden}.post-card>.post-body{display:grid;gap:10px;padding:20px 22px 22px}
|
||||
.post-image{display:block;position:relative;overflow:hidden;text-decoration:none}.post-view{position:absolute;inset:0;display:grid;place-items:center;background:color-mix(in srgb,var(--ink) 55%,transparent);color:#fff;font-weight:700;font-size:15px;letter-spacing:.4px;opacity:0}.post-card:hover .post-view,.post-card:focus-within .post-view{opacity:1}.post-image img{width:100%;height:auto;aspect-ratio:16/10;object-fit:cover;border-radius:0;display:block;background:var(--ink)}
|
||||
@@ -66,7 +68,9 @@ p{hyphens:auto}
|
||||
.block-quote blockquote p{margin:0;font-size:inherit;line-height:1.65}
|
||||
.block-quote figcaption{font-size:14px;font-weight:600}
|
||||
.block-quote figcaption span{font-weight:400;opacity:.85}
|
||||
.quote-rating{margin:0;letter-spacing:3px}
|
||||
.quote-rating{margin:0}
|
||||
.quote-rating svg{display:inline-block;width:1.1em;height:1.1em;margin-right:2px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round}
|
||||
.quote-rating .quote-star-voll{fill:currentColor}
|
||||
.block-logos{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));align-items:center;gap:24px}
|
||||
.block-logos img{max-height:52px;width:auto;margin-inline:auto;display:block}
|
||||
.kant .block-cta .button{background:var(--accent);color:var(--paper);border-color:var(--accent)}.kant .block-cta .button:hover{background:color-mix(in srgb,var(--accent) 86%,var(--ink))}.block-cta{display:flex;flex-wrap:wrap;gap:20px 34px;align-items:center;justify-content:space-between;padding:32px;border:1px solid currentColor;border-radius:14px}
|
||||
@@ -170,7 +174,7 @@ p{hyphens:auto}
|
||||
@media(max-width:767px){.form-summary-list{grid-template-columns:1fr;gap:2px 0}.form-summary-list dd{margin-bottom:8px}}
|
||||
|
||||
.block-breadcrumb ol{list-style:none;display:flex;flex-wrap:wrap;gap:6px 10px;margin:0;padding:0;font-size:13px}
|
||||
.block-breadcrumb li+li::before{content:'›';margin-right:10px;opacity:.6}
|
||||
.block-breadcrumb li+li::before{content:'';display:inline-block;width:.85em;height:.85em;background:currentColor;-webkit-mask:var(--kant-svg-rechts) center/contain no-repeat;mask:var(--kant-svg-rechts) center/contain no-repeat;margin-right:10px;opacity:.6;vertical-align:-.08em}
|
||||
.block-breadcrumb a{text-decoration:none}
|
||||
.block-breadcrumb a:hover{text-decoration:underline}
|
||||
|
||||
@@ -247,8 +251,8 @@ body.consent-open{padding-bottom:320px}
|
||||
.section-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;pointer-events:none}
|
||||
.has-video>.section-inner{position:relative;z-index:1}
|
||||
.video-toggle{position:absolute;right:16px;bottom:16px;z-index:2;width:44px;height:44px;padding:0;border:0;border-radius:50%;background:rgba(10,20,35,.72);color:#fff;font:14px/1 system-ui,sans-serif;cursor:pointer}
|
||||
.video-toggle::before{content:"❚❚"}
|
||||
.video-toggle.is-paused::before{content:"▶"}
|
||||
.video-toggle::before{content:'';display:inline-block;width:20px;height:20px;background:currentColor;-webkit-mask:var(--kant-svg-pause) center/contain no-repeat;mask:var(--kant-svg-pause) center/contain no-repeat;display:block;margin:auto}
|
||||
.video-toggle.is-paused::before{-webkit-mask-image:var(--kant-svg-play);mask-image:var(--kant-svg-play)}
|
||||
.video-toggle:focus-visible{outline:3px solid #fff;outline-offset:2px}
|
||||
.video-toggle[hidden]{display:none}
|
||||
.block-html{max-width:100%}
|
||||
@@ -603,6 +607,10 @@ html.kant-top-armed.kant-top-shown .scroll-top{opacity:1;visibility:visible;tran
|
||||
.zoom-close,.zoom-prev,.zoom-next{position:fixed;display:grid;place-items:center;width:52px;height:52px;border-radius:999px;border:0;background:rgba(255,255,255,.14);color:#fff;font-size:26px;line-height:1;cursor:pointer}
|
||||
.zoom-close:hover,.zoom-prev:hover,.zoom-next:hover{background:rgba(255,255,255,.26)}
|
||||
.zoom-close:focus-visible,.zoom-prev:focus-visible,.zoom-next:focus-visible{outline:3px solid #fff;outline-offset:3px}
|
||||
.zoom-close svg,.zoom-prev svg,.zoom-next svg,.pdf-close svg,.scroll-top svg{display:block;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
||||
.zoom-close svg,.zoom-prev svg,.zoom-next svg{width:26px;height:26px}
|
||||
.pdf-close svg{width:20px;height:20px}
|
||||
.scroll-top svg{width:46%;height:46%}
|
||||
.zoom-close{top:18px;right:18px}
|
||||
.zoom-prev{left:18px;top:50%;transform:translateY(-50%)}
|
||||
.zoom-next{right:18px;top:50%;transform:translateY(-50%)}
|
||||
@@ -644,3 +652,5 @@ html.kant-top-armed.kant-top-shown .scroll-top{opacity:1;visibility:visible;tran
|
||||
.tone-ink,.tone-mint{background:transparent;color:#000}
|
||||
[data-step][hidden],.block-form [hidden]{display:block!important}
|
||||
}
|
||||
.post-pager a[rel="prev"]::before{content:'';display:inline-block;width:1em;height:1em;background:currentColor;-webkit-mask:var(--kant-svg-pfeil-links) center/contain no-repeat;mask:var(--kant-svg-pfeil-links) center/contain no-repeat;margin-right:.35em;vertical-align:-.12em}
|
||||
.post-pager a[rel="next"]::after{content:'';display:inline-block;width:1em;height:1em;background:currentColor;-webkit-mask:var(--kant-svg-pfeil) center/contain no-repeat;mask:var(--kant-svg-pfeil) center/contain no-repeat;margin-left:.35em;vertical-align:-.12em}
|
||||
@@ -56,14 +56,14 @@ export function initSliders(doc = document) {
|
||||
go(direction > 0 ? (last ? visible[0] : visible[Math.min(visible.length - 1, position + 1)]) : (first ? visible.at(-1) : visible[Math.max(0, position - 1)]));
|
||||
};
|
||||
const manual = action => { playing = false; clearTimeout(timer); update(); action(); };
|
||||
const previous = button('←', 'Vorherige Folie', () => manual(() => step(-1))); previous.className = 'slider-prev';
|
||||
const previous = button('', 'Vorherige Folie', () => manual(() => step(-1))); previous.className = 'slider-prev';
|
||||
const count = doc.createElement('span'); count.className = 'slider-position'; controls.append(count);
|
||||
const next = button('→', 'Nächste Folie', () => manual(() => step(1))); next.className = 'slider-next';
|
||||
const next = button('', 'Nächste Folie', () => manual(() => step(1))); next.className = 'slider-next';
|
||||
const dots = [];
|
||||
if (slider.classList.contains('slider-dots')) {
|
||||
const group = doc.createElement('div'); group.className = 'slider-control-dots'; controls.append(group);
|
||||
slides.forEach((slide, i) => {
|
||||
const dot = button('●', `Folie ${i + 1} anzeigen`, () => manual(() => go(i))); group.append(dot); dots.push(dot);
|
||||
const dot = button('', `Folie ${i + 1} anzeigen`, () => manual(() => go(i))); group.append(dot); dots.push(dot);
|
||||
});
|
||||
}
|
||||
const play = seconds >= 3 ? button('', 'Automatische Wiedergabe pausieren', () => { playing = !playing; update(); schedule(); }) : null;
|
||||
|
||||
@@ -452,8 +452,8 @@ $kopf = [
|
||||
]],
|
||||
// Goldene Linie, die beim Überfahren wächst; das Klappmenü liegt als Fläche
|
||||
// unter dem ganzen Kopf.
|
||||
'css' => "& .menu-list{gap:4px 28px;align-items:center}\n"
|
||||
."& .menu-list a{position:relative;padding:12px 0;text-decoration:none}\n"
|
||||
'css' => "& .menu-list{gap:4px clamp(10px,calc(4.2vw - 32px),28px);align-items:center}\n"
|
||||
."& .menu-list a{position:relative;padding:12px 0;text-decoration:none;font-size:clamp(13px,1.05vw,15px)}\n"
|
||||
."& .menu-list a::after{content:'';position:absolute;left:0;right:100%;bottom:6px;height:1.5px;background:#BDA076;transition:right .25s ease}\n"
|
||||
."& .menu-list a:hover::after{right:0}\n"
|
||||
."& .menu-burger summary{width:46px;height:46px;display:flex;align-items:center;justify-content:center;padding:0}\n"
|
||||
@@ -501,7 +501,7 @@ $fuss = [
|
||||
]),
|
||||
$column('fuss-seiten', [
|
||||
$kleinzeile('fuss-seiten-titel', 'Leistungen', '@gold-dunkel', '8px'),
|
||||
$fussText('fuss-seiten-text', '<a href="/#leistungen">Immobilienverkauf</a><br><a href="/#leistungen">WEG-Verwaltung</a><br><a href="/#leistungen">Mietverwaltung</a><br><a href="/#leistungen">Sondereigentum</a><br><a href="/verwaltungsanfrage">Verwaltungsanfrage</a><br><a href="/immobilienbewertung">Immobilienbewertung</a>'),
|
||||
$fussText('fuss-seiten-text', '<a href="/#leistungen">Immobilienverkauf</a><br><a href="/#leistungen">WEG-Verwaltung</a><br><a href="/#leistungen">Mietverwaltung</a><br><a href="/#leistungen">Sondereigentum</a><br><a href="/verwaltungsanfrage">Verwaltungsanfrage</a><br><a href="/immobilienbewertung">Immobilienbewertung</a><br><a href="/immobilien">Immobilien</a>'),
|
||||
]),
|
||||
], [
|
||||
'desktop' => ['display' => 'grid', 'gridColumns' => 3, 'gap' => '40px', 'padding' => ['top' => '56px', 'bottom' => '40px']],
|
||||
@@ -649,7 +649,10 @@ $startseite = [
|
||||
$section('leistungen-bereich', [
|
||||
$zeile('leistungen-kopf', [
|
||||
$heading('leistungen-titel', 'Leistungen', 2, $h2Stil),
|
||||
$text('leistungen-link', '<a href="/verwaltungsanfrage">Unverbindlich anfragen →</a>', ['desktop' => ['fontSize' => '15px', 'fontWeight' => '500', 'margin' => ['bottom' => '0px']]], $linkCss),
|
||||
$zeile('leistungen-link-zeile', [
|
||||
$text('leistungen-link', '<a href="/verwaltungsanfrage">Unverbindlich anfragen</a>', ['desktop' => ['fontSize' => '15px', 'fontWeight' => '500', 'margin' => ['bottom' => '0px']]], $linkCss),
|
||||
$symbol('leistungen-link-pfeil', 'arrow-right', 16, ['desktop' => ['color' => '@tinte']]),
|
||||
], '6px'),
|
||||
], '16px', ['justifyContent' => 'space-between', 'alignItems' => 'baseline', 'flexWrap' => 'wrap', 'margin' => ['bottom' => '56px']], ['margin' => ['bottom' => '36px']]),
|
||||
$column('leistungen-raster', [
|
||||
$leistung('leistung-verkauf', $medien['poster'], 'Offener Wohn- und Essbereich mit Treppe, Holzlamellen und großer Glasfront', 'Immobilienverkauf', 'Professionelle Vermarktung, marktgerechte Bewertung und persönliche Begleitung bis zum erfolgreichen Verkauf.', [
|
||||
@@ -816,7 +819,11 @@ $startseite = [
|
||||
]),
|
||||
$column('kontakt-mehr', [
|
||||
$kleinzeile('kontakt-mehr-titel', 'Direkt', '@gold-dunkel', '8px'),
|
||||
$text('kontakt-mehr-text', '<a href="'.$tel.'">'.$telefon.'</a><br><a href="mailto:'.$mail.'">'.$mail.'</a><br>Für ein Angebot:<br><a href="/verwaltungsanfrage">Verwaltungsanfrage →</a>', ['desktop' => ['fontSize' => '17px', 'lineHeight' => 1.6, 'margin' => ['bottom' => '0px']]], $linkCss),
|
||||
$text('kontakt-mehr-text', '<a href="'.$tel.'">'.$telefon.'</a><br><a href="mailto:'.$mail.'">'.$mail.'</a><br>Für ein Angebot:', ['desktop' => ['fontSize' => '17px', 'lineHeight' => 1.6, 'margin' => ['bottom' => '0px']]], $linkCss),
|
||||
$zeile('kontakt-mehr-zeile', [
|
||||
$text('kontakt-mehr-link', '<a href="/verwaltungsanfrage">Verwaltungsanfrage</a>', ['desktop' => ['fontSize' => '17px', 'lineHeight' => 1.6, 'margin' => ['bottom' => '0px']]], $linkCss),
|
||||
$symbol('kontakt-mehr-pfeil', 'arrow-right', 16, ['desktop' => ['color' => '@tinte']]),
|
||||
], '6px'),
|
||||
]),
|
||||
], '56px', ['alignItems' => 'flex-start', 'flexWrap' => 'wrap', 'rowGap' => '32px']),
|
||||
]),
|
||||
@@ -959,6 +966,21 @@ $hinweis = static fn (string $id, string $titel, array $punkte) => $column($id,
|
||||
// Die Bildkarten einer Auswahl: Bild oben, gerundet, dunkler Rand bei Wahl.
|
||||
$kartenCss = "\n& .form-choice-grid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:14px}\n& .form-choice-card label{border:1.5px solid #E6DED2;border-radius:20px;background:#fff;padding:10px 10px 14px;font-weight:500;font-size:15px;color:#141414}\n& .form-choice-card label:hover{border-color:#BDA076}\n& .form-choice-card input:checked+label{border-color:#141414;box-shadow:0 0 0 1.5px #141414}\n& .form-choice-card input{accent-color:#141414;top:20px;left:20px;width:20px;height:20px;min-height:0;padding:0;margin:0}\n& .form-choice-card input:focus{outline:none}\n& .form-choice-picture{border-radius:12px}";
|
||||
|
||||
// Die Objekte kommen aus dem Plugin „ImmoScout-Abgleich“; der Baustein trägt das Luximmo-Aussehen.
|
||||
// Ohne eingeschaltetes Plugin bleibt die Seite erreichbar, nur die Liste fehlt.
|
||||
$anlegen('immobilien', $einblenden([
|
||||
'schemaVersion' => $SCHEMA, 'title' => 'Immobilien',
|
||||
'description' => 'Aktuelle Immobilienangebote von Luximmo in Gaggenau und Umgebung, Baden-Baden und im Schwarzwald.',
|
||||
'blocks' => [
|
||||
$seitenkopf('immobilien', 'Aktuelle Angebote', 'Unsere Immobilien.', 'Wohnungen und Häuser, die wir aktuell in Gaggenau und Umgebung, Baden-Baden und im Schwarzwald anbieten.'),
|
||||
$section('immobilien', [
|
||||
['id' => 'immobilien-liste', 'type' => 'immoscout.liste',
|
||||
'props' => ['art' => 'alle', 'darstellung' => 'kacheln', 'spalten' => '3', 'spaltenTablet' => '2', 'spaltenMobil' => '1', 'reihen' => 0, 'anzahl' => 0, 'bild' => 'breit', 'abstand' => 'normal', 'ausrichtung' => 'links', 'zeigeArt' => true, 'zeigeOrt' => true, 'zeigeFakten' => true],
|
||||
'css' => "& .immoscout-karte{border:0;border-radius:24px;overflow:hidden;background:#F7F4EF}\n& .immoscout-karte-text{padding:24px 26px 28px}\n& .immoscout-karte h2{font-size:22px;font-weight:500;letter-spacing:-0.015em}\n& .immoscout-art{font-size:13px;font-weight:500;letter-spacing:0.04em;color:#6E5830}\n& .immoscout-ort{color:#5A554D;opacity:1}\n& .immoscout-karte dt{color:#5A554D;opacity:1}\n& .immoscout-karte dd{font-weight:500}\n& .immoscout-leer{border:0;border-radius:24px;background:#F7F4EF}\n& .immoscout-leer h2{font-weight:500;letter-spacing:-0.02em}\n& .immoscout-leer p{color:#5A554D}"],
|
||||
], $abschnitt('0px', '160px'), null, '', 'wide'),
|
||||
],
|
||||
], ['immobilien-liste' => ['rise']]), 'Immobilien in Gaggenau, Baden-Baden und im Schwarzwald | LUXIMMO', $medien['miet']['id']);
|
||||
|
||||
$anlegen('immobilienbewertung', $einblenden([
|
||||
'schemaVersion' => $SCHEMA, 'title' => 'Immobilienbewertung',
|
||||
'description' => 'Was ist Ihre Immobilie wert? Luximmo schätzt Wohnungen, Häuser, Mehrfamilienhäuser und Grundstücke in Gaggenau und Umgebung – kostenlos und unverbindlich.',
|
||||
@@ -1093,6 +1115,7 @@ $anker = static fn (string $label, string $anker): array => ['label' => $label,
|
||||
$menus->save('header', 'Hauptnavigation', [
|
||||
$anker('Leistungen', 'leistungen'),
|
||||
$anker('Über uns', 'ueber-uns'),
|
||||
['label' => 'Immobilien', 'type' => 'page', 'pageId' => $seiteId('immobilien'), 'children' => []],
|
||||
['label' => 'Bewertung', 'type' => 'page', 'pageId' => $seiteId('immobilienbewertung'), 'children' => []],
|
||||
['label' => 'Anfrage', 'type' => 'page', 'pageId' => $seiteId('verwaltungsanfrage'), 'children' => []],
|
||||
], 0);
|
||||
|
||||
@@ -81,8 +81,8 @@ final class LanguageExtension extends AbstractExtension
|
||||
'Beiträge in der Kategorie „%s“.' => 'Posts in the category “%s”.',
|
||||
'Beiträge zum Schlagwort „%s“.' => 'Posts tagged “%s”.',
|
||||
'von' => 'by',
|
||||
'← Neuere' => '← Newer',
|
||||
'Ältere →' => 'Older →',
|
||||
'Neuere' => 'Newer',
|
||||
'Ältere' => 'Older',
|
||||
'Seite %d von %d' => 'Page %d of %d',
|
||||
'Externe Inhalte und Einwilligung' => 'External content and consent',
|
||||
'Diese Website lädt bestimmte Inhalte erst, wenn du zustimmst. Ohne Zustimmung wird die Seite vollständig angezeigt, nur eingebettete Inhalte anderer Anbieter bleiben leer.' => 'This website only loads certain content once you agree. Without consent the page is shown in full; only embedded content from other providers stays empty.',
|
||||
@@ -173,8 +173,8 @@ final class LanguageExtension extends AbstractExtension
|
||||
'Beiträge in der Kategorie „%s“.' => '„%s“ kategorisindeki yazılar.',
|
||||
'Beiträge zum Schlagwort „%s“.' => '„%s“ etiketli yazılar.',
|
||||
'von' => 'yazan:',
|
||||
'← Neuere' => '← Daha yeni',
|
||||
'Ältere →' => 'Daha eski →',
|
||||
'Neuere' => 'Daha yeni',
|
||||
'Ältere' => 'Daha eski',
|
||||
'Seite %d von %d' => 'Sayfa %d / %d',
|
||||
'Externe Inhalte und Einwilligung' => 'Harici içerikler ve onay',
|
||||
'Diese Website lädt bestimmte Inhalte erst, wenn du zustimmst. Ohne Zustimmung wird die Seite vollständig angezeigt, nur eingebettete Inhalte anderer Anbieter bleiben leer.' => 'Bu web sitesi bazı içerikleri ancak onayınızdan sonra yükler. Onay vermeseniz de sayfa eksiksiz görüntülenir; yalnızca diğer sağlayıcıların yerleştirilmiş içerikleri boş kalır.',
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
{% elseif type == 'quote' %}
|
||||
<figure id="{{ block.id }}" class="block-quote{{ designClasses }}">
|
||||
{% if props.rating|default(0) > 0 %}
|
||||
<p class="quote-rating"><span class="visually-hidden">Bewertung: {{ props.rating }} von 5</span><span aria-hidden="true">{% for i in 1..5 %}{{ i <= props.rating ? '★' : '☆' }}{% endfor %}</span></p>
|
||||
<p class="quote-rating"><span class="visually-hidden">Bewertung: {{ props.rating }} von 5</span><span aria-hidden="true">{% for i in 1..5 %}<svg class="{{ i <= props.rating ? 'quote-star-voll' : 'quote-star' }}" viewBox="0 0 24 24" focusable="false"><path d="m12 3 2.7 5.9 6.3.7-4.7 4.3 1.3 6.1L12 17l-5.6 3 1.3-6.1L3 9.6l6.3-.7Z"/></svg>{% endfor %}</span></p>
|
||||
{% endif %}
|
||||
<blockquote><p>{{ props.text }}</p></blockquote>
|
||||
<figcaption>{{ props.author }}{% if props.role|default('') %} <span>{{ props.role }}</span>{% endif %}</figcaption>
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
{% if pages|default(1) > 1 %}
|
||||
{# Dieselbe Blätterleiste wie im Archiv: eine Liste, die mehr hat als sie zeigt, sagt es. #}
|
||||
<nav class="post-pager" aria-label="{{ 'Weitere Beiträge'|kant_t }}">
|
||||
{% if page > 1 %}<a rel="prev" href="?seite={{ page - 1 }}">{{ '← Neuere'|kant_t }}</a>{% endif %}
|
||||
{% if page > 1 %}<a rel="prev" href="?seite={{ page - 1 }}">{{ 'Neuere'|kant_t }}</a>{% endif %}
|
||||
<span>{{ 'Seite %d von %d'|kant_t|format(page, pages) }}{% if total %} · {{ total }} {{ 'Beiträge'|kant_t }}{% endif %}</span>
|
||||
{% if page < pages %}<a rel="next" href="?seite={{ page + 1 }}">{{ 'Ältere →'|kant_t }}</a>{% endif %}
|
||||
{% if page < pages %}<a rel="next" href="?seite={{ page + 1 }}">{{ 'Ältere'|kant_t }}</a>{% endif %}
|
||||
</nav>
|
||||
{% endif %}
|
||||
@@ -125,7 +125,7 @@
|
||||
{# Ein Anker, kein Skript. Er springt an den Anfang - das kann ein Browser allein. Der nav-Rahmen
|
||||
gibt ihm eine Landmarke: ein Verweis außerhalb jeder Landmarke ist für Vorlesesoftware
|
||||
Inhalt ohne Ort, und axe meldet ihn als Verstoß gegen „region“. #}
|
||||
<nav aria-label="{{ oben.scrollTopLabel|default('Nach oben')|kant_t }}"><a class="scroll-top{{ oben.scrollTopPosition|default('rechts') == 'links' ? ' scroll-top-links' : '' }}" href="#seitenanfang" aria-label="{{ oben.scrollTopLabel|default('Nach oben')|kant_t }}"><span aria-hidden="true">↑</span></a></nav>
|
||||
<nav aria-label="{{ oben.scrollTopLabel|default('Nach oben')|kant_t }}"><a class="scroll-top{{ oben.scrollTopPosition|default('rechts') == 'links' ? ' scroll-top-links' : '' }}" href="#seitenanfang" aria-label="{{ oben.scrollTopLabel|default('Nach oben')|kant_t }}"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 20V4.5m-6.5 6.5L12 4.5l6.5 6.5"/></svg></a></nav>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user