The icon set had no drawing for people, music or a house - the three pictures
the Tagespflege Moldovan template asks for. They join as `people`, `music` and
`home`; a test keeps the list and the drawings together, because a missing path
renders an empty `<path d="">`: invisible, without an error.
An icon block's own colour never reached its drawing: the embedded SVG carries
the same `block-icon` class as its wrapper and set the accent colour again.
`.block-icon .block-icon{color:inherit}` fixes it at the root.
The menu button becomes a thing you can shape. `burgerLabel` chooses symbol and
text, text only or symbol only (which keeps the name for screen readers), and
the new style group `menu` targets the button itself, the way `img` targets an
image and `controls` the slider. Inside the header the opened menu now lies
under the header across the full width instead of pushing the header apart -
on a phone that looked like a missing navigation.
The back-to-top button no longer depends on `animation-timeline: scroll()`. A
browser that parses the property but does not run the timeline left it in the
first frame of the animation: permanently invisible. Two classes from
scrolled.js decide now, and without a script the button simply stays visible.
Also: the Tagespflege Moldovan rebuild as its own installation, built only by
`scripts/seed-tagespflege-moldovan.php`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
756 lines
51 KiB
PHP
756 lines
51 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Baut die Website „Tagespflege Jacqueline Moldovan“ als Inhalt dieses CMS auf.
|
||
*
|
||
* Vorlage ist das gelieferte Paket „Tagespflege_Moldovan_Website.zip“ (09.09.2026): ein Onepager
|
||
* aus index.html, style.css und script.js. Wortlaut, Farben, Schriftgrößen, Abstände und die
|
||
* Reihenfolge der Abschnitte sind daraus übernommen. Gebaut ist alles aus gewöhnlichen
|
||
* Bausteinen – kein eigener Baustein, kein eigenes Skript, keine externe Schrift.
|
||
*
|
||
* Zwei Stellen weichen bewusst ab:
|
||
* - Das Kontaktformular verschickt serverseitig, statt im Mailprogramm des Besuchers eine
|
||
* vorbereitete E-Mail zu öffnen. Der Hinweistext darunter sagt das entsprechend.
|
||
* - Das Markenzeichen liegt in der Vorlage als SVG vor; die Medienverwaltung nimmt JPEG, PNG und
|
||
* WebP. Verwendet wird deshalb marke.png, die verlustfreie Umsetzung derselben Zeichnung.
|
||
*
|
||
* Das Skript schreibt ausschließlich in die Datenbank aus DATABASE_URL und in MEDIA_DIRECTORY,
|
||
* beide müssen auf eine frische, migrierte Installation zeigen (siehe reset-tagespflege-moldovan.sh).
|
||
* Erstes Argument: der Ordner mit gemeinsam.webp, jacqueline-moldovan.png und marke.png.
|
||
*/
|
||
|
||
require dirname(__DIR__).'/config/bootstrap.php';
|
||
|
||
use App\Content\DocumentValidator;
|
||
use App\Content\FormRepository;
|
||
use App\Content\MediaLibrary;
|
||
use App\Content\MenuRepository;
|
||
use App\Content\PageRepository;
|
||
use App\Content\PartialRepository;
|
||
use App\Content\SiteSettings;
|
||
use App\Content\Theme;
|
||
use App\Infrastructure\ConnectionFactory;
|
||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||
|
||
$root = dirname(__DIR__);
|
||
$assets = $argv[1] ?? null;
|
||
if (null === $assets || !is_dir($assets)) {
|
||
fwrite(STDERR, "Bitte den Ordner mit den Bildern als Argument angeben.\n");
|
||
exit(1);
|
||
}
|
||
$url = str_replace('%kernel.project_dir%', str_replace('\\', '/', $root), (string) $_SERVER['DATABASE_URL']);
|
||
$mediaDirectory = str_replace('%kernel.project_dir%', $root, (string) $_SERVER['MEDIA_DIRECTORY']);
|
||
if (!str_contains($url, 'tagespflege-moldovan')) {
|
||
fwrite(STDERR, "Sicherung: DATABASE_URL muss auf die Moldovan-Datenbank zeigen.\n");
|
||
exit(1);
|
||
}
|
||
|
||
$db = ConnectionFactory::create($url);
|
||
if (false !== $db->fetchOne('SELECT id FROM page LIMIT 1')) {
|
||
fwrite(STDERR, "Diese Datenbank enthält bereits Seiten. Abbruch, damit nichts überschrieben wird.\n");
|
||
exit(1);
|
||
}
|
||
|
||
$media = new MediaLibrary($db, $mediaDirectory);
|
||
$settings = new SiteSettings($db, $media);
|
||
$pages = new PageRepository($db, new DocumentValidator(), $settings);
|
||
$partials = new PartialRepository($db, new DocumentValidator());
|
||
$menus = new MenuRepository($db, $settings);
|
||
$forms = new FormRepository($db);
|
||
$theme = new Theme($db);
|
||
|
||
$mail = 'info@tagespflege-moldovan.com';
|
||
$telefon = '07221 / 922 7961';
|
||
$telHref = 'tel:+4972219227961';
|
||
$SCHEMA = 23;
|
||
|
||
// ---------------------------------------------------------------------------------------------
|
||
// Bausteine
|
||
// ---------------------------------------------------------------------------------------------
|
||
|
||
$ecken = static fn (string $r): array => ['topLeft' => $r, 'topRight' => $r, 'bottomRight' => $r, 'bottomLeft' => $r];
|
||
$seiten = static fn (string $w): array => ['top' => $w, 'right' => $w, 'bottom' => $w, 'left' => $w];
|
||
$nurOben = static fn (string $w): array => ['top' => $w, 'right' => '0px', 'bottom' => '0px', 'left' => '0px'];
|
||
$nurUnten = static fn (string $w): array => ['top' => '0px', 'right' => '0px', 'bottom' => $w, 'left' => '0px'];
|
||
$nurLinks = static fn (string $w): array => ['top' => '0px', 'right' => '0px', 'bottom' => '0px', 'left' => $w];
|
||
|
||
$section = static function (string $id, array $children, array $style = [], ?string $anchor = null): array {
|
||
$block = ['id' => $id, 'type' => 'section', 'children' => $children, 'style' => $style];
|
||
if (null !== $anchor) {
|
||
$block['anchor'] = $anchor;
|
||
}
|
||
|
||
return $block;
|
||
};
|
||
|
||
/** Der Rhythmus der Vorlage: 100 px am Schreibtisch, 75 auf dem Tablet, 61 auf dem Telefon. */
|
||
$abschnitt = static function (string $id, array $children, array $style = [], ?string $anchor = null) use ($section): array {
|
||
$basis = [
|
||
'desktop' => ['padding' => ['top' => '100px', 'bottom' => '100px']],
|
||
'tablet' => ['padding' => ['top' => '75px', 'bottom' => '75px']],
|
||
'mobile' => ['padding' => ['top' => '61px', 'bottom' => '61px']],
|
||
];
|
||
foreach ($style as $device => $values) {
|
||
$basis[$device] = [...($basis[$device] ?? []), ...$values];
|
||
}
|
||
|
||
return $section($id, $children, $basis, $anchor);
|
||
};
|
||
|
||
$row = static function (string $id, array $children, array $design = [], array $style = []): array {
|
||
$block = ['id' => $id, 'type' => 'row', 'children' => $children];
|
||
if ([] !== $design) {
|
||
$block['layout'] = ['design' => $design];
|
||
}
|
||
if ([] !== $style) {
|
||
$block['style'] = $style;
|
||
}
|
||
|
||
return $block;
|
||
};
|
||
|
||
/** Eine Zeile, die nebeneinander stellt statt zu rastern – Marke, Signatur, Wertepunkt, Zeitleiste. */
|
||
$zeile = static function (string $id, array $children, string $gap, array $extra = [], array $mobil = [], array $tablet = []) use ($row): array {
|
||
$style = ['desktop' => ['display' => 'flex', 'alignItems' => 'center', 'gap' => $gap, 'margin' => ['top' => '0px'], ...$extra]];
|
||
if ([] !== $tablet) {
|
||
$style['tablet'] = $tablet;
|
||
}
|
||
if ([] !== $mobil) {
|
||
$style['mobile'] = $mobil;
|
||
}
|
||
|
||
return $row($id, $children, [], $style);
|
||
};
|
||
|
||
$column = static function (string $id, array $children, array $style = [], string $sichtbarkeit = 'all'): array {
|
||
$block = ['id' => $id, 'type' => 'column', 'children' => $children];
|
||
if ([] !== $style) {
|
||
$block['style'] = $style;
|
||
}
|
||
if ('all' !== $sichtbarkeit) {
|
||
$block['layout'] = ['visibility' => $sichtbarkeit];
|
||
}
|
||
|
||
return $block;
|
||
};
|
||
|
||
$heading = static function (string $id, string $text, int $level, array $style = [], string $css = ''): array {
|
||
$block = ['id' => $id, 'type' => 'heading', 'props' => ['text' => $text, 'level' => $level]];
|
||
if ([] !== $style) {
|
||
$block['style'] = $style;
|
||
}
|
||
if ('' !== $css) {
|
||
$block['css'] = $css;
|
||
}
|
||
|
||
return $block;
|
||
};
|
||
|
||
$text = static function (string $id, string $inhalt, array $style = [], string $css = ''): array {
|
||
$block = ['id' => $id, 'type' => 'text', 'props' => ['text' => $inhalt]];
|
||
if ([] !== $style) {
|
||
$block['style'] = $style;
|
||
}
|
||
if ('' !== $css) {
|
||
$block['css'] = $css;
|
||
}
|
||
|
||
return $block;
|
||
};
|
||
|
||
/** Eine reine Fläche: der Strich vor einer Kleinzeile, die Linie der Zeitleiste, die grüne Form. */
|
||
$flaeche = static function (string $id, array $style, string $css = ''): array {
|
||
$block = ['id' => $id, 'type' => 'spacer', 'props' => ['size' => 'small'], 'style' => $style];
|
||
if ('' !== $css) {
|
||
$block['css'] = $css;
|
||
}
|
||
|
||
return $block;
|
||
};
|
||
|
||
$button = static function (string $id, string $text, string $href, array $style = []): array {
|
||
return ['id' => $id, 'type' => 'button', 'props' => ['text' => $text, 'href' => $href], 'style' => $style];
|
||
};
|
||
|
||
$bild = static function (string $id, array $eintrag, string $alt, array $style = [], ?string $href = null, string $css = ''): array {
|
||
$gross = end($eintrag['variants']);
|
||
$props = [
|
||
'src' => $gross['src'], 'alt' => $alt, 'decorative' => '' === $alt, 'width' => $gross['width'], 'height' => $gross['height'],
|
||
'mediaId' => $eintrag['id'],
|
||
'sources' => array_map(static fn (array $v): array => ['src' => $v['src'], 'width' => $v['width']], $eintrag['variants']),
|
||
];
|
||
if (null !== $href) {
|
||
$props['href'] = $href;
|
||
$props['click'] = 'link';
|
||
}
|
||
|
||
$block = ['id' => $id, 'type' => 'image', 'props' => $props, 'style' => $style];
|
||
if ('' !== $css) {
|
||
$block['css'] = $css;
|
||
}
|
||
|
||
return $block;
|
||
};
|
||
|
||
$symbol = static function (string $id, string $name, int $groesse, array $style = []): array {
|
||
return ['id' => $id, 'type' => 'icon', 'props' => ['icon' => $name, 'size' => $groesse, 'decorative' => true, 'label' => ''], 'style' => $style];
|
||
};
|
||
|
||
// Wiederkehrende Gestaltungswerte der Vorlage.
|
||
$serif = ['fontFamily' => 'heading', 'fontWeight' => '400', 'letterSpacing' => '-0.045em', 'lineHeight' => 1.1];
|
||
$h2Stil = ['desktop' => [...$serif, 'fontSize' => '53px', 'margin' => ['bottom' => '0px']], 'tablet' => ['fontSize' => '42px'], 'mobile' => ['fontSize' => '38px']];
|
||
$emGruen = '& em{color:#718f3d;font-weight:400}';
|
||
$fliess = ['desktop' => ['color' => '@gedaempft', 'fontSize' => '16px', 'lineHeight' => 1.65, 'margin' => ['bottom' => '20px']]];
|
||
$klein = ['desktop' => ['fontSize' => '11px', 'fontWeight' => '700', 'letterSpacing' => '0.13em', 'color' => '#6a795e', 'lineHeight' => 1.5, 'margin' => ['bottom' => '0px']]];
|
||
$h3Stil = ['desktop' => ['fontFamily' => 'body', 'fontSize' => '19px', 'fontWeight' => '500', 'letterSpacing' => '-0.025em', 'lineHeight' => 1.35, 'margin' => ['bottom' => '13px']]];
|
||
|
||
/** Die Kleinzeile über einer Überschrift: ein kurzer Strich, dann Versalien. */
|
||
$kleinzeile = static function (string $id, string $inhalt, string $farbe = '#527236', string $strich = '@gruen', string $abstand = '25px') use ($zeile, $flaeche, $text): array {
|
||
return $zeile($id, [
|
||
$flaeche($id.'-strich', ['desktop' => ['width' => '24px', 'height' => '3px', 'backgroundColor' => $strich, 'flexShrink' => 0]]),
|
||
$text($id.'-text', $inhalt, [
|
||
'desktop' => ['fontSize' => '12px', 'fontWeight' => '700', 'letterSpacing' => '0.16em', 'textTransform' => 'uppercase', 'lineHeight' => 1.7, 'color' => $farbe, 'margin' => ['bottom' => '0px']],
|
||
'mobile' => ['fontSize' => '11px'],
|
||
]),
|
||
], '11px', ['margin' => ['top' => '0px', 'bottom' => $abstand]], ['margin' => ['top' => '0px', 'bottom' => '18px']]);
|
||
};
|
||
|
||
// ---------------------------------------------------------------------------------------------
|
||
// Website, Gestaltung, Medien, Formular
|
||
// ---------------------------------------------------------------------------------------------
|
||
|
||
$db->insert('website', ['id' => 'default', 'name' => 'Tagespflege Jacqueline Moldovan', 'default_locale' => 'de', 'theme' => '{}']);
|
||
|
||
$theme->save(
|
||
[
|
||
['key' => 'tinte', 'name' => 'Tinte', 'value' => '#294655'],
|
||
['key' => 'blau', 'name' => 'Blau', 'value' => '#2e7595'],
|
||
['key' => 'blau-dunkel', 'name' => 'Blau dunkel', 'value' => '#245e79'],
|
||
['key' => 'dunkelblau', 'name' => 'Kontaktbereich', 'value' => '#284f63'],
|
||
['key' => 'gruen', 'name' => 'Grün', 'value' => '#9abf56'],
|
||
['key' => 'limette', 'name' => 'Limette', 'value' => '#c0d348'],
|
||
['key' => 'oliv', 'name' => 'Oliv', 'value' => '#718f3d'],
|
||
['key' => 'marke', 'name' => 'Markengrün', 'value' => '#83a944'],
|
||
['key' => 'gedaempft', 'name' => 'Gedämpft', 'value' => '#647078'],
|
||
['key' => 'blass', 'name' => 'Blass', 'value' => '#f3f6ef'],
|
||
['key' => 'leiste', 'name' => 'Kopfleiste', 'value' => '#f1f4ee'],
|
||
['key' => 'sand', 'name' => 'Werteband', 'value' => '#fafbf8'],
|
||
['key' => 'linie', 'name' => 'Trennlinie', 'value' => '#dce3dd'],
|
||
['key' => 'papier', 'name' => 'Papier', 'value' => '#ffffff'],
|
||
],
|
||
[
|
||
// Beide Schriften stehen auf jedem Gerät bereit; die Vorlage lädt bewusst keine Webschrift.
|
||
['key' => 'body', 'name' => 'Fließtext', 'family' => 'Arial', 'source' => 'system', 'weights' => [400, 600, 700], 'fallback' => 'sans-serif'],
|
||
['key' => 'heading', 'name' => 'Überschriften', 'family' => 'Georgia', 'source' => 'system', 'weights' => [400], 'fallback' => 'serif'],
|
||
],
|
||
['fontFamily' => 'body', 'headingFontFamily' => 'heading', 'fontSize' => '16px', 'lineHeight' => 1.65, 'color' => '@tinte', 'backgroundColor' => '@papier', 'linkColor' => '@tinte', 'containerWidth' => '1240px', 'headingScale' => 1.25, 'linkUnderline' => false],
|
||
['shape' => 'square', 'appearance' => 'solid', 'size' => 'normal', 'fontFamily' => 'inherit', 'fontSize' => 15, 'fontWeight' => 600, 'letterSpacing' => 0, 'textTransform' => 'none', 'backgroundColor' => '@blau', 'color' => '@papier', 'hoverBackgroundColor' => '@blau-dunkel', 'hoverColor' => '@papier'],
|
||
);
|
||
echo "Farben, Schriften und Buttons gesetzt\n";
|
||
|
||
$medien = [];
|
||
foreach ([
|
||
'marke' => ['marke.png', 'Markenzeichen der Tagespflege Jacqueline Moldovan: ein Schmetterling in Grün und Blau'],
|
||
'gemeinsam' => ['gemeinsam.webp', 'Illustrative Szene: Eine Seniorin und eine Begleiterin lachen gemeinsam an einem Tisch.'],
|
||
'portraet' => ['jacqueline-moldovan.png', 'Jacqueline Moldovan'],
|
||
] as $schluessel => [$datei, $alt]) {
|
||
$pfad = rtrim($assets, '/\\').'/'.$datei;
|
||
if (!is_file($pfad)) {
|
||
fwrite(STDERR, "Bild fehlt: $pfad\n");
|
||
exit(1);
|
||
}
|
||
$eintrag = $media->upload(new UploadedFile($pfad, $datei, null, null, true));
|
||
$media->update($eintrag['id'], ['title' => pathinfo($datei, PATHINFO_FILENAME), 'alt' => $alt, 'archived' => false, 'version' => $eintrag['version']]);
|
||
$medien[$schluessel] = $media->find($eintrag['id']);
|
||
echo "Bild übernommen: $datei\n";
|
||
}
|
||
|
||
$forms->save('kontakt', 'Kontaktanfrage', [
|
||
['name' => 'name', 'type' => 'text', 'label' => 'Ihr Name', 'required' => true],
|
||
['name' => 'email', 'type' => 'email', 'label' => 'E-Mail-Adresse', 'required' => true],
|
||
['name' => 'telefon', 'type' => 'phone', 'label' => 'Telefon', 'required' => false, 'help' => 'Für einen persönlichen Rückruf'],
|
||
['name' => 'nachricht', 'type' => 'textarea', 'label' => 'Ihre Nachricht', 'required' => true, 'help' => 'Erzählen Sie uns, was Ihnen wichtig ist.'],
|
||
], ['recipient' => $mail, 'subject' => 'Neue Nachricht über tagespflege-moldovan.com', 'success' => 'Vielen Dank. Ihre Nachricht ist angekommen – wir melden uns bei Ihnen.', 'replyToField' => 'email'], 0);
|
||
echo "Formular angelegt: kontakt\n";
|
||
|
||
// ---------------------------------------------------------------------------------------------
|
||
// Kopfbereich: schmale Leiste, darunter der weiße Kopf, der beim Scrollen oben bleibt
|
||
// ---------------------------------------------------------------------------------------------
|
||
|
||
/** Die Wortmarke: Schmetterling, darüber „Tagespflege“, darunter der Name. */
|
||
$wortmarke = static function (string $praefix, string $bildhoehe, string $bildbreite, string $gross, string $klein) use ($zeile, $column, $bild, $text, $medien, $seiten): array {
|
||
return $zeile($praefix.'-zeile', [
|
||
$column($praefix.'-bild', [
|
||
$bild($praefix.'-logo', $medien['marke'], 'Tagespflege Jacqueline Moldovan', [
|
||
'desktop' => ['maxWidth' => $bildbreite, 'imageHeight' => $bildhoehe, 'objectFit' => 'contain', 'margin' => $seiten('0px')],
|
||
], '/'),
|
||
], ['desktop' => ['flexShrink' => 0]]),
|
||
$column($praefix.'-schrift', [
|
||
$text($praefix.'-name', 'Tagespflege', ['desktop' => ['fontSize' => $gross, 'fontWeight' => '700', 'letterSpacing' => '-0.04em', 'lineHeight' => 1.3, 'color' => '@marke', 'margin' => ['bottom' => '0px']]]),
|
||
$text($praefix.'-zusatz', 'Jacqueline Moldovan', ['desktop' => ['fontSize' => $klein, 'color' => '#62676b', 'lineHeight' => 1.3, 'margin' => ['top' => '3px', 'bottom' => '0px']]]),
|
||
]),
|
||
], '11px', ['flexShrink' => 0]);
|
||
};
|
||
|
||
$kopf = [
|
||
'schemaVersion' => $SCHEMA, 'title' => 'Kopfbereich', 'description' => 'Erscheint auf jeder Seite über dem Inhalt.',
|
||
'blocks' => [
|
||
$section('kopf-leiste', [
|
||
$row('kopf-leiste-zeile', [
|
||
$column('kopf-leiste-ort', [
|
||
$text('kopf-leiste-ort-text', 'Mitten in Baden-Baden. Mitten im Leben.', ['desktop' => ['fontSize' => '14px', 'lineHeight' => 1.5, 'margin' => ['bottom' => '0px']]]),
|
||
], [], 'hide-mobile'),
|
||
$column('kopf-leiste-kontakt', [
|
||
$text('kopf-leiste-telefon', '<a href="'.$telHref.'">Ihr direkter Kontakt: '.$telefon.'</a>', [
|
||
'desktop' => ['fontSize' => '14px', 'lineHeight' => 1.5, 'textAlign' => 'right', 'margin' => ['bottom' => '0px']],
|
||
'mobile' => ['fontSize' => '12px', 'textAlign' => 'center'],
|
||
], '& a:hover{text-decoration:underline}'),
|
||
]),
|
||
], ['desktop' => ['columns' => 'two'], 'mobile' => ['columns' => 'one']], ['desktop' => ['alignItems' => 'center', 'margin' => ['top' => '0px']]]),
|
||
], [
|
||
'desktop' => ['backgroundColor' => '@leiste', 'color' => '#506054', 'padding' => ['top' => '8px', 'bottom' => '8px']],
|
||
]),
|
||
$section('kopf-haupt', [
|
||
$row('kopf-haupt-zeile', [
|
||
$column('kopf-marke', [$wortmarke('kopf-marke', '60px', '40px', '24px', '15px')], ['desktop' => ['flexShrink' => 0]]),
|
||
$column('kopf-navigation', [
|
||
['id' => 'kopf-menue', 'type' => 'menu', 'props' => ['slot' => 'header', 'layout' => 'horizontal', 'collapse' => 'mobile', 'burgerLabel' => 'both'],
|
||
'style' => ['desktop' => [
|
||
'fontSize' => '15px', 'justifyContent' => 'flex-end', 'display' => 'flex',
|
||
// Der Menü-Knopf im Zuschnitt der Vorlage: heller Rahmen, kaum gerundet.
|
||
'burgerColor' => '@tinte', 'burgerBorderColor' => '#d8e0d1', 'burgerBorderRadius' => '3px', 'burgerFontSize' => '14px',
|
||
]],
|
||
'css' => "& .menu-list{gap:4px 29px;justify-content:flex-end}\n& .menu-list a{transition:color .2s}\n& .menu-list a:hover{color:#688f30;text-decoration:none}\n& .menu-list>li:last-child>a{border:1px solid #cfd9ce;border-radius:4px;padding:12px 19px}",
|
||
],
|
||
], ['desktop' => ['display' => 'flex', 'justifyContent' => 'flex-end', 'alignItems' => 'center']]),
|
||
], [], [
|
||
'desktop' => ['display' => 'flex', 'alignItems' => 'center', 'justifyContent' => 'space-between', 'gap' => '25px', 'minHeight' => '100px', 'margin' => ['top' => '0px']],
|
||
'tablet' => ['minHeight' => '86px'],
|
||
'mobile' => ['minHeight' => '80px'],
|
||
]),
|
||
], [
|
||
'desktop' => ['backgroundColor' => '#fffffff7', 'borderWidth' => $nurUnten('1px'), 'borderStyle' => 'solid', 'borderColor' => '#e7ece7', 'padding' => ['top' => '0px', 'bottom' => '0px']],
|
||
]),
|
||
],
|
||
];
|
||
|
||
// ---------------------------------------------------------------------------------------------
|
||
// Fußbereich
|
||
// ---------------------------------------------------------------------------------------------
|
||
|
||
$fuss = [
|
||
'schemaVersion' => $SCHEMA, 'title' => 'Fußbereich', 'description' => 'Erscheint auf jeder Seite unter dem Inhalt.',
|
||
'blocks' => [
|
||
$section('fuss', [
|
||
$zeile('fuss-oben', [
|
||
$column('fuss-marke', [$wortmarke('fuss-marke', '51px', '34px', '19px', '13px')], ['desktop' => ['flexShrink' => 0]]),
|
||
$column('fuss-spruch', [
|
||
$text('fuss-spruch-text', 'Mit Aufmerksamkeit. Mit Freude. Mit Herz.', [
|
||
'desktop' => ['fontFamily' => 'heading', 'fontStyle' => 'italic', 'fontSize' => '17px', 'color' => '#737b78', 'textAlign' => 'center', 'margin' => ['bottom' => '0px']],
|
||
'tablet' => ['maxWidth' => '210px'],
|
||
'mobile' => ['fontSize' => '15px', 'textAlign' => 'left', 'maxWidth' => '100%'],
|
||
]),
|
||
], ['mobile' => ['order' => 3, 'flexBasis' => '100%']]),
|
||
$column('fuss-nachoben', [
|
||
$text('fuss-nachoben-text', '<a href="#start">Nach oben ↑</a>', [
|
||
'desktop' => ['fontSize' => '13px', 'textAlign' => 'right', 'margin' => ['bottom' => '0px']],
|
||
'mobile' => ['margin' => ['left' => 'auto']],
|
||
], '& a:hover{text-decoration:underline}'),
|
||
]),
|
||
], '25px', ['justifyContent' => 'space-between', 'padding' => ['top' => '37px', 'bottom' => '37px']], ['flexWrap' => 'wrap', 'gap' => '22px', 'padding' => ['top' => '30px', 'bottom' => '30px']]),
|
||
$zeile('fuss-unten', [
|
||
$column('fuss-recht', [
|
||
$text('fuss-copyright', '© 2026 Tagespflege Jacqueline Moldovan', ['desktop' => ['fontSize' => '12px', 'margin' => ['bottom' => '0px']], 'mobile' => ['fontSize' => '11px']]),
|
||
]),
|
||
$column('fuss-hinweis', [
|
||
$text('fuss-hinweis-text', 'Gestaltungsentwurf · Beispieltexte & illustratives KI-Bild', ['desktop' => ['fontSize' => '12px', 'textAlign' => 'right', 'margin' => ['bottom' => '0px']], 'mobile' => ['fontSize' => '11px', 'textAlign' => 'left']]),
|
||
]),
|
||
], '20px', ['justifyContent' => 'space-between', 'alignItems' => 'flex-start', 'borderWidth' => $nurOben('1px'), 'borderStyle' => 'solid', 'borderColor' => '#e7ebe4', 'padding' => ['top' => '18px', 'bottom' => '18px'], 'color' => '#78817b'], ['flexDirection' => 'column', 'gap' => '7px']),
|
||
], [
|
||
'desktop' => ['borderWidth' => $nurUnten('7px'), 'borderStyle' => 'solid', 'borderColor' => '@limette', 'padding' => ['top' => '0px', 'bottom' => '0px']],
|
||
]),
|
||
],
|
||
];
|
||
|
||
$partials->create('header', 'default', 'Kopfbereich', $kopf);
|
||
$partials->create('footer', 'default', 'Fußbereich', $fuss);
|
||
echo "Kopf- und Fußbereich angelegt\n";
|
||
|
||
// ---------------------------------------------------------------------------------------------
|
||
// Startseite
|
||
// ---------------------------------------------------------------------------------------------
|
||
|
||
$werte = ['Persönlich begleitet', 'Gemeinsam aktiv', 'Mit Freude durch den Tag'];
|
||
|
||
// Nummer, Symbol, Farbe des oberen Rands, Titel, Text – die drei Karten aus „Unser Angebot“.
|
||
$angebote = [
|
||
['01 / MITEINANDER', 'people', '#a9c563', '#f0f5e7', '#6b8f36', 'Gesellschaft genießen', 'Erzählen, zuhören, gemeinsam lachen. Hier können aus Begegnungen vertraute Beziehungen werden.'],
|
||
['02 / LEBENSFREUDE', 'music', '#4285a2', '#edf5f8', '#347895', 'Mit Freude aktiv sein', 'Musik, Bewegung und kreative Momente bringen Abwechslung in den Tag. Jeder macht mit, wie es sich gut anfühlt.'],
|
||
['03 / GEBORGENHEIT', 'home', '#bdce62', '#f0f5e7', '#6b8f36', 'Sich aufgehoben fühlen', 'Ein liebevoll gedeckter Tisch, Zeit zum Durchatmen und aufmerksame Begleitung geben dem Tag einen vertrauten Rahmen.'],
|
||
];
|
||
|
||
$tagesablauf = [
|
||
['01', 'ANKOMMEN', 'In Ruhe in den Tag starten', 'Ein freundliches Willkommen, ein gemeinsames Frühstück und Zeit für die ersten Gespräche.'],
|
||
['02', 'GEMEINSAM ERLEBEN', 'Den Vormittag gestalten', 'Ein Spiel, etwas Bewegung oder gemeinsam kreativ werden – passend zu Lust und Möglichkeiten.'],
|
||
['03', 'GENIESSEN & AUSRUHEN', 'Zeit für eine Pause', 'Zusammen Mittag essen und anschließend entspannen. Jeder darf seinen eigenen Rhythmus finden.'],
|
||
['04', 'DEN TAG AUSKLINGEN LASSEN', 'Mit einem Lächeln nach Hause', 'Kaffee, eine gemütliche Runde und schöne Erinnerungen, die mit nach Hause gehen.'],
|
||
];
|
||
|
||
$startseite = [
|
||
'schemaVersion' => $SCHEMA,
|
||
'title' => 'Tagespflege Moldovan',
|
||
'description' => 'Tagespflege Jacqueline Moldovan in Baden-Baden. Ein Ort für Begegnung, Geborgenheit und schöne gemeinsame Tage.',
|
||
'blocks' => [
|
||
// 1 – Hero: Text links, Foto rechts auf einer limettenen Form, Notizkarte darüber.
|
||
$section('hero', [
|
||
$row('hero-zeile', [
|
||
$column('hero-text', [
|
||
$kleinzeile('hero-label', 'Tagespflege in Baden-Baden'),
|
||
$heading('hero-titel', 'Ein schöner Tag.<br>Ein gutes Gefühl.<br><em>Ein Stück Zuhause.</em>', 1, [
|
||
'desktop' => [...$serif, 'fontSize' => '68px', 'margin' => ['bottom' => '25px']],
|
||
'tablet' => ['fontSize' => '42px'],
|
||
'mobile' => ['fontSize' => '43px', 'lineHeight' => 1.12, 'margin' => ['bottom' => '21px']],
|
||
], $emGruen),
|
||
$text('hero-intro', 'Gemeinsam lachen, Neues erleben und sich gut aufgehoben fühlen. Wir geben dem Tag Leben – und Angehörigen ein wenig Freiraum.', [
|
||
'desktop' => ['maxWidth' => '465px', 'color' => '@gedaempft', 'fontSize' => '17px', 'lineHeight' => 1.8, 'margin' => ['bottom' => '28px']],
|
||
'mobile' => ['fontSize' => '16px', 'maxWidth' => '520px'],
|
||
]),
|
||
$zeile('hero-aktionen', [
|
||
$column('hero-aktion-knopf', [
|
||
$button('hero-knopf', 'Lernen wir uns kennen', '#kontakt', ['desktop' => ['borderRadius' => $ecken('4px'), 'margin' => ['top' => '0px']]]),
|
||
], ['desktop' => ['flexShrink' => 0]]),
|
||
$column('hero-aktion-link', [
|
||
$text('hero-textlink', '<a href="#bei-uns">Unsere Tagespflege entdecken ↓</a>', [
|
||
'desktop' => ['fontSize' => '14px', 'padding' => ['top' => '15px', 'bottom' => '15px'], 'borderWidth' => $nurUnten('1px'), 'borderStyle' => 'solid', 'borderColor' => '#cad4c8', 'margin' => ['bottom' => '0px']],
|
||
]),
|
||
], ['desktop' => ['flexShrink' => 0]]),
|
||
], '18px', ['alignItems' => 'flex-start', 'flexWrap' => 'wrap'], ['rowGap' => '8px', 'columnGap' => '20px']),
|
||
$text('hero-notiz', "Tagsüber in guter Gesellschaft.\nAbends im vertrauten Zuhause.", [
|
||
'desktop' => ['fontSize' => '14px', 'lineHeight' => 1.6, 'color' => '#737a7a', 'borderWidth' => $nurLinks('3px'), 'borderStyle' => 'solid', 'borderColor' => '@limette', 'padding' => ['left' => '15px'], 'margin' => ['top' => '29px', 'bottom' => '0px']],
|
||
'mobile' => ['margin' => ['top' => '20px', 'bottom' => '0px']],
|
||
]),
|
||
]),
|
||
$column('hero-visual', [
|
||
// Die limettene Form hinter dem Foto – dieselbe Schnittkante wie in der Vorlage.
|
||
$flaeche('hero-form', [
|
||
'desktop' => ['position' => 'absolute', 'top' => '-19px', 'right' => '-17px', 'bottom' => '35px', 'left' => '35px', 'height' => 'auto', 'width' => 'auto', 'backgroundColor' => '@limette', 'zIndex' => 0],
|
||
'mobile' => ['top' => '-14px', 'right' => '-9px', 'bottom' => '28px', 'left' => '30px'],
|
||
], 'clip-path:polygon(18% 0,100% 0,81% 100%,0 100%)'),
|
||
$bild('hero-bild', $medien['gemeinsam'], 'Illustrative Szene: Eine Seniorin und eine Begleiterin lachen gemeinsam an einem Tisch.', [
|
||
'desktop' => ['position' => 'relative', 'zIndex' => 1, 'imageHeight' => '465px', 'objectFit' => 'cover', 'objectPosition' => 'center', 'imageRadius' => ['topLeft' => '110px', 'topRight' => '6px', 'bottomRight' => '6px', 'bottomLeft' => '6px'], 'margin' => $seiten('0px')],
|
||
'tablet' => ['imageHeight' => '390px'],
|
||
'mobile' => ['imageHeight' => '380px', 'imageRadius' => ['topLeft' => '85px', 'topRight' => '6px', 'bottomRight' => '6px', 'bottomLeft' => '6px']],
|
||
], null, '& img{object-position:54% 45%}'),
|
||
$column('hero-karte', [
|
||
$text('hero-karte-label', 'WAS WIR UNS WÜNSCHEN', $klein),
|
||
$text('hero-karte-text', "Dass Sie gerne\n<em>wiederkommen.</em>", [
|
||
'desktop' => [...$serif, 'fontSize' => '30px', 'lineHeight' => 1.15, 'letterSpacing' => '-0.02em', 'margin' => ['top' => '11px', 'bottom' => '15px']],
|
||
'mobile' => ['fontSize' => '27px'],
|
||
], '& em{color:#73933d}'),
|
||
$flaeche('hero-karte-strich', ['desktop' => ['width' => '36px', 'height' => '3px', 'backgroundColor' => '@limette']]),
|
||
], [
|
||
'desktop' => ['position' => 'absolute', 'left' => '-25px', 'bottom' => '-23px', 'zIndex' => 2, 'backgroundColor' => '@papier', 'minWidth' => '245px', 'padding' => ['top' => '22px', 'right' => '28px', 'bottom' => '17px', 'left' => '28px'], 'borderWidth' => $seiten('1px'), 'borderStyle' => 'solid', 'borderColor' => '#edf0e9', 'shadowY' => '8px', 'shadowBlur' => '35px', 'shadowColor' => '#29465513'],
|
||
'tablet' => ['left' => '-12px', 'minWidth' => '190px', 'padding' => ['top' => '18px', 'right' => '22px', 'bottom' => '14px', 'left' => '22px']],
|
||
'mobile' => ['left' => '-12px', 'bottom' => '-25px', 'minWidth' => '190px', 'padding' => ['top' => '20px', 'right' => '25px', 'bottom' => '16px', 'left' => '25px']],
|
||
]),
|
||
$text('hero-caption', 'Gemeinschaft, die guttut.', [
|
||
'desktop' => ['position' => 'absolute', 'right' => '0px', 'bottom' => '-31px', 'fontSize' => '12px', 'color' => '#737b79', 'margin' => ['bottom' => '0px']],
|
||
]),
|
||
], [
|
||
'desktop' => ['position' => 'relative', 'margin' => ['left' => '10px', 'bottom' => '25px']],
|
||
'tablet' => ['margin' => ['left' => '0px', 'bottom' => '25px']],
|
||
'mobile' => ['margin' => ['top' => '0px', 'right' => '6px', 'bottom' => '22px', 'left' => '12px']],
|
||
]),
|
||
], ['desktop' => ['columns' => 'two'], 'mobile' => ['columns' => 'one']], [
|
||
'desktop' => ['gap' => '45px', 'alignItems' => 'center', 'margin' => ['top' => '0px']],
|
||
'tablet' => ['gap' => '25px'],
|
||
'mobile' => ['gap' => '45px'],
|
||
]),
|
||
], [
|
||
'desktop' => ['minHeight' => '650px', 'display' => 'flex', 'alignItems' => 'center', 'padding' => ['top' => '67px', 'bottom' => '75px']],
|
||
'tablet' => ['minHeight' => 'auto', 'padding' => ['top' => '50px', 'bottom' => '75px']],
|
||
'mobile' => ['minHeight' => 'auto', 'padding' => ['top' => '42px', 'bottom' => '57px']],
|
||
], 'start'),
|
||
|
||
// 2 – Das Band mit den drei Versprechen.
|
||
$section('werte', [
|
||
$row('werte-zeile', array_map(
|
||
static fn (string $wert, int $i): array => $column('wert-'.($i + 1), [
|
||
$symbol('wert-'.($i + 1).'-haken', 'check', 16, ['desktop' => ['color' => '#789d3e', 'flexShrink' => 0]]),
|
||
$text('wert-'.($i + 1).'-text', $wert, ['desktop' => ['fontSize' => '15px', 'letterSpacing' => '0.015em', 'margin' => ['bottom' => '0px']], 'mobile' => ['fontSize' => '14px']]),
|
||
], [
|
||
'desktop' => ['display' => 'flex', 'alignItems' => 'center', 'justifyContent' => 'center', 'gap' => '13px']
|
||
+ (0 === $i ? [] : ['borderWidth' => ['top' => '0px', 'right' => '0px', 'bottom' => '0px', 'left' => '1px'], 'borderStyle' => 'solid', 'borderColor' => '#dbe2d6']),
|
||
'mobile' => ['justifyContent' => 'flex-start', 'gap' => '16px', 'borderStyle' => 'none'],
|
||
]),
|
||
$werte, array_keys($werte),
|
||
), ['desktop' => ['columns' => 'three'], 'mobile' => ['columns' => 'one']], [
|
||
'desktop' => ['margin' => ['top' => '0px']],
|
||
'mobile' => ['gap' => '12px'],
|
||
]),
|
||
], [
|
||
'desktop' => ['backgroundColor' => '@sand', 'borderWidth' => ['top' => '1px', 'right' => '0px', 'bottom' => '1px', 'left' => '0px'], 'borderStyle' => 'solid', 'borderColor' => '@linie', 'padding' => ['top' => '22px', 'bottom' => '22px']],
|
||
'mobile' => ['padding' => ['top' => '20px', 'bottom' => '20px']],
|
||
]),
|
||
|
||
// 3 – Willkommen: Überschrift links, Text und Signatur rechts.
|
||
$abschnitt('vorstellung', [
|
||
$row('vorstellung-zeile', [
|
||
$column('vorstellung-titel', [
|
||
$kleinzeile('vorstellung-label', 'Willkommen bei uns'),
|
||
$heading('vorstellung-h2', 'Hier zählt der Mensch.<br><em>Und das Miteinander.</em>', 2, $h2Stil, $emGruen),
|
||
]),
|
||
$column('vorstellung-text', [
|
||
$text('vorstellung-lead', 'Manchmal braucht es nur ein vertrautes Gesicht, ein gutes Gespräch und das Gefühl, dazuzugehören.', [
|
||
'desktop' => ['fontSize' => '20px', 'lineHeight' => 1.7, 'color' => '@tinte', 'margin' => ['bottom' => '20px']],
|
||
'mobile' => ['fontSize' => '18px'],
|
||
]),
|
||
$text('vorstellung-p1', 'Unsere Tagespflege ist ein Ort für ältere Menschen, die ihren Tag in Gesellschaft verbringen möchten. Dabei ist uns wichtig, Raum für persönliche Gewohnheiten zu lassen: für Aktivität ebenso wie für eine ruhige Pause.', $fliess),
|
||
$text('vorstellung-p2', 'Mit Aufmerksamkeit und einem offenen Ohr möchten wir den Alltag unserer Gäste bereichern und ihre Angehörigen entlasten.', $fliess),
|
||
$zeile('vorstellung-signatur', [
|
||
$column('signatur-bild', [
|
||
$bild('signatur-portraet', $medien['portraet'], 'Jacqueline Moldovan', [
|
||
'desktop' => ['maxWidth' => '104px', 'imageHeight' => '104px', 'objectFit' => 'cover', 'objectPosition' => 'top', 'imageRadius' => $ecken('50%'), 'imageBorderWidth' => $seiten('4px'), 'imageBorderStyle' => 'solid', 'imageBorderColor' => '@papier', 'margin' => $seiten('0px')],
|
||
'tablet' => ['maxWidth' => '86px', 'imageHeight' => '86px'],
|
||
'mobile' => ['maxWidth' => '86px', 'imageHeight' => '86px'],
|
||
], null),
|
||
], ['desktop' => ['flexShrink' => 0]]),
|
||
$flaeche('signatur-strich', ['desktop' => ['width' => '28px', 'height' => '2px', 'backgroundColor' => '@gruen', 'flexShrink' => 0], 'tablet' => ['width' => '20px']]),
|
||
$column('signatur-name', [
|
||
$text('signatur-person', '<strong>Jacqueline Moldovan</strong>', ['desktop' => ['fontSize' => '15px', 'fontWeight' => '600', 'color' => '#2e6682', 'margin' => ['bottom' => '0px']]]),
|
||
$text('signatur-rolle', 'Geschäftsführerin', ['desktop' => ['fontSize' => '13px', 'color' => '@gedaempft', 'margin' => ['top' => '4px', 'bottom' => '0px']]]),
|
||
]),
|
||
], '18px', ['flexWrap' => 'wrap', 'margin' => ['top' => '29px']], ['gap' => '14px']),
|
||
]),
|
||
], ['desktop' => ['columns' => 'two'], 'mobile' => ['columns' => 'one']], [
|
||
'desktop' => ['gap' => '80px', 'margin' => ['top' => '0px']],
|
||
'tablet' => ['gap' => '50px'],
|
||
'mobile' => ['gap' => '28px'],
|
||
]),
|
||
], [], 'bei-uns'),
|
||
|
||
// 4 – Unser Angebot: drei Karten auf blasser Fläche.
|
||
$abschnitt('angebot-abschnitt', [
|
||
$zeile('angebot-kopf', [
|
||
$column('angebot-kopf-titel', [
|
||
$kleinzeile('angebot-label', 'Raum für einen guten Tag'),
|
||
$heading('angebot-h2', 'Was den Alltag<br><em>schöner macht.</em>', 2, $h2Stil, $emGruen),
|
||
]),
|
||
$column('angebot-kopf-text', [
|
||
$text('angebot-intro', "Die kleinen Dinge machen den Unterschied.\nUnd Menschen, die sich Zeit nehmen.", [
|
||
'desktop' => ['fontSize' => '15px', 'color' => '@gedaempft', 'margin' => ['bottom' => '5px']],
|
||
'tablet' => ['maxWidth' => '260px'],
|
||
'mobile' => ['margin' => ['top' => '23px', 'bottom' => '0px']],
|
||
]),
|
||
]),
|
||
], '35px', ['alignItems' => 'flex-end', 'justifyContent' => 'space-between', 'margin' => ['top' => '0px', 'bottom' => '46px']], ['flexDirection' => 'column', 'alignItems' => 'flex-start', 'gap' => '0px', 'margin' => ['top' => '0px', 'bottom' => '30px']]),
|
||
$row('angebot-raster', array_map(
|
||
static function (array $a, int $i) use ($column, $text, $symbol, $heading, $h3Stil, $seiten, $ecken): array {
|
||
$n = $i + 1;
|
||
|
||
return $column('angebot-'.$n, [
|
||
$text('angebot-'.$n.'-nummer', $a[0], ['desktop' => ['fontSize' => '11px', 'fontWeight' => '600', 'letterSpacing' => '0.14em', 'color' => '#788574', 'margin' => ['bottom' => '0px']]]),
|
||
$symbol('angebot-'.$n.'-symbol', $a[1], 32, [
|
||
'desktop' => ['width' => '55px', 'height' => '55px', 'display' => 'flex', 'alignItems' => 'center', 'justifyContent' => 'center', 'borderRadius' => $ecken('50%'), 'backgroundColor' => $a[3], 'color' => $a[4], 'margin' => ['top' => '31px', 'bottom' => '23px']],
|
||
'mobile' => ['width' => '48px', 'height' => '48px'],
|
||
]),
|
||
$heading('angebot-'.$n.'-titel', $a[5], 3, $h3Stil),
|
||
$text('angebot-'.$n.'-text', $a[6], ['desktop' => ['fontSize' => '15px', 'color' => '@gedaempft', 'lineHeight' => 1.8, 'margin' => ['bottom' => '0px']]]),
|
||
], [
|
||
'desktop' => ['backgroundColor' => '@papier', 'borderWidth' => ['top' => '3px', 'right' => '0px', 'bottom' => '0px', 'left' => '0px'], 'borderStyle' => 'solid', 'borderColor' => $a[2], 'padding' => ['top' => '30px', 'right' => '29px', 'bottom' => '28px', 'left' => '29px']],
|
||
'tablet' => ['padding' => ['top' => '23px', 'right' => '19px', 'bottom' => '23px', 'left' => '19px']],
|
||
'mobile' => ['padding' => ['top' => '25px', 'right' => '27px', 'bottom' => '25px', 'left' => '27px']],
|
||
]);
|
||
},
|
||
$angebote, array_keys($angebote),
|
||
), ['desktop' => ['columns' => 'three'], 'mobile' => ['columns' => 'one']], [
|
||
'desktop' => ['gap' => '25px', 'margin' => ['top' => '0px']],
|
||
'tablet' => ['gap' => '15px'],
|
||
'mobile' => ['gap' => '17px'],
|
||
]),
|
||
], ['desktop' => ['backgroundColor' => '@blass']], 'angebot'),
|
||
|
||
// 5 – Ein Tag bei uns: Einleitung links, die Zeitleiste rechts.
|
||
$abschnitt('tagesablauf-abschnitt', [
|
||
$row('tag-zeile', [
|
||
$column('tag-intro', [
|
||
$kleinzeile('tag-label', 'Ein Tag bei uns'),
|
||
$heading('tag-h2', 'Ein guter Rhythmus.<br><em>Ganz ohne Eile.</em>', 2, $h2Stil, $emGruen),
|
||
$text('tag-intro-text', 'So könnte ein gemeinsamer Tag aussehen. Mit vertrauten Ritualen, neuen Impulsen und Zeit für das, was Ihnen Freude macht.', [
|
||
'desktop' => ['maxWidth' => '375px', 'color' => '@gedaempft', 'margin' => ['top' => '27px', 'bottom' => '0px']],
|
||
'mobile' => ['maxWidth' => '100%'],
|
||
]),
|
||
$bild('tag-marke', $medien['marke'], '', [
|
||
'desktop' => ['maxWidth' => '110px', 'opacity' => 0.65, 'margin' => ['top' => '36px']],
|
||
]) + ['layout' => ['visibility' => 'hide-mobile']],
|
||
]),
|
||
$column('tag-liste', array_map(
|
||
static function (array $s, int $i) use ($zeile, $column, $text, $heading, $flaeche, $klein, $h3Stil, $ecken, $seiten, $tagesablauf): array {
|
||
$n = $i + 1;
|
||
$letzte = $n === count($tagesablauf);
|
||
$links = [
|
||
$text('tag-'.$n.'-zahl', $s[0], ['desktop' => [
|
||
'width' => '42px', 'height' => '42px', 'flexShrink' => 0, 'display' => 'flex', 'alignItems' => 'center', 'justifyContent' => 'center',
|
||
'backgroundColor' => '#f2f6e9', 'borderWidth' => $seiten('1px'), 'borderStyle' => 'solid', 'borderColor' => '#dbe7cc', 'borderRadius' => $ecken('50%'),
|
||
'fontSize' => '12px', 'color' => '#72943d', 'margin' => ['bottom' => '0px'],
|
||
]]),
|
||
];
|
||
if (!$letzte) {
|
||
$links[] = $flaeche('tag-'.$n.'-linie', ['desktop' => ['width' => '1px', 'height' => 'auto', 'flexGrow' => 1, 'backgroundColor' => '#dbe3d4']]);
|
||
}
|
||
|
||
return $zeile('tag-schritt-'.$n, [
|
||
$column('tag-'.$n.'-spur', $links, ['desktop' => ['width' => '43px', 'flexShrink' => 0, 'display' => 'flex', 'flexDirection' => 'column', 'alignItems' => 'center']]),
|
||
$column('tag-'.$n.'-inhalt', [
|
||
$text('tag-'.$n.'-label', $s[1], $klein),
|
||
$heading('tag-'.$n.'-titel', $s[2], 3, ['desktop' => [...$h3Stil['desktop'], 'margin' => ['top' => '7px', 'bottom' => '9px']]]),
|
||
$text('tag-'.$n.'-text', $s[3], ['desktop' => ['fontSize' => '15px', 'color' => '@gedaempft', 'lineHeight' => 1.75, 'margin' => ['bottom' => '0px']]]),
|
||
]),
|
||
], '24px', ['alignItems' => 'stretch', 'padding' => ['bottom' => $letzte ? '0px' : '34px']], ['gap' => '19px']);
|
||
},
|
||
$tagesablauf, array_keys($tagesablauf),
|
||
)),
|
||
], ['desktop' => ['columns' => 'two'], 'mobile' => ['columns' => 'one']], [
|
||
'desktop' => ['gap' => '90px', 'margin' => ['top' => '0px']],
|
||
'tablet' => ['gap' => '50px'],
|
||
'mobile' => ['gap' => '28px'],
|
||
]),
|
||
], [], 'tagesablauf'),
|
||
|
||
// 6 – Kontakt: dunkelblaue Fläche, rechts die weiße Formularkarte.
|
||
$section('kontakt-abschnitt', [
|
||
// Die schräge hellere Fläche am rechten Rand, mit dem limettenen Streifen davor.
|
||
$flaeche('kontakt-form', [
|
||
'desktop' => ['position' => 'absolute', 'top' => '0px', 'bottom' => '0px', 'right' => '-80px', 'width' => '180px', 'height' => 'auto', 'backgroundColor' => '#315d71', 'borderWidth' => $nurLinks('12px'), 'borderStyle' => 'solid', 'borderColor' => '#a1bb59', 'zIndex' => 0],
|
||
'mobile' => ['right' => '-150px'],
|
||
], 'transform:skewX(-16deg);pointer-events:none'),
|
||
$row('kontakt-zeile', [
|
||
$column('kontakt-text', [
|
||
$kleinzeile('kontakt-label', 'Der erste Schritt ist ein Gespräch', '#c4d998', '@limette', '22px'),
|
||
$heading('kontakt-h2', 'Ein gutes Gefühl<br>beginnt mit einem<br><em>persönlichen Hallo.</em>', 2, [
|
||
'desktop' => [...$serif, 'fontSize' => '59px', 'color' => '@papier', 'margin' => ['bottom' => '24px']],
|
||
'tablet' => ['fontSize' => '45px'],
|
||
'mobile' => ['fontSize' => '43px'],
|
||
], '& em{color:#c1d786;font-weight:400}'),
|
||
$text('kontakt-intro', 'Sie möchten unsere Tagespflege kennenlernen oder haben Fragen? Erzählen Sie uns, was Ihnen wichtig ist. Wir freuen uns auf Sie.', [
|
||
'desktop' => ['maxWidth' => '430px', 'color' => '#d5e0e4', 'fontSize' => '15px', 'lineHeight' => 1.8, 'margin' => ['bottom' => '28px']],
|
||
]),
|
||
// Ein Telefonlink, kein Button-Baustein: Buttons verweisen auf Seiten, nicht auf tel:.
|
||
$text('kontakt-anrufen', '<a href="'.$telHref.'">Rufen Sie uns an ↗</a>', ['desktop' => ['margin' => ['bottom' => '0px']]],
|
||
"& a{display:inline-flex;align-items:center;gap:25px;background:#c3d886;color:#27434a;border-radius:4px;padding:15px 22px;font-size:15px;font-weight:600;transition:background .2s,transform .2s}\n& a:hover{background:#d1e3a5;transform:translateY(-2px)}"),
|
||
['id' => 'kontakt-daten', 'type' => 'contact',
|
||
'props' => ['phone' => $telefon, 'email' => $mail, 'address' => "Fremersbergstraße 75\n76530 Baden-Baden"],
|
||
'style' => ['desktop' => ['fontSize' => '15px', 'color' => '#dce7eb', 'gap' => '10px', 'borderWidth' => $nurOben('1px'), 'borderStyle' => 'solid', 'borderColor' => '#ffffff30', 'padding' => ['top' => '26px'], 'margin' => ['top' => '30px']]],
|
||
// Die Vorlage führt die Angaben ohne Symbole; die Adresse behält ihren Umbruch.
|
||
'css' => "& svg{display:none}\n& span{display:block}\n& a{overflow-wrap:anywhere}\n& a:hover{text-decoration:underline}\n& span:first-child a{font-size:22px;color:#ffffff;letter-spacing:-0.025em}\n& span:last-child{white-space:pre-line;line-height:1.65;margin-top:5px}",
|
||
],
|
||
], ['desktop' => ['alignSelf' => 'center']]),
|
||
$column('kontakt-karte', [
|
||
$text('kontakt-karte-label', 'WIR FREUEN UNS AUF IHRE NACHRICHT', ['desktop' => [...$klein['desktop'], 'margin' => ['bottom' => '18px']]]),
|
||
$heading('kontakt-karte-titel', 'Was können wir<br>für Sie tun?', 3, [
|
||
'desktop' => ['fontFamily' => 'heading', 'fontWeight' => '400', 'fontSize' => '30px', 'lineHeight' => 1.25, 'letterSpacing' => '-0.02em', 'margin' => ['bottom' => '25px']],
|
||
]),
|
||
['id' => 'kontakt-formular', 'type' => 'form', 'props' => ['form' => 'kontakt'],
|
||
// Felder und Knopf im Zuschnitt der Vorlage; der Wortlaut des Knopfes kommt vom Baustein.
|
||
'css' => "& .form-field label{font-size:14px;font-weight:600;color:#294655}
|
||
& .form-field input{background:#fafcf8;border:1px solid #cfd9ce;border-radius:4px;padding:12px 13px;font-size:16px;color:#294655}
|
||
& .form-field textarea{background:#fafcf8;border:1px solid #cfd9ce;border-radius:4px;padding:12px 13px;font-size:16px;color:#294655;min-height:120px}
|
||
& .field-note{font-size:12px;color:#748078}
|
||
& .cms-button{width:100%;justify-content:center;border-radius:4px;margin-top:4px}",
|
||
],
|
||
$text('kontakt-formular-hinweis', 'Ihre Nachricht geht direkt an die Tagespflege. Wir verwenden Ihre Angaben ausschließlich, um Ihre Anfrage zu beantworten.', [
|
||
'desktop' => ['fontSize' => '13px', 'lineHeight' => 1.65, 'color' => '#64736b', 'margin' => ['top' => '19px', 'bottom' => '0px']],
|
||
]),
|
||
], [
|
||
'desktop' => ['alignSelf' => 'center', 'backgroundColor' => '@papier', 'color' => '@tinte', 'borderRadius' => $ecken('3px'), 'borderWidth' => $nurOben('4px'), 'borderStyle' => 'solid', 'borderColor' => '#bdd26f', 'padding' => ['top' => '32px', 'right' => '35px', 'bottom' => '32px', 'left' => '35px']],
|
||
'tablet' => ['padding' => ['top' => '28px', 'right' => '25px', 'bottom' => '28px', 'left' => '25px']],
|
||
'mobile' => ['padding' => ['top' => '28px', 'right' => '25px', 'bottom' => '28px', 'left' => '25px']],
|
||
]),
|
||
], ['desktop' => ['columns' => 'two'], 'mobile' => ['columns' => 'one']], [
|
||
'desktop' => ['gap' => '100px', 'position' => 'relative', 'zIndex' => 1, 'margin' => ['top' => '0px']],
|
||
'tablet' => ['gap' => '35px'],
|
||
'mobile' => ['gap' => '35px'],
|
||
]),
|
||
], [
|
||
'desktop' => ['backgroundColor' => '@dunkelblau', 'color' => '@papier', 'position' => 'relative', 'overflow' => 'hidden', 'padding' => ['top' => '83px', 'bottom' => '83px']],
|
||
'mobile' => ['padding' => ['top' => '60px', 'bottom' => '60px']],
|
||
], 'kontakt'),
|
||
],
|
||
];
|
||
|
||
// ---------------------------------------------------------------------------------------------
|
||
// Seiten anlegen und veröffentlichen
|
||
// ---------------------------------------------------------------------------------------------
|
||
|
||
$erstellt = [];
|
||
$anlegen = static function (string $slug, array $dokument, string $seoTitel = '', string $teilbild = '') use ($pages, $db, &$erstellt): string {
|
||
$id = $pages->createPage($slug, null, 'page', $dokument);
|
||
if ('' !== $seoTitel) {
|
||
$db->executeStatement('UPDATE page SET seo_title = ? WHERE id = ?', [$seoTitel, $id]);
|
||
}
|
||
if ('' !== $teilbild) {
|
||
$db->executeStatement('UPDATE page SET og_media_id = ? WHERE id = ?', [$teilbild, $id]);
|
||
}
|
||
$seite = $db->fetchAssociative('SELECT draft_revision_id, version FROM page WHERE id = ?', [$id]);
|
||
$pages->publish($id, $seite['draft_revision_id'], (int) $seite['version']);
|
||
$erstellt[$slug] = $id;
|
||
echo 'Seite angelegt: /'.$db->fetchOne('SELECT path FROM page WHERE id = ?', [$id])."\n";
|
||
|
||
return $id;
|
||
};
|
||
|
||
$anlegen('home', $startseite, 'Tagespflege Moldovan · Gemeinsam den Tag genießen', $medien['gemeinsam']['id']);
|
||
|
||
$fehlerId = $anlegen('404', [
|
||
'schemaVersion' => $SCHEMA, 'title' => 'Seite nicht gefunden',
|
||
'description' => 'Die gesuchte Seite gibt es nicht oder sie wurde verschoben.',
|
||
'blocks' => [
|
||
$abschnitt('fehler', [
|
||
$kleinzeile('fehler-label', 'Fehler 404'),
|
||
$heading('fehler-titel', 'Diese Seite<br><em>haben wir nicht.</em>', 1, [
|
||
'desktop' => [...$serif, 'fontSize' => '59px', 'margin' => ['bottom' => '25px']],
|
||
'mobile' => ['fontSize' => '40px'],
|
||
], $emGruen),
|
||
$text('fehler-text', 'Vielleicht hat sich ein Tippfehler in die Adresse geschlichen. Über die Startseite finden Sie zurück.', [
|
||
'desktop' => ['maxWidth' => '465px', 'color' => '@gedaempft', 'fontSize' => '17px', 'lineHeight' => 1.8, 'margin' => ['bottom' => '28px']],
|
||
]),
|
||
$button('fehler-knopf', 'Zur Startseite', '/', ['desktop' => ['borderRadius' => $ecken('4px'), 'margin' => ['top' => '0px']]]),
|
||
], ['desktop' => ['padding' => ['top' => '120px', 'bottom' => '140px']]]),
|
||
],
|
||
]);
|
||
$db->executeStatement('UPDATE page SET robots = ? WHERE id = ?', ['noindex', $fehlerId]);
|
||
|
||
// ---------------------------------------------------------------------------------------------
|
||
// Menü, Einstellungen, Konto
|
||
// ---------------------------------------------------------------------------------------------
|
||
|
||
$sprung = static fn (string $label, string $anchor): array => ['label' => $label, 'type' => 'page', 'pageId' => $erstellt['home'], 'anchor' => $anchor, 'children' => []];
|
||
|
||
$menus->save('header', 'Hauptnavigation', [
|
||
$sprung('Bei uns', 'bei-uns'),
|
||
$sprung('Unser Angebot', 'angebot'),
|
||
$sprung('Ein Tag bei uns', 'tagesablauf'),
|
||
$sprung('Kontakt aufnehmen ↗', 'kontakt'),
|
||
], 0);
|
||
echo "Menü angelegt\n";
|
||
|
||
$settings->assignNotFoundPage($fehlerId, '');
|
||
$settings->save([
|
||
'legalName' => 'Tagespflege Jacqueline Moldovan',
|
||
'description' => 'Tagespflege in Baden-Baden: ein Ort für ältere Menschen, die ihren Tag in Gesellschaft verbringen möchten. Persönliche Begleitung, gemeinsame Aktivitäten und Zeit für Ruhe – abends wieder im vertrauten Zuhause.',
|
||
'phone' => $telefon, 'email' => $mail,
|
||
'street' => 'Fremersbergstraße 75', 'postalCode' => '76530', 'city' => 'Baden-Baden', 'country' => 'DE',
|
||
'localBusiness' => true, 'llmsTxt' => true,
|
||
'stickyHeader' => true, 'headerOverlay' => false,
|
||
'motion' => 'always',
|
||
'faviconMediaId' => $medien['marke']['id'],
|
||
'homePath' => 'home',
|
||
'consentBanner' => false, 'scrollTop' => false, 'postMetaHeader' => true,
|
||
]);
|
||
echo "Einstellungen gespeichert\n";
|
||
|
||
$passwort = bin2hex(random_bytes(12));
|
||
$db->insert('cms_user', ['id' => bin2hex(random_bytes(16)), 'username' => 'umut', 'password_hash' => password_hash($passwort, PASSWORD_BCRYPT), 'roles' => '["ROLE_ADMIN"]']);
|
||
|
||
echo "\nFertig.\nVerwaltung: Benutzer „umut“, Passwort: $passwort\n";
|