Web-Frontend: Umbau Spokes/Hub, Kontakt-Widget (contact-launcher)
Startseiten/Feeds/Kategorie/Rechtsseiten ueberarbeitet, Kontakt-Modal durch schwebendes contact-launcher-Widget ersetzt, legal-language-notice ergaenzt; Platzhalter-SVGs + Theme-CSS angepasst. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
@ -4,13 +4,13 @@
|
|||
<stop offset="0" stop-color="#1a2540"/>
|
||||
<stop offset="1" stop-color="#2e3d66"/>
|
||||
</linearGradient>
|
||||
<pattern id="waves" width="260" height="120" patternUnits="userSpaceOnUse">
|
||||
<path d="M-20 70C30 30 80 30 130 70S230 110 280 70" fill="none" stroke="#ffffff" stroke-opacity="0.10" stroke-width="4"/>
|
||||
<path d="M-20 110C30 70 80 70 130 110S230 150 280 110" fill="none" stroke="#ffffff" stroke-opacity="0.06" stroke-width="3"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect width="1600" height="900" fill="url(#waves)"/>
|
||||
<circle cx="1270" cy="260" r="220" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="360" cy="690" r="180" fill="#ffffff" fill-opacity="0.055"/>
|
||||
<path d="M0 470C133 400 267 400 400 470S667 540 800 470 1067 400 1200 470 1467 540 1600 470" fill="none" stroke="#ffffff" stroke-opacity="0.11" stroke-width="4"/>
|
||||
<path d="M0 550C133 480 267 480 400 550S667 620 800 550 1067 480 1200 550 1467 620 1600 550" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3.5"/>
|
||||
<path d="M0 630C133 560 267 560 400 630S667 700 800 630 1067 560 1200 630 1467 700 1600 630" fill="none" stroke="#ffffff" stroke-opacity="0.07" stroke-width="3"/>
|
||||
<path d="M0 710C133 640 267 640 400 710S667 780 800 710 1067 640 1200 710 1467 780 1600 710" fill="none" stroke="#ffffff" stroke-opacity="0.055" stroke-width="3"/>
|
||||
<path d="M0 790C133 720 267 720 400 790S667 860 800 790 1067 720 1200 790 1467 860 1600 790" fill="none" stroke="#ffffff" stroke-opacity="0.04" stroke-width="2.5"/>
|
||||
<circle cx="1270" cy="250" r="220" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="340" cy="220" r="140" fill="#ffffff" fill-opacity="0.045"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 932 B After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,13 +4,13 @@
|
|||
<stop offset="0" stop-color="#1f2e22"/>
|
||||
<stop offset="1" stop-color="#3a5a3a"/>
|
||||
</linearGradient>
|
||||
<pattern id="waves" width="260" height="120" patternUnits="userSpaceOnUse">
|
||||
<path d="M-20 70C30 30 80 30 130 70S230 110 280 70" fill="none" stroke="#ffffff" stroke-opacity="0.10" stroke-width="4"/>
|
||||
<path d="M-20 110C30 70 80 70 130 110S230 150 280 110" fill="none" stroke="#ffffff" stroke-opacity="0.06" stroke-width="3"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect width="1600" height="900" fill="url(#waves)"/>
|
||||
<circle cx="1270" cy="260" r="220" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="360" cy="690" r="180" fill="#ffffff" fill-opacity="0.055"/>
|
||||
<path d="M0 470C133 400 267 400 400 470S667 540 800 470 1067 400 1200 470 1467 540 1600 470" fill="none" stroke="#ffffff" stroke-opacity="0.11" stroke-width="4"/>
|
||||
<path d="M0 550C133 480 267 480 400 550S667 620 800 550 1067 480 1200 550 1467 620 1600 550" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3.5"/>
|
||||
<path d="M0 630C133 560 267 560 400 630S667 700 800 630 1067 560 1200 630 1467 700 1600 630" fill="none" stroke="#ffffff" stroke-opacity="0.07" stroke-width="3"/>
|
||||
<path d="M0 710C133 640 267 640 400 710S667 780 800 710 1067 640 1200 710 1467 780 1600 710" fill="none" stroke="#ffffff" stroke-opacity="0.055" stroke-width="3"/>
|
||||
<path d="M0 790C133 720 267 720 400 790S667 860 800 790 1067 720 1200 790 1467 860 1600 790" fill="none" stroke="#ffffff" stroke-opacity="0.04" stroke-width="2.5"/>
|
||||
<circle cx="1270" cy="250" r="220" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="340" cy="220" r="140" fill="#ffffff" fill-opacity="0.045"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 932 B After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,13 +4,13 @@
|
|||
<stop offset="0" stop-color="#2e2117"/>
|
||||
<stop offset="1" stop-color="#8a5e27"/>
|
||||
</linearGradient>
|
||||
<pattern id="waves" width="260" height="120" patternUnits="userSpaceOnUse">
|
||||
<path d="M-20 70C30 30 80 30 130 70S230 110 280 70" fill="none" stroke="#ffffff" stroke-opacity="0.10" stroke-width="4"/>
|
||||
<path d="M-20 110C30 70 80 70 130 110S230 150 280 110" fill="none" stroke="#ffffff" stroke-opacity="0.06" stroke-width="3"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect width="1600" height="900" fill="url(#waves)"/>
|
||||
<circle cx="1270" cy="260" r="220" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="360" cy="690" r="180" fill="#ffffff" fill-opacity="0.055"/>
|
||||
<path d="M0 470C133 400 267 400 400 470S667 540 800 470 1067 400 1200 470 1467 540 1600 470" fill="none" stroke="#ffffff" stroke-opacity="0.11" stroke-width="4"/>
|
||||
<path d="M0 550C133 480 267 480 400 550S667 620 800 550 1067 480 1200 550 1467 620 1600 550" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3.5"/>
|
||||
<path d="M0 630C133 560 267 560 400 630S667 700 800 630 1067 560 1200 630 1467 700 1600 630" fill="none" stroke="#ffffff" stroke-opacity="0.07" stroke-width="3"/>
|
||||
<path d="M0 710C133 640 267 640 400 710S667 780 800 710 1067 640 1200 710 1467 780 1600 710" fill="none" stroke="#ffffff" stroke-opacity="0.055" stroke-width="3"/>
|
||||
<path d="M0 790C133 720 267 720 400 790S667 860 800 790 1067 720 1200 790 1467 860 1600 790" fill="none" stroke="#ffffff" stroke-opacity="0.04" stroke-width="2.5"/>
|
||||
<circle cx="1270" cy="250" r="220" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="340" cy="220" r="140" fill="#ffffff" fill-opacity="0.045"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 932 B After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,14 +4,18 @@
|
|||
<stop offset="0" stop-color="#1a2540"/>
|
||||
<stop offset="1" stop-color="#2e3d66"/>
|
||||
</linearGradient>
|
||||
<pattern id="rules" width="1600" height="56" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="55" x2="1600" y2="55" stroke="#ffffff" stroke-opacity="0.04" stroke-width="1"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect x="170" y="190" width="520" height="42" rx="10" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<rect x="170" y="282" width="820" height="22" rx="8" fill="#ffffff" fill-opacity="0.08"/>
|
||||
<rect x="170" y="334" width="690" height="22" rx="8" fill="#ffffff" fill-opacity="0.07"/>
|
||||
<rect x="170" y="386" width="760" height="22" rx="8" fill="#ffffff" fill-opacity="0.06"/>
|
||||
<rect x="1030" y="250" width="330" height="240" rx="20" fill="#ffffff" fill-opacity="0.055"/>
|
||||
<path d="M1100 430L1190 340L1260 400L1305 355L1360 430H1100Z" fill="#ffffff" fill-opacity="0.10"/>
|
||||
<circle cx="1290" cy="315" r="28" fill="#ffffff" fill-opacity="0.11"/>
|
||||
<circle cx="1280" cy="700" r="180" fill="#ffffff" fill-opacity="0.04"/>
|
||||
<rect width="1600" height="900" fill="url(#rules)"/>
|
||||
<rect x="440" y="270" width="96" height="10" rx="5" fill="#ffffff" fill-opacity="0.14"/>
|
||||
<rect x="440" y="320" width="620" height="40" rx="10" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<rect x="440" y="384" width="480" height="40" rx="10" fill="#ffffff" fill-opacity="0.10"/>
|
||||
<rect x="440" y="472" width="720" height="18" rx="9" fill="#ffffff" fill-opacity="0.07"/>
|
||||
<rect x="440" y="516" width="660" height="18" rx="9" fill="#ffffff" fill-opacity="0.06"/>
|
||||
<rect x="440" y="560" width="540" height="18" rx="9" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="1280" cy="240" r="200" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="300" cy="700" r="150" fill="#ffffff" fill-opacity="0.055"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,14 +4,18 @@
|
|||
<stop offset="0" stop-color="#1f2e22"/>
|
||||
<stop offset="1" stop-color="#3a5a3a"/>
|
||||
</linearGradient>
|
||||
<pattern id="rules" width="1600" height="56" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="55" x2="1600" y2="55" stroke="#ffffff" stroke-opacity="0.04" stroke-width="1"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect x="170" y="190" width="520" height="42" rx="10" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<rect x="170" y="282" width="820" height="22" rx="8" fill="#ffffff" fill-opacity="0.08"/>
|
||||
<rect x="170" y="334" width="690" height="22" rx="8" fill="#ffffff" fill-opacity="0.07"/>
|
||||
<rect x="170" y="386" width="760" height="22" rx="8" fill="#ffffff" fill-opacity="0.06"/>
|
||||
<rect x="1030" y="250" width="330" height="240" rx="20" fill="#ffffff" fill-opacity="0.055"/>
|
||||
<path d="M1100 430L1190 340L1260 400L1305 355L1360 430H1100Z" fill="#ffffff" fill-opacity="0.10"/>
|
||||
<circle cx="1290" cy="315" r="28" fill="#ffffff" fill-opacity="0.11"/>
|
||||
<circle cx="1280" cy="700" r="180" fill="#ffffff" fill-opacity="0.04"/>
|
||||
<rect width="1600" height="900" fill="url(#rules)"/>
|
||||
<rect x="440" y="270" width="96" height="10" rx="5" fill="#ffffff" fill-opacity="0.14"/>
|
||||
<rect x="440" y="320" width="620" height="40" rx="10" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<rect x="440" y="384" width="480" height="40" rx="10" fill="#ffffff" fill-opacity="0.10"/>
|
||||
<rect x="440" y="472" width="720" height="18" rx="9" fill="#ffffff" fill-opacity="0.07"/>
|
||||
<rect x="440" y="516" width="660" height="18" rx="9" fill="#ffffff" fill-opacity="0.06"/>
|
||||
<rect x="440" y="560" width="540" height="18" rx="9" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="1280" cy="240" r="200" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="300" cy="700" r="150" fill="#ffffff" fill-opacity="0.055"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,14 +4,18 @@
|
|||
<stop offset="0" stop-color="#2e2117"/>
|
||||
<stop offset="1" stop-color="#8a5e27"/>
|
||||
</linearGradient>
|
||||
<pattern id="rules" width="1600" height="56" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="55" x2="1600" y2="55" stroke="#ffffff" stroke-opacity="0.04" stroke-width="1"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect x="170" y="190" width="520" height="42" rx="10" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<rect x="170" y="282" width="820" height="22" rx="8" fill="#ffffff" fill-opacity="0.08"/>
|
||||
<rect x="170" y="334" width="690" height="22" rx="8" fill="#ffffff" fill-opacity="0.07"/>
|
||||
<rect x="170" y="386" width="760" height="22" rx="8" fill="#ffffff" fill-opacity="0.06"/>
|
||||
<rect x="1030" y="250" width="330" height="240" rx="20" fill="#ffffff" fill-opacity="0.055"/>
|
||||
<path d="M1100 430L1190 340L1260 400L1305 355L1360 430H1100Z" fill="#ffffff" fill-opacity="0.10"/>
|
||||
<circle cx="1290" cy="315" r="28" fill="#ffffff" fill-opacity="0.11"/>
|
||||
<circle cx="1280" cy="700" r="180" fill="#ffffff" fill-opacity="0.04"/>
|
||||
<rect width="1600" height="900" fill="url(#rules)"/>
|
||||
<rect x="440" y="270" width="96" height="10" rx="5" fill="#ffffff" fill-opacity="0.14"/>
|
||||
<rect x="440" y="320" width="620" height="40" rx="10" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<rect x="440" y="384" width="480" height="40" rx="10" fill="#ffffff" fill-opacity="0.10"/>
|
||||
<rect x="440" y="472" width="720" height="18" rx="9" fill="#ffffff" fill-opacity="0.07"/>
|
||||
<rect x="440" y="516" width="660" height="18" rx="9" fill="#ffffff" fill-opacity="0.06"/>
|
||||
<rect x="440" y="560" width="540" height="18" rx="9" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="1280" cy="240" r="200" fill="#ffffff" fill-opacity="0.05"/>
|
||||
<circle cx="300" cy="700" r="150" fill="#ffffff" fill-opacity="0.055"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,13 +4,15 @@
|
|||
<stop offset="0" stop-color="#1a2540"/>
|
||||
<stop offset="1" stop-color="#2e3d66"/>
|
||||
</linearGradient>
|
||||
<pattern id="rings" width="180" height="180" patternUnits="userSpaceOnUse">
|
||||
<circle cx="90" cy="90" r="38" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3"/>
|
||||
<circle cx="90" cy="90" r="4" fill="#ffffff" fill-opacity="0.13"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect width="1600" height="900" fill="url(#rings)"/>
|
||||
<path d="M260 680C510 540 710 560 960 410C1140 302 1260 260 1410 288" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="8" stroke-linecap="round"/>
|
||||
<circle cx="960" cy="410" r="100" fill="#ffffff" fill-opacity="0.045"/>
|
||||
<circle cx="1150" cy="450" r="90" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="3"/>
|
||||
<circle cx="1150" cy="450" r="180" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="2.5"/>
|
||||
<circle cx="1150" cy="450" r="280" fill="none" stroke="#ffffff" stroke-opacity="0.065" stroke-width="2"/>
|
||||
<circle cx="1150" cy="450" r="390" fill="none" stroke="#ffffff" stroke-opacity="0.045" stroke-width="2"/>
|
||||
<circle cx="1150" cy="450" r="510" fill="none" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1.5"/>
|
||||
<circle cx="1150" cy="450" r="10" fill="#ffffff" fill-opacity="0.16"/>
|
||||
<circle cx="330" cy="450" r="5" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<line x1="345" y1="450" x2="1130" y2="450" stroke="#ffffff" stroke-opacity="0.08" stroke-width="2" stroke-dasharray="2 14" stroke-linecap="round"/>
|
||||
<circle cx="320" cy="210" r="130" fill="#ffffff" fill-opacity="0.045"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 944 B After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,13 +4,15 @@
|
|||
<stop offset="0" stop-color="#1f2e22"/>
|
||||
<stop offset="1" stop-color="#3a5a3a"/>
|
||||
</linearGradient>
|
||||
<pattern id="rings" width="180" height="180" patternUnits="userSpaceOnUse">
|
||||
<circle cx="90" cy="90" r="38" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3"/>
|
||||
<circle cx="90" cy="90" r="4" fill="#ffffff" fill-opacity="0.13"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect width="1600" height="900" fill="url(#rings)"/>
|
||||
<path d="M260 680C510 540 710 560 960 410C1140 302 1260 260 1410 288" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="8" stroke-linecap="round"/>
|
||||
<circle cx="960" cy="410" r="100" fill="#ffffff" fill-opacity="0.045"/>
|
||||
<circle cx="1150" cy="450" r="90" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="3"/>
|
||||
<circle cx="1150" cy="450" r="180" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="2.5"/>
|
||||
<circle cx="1150" cy="450" r="280" fill="none" stroke="#ffffff" stroke-opacity="0.065" stroke-width="2"/>
|
||||
<circle cx="1150" cy="450" r="390" fill="none" stroke="#ffffff" stroke-opacity="0.045" stroke-width="2"/>
|
||||
<circle cx="1150" cy="450" r="510" fill="none" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1.5"/>
|
||||
<circle cx="1150" cy="450" r="10" fill="#ffffff" fill-opacity="0.16"/>
|
||||
<circle cx="330" cy="450" r="5" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<line x1="345" y1="450" x2="1130" y2="450" stroke="#ffffff" stroke-opacity="0.08" stroke-width="2" stroke-dasharray="2 14" stroke-linecap="round"/>
|
||||
<circle cx="320" cy="210" r="130" fill="#ffffff" fill-opacity="0.045"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 944 B After Width: | Height: | Size: 1.3 KiB |
|
|
@ -4,13 +4,15 @@
|
|||
<stop offset="0" stop-color="#2e2117"/>
|
||||
<stop offset="1" stop-color="#8a5e27"/>
|
||||
</linearGradient>
|
||||
<pattern id="rings" width="180" height="180" patternUnits="userSpaceOnUse">
|
||||
<circle cx="90" cy="90" r="38" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3"/>
|
||||
<circle cx="90" cy="90" r="4" fill="#ffffff" fill-opacity="0.13"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="900" fill="url(#bg)"/>
|
||||
<rect width="1600" height="900" fill="url(#rings)"/>
|
||||
<path d="M260 680C510 540 710 560 960 410C1140 302 1260 260 1410 288" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="8" stroke-linecap="round"/>
|
||||
<circle cx="960" cy="410" r="100" fill="#ffffff" fill-opacity="0.045"/>
|
||||
<circle cx="1150" cy="450" r="90" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="3"/>
|
||||
<circle cx="1150" cy="450" r="180" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="2.5"/>
|
||||
<circle cx="1150" cy="450" r="280" fill="none" stroke="#ffffff" stroke-opacity="0.065" stroke-width="2"/>
|
||||
<circle cx="1150" cy="450" r="390" fill="none" stroke="#ffffff" stroke-opacity="0.045" stroke-width="2"/>
|
||||
<circle cx="1150" cy="450" r="510" fill="none" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1.5"/>
|
||||
<circle cx="1150" cy="450" r="10" fill="#ffffff" fill-opacity="0.16"/>
|
||||
<circle cx="330" cy="450" r="5" fill="#ffffff" fill-opacity="0.12"/>
|
||||
<line x1="345" y1="450" x2="1130" y2="450" stroke="#ffffff" stroke-opacity="0.08" stroke-width="2" stroke-dasharray="2 14" stroke-linecap="round"/>
|
||||
<circle cx="320" cy="210" r="130" fill="#ffffff" fill-opacity="0.045"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 944 B After Width: | Height: | Size: 1.3 KiB |
|
|
@ -1478,6 +1478,60 @@
|
|||
margin-top: 1px;
|
||||
}
|
||||
|
||||
/* Fehler-Zusammenfassung (bleibt bei den Speichern-Buttons stehen,
|
||||
Einträge scrollen per Klick zum betroffenen Panel) */
|
||||
.pr-error-summary {
|
||||
background: var(--color-err-soft);
|
||||
border: 1px solid color-mix(in srgb, var(--color-err) 45%, transparent);
|
||||
border-radius: 4px;
|
||||
padding: 12px 14px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.pr-error-summary .head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
font-size: 12.5px;
|
||||
font-weight: 600;
|
||||
color: var(--color-err);
|
||||
}
|
||||
.pr-error-summary ul {
|
||||
list-style: none;
|
||||
margin: 8px 0 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
}
|
||||
.pr-error-summary li button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
color: var(--color-err);
|
||||
background: transparent;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dotted;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
.pr-error-summary li button:hover {
|
||||
text-decoration-style: solid;
|
||||
}
|
||||
|
||||
/* Panel mit Validierungsfehler — macht z.B. die Pflicht-Kategorie in
|
||||
der Sidebar unübersehbar */
|
||||
.panel.is-invalid {
|
||||
border-color: var(--color-err);
|
||||
box-shadow: 0 0 0 1px var(--color-err) inset;
|
||||
}
|
||||
.panel.is-invalid > .panel-head {
|
||||
border-bottom-color: color-mix(in srgb, var(--color-err) 35%, transparent);
|
||||
background: var(--color-err-soft);
|
||||
}
|
||||
|
||||
/* Boilerplate-Box (Read-only Firmenprofil) */
|
||||
.pr-boiler {
|
||||
background: var(--color-bg-elev);
|
||||
|
|
|
|||
|
|
@ -227,6 +227,10 @@
|
|||
animation: bp-ticker-marquee var(--bp-ticker-duration, 42s) linear infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
/* Anklickbare Meldungen: Lauf anhalten, solange die Maus darüber steht */
|
||||
.ticker-marquee-track:hover {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ticker-marquee-track {
|
||||
animation: none;
|
||||
|
|
|
|||
|
|
@ -232,6 +232,10 @@
|
|||
animation: bp-ticker-marquee var(--bp-ticker-duration, 42s) linear infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
/* Anklickbare Meldungen: Lauf anhalten, solange die Maus darüber steht */
|
||||
.ticker-marquee-track:hover {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ticker-marquee-track {
|
||||
animation: none;
|
||||
|
|
|
|||
199
resources/views/components/web/contact-launcher.blade.php
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
{{--
|
||||
Schwebendes Kontakt-Widget (unten rechts, alle Seiten): runder Launcher-
|
||||
Button, der ein kleines Panel mit Themenauswahl und Kontaktformular
|
||||
öffnet — Vorbereitung für einen späteren Chatbot. Öffnet auch auf das
|
||||
Window-Event `open-contact-modal` (bestehende „Kontakt"-Trigger in
|
||||
Footer/Utility-Bar/Landing) und automatisch nach dem Absenden
|
||||
(Erfolgs-Flash bzw. Validierungsfehler). Versand über den
|
||||
host-agnostischen POST-Endpunkt des Kontaktformulars (kontakt.store),
|
||||
der das Anliegen zusätzlich in der Admin-Queue „Kontakt" persistiert.
|
||||
|
||||
Styling: nutzt nur Token-Utilities, die in Web- UND Portal-Build
|
||||
existieren (bg-bg, text-ink, border-bg-rule …); die Akzentfarbe kommt
|
||||
per CSS-Variablen-Fallback (Hub-Blau → Brand-Farbe der Spokes).
|
||||
--}}
|
||||
|
||||
@php
|
||||
$edition = in_array(app()->getLocale(), ['de', 'en'], true) ? app()->getLocale() : 'de';
|
||||
$launcherAccent = 'background-color: var(--color-hub, var(--color-brand, #1A2540));';
|
||||
$prefillName = old('name', auth()->user()->name ?? '');
|
||||
$prefillEmail = old('email', auth()->user()->email ?? '');
|
||||
|
||||
$launcherTopics = [
|
||||
[
|
||||
'value' => \App\Enums\ContactMessageTopic::Contact->value,
|
||||
'label' => __('web.launcher.topic_contact'),
|
||||
'description' => __('web.launcher.topic_contact_desc'),
|
||||
],
|
||||
[
|
||||
'value' => \App\Enums\ContactMessageTopic::BugReport->value,
|
||||
'label' => __('web.launcher.topic_bug'),
|
||||
'description' => __('web.launcher.topic_bug_desc'),
|
||||
],
|
||||
[
|
||||
'value' => \App\Enums\ContactMessageTopic::PressReleaseReport->value,
|
||||
'label' => __('web.launcher.topic_press'),
|
||||
'description' => __('web.launcher.topic_press_desc'),
|
||||
],
|
||||
[
|
||||
'value' => \App\Enums\ContactMessageTopic::Feedback->value,
|
||||
'label' => __('web.launcher.topic_feedback'),
|
||||
'description' => __('web.launcher.topic_feedback_desc'),
|
||||
],
|
||||
];
|
||||
$launcherTopicLabels = collect($launcherTopics)->pluck('label', 'value');
|
||||
@endphp
|
||||
|
||||
<div
|
||||
x-data="{
|
||||
open: @js(session()->has('contact-status') || (old('topic') !== null && $errors->any())),
|
||||
topic: @js(old('topic')),
|
||||
topicLabels: @js($launcherTopicLabels),
|
||||
}"
|
||||
@open-contact-modal.window="open = true"
|
||||
@keydown.escape.window="open = false"
|
||||
class="fixed bottom-5 right-5 z-50 flex flex-col items-end gap-3 print:hidden"
|
||||
>
|
||||
{{-- Panel --}}
|
||||
<div x-show="open" x-transition.origin.bottom.right.duration.150ms style="display: none;"
|
||||
class="w-[calc(100vw-40px)] max-w-[360px] bg-bg-elev border border-bg-rule rounded-[6px] shadow-2xl overflow-hidden"
|
||||
role="dialog" aria-modal="false" aria-label="{{ __('web.launcher.contact') }}">
|
||||
|
||||
{{-- Kopf --}}
|
||||
<div class="flex items-center justify-between gap-3 px-5 py-4 text-white" style="{{ $launcherAccent }}">
|
||||
<div>
|
||||
<div class="text-[10px] font-bold tracking-[0.18em] uppercase opacity-70">{{ __('web.launcher.contact') }}</div>
|
||||
<div class="text-[15px] font-semibold leading-tight" x-text="topic ? topicLabels[topic] : @js(__('web.launcher.title'))"></div>
|
||||
</div>
|
||||
<button type="button" @click="open = false" aria-label="{{ __('web.launcher.close') }}"
|
||||
class="w-8 h-8 flex items-center justify-center rounded-full text-white/80 hover:text-white hover:bg-white/10 transition-colors cursor-pointer">
|
||||
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if (session('contact-status'))
|
||||
{{-- Erfolgsmeldung nach Absenden --}}
|
||||
<div class="p-5">
|
||||
<p class="text-[13px] text-ink-2 leading-[1.6] m-0" role="status">
|
||||
{{ session('contact-status') }}
|
||||
</p>
|
||||
<button type="button" @click="open = false"
|
||||
class="mt-4 inline-flex items-center justify-center px-4 py-2 text-[12.5px] font-semibold text-white rounded-[4px] transition-opacity hover:opacity-90 cursor-pointer"
|
||||
style="{{ $launcherAccent }}">
|
||||
{{ __('web.launcher.close') }}
|
||||
</button>
|
||||
</div>
|
||||
@else
|
||||
{{-- Schritt 1: Themenauswahl --}}
|
||||
<div x-show="!topic" class="p-3">
|
||||
<p class="text-[12px] text-ink-3 leading-[1.5] m-0 px-2 pt-1 pb-2">
|
||||
{{ __('web.launcher.intro') }}
|
||||
</p>
|
||||
@foreach ($launcherTopics as $launcherTopic)
|
||||
<button type="button" @click="topic = '{{ $launcherTopic['value'] }}'"
|
||||
class="w-full flex items-center justify-between gap-3 px-3 py-2.5 text-left rounded-[4px] hover:bg-bg transition-colors cursor-pointer">
|
||||
<span>
|
||||
<span class="block text-[13px] font-semibold text-ink">{{ $launcherTopic['label'] }}</span>
|
||||
<span class="block text-[11.5px] text-ink-3">{{ $launcherTopic['description'] }}</span>
|
||||
</span>
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" class="text-ink-3 flex-shrink-0" aria-hidden="true">
|
||||
<path d="M4 2l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
{{-- Schritt 2: Formular --}}
|
||||
<form x-show="topic" method="POST" action="{{ route('kontakt.store', ['edition' => $edition]) }}"
|
||||
class="p-5 space-y-3.5" novalidate style="display: none;">
|
||||
@csrf
|
||||
<input type="hidden" name="topic" :value="topic" />
|
||||
<input type="hidden" name="page_url" value="{{ request()->fullUrl() }}" />
|
||||
|
||||
<button type="button" @click="topic = null"
|
||||
class="inline-flex items-center gap-1.5 text-[11.5px] font-medium text-ink-3 hover:text-ink transition-colors cursor-pointer">
|
||||
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M8 2L4 6l4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
{{ __('web.launcher.back') }}
|
||||
</button>
|
||||
|
||||
<div>
|
||||
<label for="contact-launcher-name" class="block text-[11.5px] font-semibold text-ink mb-1">{{ __('web.launcher.name') }}</label>
|
||||
<input id="contact-launcher-name" type="text" name="name" value="{{ $prefillName }}" required
|
||||
autocomplete="name"
|
||||
class="w-full border border-bg-rule rounded-[3px] px-3 py-2 text-[13px] bg-bg text-ink focus:outline-none" />
|
||||
@error('name')
|
||||
<p class="mt-1 text-[11.5px] text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="contact-launcher-email" class="block text-[11.5px] font-semibold text-ink mb-1">{{ __('web.launcher.email') }}</label>
|
||||
<input id="contact-launcher-email" type="email" name="email" value="{{ $prefillEmail }}" required
|
||||
autocomplete="email"
|
||||
class="w-full border border-bg-rule rounded-[3px] px-3 py-2 text-[13px] bg-bg text-ink focus:outline-none" />
|
||||
@error('email')
|
||||
<p class="mt-1 text-[11.5px] text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="contact-launcher-message" class="block text-[11.5px] font-semibold text-ink mb-1">{{ __('web.launcher.message') }}</label>
|
||||
<textarea id="contact-launcher-message" name="message" rows="4" required
|
||||
class="w-full border border-bg-rule rounded-[3px] px-3 py-2 text-[13px] bg-bg text-ink focus:outline-none"
|
||||
placeholder="{{ __('web.launcher.message_placeholder') }}">{{ old('message') }}</textarea>
|
||||
@error('message')
|
||||
<p class="mt-1 text-[11.5px] text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- Rechtswidrige Inhalte gehören ins förmliche Meldeverfahren (DSA). --}}
|
||||
<p x-show="topic === '{{ \App\Enums\ContactMessageTopic::PressReleaseReport->value }}'"
|
||||
class="text-[11px] text-ink-3 leading-[1.5] m-0">
|
||||
{{ __('web.launcher.legal_hint') }}
|
||||
<a href="{{ route('melden', ['edition' => $edition]) }}" class="underline underline-offset-2 hover:text-ink">{{ __('web.launcher.legal_link') }}</a>
|
||||
</p>
|
||||
|
||||
{{-- Bot-Schutz: versteckte Honeypot-Felder (siehe ContactController). --}}
|
||||
<div class="hidden" aria-hidden="true">
|
||||
<label for="contact-launcher-website">Website</label>
|
||||
<input id="contact-launcher-website" type="text" name="website" tabindex="-1" autocomplete="off" value="{{ old('website') }}" />
|
||||
<label for="contact-launcher-homepage">Homepage</label>
|
||||
<input id="contact-launcher-homepage" type="text" name="homepage" tabindex="-1" autocomplete="off" value="{{ old('homepage') }}" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-3 pt-1">
|
||||
<p class="text-[10.5px] text-ink-3 leading-[1.5] m-0">
|
||||
{{ __('web.launcher.privacy_note') }}
|
||||
(<a href="{{ route('datenschutz', ['edition' => $edition]) }}" class="underline hover:text-ink">{{ __('web.footer.privacy') }}</a>).
|
||||
</p>
|
||||
<button type="submit"
|
||||
class="inline-flex items-center justify-center px-4 py-2 text-[12.5px] font-semibold text-white rounded-[4px] whitespace-nowrap transition-opacity hover:opacity-90 cursor-pointer"
|
||||
style="{{ $launcherAccent }}">
|
||||
{{ __('web.launcher.submit') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Runder Launcher-Button --}}
|
||||
<button type="button" @click="open = !open"
|
||||
class="rounded-full shadow-xl flex items-center justify-center text-white transition-transform hover:scale-105 cursor-pointer"
|
||||
style="{{ $launcherAccent }} width: 52px; height: 52px;"
|
||||
:aria-expanded="open.toString()"
|
||||
aria-haspopup="dialog"
|
||||
aria-label="{{ __('web.launcher.contact') }}">
|
||||
{{-- Sprechblasen-Icon (geschlossen) / X (offen) --}}
|
||||
<svg x-show="!open" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"
|
||||
stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
<svg x-show="open" width="18" height="18" viewBox="0 0 16 16" fill="none" aria-hidden="true" style="display: none;">
|
||||
<path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
$categoryName = $category?->name;
|
||||
$image = $release?->images?->first();
|
||||
$imageUrl = $image?->variantUrl('card') ?? $image?->url();
|
||||
$placeholderUrl = $imageUrl ? null : $release?->chosenPlaceholderUrl();
|
||||
$teaser = (string) \Illuminate\Support\Str::of(strip_tags((string) ($release?->text ?? '')))->squish()->limit(180);
|
||||
$company = $release?->company?->name;
|
||||
$title = $release->title;
|
||||
|
|
@ -23,6 +24,8 @@
|
|||
<a href="{{ $href }}" class="relative overflow-hidden bg-feature-grad block cursor-pointer" style="width:100%; max-width:240px; height:160px;">
|
||||
@if ($imageUrl)
|
||||
<img src="{{ $imageUrl }}" alt="{{ $title }}" class="absolute inset-0 h-full w-full object-cover transition-transform group-hover:scale-105" loading="lazy">
|
||||
@elseif ($placeholderUrl)
|
||||
<img src="{{ $placeholderUrl }}" alt="" aria-hidden="true" class="absolute inset-0 h-full w-full object-cover transition-transform group-hover:scale-105" loading="lazy">
|
||||
@else
|
||||
<svg width="100%" height="100%" viewBox="0 0 240 160" class="absolute inset-0" aria-hidden="true">
|
||||
<g opacity="0.5">
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
$leadCategoryName = $leadCategory?->name;
|
||||
$leadImage = $leadRelease->images?->first();
|
||||
$leadImageUrl = $leadImage?->variantUrl('card') ?? $leadImage?->url();
|
||||
$leadPlaceholderUrl = $leadImageUrl ? null : $leadRelease->chosenPlaceholderUrl();
|
||||
$leadTitle = $leadRelease->title;
|
||||
$leadTeaser = (string) \Illuminate\Support\Str::of(strip_tags((string) $leadRelease->text))->squish()->limit(200);
|
||||
$leadCompany = $leadRelease->company?->name;
|
||||
|
|
@ -42,6 +43,9 @@
|
|||
class="absolute inset-0 h-full w-full object-cover opacity-90 transition-opacity group-hover:opacity-100"
|
||||
loading="eager">
|
||||
<div class="absolute inset-0 bg-black/10"></div>
|
||||
@elseif ($leadPlaceholderUrl)
|
||||
<img src="{{ $leadPlaceholderUrl }}" alt="" aria-hidden="true"
|
||||
class="absolute inset-0 h-full w-full object-cover" loading="eager">
|
||||
@else
|
||||
<x-web.hero-fallback />
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
$href = route('release.detail', ['slug' => $release->slug]);
|
||||
$image = $release?->images?->first();
|
||||
$imageUrl = $image?->variantUrl('card') ?? $image?->url();
|
||||
$placeholderUrl = $imageUrl ? null : $release?->chosenPlaceholderUrl();
|
||||
$gradient = 'linear-gradient(135deg,#3A4A5A,#6B7C95)';
|
||||
$number = str_pad((string) $index, 2, '0', STR_PAD_LEFT);
|
||||
@endphp
|
||||
|
|
@ -34,6 +35,8 @@
|
|||
<div class="w-16 h-16 flex-shrink-0 relative overflow-hidden" style="background: {{ $gradient }};">
|
||||
@if ($imageUrl)
|
||||
<img src="{{ $imageUrl }}" alt="" class="absolute inset-0 h-full w-full object-cover transition-transform group-hover:scale-105" loading="lazy">
|
||||
@elseif ($placeholderUrl)
|
||||
<img src="{{ $placeholderUrl }}" alt="" aria-hidden="true" class="absolute inset-0 h-full w-full object-cover transition-transform group-hover:scale-105" loading="lazy">
|
||||
@else
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" class="absolute inset-0" aria-hidden="true">
|
||||
<circle cx="48" cy="20" r="18" fill="rgba(255,255,255,0.08)" />
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
{{--
|
||||
Kontakt-Modal der Hub-Landing: einfaches Formular statt sichtbarer
|
||||
E-Mail-Adresse (Spam-Schutz). Öffnet auf das Window-Event
|
||||
`open-contact-modal` (Trigger: `<button x-data @click="$dispatch('open-contact-modal')">`)
|
||||
und automatisch nach Absenden (Erfolgs-Flash bzw. Validierungsfehler).
|
||||
Versand über den host-agnostischen POST-Endpunkt des Kontaktformulars.
|
||||
--}}
|
||||
<div
|
||||
x-data="{ open: @js(session()->has('contact-status') || $errors->any()) }"
|
||||
@open-contact-modal.window="open = true"
|
||||
@keydown.escape.window="open = false"
|
||||
>
|
||||
<div x-show="open" x-cloak class="fixed inset-0 z-50 flex items-center justify-center p-4">
|
||||
<div class="absolute inset-0 bg-black/50" @click="open = false" aria-hidden="true"></div>
|
||||
|
||||
<div class="relative bg-white border border-bg-rule rounded-[4px] w-full max-w-[520px] max-h-[90vh] overflow-y-auto p-7"
|
||||
role="dialog" aria-modal="true" aria-label="Kontaktanfrage">
|
||||
|
||||
<button type="button" @click="open = false" aria-label="Schließen"
|
||||
class="absolute top-4 right-4 w-8 h-8 flex items-center justify-center text-ink-3 hover:text-ink transition-colors cursor-pointer">
|
||||
<svg width="14" height="14" viewBox="0 0 16 16" fill="none">
|
||||
<path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
@if (session('contact-status'))
|
||||
<div class="section-eyebrow mb-4">Kontakt</div>
|
||||
<h3 class="text-[20px] font-bold text-ink tracking-[-0.4px] m-0 mb-3">Nachricht gesendet</h3>
|
||||
<p class="text-[13.5px] text-ink-2 leading-[1.6] m-0" role="status">
|
||||
{{ session('contact-status') }}
|
||||
</p>
|
||||
<button type="button" @click="open = false"
|
||||
class="mt-6 inline-flex items-center justify-center px-5 py-2.5 text-[13px] font-semibold text-white bg-hub hover:bg-hub-2 rounded-[4px] transition-colors cursor-pointer">
|
||||
Schließen
|
||||
</button>
|
||||
@else
|
||||
<div class="section-eyebrow mb-4">Kontakt</div>
|
||||
<h3 class="text-[20px] font-bold text-ink tracking-[-0.4px] m-0 mb-2">Schreiben Sie uns</h3>
|
||||
<p class="text-[12.5px] text-ink-3 leading-[1.55] m-0 mb-6">
|
||||
Ob Enterprise-Anfrage, Support oder Fragen zu Ihren Daten — wir melden uns werktags
|
||||
schnellstmöglich zurück.
|
||||
</p>
|
||||
|
||||
<form method="POST" action="{{ route('kontakt.store', ['edition' => 'de']) }}" class="space-y-4" novalidate>
|
||||
@csrf
|
||||
|
||||
<div>
|
||||
<label for="hub-contact-name" class="block text-[12px] font-semibold text-ink mb-1.5">Ihr Name</label>
|
||||
<input id="hub-contact-name" type="text" name="name" value="{{ old('name') }}" required
|
||||
autocomplete="name"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
|
||||
@error('name')
|
||||
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="hub-contact-email" class="block text-[12px] font-semibold text-ink mb-1.5">E-Mail-Adresse</label>
|
||||
<input id="hub-contact-email" type="email" name="email" value="{{ old('email') }}" required
|
||||
autocomplete="email"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
|
||||
@error('email')
|
||||
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="hub-contact-message" class="block text-[12px] font-semibold text-ink mb-1.5">Ihre Nachricht</label>
|
||||
<textarea id="hub-contact-message" name="message" rows="5" required
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub"
|
||||
placeholder="Wie können wir Ihnen helfen?">{{ old('message') }}</textarea>
|
||||
@error('message')
|
||||
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- Bot-Schutz: versteckte Honeypot-Felder (siehe ContactController). --}}
|
||||
<div class="hidden" aria-hidden="true">
|
||||
<label for="hub-contact-website">Website</label>
|
||||
<input id="hub-contact-website" type="text" name="website" tabindex="-1" autocomplete="off" value="{{ old('website') }}" />
|
||||
<label for="hub-contact-homepage">Homepage</label>
|
||||
<input id="hub-contact-homepage" type="text" name="homepage" tabindex="-1" autocomplete="off" value="{{ old('homepage') }}" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-4 pt-1">
|
||||
<p class="text-[11px] text-ink-3 leading-[1.5] m-0">
|
||||
Ihre Angaben werden nur zur Bearbeitung der Anfrage verarbeitet
|
||||
(<a href="{{ route('datenschutz', ['edition' => 'de']) }}" class="underline hover:text-ink">Datenschutz</a>).
|
||||
</p>
|
||||
<button type="submit"
|
||||
class="inline-flex items-center justify-center px-5 py-2.5 text-[13px] font-semibold text-white bg-hub hover:bg-hub-2 rounded-[4px] whitespace-nowrap transition-colors cursor-pointer">
|
||||
Nachricht senden
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -54,6 +54,8 @@
|
|||
<ul class="space-y-2 text-[13px] text-white/75 list-none p-0 m-0">
|
||||
<li><a href="{{ route('home') }}#funktion" class="hover:text-white transition-colors">So funktioniert es</a></li>
|
||||
<li><a href="{{ route('home') }}#familie" class="hover:text-white transition-colors">Die Portale</a></li>
|
||||
<li><a href="{{ route('faq', ['edition' => 'de']) }}" class="hover:text-white transition-colors">FAQ</a></li>
|
||||
<li><a href="{{ route('hilfe', ['edition' => 'de']) }}" class="hover:text-white transition-colors">Hilfe-Center</a></li>
|
||||
<li><a href="{{ route('api', ['edition' => 'de']) }}" class="hover:text-white transition-colors">API-Referenz</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
<span class="flex-1"></span>
|
||||
|
||||
<span class="flex items-center gap-4 py-2.5 whitespace-nowrap text-white/65">
|
||||
<a href="{{ route('faq', ['edition' => 'de']) }}" class="hover:text-white transition-colors">FAQ</a>
|
||||
<a href="{{ route('hilfe', ['edition' => 'de']) }}" class="hover:text-white transition-colors">Hilfe</a>
|
||||
<button type="button" x-data @click="$dispatch('open-contact-modal')" class="hover:text-white cursor-pointer">Kontakt</button>
|
||||
</span>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
{{--
|
||||
Hinweis auf der EN-Ausgabe der rechtsverbindlichen Langtexte (AGB,
|
||||
Datenschutzerklärung, Richtlinien): englische Fassungen sind bewusst
|
||||
zurückgestellt (docs/legal/Entscheidung.md O-C, erst nach
|
||||
fachanwaltlicher Prüfung) — maßgeblich ist die deutsche Fassung.
|
||||
--}}
|
||||
|
||||
@if (app()->getLocale() === 'en')
|
||||
@php
|
||||
$legalNoticeEmail = (string) config('legal.contact_email');
|
||||
@endphp
|
||||
<div class="max-w-[760px] mb-8 border border-bg-rule border-l-[3px] border-l-brand bg-bg-elev px-5 py-4" role="note">
|
||||
<div class="text-[12px] font-semibold text-ink mb-1">{{ __('static.legal.german_binding_notice_title') }}</div>
|
||||
<p class="text-[13px] leading-[1.6] text-ink-2 m-0">
|
||||
{{ __('static.legal.german_binding_notice', ['email' => $legalNoticeEmail]) }}
|
||||
</p>
|
||||
</div>
|
||||
@endif
|
||||
|
|
@ -21,17 +21,31 @@
|
|||
<span class="sr-only">
|
||||
{{ __('web.ticker.sr_intro') }}
|
||||
@foreach ($items as $item)
|
||||
{{ $item['time'] }} {{ $item['text'] }}.
|
||||
@if (! empty($item['href']))
|
||||
<a href="{{ $item['href'] }}">{{ $item['time'] }} {{ $item['text'] }}.</a>
|
||||
@else
|
||||
{{ $item['time'] }} {{ $item['text'] }}.
|
||||
@endif
|
||||
@endforeach
|
||||
</span>
|
||||
|
||||
<div class="overflow-hidden min-w-0 flex-1" aria-hidden="true">
|
||||
<div class="ticker-marquee-track text-[12px] sm:text-[12.5px] whitespace-nowrap">
|
||||
{{-- tabindex=-1: Duplikate im aria-hidden-Marquee dürfen keinen Fokus erhalten,
|
||||
die zugängliche Variante steht im sr-only-Block darüber. --}}
|
||||
@foreach (array_merge($items, $items) as $item)
|
||||
<span class="inline-flex shrink-0 gap-2 items-baseline">
|
||||
<span class="font-mono text-[11px] text-ink-on-dark-muted">{{ $item['time'] }}</span>
|
||||
<span class="text-ink-on-dark">{{ $item['text'] }}</span>
|
||||
</span>
|
||||
@if (! empty($item['href']))
|
||||
<a href="{{ $item['href'] }}" tabindex="-1"
|
||||
class="inline-flex shrink-0 gap-2 items-baseline cursor-pointer group/ticker">
|
||||
<span class="font-mono text-[11px] text-ink-on-dark-muted">{{ $item['time'] }}</span>
|
||||
<span class="text-ink-on-dark group-hover/ticker:text-brand group-hover/ticker:underline underline-offset-2 transition-colors">{{ $item['text'] }}</span>
|
||||
</a>
|
||||
@else
|
||||
<span class="inline-flex shrink-0 gap-2 items-baseline">
|
||||
<span class="font-mono text-[11px] text-ink-on-dark-muted">{{ $item['time'] }}</span>
|
||||
<span class="text-ink-on-dark">{{ $item['text'] }}</span>
|
||||
</span>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,12 +15,16 @@
|
|||
|
||||
$brandName = $brand['name'] ?? 'businessportal';
|
||||
$brandAccent = $brand['accent'] ?? '';
|
||||
$brandTagline = $brand['tagline_short'] ?? 'Pressemitteilungen · DACH';
|
||||
$brandTaglineLong = $brand['tagline_long'] ?? 'Pressemitteilungen aus dem DACH-Raum.';
|
||||
// Taglines lokalisiert (web.footer.*); Brand-Config bleibt Fallback für
|
||||
// Themes ohne eigenen Übersetzungsschlüssel.
|
||||
$brandTagline = __('web.footer.tagline_short');
|
||||
$brandTaglineLong = \Illuminate\Support\Facades\Lang::has('web.footer.tagline_long_'.$themeKey)
|
||||
? __('web.footer.tagline_long_'.$themeKey)
|
||||
: ($brand['tagline_long'] ?? 'Pressemitteilungen aus dem DACH-Raum.');
|
||||
// Betreiber-Postfach (adametz.media) als Fallback, bis die portal-
|
||||
// spezifischen CONTACT_EMAIL_*-Adressen gesetzt sind (R2.1).
|
||||
$contactEmail = $brand['contact_email'] ?? 'info@businessportal24.com';
|
||||
$legal = str_replace(':year', (string) now()->format('Y'), $brand['footer_legal'] ?? '© :year · Alle Rechte vorbehalten');
|
||||
$legal = __('web.footer.rights', ['year' => now()->format('Y'), 'brand' => $brandName.$brandAccent]);
|
||||
@endphp
|
||||
|
||||
<footer class="mt-16 bg-topbar-grad text-ink-on-dark">
|
||||
|
|
@ -61,7 +65,7 @@
|
|||
<div>
|
||||
<div class="eyebrow mb-3.5">{{ __('web.footer.company') }}</div>
|
||||
<ul class="space-y-2 text-[13px] text-white/75 list-none p-0 m-0">
|
||||
<li><a href="mailto:{{ $contactEmail }}" class="cursor-pointer hover:text-white transition-colors">{{ __('web.footer.contact') }}</a></li>
|
||||
<li><button type="button" x-data @click="$dispatch('open-contact-modal')" class="cursor-pointer hover:text-white transition-colors">{{ __('web.footer.contact') }}</button></li>
|
||||
<li><a href="{{ route('faq') }}" class="cursor-pointer hover:text-white transition-colors">FAQ</a></li>
|
||||
<li><a href="{{ route('hilfe') }}" class="cursor-pointer hover:text-white transition-colors">{{ __('web.footer.help') }}</a></li>
|
||||
<li><a href="{{ route('kuendigung') }}" class="cursor-pointer hover:text-white transition-colors">{{ __('web.footer.cancellation') }}</a></li>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
]);
|
||||
$brandName = $brand['name'] ?? 'businessportal';
|
||||
$brandAccent = $brand['accent'] ?? '';
|
||||
$brandTagline = $brand['tagline_short'] ?? 'Pressemitteilungen · DACH';
|
||||
$brandTagline = __('web.footer.tagline_short');
|
||||
@endphp
|
||||
|
||||
@php
|
||||
|
|
@ -28,17 +28,25 @@
|
|||
|
||||
// Navigation = echte Rubriken der aktiven Ausgabe. Es gibt keine separate
|
||||
// Übersichtsseite; jeder Eintrag führt direkt auf die Kategorieseite.
|
||||
$navigation ??= collect([
|
||||
['label' => __('web.nav.home'), 'href' => route('web.home'), 'active' => request()->routeIs('web.home')],
|
||||
])->concat(
|
||||
\App\Support\CategoryNavigation::items()->map(fn (array $category): array => [
|
||||
// Die meistbespielten Rubriken erscheinen als Tabs, der Rest im
|
||||
// „Mehr“-Dropdown (Desktop) bzw. in der Mobile-Liste.
|
||||
$moreNavigation = [];
|
||||
|
||||
if ($navigation === null) {
|
||||
$categoryItems = \App\Support\CategoryNavigation::items(null)->map(fn (array $category): array => [
|
||||
'label' => $category['label'],
|
||||
'href' => $category['href'],
|
||||
'active' => request()->routeIs('kategorie') && request()->route('slug') === $category['slug'],
|
||||
])
|
||||
)->all();
|
||||
]);
|
||||
|
||||
$activeLabel = collect($navigation)->firstWhere('active', true)['label'] ?? __('web.nav.menu');
|
||||
$moreNavigation = $categoryItems->slice(9)->values()->all();
|
||||
$navigation = collect([
|
||||
['label' => __('web.nav.home'), 'href' => route('web.home'), 'active' => request()->routeIs('web.home')],
|
||||
])->concat($categoryItems->take(9))->all();
|
||||
}
|
||||
|
||||
$moreActive = collect($moreNavigation)->contains(fn (array $item): bool => $item['active'] ?? false);
|
||||
$activeLabel = collect($navigation)->concat($moreNavigation)->firstWhere('active', true)['label'] ?? __('web.nav.menu');
|
||||
@endphp
|
||||
|
||||
<header>
|
||||
|
|
@ -89,10 +97,10 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Header (Logo + Suche + Buttons + Burger) --}}
|
||||
{{-- Header (Logo + Suche mittig + Buttons rechtsbündig + Burger) --}}
|
||||
<div id="header" class="header-normal bg-bg border-b border-bg-rule"
|
||||
x-data="{ searchOpen: false }"
|
||||
@keydown.escape.window="searchOpen = false"
|
||||
x-data="{ searchOpen: false, loginOpen: false }"
|
||||
@keydown.escape.window="searchOpen = false; loginOpen = false"
|
||||
@keydown.window.prevent.cmd.k="$refs.desktopSearch ? $refs.desktopSearch.focus() : searchOpen = true"
|
||||
@keydown.window.prevent.ctrl.k="$refs.desktopSearch ? $refs.desktopSearch.focus() : searchOpen = true">
|
||||
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-3 lg:py-[18px] flex items-center gap-3 sm:gap-4 lg:gap-6">
|
||||
|
|
@ -105,66 +113,127 @@
|
|||
</div>
|
||||
</a>
|
||||
|
||||
{{-- Suchfeld nur ab md sichtbar --}}
|
||||
<form action="{{ route('suche') }}" method="get" class="hidden md:block flex-1 max-w-[460px]">
|
||||
<label class="sr-only" for="site-search">{{ __('web.header.search_label') }}</label>
|
||||
<div class="flex items-center gap-2.5 px-3.5 py-2.5 border border-bg-rule bg-bg-elev text-[13px] text-ink-3 rounded-[2px] focus-within:border-brand transition-colors">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
|
||||
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
<input id="site-search" type="search" name="q" x-ref="desktopSearch"
|
||||
placeholder="{{ __('web.header.search_placeholder') }}"
|
||||
class="flex-1 bg-transparent border-0 p-0 text-[13px] text-ink placeholder:text-ink-3 focus:outline-none focus:ring-0 min-w-0">
|
||||
<span class="hidden xl:inline-block text-[10.5px] text-ink-4 border border-bg-rule px-1.5 py-0.5 rounded-[2px] font-mono">⌘K</span>
|
||||
</div>
|
||||
<div class="hidden lg:flex justify-end mt-1.5">
|
||||
<a href="{{ route('suche') }}" class="inline-flex items-center gap-1.5 text-[11.5px] text-ink-3 underline underline-offset-2 decoration-[#1C1A17]/40 cursor-pointer hover:text-ink hover:decoration-brand transition-colors">
|
||||
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M2 3h8M3.5 6h5M5 9h2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" />
|
||||
{{-- Suchfeld nur ab md sichtbar, mittig im verbleibenden Raum --}}
|
||||
<div class="hidden md:flex flex-1 justify-center min-w-0">
|
||||
<form action="{{ route('suche') }}" method="get" class="w-full max-w-[460px]">
|
||||
<label class="sr-only" for="site-search">{{ __('web.header.search_label') }}</label>
|
||||
<div class="flex items-center gap-2.5 px-3.5 py-2.5 border border-bg-rule bg-bg-elev text-[13px] text-ink-3 rounded-[2px] focus-within:border-brand transition-colors">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
|
||||
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
{{ __('web.header.advanced_search') }}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
<input id="site-search" type="search" name="q" x-ref="desktopSearch"
|
||||
placeholder="{{ __('web.header.search_placeholder') }}"
|
||||
class="flex-1 bg-transparent border-0 p-0 text-[13px] text-ink placeholder:text-ink-3 focus:outline-none focus:ring-0 min-w-0">
|
||||
<span class="hidden xl:inline-block text-[10.5px] text-ink-4 border border-bg-rule px-1.5 py-0.5 rounded-[2px] font-mono">⌘K</span>
|
||||
</div>
|
||||
<div class="hidden lg:flex justify-end mt-1.5">
|
||||
<a href="{{ route('suche') }}" class="inline-flex items-center gap-1.5 text-[11.5px] text-ink-3 underline underline-offset-2 decoration-[#1C1A17]/40 cursor-pointer hover:text-ink hover:decoration-brand transition-colors">
|
||||
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M2 3h8M3.5 6h5M5 9h2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" />
|
||||
</svg>
|
||||
{{ __('web.header.advanced_search') }}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<span class="flex-1 md:hidden"></span>
|
||||
|
||||
{{-- Such-Icon nur auf mobile --}}
|
||||
<button type="button"
|
||||
@click="searchOpen = true"
|
||||
class="md:hidden inline-flex items-center justify-center w-10 h-10 text-ink rounded-[2px] cursor-pointer hover:bg-bg-elev transition-colors"
|
||||
aria-label="{{ __('web.header.search_open') }}">
|
||||
<svg width="20" height="20" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
|
||||
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
{{-- Buttons rechtsbündig --}}
|
||||
<div class="flex items-center gap-1 sm:gap-2 flex-shrink-0">
|
||||
{{-- Such-Icon nur auf mobile --}}
|
||||
<button type="button"
|
||||
@click="searchOpen = true"
|
||||
class="md:hidden inline-flex items-center justify-center w-10 h-10 text-ink rounded-[2px] cursor-pointer hover:bg-bg-elev transition-colors"
|
||||
aria-label="{{ __('web.header.search_open') }}">
|
||||
<svg width="20" height="20" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
|
||||
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{{-- Anmelden: führt in den Hub (Portal-Domain). --}}
|
||||
<a href="{{ rtrim(config('domains.domain_portal_url', config('app.url')), '/') }}/login"
|
||||
class="inline-flex items-center gap-2 px-2 sm:px-3 lg:px-4 py-2 lg:py-2.5 text-[13px] font-semibold text-ink rounded-[2px] cursor-pointer hover:text-brand transition-colors"
|
||||
aria-label="{{ __('web.header.login') }}">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true">
|
||||
<circle cx="12" cy="8" r="4" stroke="currentColor" stroke-width="1.8" />
|
||||
<path d="M4 21c0-4 4-7 8-7s8 3 8 7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
||||
</svg>
|
||||
<span class="hidden sm:inline">{{ __('web.header.login') }}</span>
|
||||
</a>
|
||||
{{-- Anmelden: öffnet Modal mit Pressekonto-Erklärung --}}
|
||||
<button type="button"
|
||||
@click="loginOpen = true"
|
||||
class="inline-flex items-center gap-2 px-2 sm:px-3 lg:px-4 py-2 lg:py-2.5 text-[13px] font-semibold text-ink rounded-[2px] cursor-pointer hover:text-brand transition-colors"
|
||||
aria-label="{{ __('web.header.login') }}"
|
||||
aria-haspopup="dialog">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true">
|
||||
<circle cx="12" cy="8" r="4" stroke="currentColor" stroke-width="1.8" />
|
||||
<path d="M4 21c0-4 4-7 8-7s8 3 8 7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
||||
</svg>
|
||||
<span class="hidden sm:inline">{{ __('web.header.login') }}</span>
|
||||
</button>
|
||||
|
||||
{{-- Veröffentlichen --}}
|
||||
<a href="{{ route('veroeffentlichen') }}"
|
||||
class="inline-flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 lg:px-[18px] py-2 lg:py-2.5 text-[12.5px] sm:text-[13px] font-semibold text-white bg-brand cursor-pointer hover:bg-brand-deep rounded-[2px] transition-colors whitespace-nowrap"
|
||||
aria-label="{{ __('web.header.publish_aria') }}">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true">
|
||||
<path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" />
|
||||
</svg>
|
||||
<span class="sm:hidden">PM</span>
|
||||
<span class="hidden sm:inline">{{ __('web.header.publish') }}</span>
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" class="hidden sm:inline" aria-hidden="true">
|
||||
<path d="M3 6h6M6 3l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</a>
|
||||
{{-- Veröffentlichen --}}
|
||||
<a href="{{ route('veroeffentlichen') }}"
|
||||
class="inline-flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 lg:px-[18px] py-2 lg:py-2.5 text-[12.5px] sm:text-[13px] font-semibold text-white bg-brand cursor-pointer hover:bg-brand-deep rounded-[2px] transition-colors whitespace-nowrap"
|
||||
aria-label="{{ __('web.header.publish_aria') }}">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true">
|
||||
<path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" />
|
||||
</svg>
|
||||
<span class="sm:hidden">PM</span>
|
||||
<span class="hidden sm:inline">{{ __('web.header.publish') }}</span>
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" class="hidden sm:inline" aria-hidden="true">
|
||||
<path d="M3 6h6M6 3l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Anmelde-Modal: erklärt Pressekonto (Hub) und verlinkt dorthin --}}
|
||||
@php
|
||||
$portalUrl = rtrim(config('domains.domain_portal_url', config('app.url')), '/');
|
||||
@endphp
|
||||
<div x-show="loginOpen"
|
||||
x-transition.opacity.duration.150ms
|
||||
class="fixed inset-0 z-50 bg-ink/70 backdrop-blur-sm flex items-start sm:items-center justify-center p-4 sm:p-6 overflow-y-auto"
|
||||
@click.self="loginOpen = false"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="login-modal-title"
|
||||
style="display: none;">
|
||||
<div x-show="loginOpen"
|
||||
x-transition.duration.200ms
|
||||
class="relative w-full max-w-[520px] bg-bg border border-bg-rule-strong shadow-2xl mt-10 sm:mt-0">
|
||||
<button type="button"
|
||||
@click="loginOpen = false"
|
||||
class="absolute top-3 right-3 inline-flex items-center justify-center w-10 h-10 text-ink-3 rounded-[2px] cursor-pointer hover:text-ink hover:bg-bg-elev transition-colors"
|
||||
aria-label="{{ __('web.header.login_modal_close') }}">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M6 6l12 12M6 18L18 6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div class="px-6 sm:px-8 pt-7 pb-6">
|
||||
<div class="eyebrow mb-2">{{ __('web.header.login_modal_eyebrow') }}</div>
|
||||
<h2 id="login-modal-title" class="font-serif text-[24px] sm:text-[26px] font-semibold text-ink tracking-[-0.4px] leading-[1.15] m-0 mb-3.5">
|
||||
{{ __('web.header.login_modal_title') }}
|
||||
</h2>
|
||||
<p class="text-[13.5px] leading-[1.65] text-ink-2 m-0 mb-6">
|
||||
{{ __('web.header.login_modal_text') }}
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-2.5">
|
||||
<a href="{{ $portalUrl }}/login"
|
||||
class="inline-flex items-center justify-center gap-2 px-[18px] py-2.5 text-[13px] font-semibold text-white bg-brand cursor-pointer hover:bg-brand-deep rounded-[2px] transition-colors">
|
||||
{{ __('web.header.login_modal_login') }}
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M3 6h6M6 3l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</a>
|
||||
<a href="{{ $portalUrl }}"
|
||||
class="inline-flex items-center justify-center gap-2 px-[18px] py-2.5 text-[13px] font-semibold text-ink border border-bg-rule-strong cursor-pointer hover:border-brand hover:text-brand rounded-[2px] transition-colors">
|
||||
{{ __('web.header.login_modal_hub') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p class="text-[11.5px] text-ink-3 m-0 mt-4">
|
||||
{{ __('web.header.login_modal_note') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Such-Overlay --}}
|
||||
|
|
@ -245,6 +314,44 @@
|
|||
{{ $item['label'] }}
|
||||
</a>
|
||||
@endforeach
|
||||
|
||||
@if (count($moreNavigation) > 0)
|
||||
{{-- Restliche Rubriken (jenseits der Top 9) im Dropdown --}}
|
||||
<div class="relative flex items-stretch"
|
||||
x-data="{ moreOpen: false }"
|
||||
@keydown.escape.window="moreOpen = false"
|
||||
@click.outside="moreOpen = false">
|
||||
<button type="button"
|
||||
@click="moreOpen = !moreOpen"
|
||||
class="flex items-center gap-1.5 px-4 py-3.5 text-[13.5px] whitespace-nowrap border-b-2 -mb-px cursor-pointer transition-colors
|
||||
@if ($moreActive) font-semibold text-ink border-brand
|
||||
@else font-medium text-ink-2 border-transparent hover:text-ink hover:border-bg-rule-strong/30 @endif"
|
||||
:aria-expanded="moreOpen.toString()"
|
||||
aria-controls="desktop-nav-more">
|
||||
{{ __('web.nav.more') }}
|
||||
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" class="transition-transform"
|
||||
:class="{ 'rotate-180': moreOpen }" aria-hidden="true">
|
||||
<path d="M2 4l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div id="desktop-nav-more"
|
||||
x-show="moreOpen"
|
||||
x-transition.origin.top
|
||||
x-cloak
|
||||
class="absolute top-full right-0 z-40 min-w-[220px] bg-bg-elev border border-bg-rule shadow-lg py-1.5"
|
||||
style="display: none;">
|
||||
@foreach ($moreNavigation as $item)
|
||||
<a href="{{ $item['href'] }}"
|
||||
class="block px-4 py-2.5 text-[13.5px] whitespace-nowrap cursor-pointer transition-colors
|
||||
@if ($item['active'] ?? false) font-semibold text-brand bg-brand/[0.04]
|
||||
@else font-medium text-ink-2 hover:text-ink hover:bg-bg @endif">
|
||||
{{ $item['label'] }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Mobile: aktive Kategorie + Burger --}}
|
||||
|
|
@ -282,7 +389,7 @@
|
|||
class="lg:hidden border-t border-bg-rule bg-bg-elev absolute left-0 right-0 z-40 shadow-lg"
|
||||
style="display: none;">
|
||||
<div class="max-w-layout mx-auto px-4 sm:px-6 py-2">
|
||||
@foreach ($navigation as $item)
|
||||
@foreach (collect($navigation)->concat($moreNavigation) as $item)
|
||||
<a href="{{ $item['href'] }}"
|
||||
class="flex items-center justify-between px-3 py-3 text-[14px] border-b border-bg-rule last:border-b-0 cursor-pointer transition-colors
|
||||
@if ($item['active'] ?? false) font-semibold text-brand bg-brand/[0.04]
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@
|
|||
</main>
|
||||
|
||||
@if ($isHub)
|
||||
<x-web.hub.contact-modal />
|
||||
<x-web.hub.site-footer />
|
||||
@else
|
||||
<x-web.site-footer />
|
||||
|
|
|
|||
|
|
@ -27,11 +27,13 @@
|
|||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Rechtliches"
|
||||
:eyebrow="__('static.legal.eyebrow')"
|
||||
title="Allgemeine Geschäftsbedingungen"
|
||||
breadcrumb="AGB"
|
||||
updated="Stand: {{ $agbStand }} · Version {{ $agbVersion }}"
|
||||
>
|
||||
<x-web.legal-language-notice />
|
||||
|
||||
<div class="pm-body max-w-[760px]">
|
||||
<h2>§ 1 Geltungsbereich und Vertragspartner</h2>
|
||||
<p>
|
||||
|
|
@ -313,12 +315,12 @@
|
|||
<p>(1) Einzelveröffentlichungen und Credit-Käufe begründen kein Dauerschuldverhältnis.</p>
|
||||
<p>
|
||||
(2) Abonnements haben eine Laufzeit von einem Monat (monatliche Zahlweise) bzw. zwölf
|
||||
Monaten (jährliche Zahlweise). Nach Ablauf der Erstlaufzeit verlängert sich das Abonnement
|
||||
auf unbestimmte Zeit und ist jederzeit mit einer Frist von einem Monat kündbar.
|
||||
<strong>Bei jährlicher Zahlweise erfolgt die Abrechnung nach Ablauf der Erstlaufzeit
|
||||
monatlich zu dem für den jeweiligen Tarif ausgewiesenen Monatspreis, sofern der Kunde nicht
|
||||
ausdrücklich eine erneute jährliche Zahlweise wählt. Der Jahresrabatt („2 Monate gratis")
|
||||
gilt nur bei aktiv gewählter jährlicher Zahlweise.</strong>
|
||||
Monaten (jährliche Zahlweise). Das Abonnement verlängert sich jeweils automatisch um die
|
||||
gewählte Laufzeit (einen Monat bzw. zwölf Monate), sofern es nicht vor Ablauf der laufenden
|
||||
Laufzeit gekündigt wird. <strong>Die Kündigung ist jederzeit mit Wirkung zum Ende der
|
||||
laufenden Laufzeit möglich; bei monatlicher Zahlweise also monatlich, bei jährlicher
|
||||
Zahlweise zum Ende des jeweiligen Zwölfmonats-Zeitraums. Der Jahresrabatt („2 Monate
|
||||
gratis") gilt nur bei jährlicher Zahlweise.</strong>
|
||||
</p>
|
||||
<p>(3) Die Kündigung ist möglich:</p>
|
||||
<ul>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('web.layouts.web-master')
|
||||
|
||||
@section('title', 'API-Dokumentation')
|
||||
@section('meta_description', 'REST-API v1: Pressemitteilungen programmatisch erstellen, mit Bildern versehen und zur Prüfung einreichen — Token-basiert, JSON, versioniert.')
|
||||
@section('title', __('static.api.meta_title'))
|
||||
@section('meta_description', __('static.api.meta_description'))
|
||||
|
||||
@php
|
||||
// Die API läuft zentral über den Publisher-Hub (pressekonto).
|
||||
|
|
@ -15,62 +15,62 @@
|
|||
|
||||
$endpoints = [
|
||||
[
|
||||
'group' => 'Pressemitteilungen',
|
||||
'group' => __('static.api.group_releases'),
|
||||
'items' => [
|
||||
['method' => 'GET', 'path' => '/press-releases', 'desc' => 'Eigene Mitteilungen auflisten (paginiert, filterbar über ?status= und ?per_page=, max. 100).', 'ability' => 'press-releases:read'],
|
||||
['method' => 'POST', 'path' => '/press-releases', 'desc' => 'Neue Mitteilung anlegen — immer als Entwurf (Status draft).', 'ability' => 'press-releases:write'],
|
||||
['method' => 'GET', 'path' => '/press-releases/{id}', 'desc' => 'Eine Mitteilung inkl. Firma, Rubrik und Bildern abrufen.', 'ability' => 'press-releases:read'],
|
||||
['method' => 'PATCH', 'path' => '/press-releases/{id}', 'desc' => 'Mitteilung ändern — nur im Status draft oder rejected.', 'ability' => 'press-releases:write'],
|
||||
['method' => 'POST', 'path' => '/press-releases/{id}/submit', 'desc' => 'Zur Inhaltsprüfung einreichen — der einzige Weg Richtung Veröffentlichung.', 'ability' => 'press-releases:write'],
|
||||
['method' => 'DELETE', 'path' => '/press-releases/{id}', 'desc' => 'Mitteilung löschen — veröffentlichte Mitteilungen sind ausgenommen.', 'ability' => 'press-releases:write'],
|
||||
['method' => 'GET', 'path' => '/press-releases', 'desc' => __('static.api.ep_pr_index'), 'ability' => 'press-releases:read'],
|
||||
['method' => 'POST', 'path' => '/press-releases', 'desc' => __('static.api.ep_pr_store'), 'ability' => 'press-releases:write'],
|
||||
['method' => 'GET', 'path' => '/press-releases/{id}', 'desc' => __('static.api.ep_pr_show'), 'ability' => 'press-releases:read'],
|
||||
['method' => 'PATCH', 'path' => '/press-releases/{id}', 'desc' => __('static.api.ep_pr_update'), 'ability' => 'press-releases:write'],
|
||||
['method' => 'POST', 'path' => '/press-releases/{id}/submit', 'desc' => __('static.api.ep_pr_submit'), 'ability' => 'press-releases:write'],
|
||||
['method' => 'DELETE', 'path' => '/press-releases/{id}', 'desc' => __('static.api.ep_pr_destroy'), 'ability' => 'press-releases:write'],
|
||||
],
|
||||
],
|
||||
[
|
||||
'group' => 'Bilder',
|
||||
'group' => __('static.api.group_images'),
|
||||
'items' => [
|
||||
['method' => 'GET', 'path' => '/press-releases/{id}/images', 'desc' => 'Bilder einer Mitteilung auflisten.', 'ability' => 'press-releases:read'],
|
||||
['method' => 'POST', 'path' => '/press-releases/{id}/images', 'desc' => 'Bild hochladen (multipart/form-data) — nur bei draft/rejected.', 'ability' => 'press-release-images:write'],
|
||||
['method' => 'DELETE', 'path' => '/press-release-images/{imageId}', 'desc' => 'Bild entfernen — nur bei draft/rejected.', 'ability' => 'press-release-images:write'],
|
||||
['method' => 'GET', 'path' => '/press-releases/{id}/images', 'desc' => __('static.api.ep_img_index'), 'ability' => 'press-releases:read'],
|
||||
['method' => 'POST', 'path' => '/press-releases/{id}/images', 'desc' => __('static.api.ep_img_store'), 'ability' => 'press-release-images:write'],
|
||||
['method' => 'DELETE', 'path' => '/press-release-images/{imageId}', 'desc' => __('static.api.ep_img_destroy'), 'ability' => 'press-release-images:write'],
|
||||
],
|
||||
],
|
||||
[
|
||||
'group' => 'Stammdaten',
|
||||
'group' => __('static.api.group_master_data'),
|
||||
'items' => [
|
||||
['method' => 'GET', 'path' => '/companies', 'desc' => 'Eigene Firmenprofile (Newsrooms) auflisten.', 'ability' => 'companies:read'],
|
||||
['method' => 'GET', 'path' => '/companies/{id}', 'desc' => 'Ein Firmenprofil abrufen.', 'ability' => 'companies:read'],
|
||||
['method' => 'GET', 'path' => '/categories', 'desc' => 'Aktive Rubriken inkl. Übersetzungen — liefert die category_id für neue Mitteilungen.', 'ability' => 'press-releases:read'],
|
||||
['method' => 'GET', 'path' => '/companies', 'desc' => __('static.api.ep_companies_index'), 'ability' => 'companies:read'],
|
||||
['method' => 'GET', 'path' => '/companies/{id}', 'desc' => __('static.api.ep_companies_show'), 'ability' => 'companies:read'],
|
||||
['method' => 'GET', 'path' => '/categories', 'desc' => __('static.api.ep_categories_index'), 'ability' => 'press-releases:read'],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$pressReleaseFields = [
|
||||
['name' => 'company_id', 'type' => 'integer', 'required' => true, 'desc' => 'ID eines eigenen Firmenprofils — bestimmt Newsroom und Portal.'],
|
||||
['name' => 'category_id', 'type' => 'integer', 'required' => true, 'desc' => 'Rubrik (siehe GET /categories).'],
|
||||
['name' => 'language', 'type' => 'string', 'required' => true, 'desc' => 'Sprachcode, zwei Zeichen: de oder en.'],
|
||||
['name' => 'title', 'type' => 'string', 'required' => true, 'desc' => 'Überschrift, max. 255 Zeichen.'],
|
||||
['name' => 'text', 'type' => 'string', 'required' => true, 'desc' => 'Inhalt. Erlaubtes HTML: p, br, h2, h3, strong, em, ul, ol, li, blockquote, a — alles andere wird entfernt.'],
|
||||
['name' => 'backlink_url', 'type' => 'string', 'required' => false, 'desc' => 'Link zur Quelle/Website, max. 255 Zeichen.'],
|
||||
['name' => 'keywords', 'type' => 'string', 'required' => false, 'desc' => 'Schlagworte, kommagetrennt, max. 255 Zeichen.'],
|
||||
['name' => 'teaser_begin / teaser_end', 'type' => 'integer', 'required' => false, 'desc' => 'Zeichen-Offsets für den Teaser-Ausschnitt.'],
|
||||
['name' => 'no_export', 'type' => 'boolean', 'required' => false, 'desc' => 'Mitteilung von Feeds/Exporten ausnehmen.'],
|
||||
['name' => 'company_id', 'type' => 'integer', 'required' => true, 'desc' => __('static.api.field_company_id')],
|
||||
['name' => 'category_id', 'type' => 'integer', 'required' => true, 'desc' => __('static.api.field_category_id')],
|
||||
['name' => 'language', 'type' => 'string', 'required' => true, 'desc' => __('static.api.field_language')],
|
||||
['name' => 'title', 'type' => 'string', 'required' => true, 'desc' => __('static.api.field_title')],
|
||||
['name' => 'text', 'type' => 'string', 'required' => true, 'desc' => __('static.api.field_text')],
|
||||
['name' => 'backlink_url', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_backlink_url')],
|
||||
['name' => 'keywords', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_keywords')],
|
||||
['name' => 'teaser_begin / teaser_end', 'type' => 'integer', 'required' => false, 'desc' => __('static.api.field_teaser')],
|
||||
['name' => 'no_export', 'type' => 'boolean', 'required' => false, 'desc' => __('static.api.field_no_export')],
|
||||
];
|
||||
|
||||
$imageFields = [
|
||||
['name' => 'image', 'type' => 'file', 'required' => true, 'desc' => 'JPG, PNG oder WebP, max. 8 MB.'],
|
||||
['name' => 'title', 'type' => 'string', 'required' => false, 'desc' => 'Bildtitel, max. 120 Zeichen.'],
|
||||
['name' => 'description', 'type' => 'string', 'required' => false, 'desc' => 'Beschreibung, max. 500 Zeichen.'],
|
||||
['name' => 'copyright', 'type' => 'string', 'required' => false, 'desc' => 'Urheberangabe, max. 255 Zeichen.'],
|
||||
['name' => 'is_preview', 'type' => 'boolean', 'required' => false, 'desc' => 'Als Vorschaubild setzen (ersetzt ein vorhandenes).'],
|
||||
['name' => 'image', 'type' => 'file', 'required' => true, 'desc' => __('static.api.field_image')],
|
||||
['name' => 'title', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_image_title')],
|
||||
['name' => 'description', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_image_description')],
|
||||
['name' => 'copyright', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_image_copyright')],
|
||||
['name' => 'is_preview', 'type' => 'boolean', 'required' => false, 'desc' => __('static.api.field_image_is_preview')],
|
||||
];
|
||||
|
||||
$statusCodes = [
|
||||
['code' => '200 / 201 / 204', 'desc' => 'Erfolg — Abruf, Ressource erstellt bzw. gelöscht.'],
|
||||
['code' => '401', 'desc' => 'Kein oder ungültiger API-Token.'],
|
||||
['code' => '402', 'desc' => 'Einreichen erfordert eine aktive Buchung (Tarif oder Einzel-PM).'],
|
||||
['code' => '403', 'desc' => 'Token-Berechtigung fehlt oder die Ressource gehört nicht zu Ihrem Konto.'],
|
||||
['code' => '409', 'desc' => 'Statuskonflikt — z. B. Bearbeiten einer bereits veröffentlichten Mitteilung.'],
|
||||
['code' => '422', 'desc' => 'Validierungsfehler oder Kontingent-/Richtlinienverstoß (Details im Body).'],
|
||||
['code' => '429', 'desc' => 'Rate-Limit erreicht: 60 Anfragen pro Minute je Token (Header X-RateLimit-*).'],
|
||||
['code' => '200 / 201 / 204', 'desc' => __('static.api.status_2xx')],
|
||||
['code' => '401', 'desc' => __('static.api.status_401')],
|
||||
['code' => '402', 'desc' => __('static.api.status_402')],
|
||||
['code' => '403', 'desc' => __('static.api.status_403')],
|
||||
['code' => '409', 'desc' => __('static.api.status_409')],
|
||||
['code' => '422', 'desc' => __('static.api.status_422')],
|
||||
['code' => '429', 'desc' => __('static.api.status_429')],
|
||||
];
|
||||
|
||||
$methodColors = [
|
||||
|
|
@ -83,37 +83,21 @@
|
|||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Entwickler"
|
||||
title="API-Dokumentation"
|
||||
lead="Pressemitteilungen programmatisch erstellen, mit Bildern versehen und zur Prüfung einreichen — über die versionierte REST-API des Publisher-Hubs."
|
||||
breadcrumb="API"
|
||||
:eyebrow="__('static.api.eyebrow')"
|
||||
:title="__('static.api.title')"
|
||||
:lead="__('static.api.lead')"
|
||||
:breadcrumb="__('static.api.breadcrumb')"
|
||||
>
|
||||
{{-- Überblick + Authentifizierung --}}
|
||||
<div class="pm-body max-w-[760px]">
|
||||
<h2>Grundlagen</h2>
|
||||
<p>
|
||||
Die API v1 ist ein RESTful Web Service mit JSON-Responses. Basis-URL:
|
||||
<strong>{{ $apiBase }}</strong>. Eine über die API angelegte Mitteilung ist immer ein
|
||||
Entwurf; veröffentlicht wird sie erst nach dem Einreichen über die Submit-Route und der
|
||||
anschließenden Inhaltsprüfung — sie erscheint dann wie jede andere Mitteilung auf beiden Portalen.
|
||||
</p>
|
||||
<h3>Authentifizierung</h3>
|
||||
<p>
|
||||
Alle Anfragen benötigen einen persönlichen API-Token als Bearer-Header:
|
||||
<code>Authorization: Bearer <token></code>. Jeder Token trägt Berechtigungen
|
||||
(z. B. <code>press-releases:write</code>), die den Zugriff auf die jeweiligen Endpunkte steuern.
|
||||
Tokens erstellen und widerrufen Sie selbst in Ihrem Publisher-Konto unter „API-Tokens" —
|
||||
Voraussetzung ist eine aktive Buchung (Tarif oder Einzel-Pressemitteilung).
|
||||
<strong>Bestandskunden der Altportale:</strong> Ihre bisherigen API-Schlüssel wurden
|
||||
übernommen und funktionieren weiter — sowohl als Bearer-Token als auch in der alten
|
||||
Form (<code>X-ApiKey</code>-Header) und auf den dokumentierten
|
||||
<code>/service/…</code>-Pfaden. Für neue Integrationen empfehlen wir die aktuellen
|
||||
<code>/api/v1/…</code>-Endpunkte mit Bearer-Token.
|
||||
</p>
|
||||
<h2>{{ __('static.api.basics_heading') }}</h2>
|
||||
<p>{!! __('static.api.basics_text', ['base' => e($apiBase)]) !!}</p>
|
||||
<h3>{{ __('static.api.auth_heading') }}</h3>
|
||||
<p>{!! __('static.api.auth_text') !!}</p>
|
||||
</div>
|
||||
|
||||
{{-- Endpunkte --}}
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">Endpunkte</h2>
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.endpoints_heading') }}</h2>
|
||||
<div class="max-w-[900px] space-y-8">
|
||||
@foreach ($endpoints as $group)
|
||||
<div>
|
||||
|
|
@ -126,7 +110,7 @@
|
|||
<code class="font-mono text-[13px] text-ink">{{ $endpoint['path'] }}</code>
|
||||
<p class="text-[12.5px] leading-[1.55] text-ink-2 mt-1 mb-0">
|
||||
{{ $endpoint['desc'] }}
|
||||
<span class="text-ink-4">· Berechtigung: <code class="font-mono text-[11.5px]">{{ $endpoint['ability'] }}</code></span>
|
||||
<span class="text-ink-4">· {{ __('static.api.permission') }}: <code class="font-mono text-[11.5px]">{{ $endpoint['ability'] }}</code></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -137,15 +121,15 @@
|
|||
</div>
|
||||
|
||||
{{-- Felder --}}
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">Felder einer Pressemitteilung</h2>
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.fields_pr_heading') }}</h2>
|
||||
<div class="max-w-[900px] border border-bg-rule overflow-x-auto">
|
||||
<table class="w-full text-[13px] border-collapse">
|
||||
<thead>
|
||||
<tr class="text-left text-ink-3 bg-bg-elev border-b border-bg-rule">
|
||||
<th class="font-medium px-4 py-2.5">Feld</th>
|
||||
<th class="font-medium px-4 py-2.5">Typ</th>
|
||||
<th class="font-medium px-4 py-2.5">Pflicht</th>
|
||||
<th class="font-medium px-4 py-2.5">Beschreibung</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_field') }}</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_type') }}</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_required') }}</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-bg-rule">
|
||||
|
|
@ -153,7 +137,7 @@
|
|||
<tr>
|
||||
<td class="px-4 py-2.5 font-mono text-[12.5px] text-ink whitespace-nowrap">{{ $field['name'] }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-3">{{ $field['type'] }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-3">{{ $field['required'] ? 'ja' : '—' }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-3">{{ $field['required'] ? __('static.api.required_yes') : '—' }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-2">{{ $field['desc'] }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
|
@ -161,15 +145,15 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-12 mb-4">Felder eines Bild-Uploads</h2>
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-12 mb-4">{{ __('static.api.fields_img_heading') }}</h2>
|
||||
<div class="max-w-[900px] border border-bg-rule overflow-x-auto">
|
||||
<table class="w-full text-[13px] border-collapse">
|
||||
<thead>
|
||||
<tr class="text-left text-ink-3 bg-bg-elev border-b border-bg-rule">
|
||||
<th class="font-medium px-4 py-2.5">Feld</th>
|
||||
<th class="font-medium px-4 py-2.5">Typ</th>
|
||||
<th class="font-medium px-4 py-2.5">Pflicht</th>
|
||||
<th class="font-medium px-4 py-2.5">Beschreibung</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_field') }}</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_type') }}</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_required') }}</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-bg-rule">
|
||||
|
|
@ -177,7 +161,7 @@
|
|||
<tr>
|
||||
<td class="px-4 py-2.5 font-mono text-[12.5px] text-ink whitespace-nowrap">{{ $field['name'] }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-3">{{ $field['type'] }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-3">{{ $field['required'] ? 'ja' : '—' }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-3">{{ $field['required'] ? __('static.api.required_yes') : '—' }}</td>
|
||||
<td class="px-4 py-2.5 text-ink-2">{{ $field['desc'] }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
|
@ -186,10 +170,10 @@
|
|||
</div>
|
||||
|
||||
{{-- Workflow-Beispiel --}}
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">Schneller Einstieg</h2>
|
||||
<p class="text-[13px] text-ink-2 m-0 mb-4 max-w-[640px]">Der typische Ablauf: Entwurf anlegen, Bild hochladen, zur Prüfung einreichen.</p>
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.quickstart_heading') }}</h2>
|
||||
<p class="text-[13px] text-ink-2 m-0 mb-4 max-w-[640px]">{{ __('static.api.quickstart_text') }}</p>
|
||||
<div class="max-w-[900px] bg-[#16140f] border border-bg-rule-strong rounded-[3px] p-5 overflow-x-auto">
|
||||
<pre class="text-[12.5px] leading-[1.6] font-mono text-[#9ad1a5] m-0"><code># 1. Entwurf anlegen
|
||||
<pre class="text-[12.5px] leading-[1.6] font-mono text-[#9ad1a5] m-0"><code>{{ __('static.api.quickstart_step_1') }}
|
||||
curl -X POST {{ $apiBase }}/press-releases \
|
||||
-H "Authorization: Bearer YOUR_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
|
|
@ -201,29 +185,29 @@ curl -X POST {{ $apiBase }}/press-releases \
|
|||
"text": "<p>Unser neues Produkt …</p>"
|
||||
}'
|
||||
|
||||
# 2. Bild hochladen (multipart)
|
||||
{{ __('static.api.quickstart_step_2') }}
|
||||
curl -X POST {{ $apiBase }}/press-releases/123/images \
|
||||
-H "Authorization: Bearer YOUR_API_TOKEN" \
|
||||
-F "image=@pressefoto.jpg" \
|
||||
-F "copyright=Mustermann GmbH" \
|
||||
-F "is_preview=1"
|
||||
|
||||
# 3. Zur Inhaltsprüfung einreichen
|
||||
{{ __('static.api.quickstart_step_3') }}
|
||||
curl -X POST {{ $apiBase }}/press-releases/123/submit \
|
||||
-H "Authorization: Bearer YOUR_API_TOKEN"</code></pre>
|
||||
</div>
|
||||
<p class="text-[12px] text-ink-3 m-0 mt-3">
|
||||
Maschinenlesbare Referenz: <a href="{{ route('docs.api.v1') }}" class="text-brand hover:underline">OpenAPI-Spezifikation (YAML)</a>.
|
||||
{{ __('static.api.openapi_note') }} <a href="{{ route('docs.api.v1') }}" class="text-brand hover:underline">{{ __('static.api.openapi_link') }}</a>.
|
||||
</p>
|
||||
|
||||
{{-- Statuscodes --}}
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">HTTP-Statuscodes</h2>
|
||||
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.status_heading') }}</h2>
|
||||
<div class="max-w-[900px] border border-bg-rule overflow-x-auto">
|
||||
<table class="w-full text-[13px] border-collapse">
|
||||
<thead>
|
||||
<tr class="text-left text-ink-3 bg-bg-elev border-b border-bg-rule">
|
||||
<th class="font-medium px-4 py-2.5">Code</th>
|
||||
<th class="font-medium px-4 py-2.5">Bedeutung</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_code') }}</th>
|
||||
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_meaning') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-bg-rule">
|
||||
|
|
@ -240,17 +224,17 @@ curl -X POST {{ $apiBase }}/press-releases/123/submit \
|
|||
{{-- CTA --}}
|
||||
<div class="mt-14 border border-bg-rule bg-bg-elev p-6 sm:p-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-5 max-w-[900px]">
|
||||
<div>
|
||||
<h2 class="font-serif text-[20px] font-semibold tracking-[-0.3px] text-ink m-0">API-Token erstellen</h2>
|
||||
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">Tokens verwalten Sie selbst im Publisher-Konto. Bei Fragen zur Anbindung hilft der Support: <a href="mailto:{{ $apiContactEmail }}" class="text-brand hover:underline">{{ $apiContactEmail }}</a></p>
|
||||
<h2 class="font-serif text-[20px] font-semibold tracking-[-0.3px] text-ink m-0">{{ __('static.api.cta_heading') }}</h2>
|
||||
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">{{ __('static.api.cta_text') }} <a href="mailto:{{ $apiContactEmail }}" class="text-brand hover:underline">{{ $apiContactEmail }}</a></p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-3 flex-shrink-0">
|
||||
<a href="{{ rtrim((string) config('domains.domain_portal_url', config('app.url')), '/') }}/login"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-white bg-brand hover:bg-brand-deep rounded-[2px] transition-colors">
|
||||
Zum Publisher-Konto
|
||||
{{ __('static.api.cta_account') }}
|
||||
</a>
|
||||
<a href="{{ route('preise') }}"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-ink border border-bg-rule-strong hover:bg-bg transition-colors rounded-[2px]">
|
||||
Preise ansehen
|
||||
{{ __('static.api.cta_pricing') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -22,11 +22,13 @@
|
|||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Rechtliches"
|
||||
:eyebrow="__('static.legal.eyebrow')"
|
||||
title="Datenschutzerklärung"
|
||||
breadcrumb="Datenschutz"
|
||||
updated="Stand: 3. Juli 2026 · Version 0.3"
|
||||
>
|
||||
<x-web.legal-language-notice />
|
||||
|
||||
<div class="pm-body max-w-[760px]">
|
||||
<h2>1. Verantwortlicher</h2>
|
||||
<p>Verantwortlicher für die Datenverarbeitung auf {{ $host }} ist:</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('web.layouts.web-master')
|
||||
|
||||
@section('title', 'Häufig gestellte Fragen (FAQ)')
|
||||
@section('meta_description', 'Antworten auf die wichtigsten Fragen rund um das Veröffentlichen von Pressemitteilungen, Konto, Abrechnung und Newsroom.')
|
||||
@section('title', __('static.faq.meta_title'))
|
||||
@section('meta_description', __('static.faq.meta_description'))
|
||||
|
||||
@php
|
||||
// Host-aware Kontaktadresse: Hub (pressekonto) vs. Spokes. Betreiber-
|
||||
|
|
@ -12,42 +12,43 @@
|
|||
: (str_contains($host, 'presseecho') ? 'presseecho' : 'businessportal24');
|
||||
$faqContactEmail = config('domains.domains.'.$faqBrandKey.'.brand.contact_email') ?? 'info@businessportal24.com';
|
||||
|
||||
// FAQ-Inhalte als Datenstruktur (DRY). Antworten dürfen kontrolliertes
|
||||
// HTML enthalten (nur eigene Literale, keine Nutzereingaben).
|
||||
// FAQ-Inhalte als Datenstruktur (DRY), Texte aus lang/{de,en}/static.php.
|
||||
// Antworten dürfen kontrolliertes HTML enthalten (nur eigene Literale,
|
||||
// keine Nutzereingaben).
|
||||
$faqCategories = [
|
||||
[
|
||||
'title' => 'Erste Schritte',
|
||||
'title' => __('static.faq.cat_start'),
|
||||
'items' => [
|
||||
['q' => 'Wie veröffentliche ich meine erste Pressemitteilung?', 'a' => 'Registrieren Sie sich im zentralen Publisher-Bereich (pressekonto), legen Sie Ihr Firmenprofil an und verfassen Sie die Mitteilung im Editor — mit Text, Bildern, Anhängen und Pressekontakt. Nach dem Einreichen durchläuft sie unsere Inhaltsprüfung und erscheint anschließend auf presseecho.de und businessportal24.com.'],
|
||||
['q' => 'An wen richtet sich das Angebot?', 'a' => 'Ausschließlich an Unternehmen, Selbstständige und Agenturen. Die Veröffentlichung erfolgt stets über ein Firmenprofil — ein Angebot für Verbraucher ist es nicht.'],
|
||||
['q' => 'Muss ich mich registrieren, um Pressemitteilungen zu lesen?', 'a' => 'Nein, alle veröffentlichten Pressemitteilungen sind frei zugänglich. Eine Registrierung ist nur erforderlich, wenn Sie selbst veröffentlichen möchten.'],
|
||||
['q' => 'Wie lange dauert die Freischaltung meiner Pressemitteilung?', 'a' => 'Die Inhaltsprüfung ist werktags in der Regel am selben Tag abgeschlossen. Nach der Freigabe geht die Mitteilung sofort online — oder automatisch zu Ihrem geplanten Wunschtermin.'],
|
||||
['q' => __('static.faq.q_first_pm'), 'a' => __('static.faq.a_first_pm')],
|
||||
['q' => __('static.faq.q_audience'), 'a' => __('static.faq.a_audience')],
|
||||
['q' => __('static.faq.q_register_to_read'), 'a' => __('static.faq.a_register_to_read')],
|
||||
['q' => __('static.faq.q_review_time'), 'a' => __('static.faq.a_review_time')],
|
||||
],
|
||||
],
|
||||
[
|
||||
'title' => 'Konto & Abrechnung',
|
||||
'title' => __('static.faq.cat_account'),
|
||||
'items' => [
|
||||
['q' => 'Wie ändere ich meinen Tarif?', 'a' => 'In Ihrem Konto unter „Buchungen & Add-ons" können Sie jederzeit upgraden oder downgraden. Upgrades gelten sofort, Downgrades zum nächsten Abrechnungszeitraum.'],
|
||||
['q' => 'Welche Zahlungsmethoden werden akzeptiert?', 'a' => 'Die Abrechnung läuft sicher über Stripe — etwa per Kreditkarte oder SEPA-Lastschrift. Bestandskunden mit laufender Vereinbarung zahlen weiterhin per Rechnung.'],
|
||||
['q' => 'Kann ich meinen Tarif kündigen?', 'a' => 'Ja, alle Tarife sind monatlich kündbar — direkt im Konto oder ohne Anmeldung über die <a href="'.route('kuendigung').'">Kündigungsseite</a>. Bei jährlicher Zahlweise läuft der bereits bezahlte Zeitraum bis zum Ende der zwölf Monate.'],
|
||||
['q' => 'Kann ich mein Konto löschen?', 'a' => 'Ja, jederzeit in den Einstellungen Ihres Kontos. Bereits veröffentlichte Pressemitteilungen bleiben im Archiv online, werden aber nicht mehr Ihrem Konto zugeordnet.'],
|
||||
['q' => __('static.faq.q_change_plan'), 'a' => __('static.faq.a_change_plan')],
|
||||
['q' => __('static.faq.q_payment_methods'), 'a' => __('static.faq.a_payment_methods')],
|
||||
['q' => __('static.faq.q_cancel_plan'), 'a' => __('static.faq.a_cancel_plan', ['url' => route('kuendigung')])],
|
||||
['q' => __('static.faq.q_delete_account'), 'a' => __('static.faq.a_delete_account')],
|
||||
],
|
||||
],
|
||||
[
|
||||
'title' => 'Pressemitteilungen & Inhalte',
|
||||
'title' => __('static.faq.cat_content'),
|
||||
'items' => [
|
||||
['q' => 'Welche Dateiformate werden unterstützt?', 'a' => 'Bilder: JPG, PNG, WebP (max. 16 MB im Editor; über die API max. 8 MB). Anhänge: PDF, Word, Excel, PowerPoint, ZIP und TXT (max. 25 MB je Datei).'],
|
||||
['q' => 'Kann ich eine Pressemitteilung nach Veröffentlichung korrigieren?', 'a' => 'Ja — wir korrigieren statt zu löschen: Die URL Ihrer Mitteilung bleibt erhalten, Verweise und Verlinkungen bestehen weiter. Wenden Sie sich mit Korrekturwünschen an unseren Support.'],
|
||||
['q' => 'Wie optimiere ich meine Pressemitteilung für SEO?', 'a' => 'Nutzen Sie aussagekräftige Headlines, integrieren Sie relevante Keywords natürlich, hinterlegen Sie Bildtitel und strukturieren Sie den Text mit Zwischenüberschriften.'],
|
||||
['q' => 'Was passiert, wenn eine Mitteilung abgelehnt wird?', 'a' => 'Sie erhalten die Ablehnung mit Begründung und können die Mitteilung überarbeiten und erneut einreichen. Ein abgelehnter Beitrag verbraucht kein Kontingent.'],
|
||||
['q' => __('static.faq.q_file_formats'), 'a' => __('static.faq.a_file_formats')],
|
||||
['q' => __('static.faq.q_corrections'), 'a' => __('static.faq.a_corrections')],
|
||||
['q' => __('static.faq.q_seo'), 'a' => __('static.faq.a_seo')],
|
||||
['q' => __('static.faq.q_rejection'), 'a' => __('static.faq.a_rejection')],
|
||||
],
|
||||
],
|
||||
[
|
||||
'title' => 'Newsroom & Funktionen',
|
||||
'title' => __('static.faq.cat_newsroom'),
|
||||
'items' => [
|
||||
['q' => 'Was ist ein Newsroom?', 'a' => 'Ihre Unternehmensseite auf beiden Portalen, auf der alle Ihre Pressemitteilungen gebündelt sind — mit Logo, Kurzprofil und Pressekontakten.'],
|
||||
['q' => 'Welche Statistiken sehe ich?', 'a' => 'Die Aufrufe jeder Mitteilung über beide Portale hinweg, direkt in Ihrem Konto. Die Zahlen werden laufend aktualisiert.'],
|
||||
['q' => 'Gibt es eine API?', 'a' => 'Ja — eine Token-basierte REST-API zum Einreichen von Mitteilungen, Statusabfragen und Bild-Upload. Details finden Sie auf der <a href="'.route('api').'">API-Seite</a>; Ihre Tokens erstellen Sie direkt im Konto, sobald eine aktive Buchung vorliegt.'],
|
||||
['q' => __('static.faq.q_newsroom'), 'a' => __('static.faq.a_newsroom')],
|
||||
['q' => __('static.faq.q_stats'), 'a' => __('static.faq.a_stats')],
|
||||
['q' => __('static.faq.q_api'), 'a' => __('static.faq.a_api', ['url' => route('api')])],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
@ -55,10 +56,10 @@
|
|||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Hilfe"
|
||||
title="Häufig gestellte Fragen"
|
||||
lead="Finden Sie schnell Antworten auf die wichtigsten Fragen rund um Veröffentlichung, Konto und Newsroom."
|
||||
breadcrumb="FAQ"
|
||||
:eyebrow="__('static.faq.eyebrow')"
|
||||
:title="__('static.faq.title')"
|
||||
:lead="__('static.faq.lead')"
|
||||
:breadcrumb="__('static.faq.breadcrumb')"
|
||||
>
|
||||
<div class="max-w-[820px] space-y-10">
|
||||
@foreach ($faqCategories as $category)
|
||||
|
|
@ -86,19 +87,20 @@
|
|||
|
||||
{{-- Abschluss-CTA: Frage nicht gefunden? --}}
|
||||
<div class="max-w-[820px] mt-12 border-t border-bg-rule pt-8">
|
||||
<h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0">Frage nicht gefunden?</h2>
|
||||
<h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0">{{ __('static.faq.not_found') }}</h2>
|
||||
<p class="text-[13.5px] leading-[1.6] text-ink-2 mt-2 mb-5 max-w-[560px]">
|
||||
Unser Support-Team hilft Ihnen gerne weiter – per E-Mail an
|
||||
<a href="mailto:{{ $faqContactEmail }}" class="underline underline-offset-2 hover:text-ink">{{ $faqContactEmail }}</a>.
|
||||
{{ __('static.faq.support_intro') }}
|
||||
<a href="mailto:{{ $faqContactEmail }}" class="underline underline-offset-2 hover:text-ink">{{ $faqContactEmail }}</a>
|
||||
{{ __('static.faq.support_outro') }}
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<a href="mailto:{{ $faqContactEmail }}"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-white bg-brand hover:bg-brand-deep rounded-[2px] transition-colors">
|
||||
Support anschreiben
|
||||
</a>
|
||||
<button type="button" x-data @click="$dispatch('open-contact-modal')"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-white bg-brand hover:bg-brand-deep rounded-[2px] transition-colors cursor-pointer">
|
||||
{{ __('static.faq.write_support') }}
|
||||
</button>
|
||||
<a href="{{ route('hilfe') }}"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-ink border border-bg-rule-strong hover:bg-bg-elev rounded-[2px] transition-colors">
|
||||
Hilfe-Center besuchen
|
||||
{{ __('static.faq.visit_help') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('web.layouts.web-master')
|
||||
|
||||
@section('title', 'Hilfe-Center')
|
||||
@section('meta_description', 'Hilfe-Center: Antworten, Anleitungen und direkter Kontakt zum Support-Team.')
|
||||
@section('title', __('static.help.meta_title'))
|
||||
@section('meta_description', __('static.help.meta_description'))
|
||||
|
||||
@php
|
||||
$publisherUrl = rtrim((string) config('domains.domain_portal_url', config('app.url')), '/');
|
||||
|
|
@ -13,61 +13,62 @@
|
|||
: (str_contains($helpHost, 'presseecho') ? 'presseecho' : 'businessportal24');
|
||||
$helpContactEmail = config('domains.domains.'.$helpBrandKey.'.brand.contact_email') ?? 'info@businessportal24.com';
|
||||
|
||||
// Hilfe-Themen mit Links auf vorhandene Ziele.
|
||||
// Hilfe-Themen mit Links auf vorhandene Ziele; Texte aus static.help.*.
|
||||
$helpTopics = [
|
||||
[
|
||||
'title' => 'Erste Schritte',
|
||||
'title' => __('static.help.topic_start'),
|
||||
'links' => [
|
||||
['label' => 'Konto erstellen', 'href' => $publisherUrl.'/register'],
|
||||
['label' => 'Erste Pressemitteilung veröffentlichen', 'href' => route('veroeffentlichen')],
|
||||
['label' => 'Newsrooms entdecken', 'href' => route('newsrooms')],
|
||||
['label' => 'Häufige Fragen zum Einstieg', 'href' => route('faq')],
|
||||
['label' => __('static.help.link_create_account'), 'href' => $publisherUrl.'/register'],
|
||||
['label' => __('static.help.link_first_pm'), 'href' => route('veroeffentlichen')],
|
||||
['label' => __('static.help.link_discover_newsrooms'), 'href' => route('newsrooms')],
|
||||
['label' => __('static.help.link_faq_start'), 'href' => route('faq')],
|
||||
],
|
||||
],
|
||||
[
|
||||
'title' => 'Pressemitteilungen',
|
||||
'title' => __('static.help.topic_releases'),
|
||||
'links' => [
|
||||
['label' => 'Dateiformate und Größen', 'href' => route('faq')],
|
||||
['label' => 'SEO-Optimierung', 'href' => route('faq')],
|
||||
['label' => 'Korrekturen nach Veröffentlichung', 'href' => route('faq')],
|
||||
['label' => __('static.help.link_file_formats'), 'href' => route('faq')],
|
||||
['label' => __('static.help.link_seo'), 'href' => route('faq')],
|
||||
['label' => __('static.help.link_corrections'), 'href' => route('faq')],
|
||||
],
|
||||
],
|
||||
[
|
||||
'title' => 'Konto & Abrechnung',
|
||||
'title' => __('static.help.topic_account'),
|
||||
'links' => [
|
||||
['label' => 'Tarif wechseln', 'href' => route('preise')],
|
||||
['label' => 'Rechnungen im Konto abrufen', 'href' => $publisherUrl.'/login'],
|
||||
['label' => 'Vertrag kündigen', 'href' => route('kuendigung')],
|
||||
['label' => __('static.help.link_change_plan'), 'href' => route('preise')],
|
||||
['label' => __('static.help.link_invoices'), 'href' => $publisherUrl.'/login'],
|
||||
['label' => __('static.help.link_cancel'), 'href' => route('kuendigung')],
|
||||
],
|
||||
],
|
||||
[
|
||||
'title' => 'Erweiterte Funktionen',
|
||||
'title' => __('static.help.topic_advanced'),
|
||||
'links' => [
|
||||
['label' => 'API-Integration', 'href' => route('api')],
|
||||
['label' => 'Statistiken zu Aufrufen', 'href' => route('faq')],
|
||||
['label' => 'Newsroom pflegen', 'href' => $publisherUrl.'/login'],
|
||||
['label' => __('static.help.link_api'), 'href' => route('api')],
|
||||
['label' => __('static.help.link_stats'), 'href' => route('faq')],
|
||||
['label' => __('static.help.link_newsroom'), 'href' => $publisherUrl.'/login'],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$quickLinks = [
|
||||
['label' => 'FAQ', 'desc' => 'Häufig gestellte Fragen', 'href' => route('faq')],
|
||||
['label' => 'Veröffentlichen', 'desc' => 'In wenigen Schritten zur Meldung', 'href' => route('veroeffentlichen')],
|
||||
['label' => 'Kontakt', 'desc' => 'Direkter Draht zum Support', 'href' => 'mailto:'.$helpContactEmail],
|
||||
['label' => __('static.help.quick_faq'), 'desc' => __('static.help.quick_faq_desc'), 'href' => route('faq')],
|
||||
['label' => __('static.help.quick_publish'), 'desc' => __('static.help.quick_publish_desc'), 'href' => route('veroeffentlichen')],
|
||||
['label' => __('static.help.quick_contact'), 'desc' => __('static.help.quick_contact_desc'), 'href' => null, 'contact' => true],
|
||||
];
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Hilfe"
|
||||
title="Hilfe-Center"
|
||||
lead="Finden Sie Antworten und Anleitungen – oder kontaktieren Sie unser Support-Team direkt."
|
||||
breadcrumb="Hilfe"
|
||||
:eyebrow="__('static.help.eyebrow')"
|
||||
:title="__('static.help.title')"
|
||||
:lead="__('static.help.lead')"
|
||||
:breadcrumb="__('static.help.breadcrumb')"
|
||||
>
|
||||
{{-- Schnellzugriff --}}
|
||||
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-3">
|
||||
@foreach ($quickLinks as $link)
|
||||
<a href="{{ $link['href'] }}" class="group bg-bg p-6 hover:bg-bg-elev transition-colors">
|
||||
<a @if ($link['contact'] ?? false) href="#" x-data @click.prevent="$dispatch('open-contact-modal')" @else href="{{ $link['href'] }}" @endif
|
||||
class="group bg-bg p-6 hover:bg-bg-elev transition-colors cursor-pointer">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<span class="text-[15px] font-semibold text-ink group-hover:text-brand transition-colors">{{ $link['label'] }}</span>
|
||||
<svg width="13" height="13" viewBox="0 0 12 12" fill="none" aria-hidden="true" class="text-ink-3 group-hover:text-brand transition-colors">
|
||||
|
|
@ -80,7 +81,7 @@
|
|||
</div>
|
||||
|
||||
{{-- Hilfe-Themen --}}
|
||||
<h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0 mt-12 mb-4">Hilfe-Themen</h2>
|
||||
<h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0 mt-12 mb-4">{{ __('static.help.topics_heading') }}</h2>
|
||||
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 md:grid-cols-2">
|
||||
@foreach ($helpTopics as $topic)
|
||||
<div class="bg-bg p-6">
|
||||
|
|
@ -102,17 +103,17 @@
|
|||
{{-- Support-CTA --}}
|
||||
<div class="mt-12 border border-bg-rule bg-bg-elev p-6 sm:p-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-5">
|
||||
<div>
|
||||
<h2 class="font-serif text-[20px] font-semibold tracking-[-0.3px] text-ink m-0">Benötigen Sie weitere Hilfe?</h2>
|
||||
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">Unser Support-Team antwortet werktags per E-Mail.</p>
|
||||
<h2 class="font-serif text-[20px] font-semibold tracking-[-0.3px] text-ink m-0">{{ __('static.help.cta_heading') }}</h2>
|
||||
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">{{ __('static.help.cta_text') }}</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-3 flex-shrink-0">
|
||||
<a href="mailto:{{ $helpContactEmail }}"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-white bg-brand hover:bg-brand-deep rounded-[2px] transition-colors">
|
||||
Support kontaktieren
|
||||
</a>
|
||||
<button type="button" x-data @click="$dispatch('open-contact-modal')"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-white bg-brand hover:bg-brand-deep rounded-[2px] transition-colors cursor-pointer">
|
||||
{{ __('static.help.cta_contact') }}
|
||||
</button>
|
||||
<a href="{{ route('faq') }}"
|
||||
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-ink border border-bg-rule-strong hover:bg-bg transition-colors rounded-[2px]">
|
||||
FAQ durchsuchen
|
||||
{{ __('static.help.cta_faq') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('web.layouts.web-master')
|
||||
|
||||
@section('title', 'Impressum')
|
||||
@section('meta_description', 'Impressum und Anbieterkennzeichnung gemäß § 5 DDG.')
|
||||
@section('title', __('static.imprint.meta_title'))
|
||||
@section('meta_description', __('static.imprint.meta_description'))
|
||||
|
||||
@php
|
||||
// Single-Source-Template (Rechtstexte-Architektur E3): ein Inhalt, drei
|
||||
|
|
@ -18,12 +18,12 @@
|
|||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Rechtliches"
|
||||
title="Impressum"
|
||||
breadcrumb="Impressum"
|
||||
:eyebrow="__('static.legal.eyebrow')"
|
||||
:title="__('static.imprint.title')"
|
||||
:breadcrumb="__('static.imprint.breadcrumb')"
|
||||
>
|
||||
<div class="pm-body max-w-[760px]">
|
||||
<h2>Anbieter (Angaben gemäß § 5 DDG)</h2>
|
||||
<h2>{{ __('static.imprint.provider_heading') }}</h2>
|
||||
<p>
|
||||
adametz.media<br>
|
||||
Inhaber: Kevin Adametz<br>
|
||||
|
|
@ -32,17 +32,17 @@
|
|||
Deutschland
|
||||
</p>
|
||||
<p>
|
||||
E-Mail: <a href="mailto:{{ $contactEmail }}">{{ $contactEmail }}</a><br>
|
||||
Telefon: +49 5206 7076721 (kein telefonischer Support)
|
||||
{{ __('static.imprint.email_label') }}: <a href="mailto:{{ $contactEmail }}">{{ $contactEmail }}</a><br>
|
||||
{{ __('static.imprint.phone_label') }}: +49 5206 7076721 {{ __('static.imprint.phone_note') }}
|
||||
</p>
|
||||
|
||||
<h3>Umsatzsteuer-Identifikationsnummer</h3>
|
||||
<h3>{{ __('static.imprint.vat_heading') }}</h3>
|
||||
<p>
|
||||
Umsatzsteuer-Identifikationsnummer gemäß § 27a UStG:<br>
|
||||
{{ __('static.imprint.vat_text') }}<br>
|
||||
DE298729654
|
||||
</p>
|
||||
|
||||
<h2>Verantwortlich für journalistisch-redaktionelle Inhalte (§ 18 Abs. 2 MStV)</h2>
|
||||
<h2>{{ __('static.imprint.editorial_heading') }}</h2>
|
||||
<p>
|
||||
Kevin Adametz<br>
|
||||
In der Lake 4<br>
|
||||
|
|
@ -50,53 +50,26 @@
|
|||
Deutschland
|
||||
</p>
|
||||
|
||||
<h2>Zu diesem Angebot</h2>
|
||||
<p>
|
||||
{{ $portalName }} ({{ $host }}) wird betrieben von adametz.media. Zum Verbund gehören die
|
||||
Presseportale <strong>presseecho.de</strong> und <strong>businessportal24.com</strong> sowie
|
||||
das zentrale Publisher-Konto <strong>pressekonto</strong>
|
||||
(<a href="{{ $hubUrl }}">{{ str_replace(['https://', 'http://'], '', $hubUrl) }}</a>),
|
||||
über das Registrierung, Buchung und Verwaltung erfolgen.
|
||||
</p>
|
||||
<h2>{{ __('static.imprint.about_heading') }}</h2>
|
||||
<p>{!! __('static.imprint.about_text', [
|
||||
'portal' => e($portalName),
|
||||
'host' => e($host),
|
||||
'hub_url' => $hubUrl,
|
||||
'hub_label' => str_replace(['https://', 'http://'], '', $hubUrl),
|
||||
]) !!}</p>
|
||||
|
||||
<h2>Verantwortlichkeit für Inhalte</h2>
|
||||
<p>
|
||||
Die auf den Portalen veröffentlichten Pressemitteilungen sind Inhalte der jeweiligen
|
||||
einreichenden Unternehmen; diese sind für ihre Inhalte selbst verantwortlich. Der Anbieter
|
||||
ist Hostingdiensteanbieter im Sinne des Digital Services Act (Verordnung (EU) 2022/2065);
|
||||
für fremde Inhalte gelten die Haftungsregeln des DSA (Art. 6) und des § 7 DDG. Wenn Sie
|
||||
einen Inhalt für rechtswidrig halten oder Ihre Rechte verletzt sehen, nutzen Sie bitte unser
|
||||
<a href="{{ route('melden') }}">Meldeverfahren</a> — Meldungen sind kostenlos.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Kontaktpunkt</strong> gemäß Art. 11 und 12 DSA (für Behörden und Nutzer):<br>
|
||||
E-Mail: <a href="mailto:{{ $reportEmail }}">{{ $reportEmail }}</a> ·
|
||||
Kommunikationssprachen: Deutsch, Englisch
|
||||
</p>
|
||||
<h2>{{ __('static.imprint.content_heading') }}</h2>
|
||||
<p>{!! __('static.imprint.content_text', ['report_url' => route('melden')]) !!}</p>
|
||||
<p>{!! __('static.imprint.contact_point', ['email' => e($reportEmail)]) !!}</p>
|
||||
|
||||
<h2>Verbotene Inhalte</h2>
|
||||
<p>
|
||||
Inhalte, die gegen geltendes Recht oder unsere
|
||||
<a href="{{ route('richtlinien') }}">Veröffentlichungsrichtlinien</a> verstoßen, werden
|
||||
nicht veröffentlicht bzw. nach Kenntnis entfernt. Bei Hinweisen auf Straftaten behalten wir
|
||||
uns die Erstattung einer Strafanzeige und die Weitergabe an die zuständigen Behörden vor.
|
||||
</p>
|
||||
<h2>{{ __('static.imprint.prohibited_heading') }}</h2>
|
||||
<p>{!! __('static.imprint.prohibited_text', ['guidelines_url' => route('richtlinien')]) !!}</p>
|
||||
|
||||
<h2>Urheberrecht</h2>
|
||||
<p>
|
||||
Die durch den Anbieter erstellten Inhalte und Werke auf diesen Seiten unterliegen dem
|
||||
deutschen Urheberrecht. Beiträge Dritter (insbesondere Pressemitteilungen) sind als solche
|
||||
gekennzeichnet; die Rechte liegen bei den jeweiligen Einreichern. Vervielfältigung,
|
||||
Bearbeitung und Verwertung außerhalb der Grenzen des Urheberrechts bedürfen der Zustimmung
|
||||
des jeweiligen Rechteinhabers.
|
||||
</p>
|
||||
<h2>{{ __('static.imprint.copyright_heading') }}</h2>
|
||||
<p>{{ __('static.imprint.copyright_text') }}</p>
|
||||
|
||||
<h2>Verbraucherstreitbeilegung</h2>
|
||||
<p>
|
||||
Der Anbieter ist nicht bereit und nicht verpflichtet, an Streitbeilegungsverfahren vor einer
|
||||
Verbraucherschlichtungsstelle teilzunehmen (§ 36 VSBG). Die frühere Plattform der
|
||||
EU-Kommission zur Online-Streitbeilegung wurde zum 20. Juli 2025 eingestellt.
|
||||
</p>
|
||||
<h2>{{ __('static.imprint.dispute_heading') }}</h2>
|
||||
<p>{{ __('static.imprint.dispute_text') }}</p>
|
||||
</div>
|
||||
</x-web.static-page>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
$leadImage = $leadRelease?->images->first();
|
||||
$leadImageUrl = $leadImage?->variantUrl('detail') ?? $leadImage?->variantUrl('card') ?? $leadImage?->url();
|
||||
$leadPlaceholderUrl = $leadImageUrl ? null : $leadRelease?->chosenPlaceholderUrl();
|
||||
$leadCat = $leadRelease?->category?->translations->firstWhere('locale', app()->getLocale()) ?? $leadRelease?->category?->translations->first();
|
||||
$leadCompany = $leadRelease?->company?->name;
|
||||
$leadLead = $leadRelease
|
||||
|
|
@ -125,6 +126,8 @@
|
|||
<div class="relative overflow-hidden bg-hero-grad" style="aspect-ratio: 16 / 10;">
|
||||
@if ($leadImageUrl)
|
||||
<img src="{{ $leadImageUrl }}" alt="{{ $leadRelease->title }}" class="absolute inset-0 w-full h-full object-cover" loading="lazy">
|
||||
@elseif ($leadPlaceholderUrl)
|
||||
<img src="{{ $leadPlaceholderUrl }}" alt="" aria-hidden="true" class="absolute inset-0 w-full h-full object-cover" loading="lazy">
|
||||
@else
|
||||
<x-web.hero-fallback />
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('web.layouts.web-master')
|
||||
|
||||
@section('title', 'Verträge hier kündigen')
|
||||
@section('meta_description', 'Kündigen Sie Ihren laufenden Vertrag online – ohne Login, über die gesetzliche Bestätigungsseite nach § 312k BGB.')
|
||||
@section('title', __('static.cancellation.meta_title'))
|
||||
@section('meta_description', __('static.cancellation.meta_description'))
|
||||
|
||||
{{--
|
||||
Bestätigungsseite des gesetzlichen Kündigungsbuttons (§ 312k BGB).
|
||||
|
|
@ -14,16 +14,16 @@
|
|||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Rechtliches"
|
||||
title="Verträge hier kündigen"
|
||||
breadcrumb="Kündigung"
|
||||
lead="Hier können Sie Ihren laufenden Vertrag (z. B. Ihr Abo) online und ohne Anmeldung kündigen. Nach dem Absenden erhalten Sie sofort eine automatische Eingangsbestätigung per E-Mail mit Datum und Uhrzeit des Zugangs."
|
||||
:eyebrow="__('static.legal.eyebrow')"
|
||||
:title="__('static.cancellation.title')"
|
||||
:breadcrumb="__('static.cancellation.breadcrumb')"
|
||||
:lead="__('static.cancellation.lead')"
|
||||
>
|
||||
<div class="max-w-[680px]">
|
||||
@if (session('termination-status'))
|
||||
<div class="border border-bg-rule bg-bg-elev p-6" role="status">
|
||||
<div class="section-eyebrow mb-3">Kündigung</div>
|
||||
<h2 class="text-[19px] font-bold text-ink tracking-[-0.3px] m-0 mb-2">Kündigung eingegangen</h2>
|
||||
<div class="section-eyebrow mb-3">{{ __('static.cancellation.received_eyebrow') }}</div>
|
||||
<h2 class="text-[19px] font-bold text-ink tracking-[-0.3px] m-0 mb-2">{{ __('static.cancellation.received_heading') }}</h2>
|
||||
<p class="text-[13.5px] text-ink-2 leading-[1.6] m-0">
|
||||
{{ session('termination-status') }}
|
||||
</p>
|
||||
|
|
@ -38,21 +38,21 @@
|
|||
|
||||
{{-- Art der Kündigung --}}
|
||||
<fieldset class="border border-bg-rule p-5 m-0">
|
||||
<legend class="text-[12px] font-semibold text-ink px-2">Art der Kündigung</legend>
|
||||
<legend class="text-[12px] font-semibold text-ink px-2">{{ __('static.cancellation.kind_legend') }}</legend>
|
||||
|
||||
<div class="space-y-3">
|
||||
<label class="flex items-start gap-3 cursor-pointer">
|
||||
<input type="radio" name="kind" value="ordentlich" x-model="kind" class="mt-0.5">
|
||||
<span>
|
||||
<span class="block text-[13.5px] font-semibold text-ink">Ordentliche Kündigung</span>
|
||||
<span class="block text-[12.5px] text-ink-3 leading-[1.5]">Kündigung zum Ende der Laufzeit bzw. zum nächstmöglichen Zeitpunkt. Ein Grund ist nicht erforderlich.</span>
|
||||
<span class="block text-[13.5px] font-semibold text-ink">{{ __('static.cancellation.kind_ordinary') }}</span>
|
||||
<span class="block text-[12.5px] text-ink-3 leading-[1.5]">{{ __('static.cancellation.kind_ordinary_desc') }}</span>
|
||||
</span>
|
||||
</label>
|
||||
<label class="flex items-start gap-3 cursor-pointer">
|
||||
<input type="radio" name="kind" value="ausserordentlich" x-model="kind" class="mt-0.5">
|
||||
<span>
|
||||
<span class="block text-[13.5px] font-semibold text-ink">Außerordentliche Kündigung</span>
|
||||
<span class="block text-[12.5px] text-ink-3 leading-[1.5]">Kündigung aus wichtigem Grund mit sofortiger Wirkung.</span>
|
||||
<span class="block text-[13.5px] font-semibold text-ink">{{ __('static.cancellation.kind_extraordinary') }}</span>
|
||||
<span class="block text-[12.5px] text-ink-3 leading-[1.5]">{{ __('static.cancellation.kind_extraordinary_desc') }}</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
@enderror
|
||||
|
||||
<div x-show="kind === 'ausserordentlich'" x-cloak class="mt-4">
|
||||
<label for="termination-reason" class="block text-[12px] font-semibold text-ink mb-1.5">Kündigungsgrund</label>
|
||||
<label for="termination-reason" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.cancellation.label_reason') }}</label>
|
||||
<textarea id="termination-reason" name="reason" rows="3"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub">{{ old('reason') }}</textarea>
|
||||
@error('reason', 'termination')
|
||||
|
|
@ -72,11 +72,11 @@
|
|||
|
||||
{{-- Zuordnung des Vertrags --}}
|
||||
<fieldset class="border border-bg-rule p-5 m-0 mt-6">
|
||||
<legend class="text-[12px] font-semibold text-ink px-2">Wer kündigt?</legend>
|
||||
<legend class="text-[12px] font-semibold text-ink px-2">{{ __('static.cancellation.who_legend') }}</legend>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label for="termination-name" class="block text-[12px] font-semibold text-ink mb-1.5">Ihr Name</label>
|
||||
<label for="termination-name" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.cancellation.label_name') }}</label>
|
||||
<input id="termination-name" type="text" name="name" value="{{ old('name') }}" required autocomplete="name"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
|
||||
@error('name', 'termination')
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label for="termination-email" class="block text-[12px] font-semibold text-ink mb-1.5">E-Mail-Adresse <span class="text-ink-3 font-normal">(zur Vertragszuordnung und für die Eingangsbestätigung)</span></label>
|
||||
<label for="termination-email" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.cancellation.label_email') }} <span class="text-ink-3 font-normal">{{ __('static.cancellation.label_email_hint') }}</span></label>
|
||||
<input id="termination-email" type="email" name="email" value="{{ old('email') }}" required autocomplete="email"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
|
||||
@error('email', 'termination')
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
|
||||
<div>
|
||||
<label for="termination-reference" class="block text-[12px] font-semibold text-ink mb-1.5">
|
||||
Vertrags-/Rechnungsnummer <span class="text-ink-3 font-normal">(falls zur Hand)</span>
|
||||
{{ __('static.cancellation.label_reference') }} <span class="text-ink-3 font-normal">{{ __('static.cancellation.label_reference_hint') }}</span>
|
||||
</label>
|
||||
<input id="termination-reference" type="text" name="contract_reference" value="{{ old('contract_reference') }}"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
|
||||
|
|
@ -108,16 +108,16 @@
|
|||
|
||||
{{-- Beendigungszeitpunkt --}}
|
||||
<fieldset class="border border-bg-rule p-5 m-0 mt-6">
|
||||
<legend class="text-[12px] font-semibold text-ink px-2">Zu welchem Zeitpunkt?</legend>
|
||||
<legend class="text-[12px] font-semibold text-ink px-2">{{ __('static.cancellation.when_legend') }}</legend>
|
||||
|
||||
<div class="space-y-3">
|
||||
<label class="flex items-center gap-3 cursor-pointer">
|
||||
<input type="radio" name="terminate_mode" value="asap" x-model="terminateMode">
|
||||
<span class="text-[13.5px] text-ink">Zum nächstmöglichen Zeitpunkt</span>
|
||||
<span class="text-[13.5px] text-ink">{{ __('static.cancellation.mode_asap') }}</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-3 cursor-pointer">
|
||||
<input type="radio" name="terminate_mode" value="date" x-model="terminateMode">
|
||||
<span class="text-[13.5px] text-ink">Zu einem bestimmten Datum</span>
|
||||
<span class="text-[13.5px] text-ink">{{ __('static.cancellation.mode_date') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
@error('terminate_mode', 'termination')
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
@enderror
|
||||
|
||||
<div x-show="terminateMode === 'date'" x-cloak class="mt-4">
|
||||
<label for="termination-date" class="block text-[12px] font-semibold text-ink mb-1.5">Gewünschtes Beendigungsdatum</label>
|
||||
<label for="termination-date" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.cancellation.label_date') }}</label>
|
||||
<input id="termination-date" type="date" name="terminate_at" value="{{ old('terminate_at') }}"
|
||||
class="border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
|
||||
@error('terminate_at', 'termination')
|
||||
|
|
@ -144,21 +144,18 @@
|
|||
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mt-7">
|
||||
<p class="text-[11px] text-ink-3 leading-[1.5] m-0 max-w-[380px]">
|
||||
Ihre Angaben werden nur zur Bearbeitung der Kündigung verarbeitet
|
||||
(<a href="{{ route('datenschutz', ['edition' => 'de']) }}" class="underline hover:text-ink">Datenschutz</a>).
|
||||
Mit dem Klick geht Ihre Kündigungserklärung bei uns ein.
|
||||
{!! __('static.cancellation.privacy_note', ['url' => route('datenschutz', ['edition' => 'de'])]) !!}
|
||||
</p>
|
||||
{{-- § 312k BGB: Bestätigungsschaltfläche, Aufschrift „jetzt kündigen". --}}
|
||||
<button type="submit"
|
||||
class="inline-flex items-center justify-center px-6 py-3 text-[14px] font-semibold text-white bg-hub hover:bg-hub-2 rounded-[4px] whitespace-nowrap transition-colors cursor-pointer">
|
||||
jetzt kündigen
|
||||
{{ __('static.cancellation.submit') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="text-[12px] text-ink-3 leading-[1.6] mt-8 mb-0">
|
||||
Hinweis: Angemeldet geht es noch schneller — in Ihrem Konto unter „Buchungen & Add-ons"
|
||||
kündigen Sie Ihr Abo mit wenigen Klicks.
|
||||
{{ __('static.cancellation.account_hint') }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,36 +7,27 @@
|
|||
// "Recht & Compliance" und bestätigen den Eingang per E-Mail.
|
||||
$isIllegalContent = $way === 'rechtswidrig';
|
||||
$pageTitle = $isIllegalContent
|
||||
? 'Rechtswidrige Inhalte melden'
|
||||
: 'Eigene Kontaktdaten entfernen lassen';
|
||||
? __('static.report_form.title_illegal')
|
||||
: __('static.report_form.title_contact_data');
|
||||
@endphp
|
||||
|
||||
@section('title', $pageTitle)
|
||||
@section('meta_description', $isIllegalContent
|
||||
? 'Rechtswidrige Inhalte oder Rechteverletzungen in einer Pressemitteilung melden (DSA) — kostenlos, mit Eingangsbestätigung.'
|
||||
: 'Entfernung eigener personenbezogener Kontaktdaten aus einer Pressemitteilung beantragen (DSGVO) — kostenlos.')
|
||||
? __('static.report_form.meta_illegal')
|
||||
: __('static.report_form.meta_contact_data'))
|
||||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Rechtliches"
|
||||
:eyebrow="__('static.legal.eyebrow')"
|
||||
:title="$pageTitle"
|
||||
breadcrumb="Inhalte melden"
|
||||
:breadcrumb="__('static.report_form.breadcrumb')"
|
||||
>
|
||||
<div class="max-w-[640px]">
|
||||
<p class="text-[13.5px] text-ink-2 leading-relaxed mb-2">
|
||||
@if ($isIllegalContent)
|
||||
Nutzen Sie dieses Formular, wenn Sie eine veröffentlichte Pressemitteilung für
|
||||
rechtswidrig halten oder Ihre Rechte verletzt sehen. Die Meldung ist kostenlos;
|
||||
Sie erhalten unverzüglich eine Eingangsbestätigung mit Vorgangsnummer und
|
||||
anschließend unsere begründete Entscheidung.
|
||||
@else
|
||||
Nutzen Sie dieses Formular, wenn Ihre persönlichen Kontaktdaten (z. B. Name,
|
||||
Telefonnummer oder E-Mail-Adresse) in einer Pressemitteilung stehen. Die Prüfung
|
||||
erfolgt nach den Vorgaben der DSGVO und ist für Sie kostenlos.
|
||||
@endif
|
||||
{{ $isIllegalContent ? __('static.report_form.intro_illegal') : __('static.report_form.intro_contact_data') }}
|
||||
</p>
|
||||
<p class="text-[12.5px] text-ink-3 leading-relaxed mb-6">
|
||||
Alle Wege im Überblick: <a href="{{ route('melden') }}" class="underline underline-offset-2 hover:text-ink">Inhalte melden oder Änderungen beantragen</a>
|
||||
{{ __('static.report_form.overview') }} <a href="{{ route('melden') }}" class="underline underline-offset-2 hover:text-ink">{{ __('static.report_form.overview_link') }}</a>
|
||||
</p>
|
||||
|
||||
@if (session('report-status'))
|
||||
|
|
@ -49,7 +40,7 @@
|
|||
@csrf
|
||||
|
||||
<div>
|
||||
<label for="reported_url" class="block text-[12px] font-semibold text-ink mb-1.5">URL der betroffenen Pressemitteilung</label>
|
||||
<label for="reported_url" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.report_form.label_url') }}</label>
|
||||
<input id="reported_url" type="url" name="reported_url" value="{{ old('reported_url') }}" required
|
||||
placeholder="https://…"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand" />
|
||||
|
|
@ -59,7 +50,7 @@
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label for="requester_name" class="block text-[12px] font-semibold text-ink mb-1.5">Ihr Name</label>
|
||||
<label for="requester_name" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.report_form.label_name') }}</label>
|
||||
<input id="requester_name" type="text" name="requester_name" value="{{ old('requester_name') }}" required
|
||||
autocomplete="name"
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand" />
|
||||
|
|
@ -70,7 +61,7 @@
|
|||
|
||||
<div>
|
||||
<label for="requester_email" class="block text-[12px] font-semibold text-ink mb-1.5">
|
||||
{{ $isIllegalContent ? 'Ihre E-Mail-Adresse' : 'Ihre E-Mail-Adresse (für Rückmeldung und ggf. Bestätigungslink)' }}
|
||||
{{ $isIllegalContent ? __('static.report_form.label_email_illegal') : __('static.report_form.label_email_contact_data') }}
|
||||
</label>
|
||||
<input id="requester_email" type="email" name="requester_email" value="{{ old('requester_email') }}" required
|
||||
autocomplete="email"
|
||||
|
|
@ -82,11 +73,11 @@
|
|||
|
||||
<div>
|
||||
<label for="message" class="block text-[12px] font-semibold text-ink mb-1.5">
|
||||
{{ $isIllegalContent ? 'Begründung: Warum halten Sie den Inhalt für rechtswidrig?' : 'Welche Angaben sind betroffen?' }}
|
||||
{{ $isIllegalContent ? __('static.report_form.label_message_illegal') : __('static.report_form.label_message_contact_data') }}
|
||||
</label>
|
||||
<textarea id="message" name="message" rows="6" required
|
||||
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand"
|
||||
placeholder="{{ $isIllegalContent ? 'Bitte beschreiben Sie konkret, welche Inhalte betroffen sind und warum.' : 'z. B. „Mein Name und meine Telefonnummer stehen im Pressekontakt.“' }}">{{ old('message') }}</textarea>
|
||||
placeholder="{{ $isIllegalContent ? __('static.report_form.placeholder_message_illegal') : __('static.report_form.placeholder_message_contact_data') }}">{{ old('message') }}</textarea>
|
||||
@error('message')
|
||||
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
|
|
@ -98,8 +89,7 @@
|
|||
<input type="checkbox" name="truth_affirmed" value="1" @checked(old('truth_affirmed'))
|
||||
class="mt-0.5 flex-shrink-0" />
|
||||
<span>
|
||||
Ich versichere, dass ich diese Meldung nach bestem Wissen und Gewissen
|
||||
abgebe und die Angaben richtig und vollständig sind.
|
||||
{{ __('static.report_form.truth_affirmation') }}
|
||||
</span>
|
||||
</label>
|
||||
@error('truth_affirmed')
|
||||
|
|
@ -118,14 +108,12 @@
|
|||
|
||||
<button type="submit"
|
||||
class="bg-brand hover:bg-brand-deep text-white px-5 py-2.5 text-[13px] font-semibold transition-colors">
|
||||
{{ $isIllegalContent ? 'Meldung absenden' : 'Antrag absenden' }}
|
||||
{{ $isIllegalContent ? __('static.report_form.submit_illegal') : __('static.report_form.submit_contact_data') }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="mt-6 text-[11.5px] text-ink-3 leading-relaxed">
|
||||
Ihre Angaben werden ausschließlich zur Bearbeitung Ihrer Meldung verarbeitet —
|
||||
Details in der <a href="{{ route('datenschutz') }}" class="underline hover:text-ink">Datenschutzerklärung</a>.
|
||||
Meldungen und die Ausübung gesetzlicher Rechte sind kostenlos.
|
||||
{!! __('static.report_form.privacy_note', ['url' => route('datenschutz')]) !!}
|
||||
</p>
|
||||
</div>
|
||||
</x-web.static-page>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('web.layouts.web-master')
|
||||
|
||||
@section('title', 'Inhalte melden oder Änderungen beantragen')
|
||||
@section('meta_description', 'Rechtswidrige Inhalte melden (DSA), personenbezogene Daten entfernen lassen (DSGVO) oder Änderungen an eigenen Pressemitteilungen beantragen — Meldungen sind kostenlos.')
|
||||
@section('title', __('static.report.meta_title'))
|
||||
@section('meta_description', __('static.report.meta_description'))
|
||||
|
||||
@php
|
||||
// Meldeverfahren v0.1 (Rechtstexte-Architektur, 03.07.2026). Die Wege 1/2
|
||||
|
|
@ -13,147 +13,76 @@
|
|||
$brandKey = $isHub ? 'pressekonto' : (str_contains($host, 'presseecho') ? 'presseecho' : 'businessportal24');
|
||||
$brand = config('domains.domains.'.$brandKey.'.brand', []);
|
||||
$portalName = ($brand['name'] ?? '').($brand['accent'] ?? '');
|
||||
$contactEmail = (string) config('legal.contact_email');
|
||||
$reportEmail = $brand['report_email'] ?? $contactEmail;
|
||||
$loginUrl = rtrim((string) config('domains.domain_portal_url', config('app.url')), '/').'/login';
|
||||
|
||||
// Statt der Melde-E-Mail-Adresse verweisen alle Wege auf das schwebende
|
||||
// Kontakt-Widget (Badge unten rechts) — derselbe Trigger wie im Footer.
|
||||
$contactTrigger = sprintf(
|
||||
'<button type="button" x-data @click="$dispatch(\'open-contact-modal\')" class="underline underline-offset-2 cursor-pointer hover:text-ink">%s</button>',
|
||||
e(__('static.report.contact_trigger_label')),
|
||||
);
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Rechtliches"
|
||||
title="Inhalte melden oder Änderungen beantragen"
|
||||
lead="Auf {{ $portalName }} veröffentlichen Unternehmen Pressemitteilungen in eigener Verantwortung. Wenn Sie ein Anliegen zu einer veröffentlichten Pressemitteilung haben, wählen Sie bitte den passenden Weg."
|
||||
breadcrumb="Inhalte melden"
|
||||
:eyebrow="__('static.legal.eyebrow')"
|
||||
:title="__('static.report.title')"
|
||||
:lead="__('static.report.lead', ['portal' => $portalName])"
|
||||
:breadcrumb="__('static.report.breadcrumb')"
|
||||
>
|
||||
<div class="pm-body max-w-[760px]">
|
||||
<p>
|
||||
Sie können eine Pressemitteilung direkt über den Link <strong>„Pressemitteilung
|
||||
melden"</strong> auf der jeweiligen Veröffentlichungsseite melden — dabei wird die
|
||||
betroffene Pressemitteilung automatisch übernommen.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Die Meldung rechtswidriger Inhalte und die Ausübung gesetzlicher Rechte sind immer
|
||||
kostenlos.</strong> Kostenpflichtig ist nur die freiwillige Entfernung rechtmäßiger Inhalte
|
||||
aus der öffentlichen Ansicht.
|
||||
</p>
|
||||
<p>{!! __('static.report.intro_direct') !!}</p>
|
||||
<p>{!! __('static.report.intro_free') !!}</p>
|
||||
|
||||
<h2>1. Rechtswidrige Inhalte oder Rechteverletzungen melden</h2>
|
||||
<p>
|
||||
Nutzen Sie diesen Weg, wenn Sie der Ansicht sind, dass eine veröffentlichte Pressemitteilung
|
||||
rechtswidrig ist oder Ihre Rechte verletzt, zum Beispiel bei:
|
||||
</p>
|
||||
<h2>{{ __('static.report.way1_heading') }}</h2>
|
||||
<p>{{ __('static.report.way1_intro') }}</p>
|
||||
<ul>
|
||||
<li>falschen Tatsachenbehauptungen,</li>
|
||||
<li>Verletzung von Persönlichkeitsrechten,</li>
|
||||
<li>Verletzung von Marken-, Urheber- oder sonstigen Rechten,</li>
|
||||
<li>Datenschutzverstößen oder unzulässiger Veröffentlichung personenbezogener Daten,</li>
|
||||
<li>Betrug, Irreführung oder rechtswidriger Werbung,</li>
|
||||
<li>sonstigen gesetzlichen Verstößen.</li>
|
||||
<li>{{ __('static.report.way1_item_1') }}</li>
|
||||
<li>{{ __('static.report.way1_item_2') }}</li>
|
||||
<li>{{ __('static.report.way1_item_3') }}</li>
|
||||
<li>{{ __('static.report.way1_item_4') }}</li>
|
||||
<li>{{ __('static.report.way1_item_5') }}</li>
|
||||
<li>{{ __('static.report.way1_item_6') }}</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Meldung:</strong> Nutzen Sie unser
|
||||
<a href="{{ route('melden.form', ['way' => 'rechtswidrig']) }}">Meldeformular für
|
||||
rechtswidrige Inhalte</a> — Sie erhalten unverzüglich eine Eingangsbestätigung mit
|
||||
Vorgangsnummer. Alternativ öffnen Sie die betroffene Pressemitteilung und nutzen dort
|
||||
den Link <em>„Inhalt melden"</em> (die Mitteilung wird dabei automatisch dem Vorgang
|
||||
zugeordnet), oder Sie senden Ihre Meldung mit der URL der betroffenen Pressemitteilung
|
||||
an <a href="mailto:{{ $reportEmail }}">{{ $reportEmail }}</a>.
|
||||
</p>
|
||||
<p>Damit wir Ihre Meldung prüfen können, benötigen wir:</p>
|
||||
<p>{!! __('static.report.way1_how', ['form_url' => route('melden.form', ['way' => 'rechtswidrig']), 'contact' => $contactTrigger]) !!}</p>
|
||||
<p>{{ __('static.report.way1_needs') }}</p>
|
||||
<ul>
|
||||
<li>die URL der betroffenen Pressemitteilung,</li>
|
||||
<li>eine Begründung, warum Sie den Inhalt für rechtswidrig halten,</li>
|
||||
<li>Ihren Namen und Ihre E-Mail-Adresse, soweit gesetzlich keine Ausnahme gilt,</li>
|
||||
<li>Ihre Bestätigung, dass Sie die Meldung nach bestem Wissen und Gewissen abgeben und die Angaben richtig und vollständig sind.</li>
|
||||
<li>{{ __('static.report.way1_need_1') }}</li>
|
||||
<li>{{ __('static.report.way1_need_2') }}</li>
|
||||
<li>{{ __('static.report.way1_need_3') }}</li>
|
||||
<li>{{ __('static.report.way1_need_4') }}</li>
|
||||
</ul>
|
||||
<p>
|
||||
Nach Absenden der Meldung erhalten Sie unverzüglich eine Eingangsbestätigung. Wir prüfen die
|
||||
Meldung sorgfältig und zeitnah. Anschließend teilen wir Ihnen unsere Entscheidung mit einer
|
||||
Begründung mit. Ist der Inhalt rechtswidrig oder besteht ein ausreichender Grund für eine
|
||||
Einschränkung, entfernen oder sperren wir ihn ganz oder teilweise.
|
||||
</p>
|
||||
<p>
|
||||
Der Autor oder Verantwortliche des Inhalts wird über eine Einschränkung des Inhalts
|
||||
informiert und erhält eine Begründung, soweit dies gesetzlich vorgesehen ist.
|
||||
</p>
|
||||
<p>{{ __('static.report.way1_process') }}</p>
|
||||
<p>{{ __('static.report.way1_author_note') }}</p>
|
||||
|
||||
<h2>2. Eigene personenbezogene Daten entfernen lassen</h2>
|
||||
<p>
|
||||
Nutzen Sie diesen Weg, wenn Sie eine natürliche Person sind und Ihre persönlichen
|
||||
Kontaktdaten in einer Pressemitteilung stehen, zum Beispiel Name, Telefonnummer oder
|
||||
E-Mail-Adresse.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Antrag:</strong> Nutzen Sie unser
|
||||
<a href="{{ route('melden.form', ['way' => 'kontaktdaten']) }}">Antragsformular zur
|
||||
Entfernung eigener Kontaktdaten</a>. Alternativ öffnen Sie die betroffene
|
||||
Pressemitteilung und nutzen dort den Link <em>„Eigene Daten entfernen"</em> — oder Sie
|
||||
senden Ihren Antrag an <a href="mailto:{{ $reportEmail }}">{{ $reportEmail }}</a>.
|
||||
</p>
|
||||
<p>
|
||||
Wir prüfen Ihren Antrag nach den Vorgaben der Datenschutz-Grundverordnung. Die Prüfung und
|
||||
Bearbeitung ist für Sie kostenlos.
|
||||
</p>
|
||||
<p>
|
||||
Zur Prüfung senden wir Ihnen in der Regel einen Bestätigungslink an die betroffene
|
||||
E-Mail-Adresse. Falls diese nicht mehr erreichbar ist, können wir einen geeigneten
|
||||
Identitäts- oder Berechtigungsnachweis verlangen. Wir verlangen nur die Angaben, die zur
|
||||
Prüfung Ihrer Berechtigung erforderlich sind.
|
||||
</p>
|
||||
<p>
|
||||
Nach erfolgreicher Prüfung entfernen, ersetzen oder anonymisieren wir Ihre persönlichen
|
||||
Kontaktdaten in der Pressemitteilung. Die Pressemitteilung selbst bleibt grundsätzlich
|
||||
bestehen, soweit keine gesetzlichen Ansprüche auf Entfernung, Sperrung oder Änderung
|
||||
bestehen.
|
||||
</p>
|
||||
<p>
|
||||
Angaben über Unternehmen und Informationen aus öffentlichen Registern prüfen wir im
|
||||
Einzelfall. Solche Angaben sind nicht automatisch wie private Kontaktdaten zu behandeln.
|
||||
</p>
|
||||
<h2>{{ __('static.report.way2_heading') }}</h2>
|
||||
<p>{{ __('static.report.way2_intro') }}</p>
|
||||
<p>{!! __('static.report.way2_how', ['form_url' => route('melden.form', ['way' => 'kontaktdaten']), 'contact' => $contactTrigger]) !!}</p>
|
||||
<p>{{ __('static.report.way2_gdpr') }}</p>
|
||||
<p>{{ __('static.report.way2_verification') }}</p>
|
||||
<p>{{ __('static.report.way2_result') }}</p>
|
||||
<p>{{ __('static.report.way2_companies') }}</p>
|
||||
|
||||
<h2>3. Eigene Pressemitteilung ändern oder verwalten</h2>
|
||||
<p>
|
||||
Nutzen Sie diesen Weg, wenn Sie der ursprüngliche Auftraggeber, Firmeninhaber oder als
|
||||
Pressekontakt in der Pressemitteilung genannt sind.
|
||||
</p>
|
||||
<p>
|
||||
Zur Prüfung Ihrer Berechtigung nutzen wir ein Magic-Link-Verfahren: Wir senden einen
|
||||
einmaligen Zugangslink an die E-Mail-Adresse, die in der Pressemitteilung oder im
|
||||
Kundenkonto hinterlegt ist. Nach Bestätigung können Sie zulässige Änderungen beantragen,
|
||||
zum Beispiel:
|
||||
</p>
|
||||
<h2>{{ __('static.report.way3_heading') }}</h2>
|
||||
<p>{{ __('static.report.way3_intro') }}</p>
|
||||
<p>{{ __('static.report.way3_magic_link') }}</p>
|
||||
<ul>
|
||||
<li>Tippfehler korrigieren,</li>
|
||||
<li>Kontaktdaten aktualisieren,</li>
|
||||
<li>veraltete Pressekontakte ersetzen,</li>
|
||||
<li>eine freiwillige Entfernung rechtmäßiger Inhalte aus der öffentlichen Ansicht beauftragen.</li>
|
||||
<li>{{ __('static.report.way3_item_1') }}</li>
|
||||
<li>{{ __('static.report.way3_item_2') }}</li>
|
||||
<li>{{ __('static.report.way3_item_3') }}</li>
|
||||
<li>{{ __('static.report.way3_item_4') }}</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Änderung beantragen:</strong> Melden Sie sich in Ihrem
|
||||
<a href="{{ rtrim((string) config('domains.domain_portal_url', config('app.url')), '/') }}/login">Publisher-Konto</a>
|
||||
an oder fordern Sie den Zugangslink über die Anmeldeseite an. Wenn die hinterlegte
|
||||
E-Mail-Adresse nicht mehr erreichbar ist, können wir einen geeigneten Berechtigungsnachweis
|
||||
verlangen — wenden Sie sich dazu an
|
||||
<a href="mailto:{{ $reportEmail }}">{{ $reportEmail }}</a>.
|
||||
</p>
|
||||
<p>{!! __('static.report.way3_how', ['login_url' => $loginUrl, 'contact' => $contactTrigger]) !!}</p>
|
||||
|
||||
<h2>4. Freiwillige Entfernung rechtmäßiger Inhalte</h2>
|
||||
<p>
|
||||
Rechtmäßige Pressemitteilungen bleiben grundsätzlich Teil unseres dauerhaften Archivs. Eine
|
||||
spätere Entfernung aus der öffentlichen Ansicht („Depublikation") bieten wir als freiwillige
|
||||
Serviceleistung an, soweit keine gesetzlichen Ansprüche auf Entfernung, Sperrung oder
|
||||
Änderung bestehen.
|
||||
</p>
|
||||
<p>
|
||||
Die Beauftragung ist nur durch eine hierzu berechtigte Person möglich, zum Beispiel durch
|
||||
den ursprünglichen Auftraggeber, den im Inhalt genannten Pressekontakt, einen
|
||||
vertretungsberechtigten Firmeninhaber oder eine nachweislich bevollmächtigte Person.
|
||||
</p>
|
||||
<p>Bei einer Depublikation gilt:</p>
|
||||
<h2>{{ __('static.report.way4_heading') }}</h2>
|
||||
<p>{{ __('static.report.way4_intro') }}</p>
|
||||
<p>{{ __('static.report.way4_authorized') }}</p>
|
||||
<p>{{ __('static.report.way4_rules_intro') }}</p>
|
||||
<ul>
|
||||
<li>Die Pressemitteilung wird aus der öffentlichen Ansicht entfernt.</li>
|
||||
<li>Die URL bleibt mit einem kurzen Hinweis auf die Entfernung bestehen („Tombstone").</li>
|
||||
<li>Eine vollständige Löschung der URL erfolgt nicht.</li>
|
||||
<li>Nicht enthalten ist die Entfernung aus Suchmaschinen-Caches, Archiven Dritter oder Weiterveröffentlichungen auf anderen Portalen, auf die wir keinen Zugriff haben.</li>
|
||||
<li>{{ __('static.report.way4_rule_1') }}</li>
|
||||
<li>{{ __('static.report.way4_rule_2') }}</li>
|
||||
<li>{{ __('static.report.way4_rule_3') }}</li>
|
||||
<li>{{ __('static.report.way4_rule_4') }}</li>
|
||||
</ul>
|
||||
@php
|
||||
// T12: Preis erscheint erst, wenn er konfiguriert ist (O6) —
|
||||
|
|
@ -161,38 +90,20 @@
|
|||
$depublicationPriceCents = (int) config('billing.depublication_price_cents');
|
||||
@endphp
|
||||
@if ($depublicationPriceCents > 0)
|
||||
<p>
|
||||
Der Preis beträgt
|
||||
<strong>{{ number_format($depublicationPriceCents / 100, 2, ',', '.') }} € zzgl. USt.</strong>
|
||||
({{ number_format($depublicationPriceCents * (1 + (float) config('billing.vat_rate')) / 100, 2, ',', '.') }} € inkl. 19 % USt.).
|
||||
<strong>Beauftragung:</strong> über Ihr Kundenkonto (Detailseite der
|
||||
Pressemitteilung) oder per E-Mail an
|
||||
<a href="mailto:{{ $reportEmail }}">{{ $reportEmail }}</a>.
|
||||
</p>
|
||||
<p>{!! __('static.report.way4_price', [
|
||||
'net' => number_format($depublicationPriceCents / 100, 2, ',', '.'),
|
||||
'gross' => number_format($depublicationPriceCents * (1 + (float) config('billing.vat_rate')) / 100, 2, ',', '.'),
|
||||
'contact' => $contactTrigger,
|
||||
]) !!}</p>
|
||||
@else
|
||||
<p>
|
||||
Der Preis wird Ihnen vor Beauftragung angezeigt.
|
||||
<strong>Beauftragung:</strong> über Ihr Kundenkonto oder per E-Mail an
|
||||
<a href="mailto:{{ $reportEmail }}">{{ $reportEmail }}</a>.
|
||||
</p>
|
||||
<p>{!! __('static.report.way4_price_fallback', ['contact' => $contactTrigger]) !!}</p>
|
||||
@endif
|
||||
<p>
|
||||
Wichtig: Dieser Service ist keine Voraussetzung für Ihre gesetzlichen Rechte. Die Meldung
|
||||
rechtswidriger Inhalte und die Ausübung gesetzlicher Rechte sind und bleiben kostenlos —
|
||||
unabhängig davon, ob Sie diesen Service nutzen.
|
||||
</p>
|
||||
<p>{{ __('static.report.way4_note') }}</p>
|
||||
|
||||
<h2>Rückfragen zu Meldungen</h2>
|
||||
<p>
|
||||
Für Meldungen nutzen Sie bitte vorrangig die Melde-Links direkt bei der jeweiligen
|
||||
Pressemitteilung.
|
||||
</p>
|
||||
<p>
|
||||
Nach Absenden einer Meldung erhalten Sie eine Eingangsbestätigung. Für Rückfragen zu einer
|
||||
bestehenden Meldung können Sie auf diese Bestätigung antworten oder uns unter Angabe des
|
||||
Vorgangs über <a href="mailto:{{ $reportEmail }}">{{ $reportEmail }}</a> kontaktieren.
|
||||
</p>
|
||||
<p>Kommunikationssprachen: Deutsch, Englisch</p>
|
||||
<h2>{{ __('static.report.questions_heading') }}</h2>
|
||||
<p>{{ __('static.report.questions_links') }}</p>
|
||||
<p>{!! __('static.report.questions_reply', ['contact' => $contactTrigger]) !!}</p>
|
||||
<p>{{ __('static.report.languages') }}</p>
|
||||
</div>
|
||||
</x-web.static-page>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
$leadImage = $leadRelease?->images->first();
|
||||
$leadImageUrl = $leadImage?->variantUrl('detail') ?? $leadImage?->variantUrl('card') ?? $leadImage?->url();
|
||||
$leadPlaceholderUrl = $leadImageUrl ? null : $leadRelease?->chosenPlaceholderUrl();
|
||||
$leadCat = $leadRelease?->category?->translations->firstWhere('locale', app()->getLocale()) ?? $leadRelease?->category?->translations->first();
|
||||
$leadLead = $leadRelease
|
||||
? (filled($leadRelease->subtitle)
|
||||
|
|
@ -154,6 +155,8 @@
|
|||
<div class="relative overflow-hidden bg-hero-grad" style="aspect-ratio: 16 / 9;">
|
||||
@if ($leadImageUrl)
|
||||
<img src="{{ $leadImageUrl }}" alt="{{ $leadRelease->title }}" class="absolute inset-0 w-full h-full object-cover" loading="lazy">
|
||||
@elseif ($leadPlaceholderUrl)
|
||||
<img src="{{ $leadPlaceholderUrl }}" alt="" aria-hidden="true" class="absolute inset-0 w-full h-full object-cover" loading="lazy">
|
||||
@else
|
||||
<x-web.hero-fallback />
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@
|
|||
<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.3" />
|
||||
<path d="M8 4v4l2.5 1.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" />
|
||||
</svg>
|
||||
Monatlich kündbar
|
||||
Monats- oder Jahrestarife
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -510,7 +510,7 @@
|
|||
</svg>
|
||||
</div>
|
||||
<div class="text-[13px] text-ink-2 leading-[1.55]">
|
||||
<strong class="text-ink font-semibold">Alle Tarife monatlich kündbar.</strong>
|
||||
<strong class="text-ink font-semibold">Monatstarife monatlich kündbar, Jahrestarife zum Ende der Laufzeit.</strong>
|
||||
Preise netto zzgl. USt. Buchung und Verwaltung direkt im Publisher-Konto,
|
||||
die Abrechnung läuft sicher über Stripe. Auch ohne Abo möglich: eine
|
||||
Einzel-Pressemitteilung für {{ $fmtEuro($singlePmPriceCents) }} € netto.
|
||||
|
|
@ -806,8 +806,8 @@
|
|||
|
||||
<details class="border-b border-bg-rule group">
|
||||
<summary class="flex items-center justify-between gap-4 py-5">
|
||||
<span class="text-[15.5px] font-semibold text-ink tracking-[-0.2px]">Kann ich monatlich
|
||||
kündigen?</span>
|
||||
<span class="text-[15.5px] font-semibold text-ink tracking-[-0.2px]">Welche Laufzeiten
|
||||
haben die Tarife — und wie kündige ich?</span>
|
||||
<svg class="faq-chev text-ink-3 flex-shrink-0" width="14" height="14"
|
||||
viewBox="0 0 16 16" fill="none">
|
||||
<path d="M3 6l5 5 5-5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"
|
||||
|
|
@ -815,9 +815,9 @@
|
|||
</svg>
|
||||
</summary>
|
||||
<div class="pb-5 text-[13.5px] text-ink-2 leading-[1.65] max-w-[640px]">
|
||||
Ja, alle Tarife sind monatlich kündbar. Bei jährlicher Zahlweise läuft der bereits bezahlte
|
||||
Zeitraum bis zum Ende der zwölf Monate; danach wird monatlich abgerechnet, sofern Sie nicht
|
||||
erneut die jährliche Zahlweise wählen. Kündigen können Sie direkt im Konto oder ohne
|
||||
Monatstarife verlängern sich monatlich und sind monatlich kündbar. Jahrestarife
|
||||
verlängern sich um jeweils zwölf Monate und sind zum Ende der jeweiligen Laufzeit
|
||||
kündbar. Kündigen können Sie direkt im Konto oder ohne
|
||||
Anmeldung über <a
|
||||
class="text-hub underline underline-offset-[3px] decoration-hub/30 hover:decoration-hub"
|
||||
href="{{ route('kuendigung', ['edition' => 'de']) }}">unsere Kündigungsseite</a>.
|
||||
|
|
@ -910,7 +910,7 @@
|
|||
In zwei Minuten registriert. Veröffentlichen mit Tarif oder als Einzel-Pressemitteilung.
|
||||
</h2>
|
||||
<p class="text-[13.5px] lg:text-[14px] text-ink-on-dark-2 leading-[1.55] mt-4 m-0 max-w-[600px]">
|
||||
Das Konto ist kostenlos. Tarife monatlich kündbar, Abrechnung sicher über Stripe.
|
||||
Das Konto ist kostenlos. Tarife mit monatlicher oder jährlicher Laufzeit, Abrechnung sicher über Stripe.
|
||||
</p>
|
||||
</div>
|
||||
<div class="relative flex flex-col gap-2.5">
|
||||
|
|
@ -942,7 +942,5 @@
|
|||
</section>
|
||||
</main>
|
||||
|
||||
<x-web.hub.contact-modal />
|
||||
|
||||
<x-web.hub.site-footer />
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -33,15 +33,20 @@
|
|||
$readTime = max(1, (int) round($wordCount / 200));
|
||||
|
||||
$teaser = (string) Str::of(strip_tags((string) $release->text))->squish()->limit(180);
|
||||
$lead = filled($release->subtitle)
|
||||
? $release->subtitle
|
||||
: $teaser;
|
||||
|
||||
// Subline nur bei explizit gesetztem Untertitel — kein Fallback auf den Textanfang,
|
||||
// sonst erscheint der erste Absatz doppelt. Der Teaser dient nur der Meta-Description.
|
||||
$lead = $release->subtitle;
|
||||
|
||||
$image = $release->images->first();
|
||||
$imageUrl = $image?->variantUrl('detail') ?? $image?->variantUrl('card') ?? $image?->url();
|
||||
$imageCaption = $image?->description ?: $image?->title;
|
||||
$imageCredit = $image?->copyright ?: $image?->author;
|
||||
|
||||
// Ohne Pressefoto: die im User-Panel gewählte Platzhalter-Variante.
|
||||
// Null bei Altbeständen ohne Variante — dann generischer Hero-Fallback.
|
||||
$placeholderUrl = $imageUrl ? null : $release->chosenPlaceholderUrl();
|
||||
|
||||
$companyName = $company?->name;
|
||||
$companyInitial = $companyName ? mb_strtoupper(mb_substr($companyName, 0, 1)) : '·';
|
||||
$companyHref = $company?->slug ? route('newsroom', ['slug' => $company->slug]) : route('newsrooms');
|
||||
|
|
@ -75,7 +80,7 @@
|
|||
@endphp
|
||||
|
||||
@section('title', $release->title.' – '.$brandLabel)
|
||||
@section('meta_description', $lead)
|
||||
@section('meta_description', filled($lead) ? $lead : $teaser)
|
||||
@section('og_type', 'article')
|
||||
@if ($imageUrl)
|
||||
@section('og_image', $imageUrl)
|
||||
|
|
@ -154,6 +159,83 @@
|
|||
</nav>
|
||||
</div>
|
||||
|
||||
@if (! $imageUrl)
|
||||
{{-- Ohne Pressefoto: Headline direkt in der Platzhalter-Fläche der PM
|
||||
(gewählte Variante wie im User-Panel, sonst generischer Fallback). --}}
|
||||
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-[18px]">
|
||||
<article class="relative overflow-hidden bg-hero-grad">
|
||||
@if ($placeholderUrl)
|
||||
<img src="{{ $placeholderUrl }}" alt="" aria-hidden="true"
|
||||
class="absolute inset-0 h-full w-full object-cover" loading="eager">
|
||||
@else
|
||||
<x-web.hero-fallback />
|
||||
@endif
|
||||
|
||||
@if ($embargoAt)
|
||||
<div class="absolute top-5 left-5 sm:top-6 sm:left-9 flex items-center gap-2.5 flex-wrap">
|
||||
<span class="text-[9.5px] font-bold tracking-[0.18em] uppercase text-white px-2.5 py-[3px] border border-white/50 font-mono bg-black/25">
|
||||
● {{ __('web.detail.embargo_lifted') }}
|
||||
</span>
|
||||
<span class="text-[11px] text-white/70 font-mono">{{ $embargoAt->translatedFormat('j. F Y, H:i') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="relative px-5 sm:px-9 pt-[110px] sm:pt-[150px] pb-7 sm:pb-9"
|
||||
style="background:linear-gradient(180deg,transparent,rgba(0,0,0,0.55) 55%,rgba(0,0,0,0.82));">
|
||||
<div class="flex items-center gap-3.5 mb-4 flex-wrap">
|
||||
@if ($categoryName)
|
||||
<a href="{{ $categoryHref }}" class="bp-cat cursor-pointer transition-colors" style="color:#FF8B6F;">{{ $categoryName }}</a>
|
||||
<span class="w-1 h-1 rounded-full bg-white/40" aria-hidden="true"></span>
|
||||
@endif
|
||||
<span class="text-[11px] text-white/60 italic font-serif">{{ __('web.detail.audience') }}</span>
|
||||
</div>
|
||||
|
||||
<h1 class="font-serif text-[30px] sm:text-[38px] lg:text-[44px] font-semibold m-0 tracking-[-0.8px] leading-[1.1] max-w-[920px] text-white" style="text-wrap:balance;">
|
||||
{{ $release->title }}
|
||||
</h1>
|
||||
|
||||
@if (filled($lead))
|
||||
<p class="font-serif text-[16.5px] sm:text-[19px] leading-[1.45] m-0 mt-5 text-white/85 max-w-[820px] font-normal" style="text-wrap:pretty;">
|
||||
{{ $lead }}
|
||||
</p>
|
||||
@endif
|
||||
|
||||
<div class="flex flex-wrap items-center text-[12.5px] text-white/75 mt-6" style="gap:10px 22px;">
|
||||
@if ($companyName)
|
||||
<span class="inline-flex items-center gap-2">
|
||||
<span class="w-7 h-7 bg-white text-ink inline-flex items-center justify-center text-[13px] font-bold font-serif">{{ $companyInitial }}</span>
|
||||
<span class="font-semibold text-white">{{ $companyName }}</span>
|
||||
</span>
|
||||
<span class="w-px h-[14px] bg-white/25" aria-hidden="true"></span>
|
||||
@endif
|
||||
@if ($publishedAt)
|
||||
<time datetime="{{ $publishedAt->toIso8601String() }}" class="font-mono text-[11.5px] text-white/65">
|
||||
{{ $publishedAt->translatedFormat('j. F Y') }} · {{ __('web.detail.time_at', ['time' => $publishedAt->format('H:i')]) }}
|
||||
</time>
|
||||
@endif
|
||||
<span class="font-mono text-[11.5px] text-white/65">{{ __('web.shared.read_time', ['minutes' => $readTime]) }} · {{ __('web.detail.words', ['count' => number_format($wordCount, 0, ',', '.')]) }}</span>
|
||||
@if ($companyCountry)
|
||||
<span class="inline-flex items-center gap-1.5 font-mono text-[11.5px] text-white/65">
|
||||
<svg width="11" height="11" viewBox="0 0 14 14" fill="none" aria-hidden="true"><path d="M7 1a5 5 0 015 5c0 4-5 7-5 7s-5-3-5-7a5 5 0 015-5z" stroke="currentColor" stroke-width="1.3" fill="none" /><circle cx="7" cy="6" r="1.5" fill="currentColor" /></svg>
|
||||
{{ $companyCountry }}
|
||||
</span>
|
||||
@endif
|
||||
|
||||
@if ($isRecommended)
|
||||
<span class="inline-flex items-center gap-1.5 px-2 py-[3px] text-[9.5px] font-bold tracking-[0.14em] uppercase text-white border border-white/40 font-mono cursor-help"
|
||||
title="{{ __('web.detail.recommended_hint') }}">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M12 2l9 4v6c0 5-3.5 9-9 10-5.5-1-9-5-9-10V6z" stroke="currentColor" stroke-width="2" fill="none" />
|
||||
<path d="M8 12l3 3 5-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
{{ __('web.detail.recommended') }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@else
|
||||
{{-- Hero Meta Block --}}
|
||||
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="pt-[18px] pb-8 border-b border-bg-rule">
|
||||
|
|
@ -221,15 +303,9 @@
|
|||
|
||||
{{-- Hero Image --}}
|
||||
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-8">
|
||||
<div class="relative flex items-end p-[18px] bg-bg-dark hatch-dark overflow-hidden" style="aspect-ratio:21/9;">
|
||||
@if ($imageUrl)
|
||||
<img src="{{ $imageUrl }}" alt="{{ $imageCaption ?: $release->title }}"
|
||||
class="absolute inset-0 h-full w-full object-cover" loading="eager">
|
||||
@else
|
||||
<span class="relative text-[10px] font-mono tracking-wider uppercase text-white/50">
|
||||
{{ $companyName ? __('web.detail.image_placeholder_company', ['company' => $companyName]) : __('web.detail.image_placeholder') }} (16:9)
|
||||
</span>
|
||||
@endif
|
||||
<div class="relative flex items-end p-[18px] bg-bg-dark overflow-hidden" style="aspect-ratio:21/9;">
|
||||
<img src="{{ $imageUrl }}" alt="{{ $imageCaption ?: $release->title }}"
|
||||
class="absolute inset-0 h-full w-full object-cover" loading="eager">
|
||||
</div>
|
||||
@if ($imageCaption || $imageCredit)
|
||||
<div class="text-[11.5px] text-ink-3 mt-2.5 italic max-w-[720px]">
|
||||
|
|
@ -237,6 +313,7 @@
|
|||
</div>
|
||||
@endif
|
||||
</section>
|
||||
@endif
|
||||
|
||||
{{-- Body + Sidebar --}}
|
||||
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-10 grid grid-cols-1 lg:grid-cols-[1fr_280px] gap-10 lg:gap-14">
|
||||
|
|
@ -331,6 +408,20 @@
|
|||
</a>
|
||||
<span class="text-ink-4">{{ __('web.detail.reports_free') }}</span>
|
||||
</div>
|
||||
|
||||
{{-- Magic-Link-Hinweis: hinterlegte Firmen-/Pressekontakte verwalten
|
||||
ihre Mitteilung über den passwortlosen Anmeldelink im pressekonto. --}}
|
||||
@php
|
||||
$portalUrl = rtrim(config('domains.domain_portal_url', config('app.url')), '/');
|
||||
@endphp
|
||||
<div class="mt-3 flex flex-wrap items-center gap-x-4 gap-y-1.5 text-[11.5px] text-ink-3">
|
||||
<span>{{ __('web.detail.manage_question') }}</span>
|
||||
<a href="{{ $portalUrl }}/anmeldelink" class="inline-flex items-center gap-1.5 text-ink-2 underline underline-offset-2 hover:text-ink transition-colors">
|
||||
<svg width="12" height="12" viewBox="0 0 14 14" class="flex-shrink-0" aria-hidden="true"><path d="M1 3h12v8H1zM1 3l6 4 6-4" stroke="currentColor" stroke-width="1.3" fill="none" /></svg>
|
||||
{{ __('web.detail.manage_link') }}
|
||||
</a>
|
||||
<span class="text-ink-4">{{ __('web.detail.manage_hint') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Sidebar --}}
|
||||
|
|
@ -433,10 +524,14 @@
|
|||
</aside>
|
||||
</section>
|
||||
|
||||
{{-- Empfehlungen --}}
|
||||
{{-- Empfehlungen: zweispaltig nur, wenn beide Listen gefüllt sind —
|
||||
eine einzelne Liste nutzt sonst die volle Layout-Breite. --}}
|
||||
@if ($companyReleases->isNotEmpty() || $relatedReleases->isNotEmpty())
|
||||
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-14">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-10">
|
||||
<div @class([
|
||||
'grid grid-cols-1 gap-10',
|
||||
'md:grid-cols-2' => $companyReleases->isNotEmpty() && $relatedReleases->isNotEmpty(),
|
||||
])>
|
||||
@if ($companyReleases->isNotEmpty())
|
||||
<div>
|
||||
<h3 class="font-serif text-[20px] font-semibold m-0 mb-1 tracking-[-0.2px]">{{ __('web.detail.more_from', ['company' => $companyName]) }}</h3>
|
||||
|
|
|
|||
|
|
@ -22,11 +22,13 @@
|
|||
|
||||
@section('content')
|
||||
<x-web.static-page
|
||||
eyebrow="Rechtliches"
|
||||
:eyebrow="__('static.legal.eyebrow')"
|
||||
title="Veröffentlichungsrichtlinien"
|
||||
breadcrumb="Richtlinien"
|
||||
updated="{{ $guidelinesStand }}"
|
||||
>
|
||||
<x-web.legal-language-notice />
|
||||
|
||||
<div class="pm-body max-w-[760px]">
|
||||
<p>
|
||||
Diese Richtlinien gelten für alle Pressemitteilungen auf presseecho.de und
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
$brandConfig = config('domains.domains.'.config('app.theme').'.brand', []);
|
||||
$brandName = $brandConfig['name'] ?? 'businessportal';
|
||||
$brandAccent = $brandConfig['accent'] ?? '24';
|
||||
$brandLabel = $brandName.$brandAccent;
|
||||
$publisherUrl = rtrim((string) config('domains.domain_portal_url', config('app.url')), '/');
|
||||
|
||||
$sinceYear = $oldestYear ?? 2012;
|
||||
|
|
@ -22,15 +23,45 @@
|
|||
$exampleReadMinutes = $example
|
||||
? max(1, (int) ceil(str_word_count(strip_tags((string) $example->text)) / 200))
|
||||
: 3;
|
||||
|
||||
// Inhalte aus static.publish.* — Reihen als Datenstrukturen (DRY).
|
||||
$trustPrinciples = [
|
||||
['k' => __('static.publish.trust_1_k'), 't' => __('static.publish.trust_1_t'), 'd' => __('static.publish.trust_1_d')],
|
||||
['k' => __('static.publish.trust_2_k'), 't' => __('static.publish.trust_2_t'), 'd' => __('static.publish.trust_2_d')],
|
||||
['k' => __('static.publish.trust_3_k'), 't' => __('static.publish.trust_3_t'), 'd' => __('static.publish.trust_3_d')],
|
||||
['k' => __('static.publish.trust_4_k'), 't' => __('static.publish.trust_4_t'), 'd' => __('static.publish.trust_4_d')],
|
||||
];
|
||||
|
||||
$flowSteps = [
|
||||
['n' => '01', 'meta' => __('static.publish.flow_1_meta'), 't' => __('static.publish.flow_1_t'), 'd' => __('static.publish.flow_1_d')],
|
||||
['n' => '02', 'meta' => __('static.publish.flow_2_meta'), 't' => __('static.publish.flow_2_t'), 'd' => __('static.publish.flow_2_d')],
|
||||
['n' => '03', 'meta' => __('static.publish.flow_3_meta'), 't' => __('static.publish.flow_3_t'), 'd' => __('static.publish.flow_3_d')],
|
||||
];
|
||||
|
||||
$occasions = [
|
||||
['t' => __('static.publish.occasion_1_t'), 'd' => __('static.publish.occasion_1_d')],
|
||||
['t' => __('static.publish.occasion_2_t'), 'd' => __('static.publish.occasion_2_d')],
|
||||
['t' => __('static.publish.occasion_3_t'), 'd' => __('static.publish.occasion_3_d')],
|
||||
['t' => __('static.publish.occasion_4_t'), 'd' => __('static.publish.occasion_4_d')],
|
||||
['t' => __('static.publish.occasion_5_t'), 'd' => __('static.publish.occasion_5_d')],
|
||||
['t' => __('static.publish.occasion_6_t'), 'd' => __('static.publish.occasion_6_d')],
|
||||
];
|
||||
|
||||
$publishFaqs = [
|
||||
['q' => __('static.publish.faq_1_q'), 'a' => __('static.publish.faq_1_a')],
|
||||
['q' => __('static.publish.faq_2_q'), 'a' => __('static.publish.faq_2_a')],
|
||||
['q' => __('static.publish.faq_3_q'), 'a' => __('static.publish.faq_3_a')],
|
||||
['q' => __('static.publish.faq_4_q'), 'a' => __('static.publish.faq_4_a')],
|
||||
['q' => __('static.publish.faq_5_q'), 'a' => __('static.publish.faq_5_a')],
|
||||
];
|
||||
@endphp
|
||||
|
||||
@section('title', 'Pressemitteilung veröffentlichen – '.$brandName.$brandAccent)
|
||||
@section('meta_description', 'Pressemitteilungen geprüft veröffentlichen und dauerhaft auffindbar im Archiv. Faire Preise, keine Vertragsbindung – Einreichung über den zentralen Publisher-Bereich.')
|
||||
@section('title', __('static.publish.meta_title', ['brand' => $brandLabel]))
|
||||
@section('meta_description', __('static.publish.meta_description'))
|
||||
|
||||
{{-- Kein hreflang="en": Der Seiteninhalt liegt bisher nur auf Deutsch vor.
|
||||
EN-Übersetzung der Langform-Seiten ist nachgelagert (siehe Release-Plan). --}}
|
||||
@section('hreflang')
|
||||
<link rel="alternate" hreflang="de" href="{{ url('/de/veroeffentlichen') }}">
|
||||
<link rel="alternate" hreflang="en" href="{{ url('/en/veroeffentlichen') }}">
|
||||
<link rel="alternate" hreflang="x-default" href="{{ url('/de/veroeffentlichen') }}">
|
||||
@endsection
|
||||
|
||||
|
|
@ -42,18 +73,18 @@
|
|||
<div class="border-b border-bg-rule">
|
||||
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex items-center justify-between gap-3 text-[12px] text-ink-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<a href="{{ route('web.home') }}" class="hover:text-ink transition-colors">{{ $brandName }}{{ $brandAccent }}</a>
|
||||
<a href="{{ route('web.home') }}" class="hover:text-ink transition-colors">{{ $brandLabel }}</a>
|
||||
<span class="text-ink-4" aria-hidden="true">›</span>
|
||||
<span class="text-ink">Veröffentlichen</span>
|
||||
<span class="text-ink">{{ __('static.publish.breadcrumb') }}</span>
|
||||
</div>
|
||||
<div class="hidden md:flex items-center gap-[18px]">
|
||||
<span class="inline-flex items-center gap-1.5">
|
||||
<svg width="11" height="11" viewBox="0 0 11 11" aria-hidden="true"><path d="M2 5.5l2.2 2.2L9 3" stroke="currentColor" class="text-ok" stroke-width="1.6" fill="none" stroke-linecap="round"/></svg>
|
||||
<span>Qualitätsgeprüft seit {{ $sinceYear }}</span>
|
||||
<span>{{ __('static.publish.quality_since', ['year' => $sinceYear]) }}</span>
|
||||
</span>
|
||||
<span class="text-ink-4">·</span>
|
||||
<a href="{{ route('hilfe') }}" class="text-ink-2 hover:text-ink transition-colors">Hilfe & Support</a>
|
||||
<a href="{{ route('preise') }}" class="text-ink-2 hover:text-ink transition-colors">Preise</a>
|
||||
<a href="{{ route('hilfe') }}" class="text-ink-2 hover:text-ink transition-colors">{{ __('static.publish.help_support') }}</a>
|
||||
<a href="{{ route('preise') }}" class="text-ink-2 hover:text-ink transition-colors">{{ __('static.publish.pricing') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -65,104 +96,101 @@
|
|||
<div>
|
||||
<div class="flex items-center gap-3 mb-7">
|
||||
<span class="w-7 h-px bg-brand"></span>
|
||||
<span class="eyebrow text-[11px]">Pressestelle · Veröffentlichen</span>
|
||||
<span class="eyebrow text-[11px]">{{ __('static.publish.eyebrow') }}</span>
|
||||
</div>
|
||||
|
||||
<h1 class="font-serif text-[40px] sm:text-[50px] lg:text-[58px] font-semibold m-0 text-ink leading-[1.05] tracking-[-1.2px] text-balance">
|
||||
Pressemitteilung veröffentlichen.<br class="hidden sm:block" />
|
||||
Geprüft. Dauerhaft auffindbar.
|
||||
{{ __('static.publish.h1_line1') }}<br class="hidden sm:block" />
|
||||
{{ __('static.publish.h1_line2') }}
|
||||
</h1>
|
||||
|
||||
<p class="font-serif mt-7 text-[18px] lg:text-[19px] leading-[1.5] text-ink-2 max-w-[560px]">
|
||||
{{ $brandName }}{{ $brandAccent }} ist die Presseplattform für mittelständische Unternehmen,
|
||||
Selbstständige und PR-Agenturen aus Deutschland, Österreich und der Schweiz. Jede Mitteilung
|
||||
wird auf Qualität geprüft und bleibt dauerhaft im Archiv auffindbar.
|
||||
{{ __('static.publish.hero_text', ['brand' => $brandLabel]) }}
|
||||
</p>
|
||||
|
||||
{{-- Störer — Hub-CTA --}}
|
||||
<div class="relative mt-9 grid items-center overflow-hidden text-ink-on-dark bg-topbar-grad gap-6 lg:gap-7 grid-cols-1 lg:grid-cols-[1.4fr_auto] px-7 py-7 lg:px-8">
|
||||
<span class="absolute left-0 top-0 bottom-0 w-[3px] bg-brand" aria-hidden="true"></span>
|
||||
<div>
|
||||
<div class="eyebrow mb-2.5 text-[10.5px] text-brand-soft">Einreichen im Publisher-Bereich</div>
|
||||
<div class="eyebrow mb-2.5 text-[10.5px] text-brand-soft">{{ __('static.publish.hub_eyebrow') }}</div>
|
||||
<h2 class="font-serif m-0 text-[21px] lg:text-[23px] font-semibold leading-[1.25] tracking-[-0.3px] text-ink-on-dark">
|
||||
Die Einreichung läuft über den zentralen Publisher-Bereich.
|
||||
{{ __('static.publish.hub_heading') }}
|
||||
</h2>
|
||||
<p class="mt-2.5 mb-0 text-[13.5px] leading-[1.55] text-ink-on-dark-2 max-w-[540px]">
|
||||
Dort verwalten Sie Mitteilungen, Credits und Newsroom — einmaliges Konto, beide Portale
|
||||
nutzbar (businessportal24 & presseecho.de).
|
||||
{{ __('static.publish.hub_text') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-start lg:items-end gap-2.5">
|
||||
<a href="{{ $publisherUrl }}/register"
|
||||
class="inline-flex items-center gap-2 px-[22px] py-3.5 text-[14px] font-semibold text-white bg-brand hover:bg-brand-deep transition-colors">
|
||||
Zum Publisher-Bereich
|
||||
{{ __('static.publish.hub_cta') }}
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M4 8L8.5 3.5M8.5 3.5H5M8.5 3.5V7" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
<span class="text-[11.5px] text-ink-on-dark-2">Login per Magic-Link · ohne Vertragsbindung</span>
|
||||
<span class="text-[11.5px] text-ink-on-dark-2">{{ __('static.publish.hub_note') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Faktenleiste --}}
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 border-t border-bg-rule mt-9">
|
||||
<div class="py-5 pr-5 border-r border-bg-rule">
|
||||
<div class="eyebrow muted text-[10px] mb-2">Seit</div>
|
||||
<div class="eyebrow muted text-[10px] mb-2">{{ __('static.publish.fact_since') }}</div>
|
||||
<div class="font-serif text-[26px] lg:text-[28px] font-semibold leading-none text-ink tracking-[-0.4px]">{{ $sinceYear }}</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">im Betrieb · durchgehende Archivierung</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">{{ __('static.publish.fact_since_sub') }}</div>
|
||||
</div>
|
||||
<div class="py-5 px-5 lg:border-r border-bg-rule">
|
||||
<div class="eyebrow muted text-[10px] mb-2">Archiv</div>
|
||||
<div class="eyebrow muted text-[10px] mb-2">{{ __('static.publish.fact_archive') }}</div>
|
||||
<div class="font-serif text-[26px] lg:text-[28px] font-semibold leading-none text-ink tracking-[-0.4px]">{{ $archiveLabel }}</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">Mitteilungen weiterhin abrufbar</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">{{ __('static.publish.fact_archive_sub') }}</div>
|
||||
</div>
|
||||
<div class="py-5 pr-5 lg:px-5 border-r border-t lg:border-t-0 border-bg-rule">
|
||||
<div class="eyebrow muted text-[10px] mb-2">Reichweite</div>
|
||||
<div class="eyebrow muted text-[10px] mb-2">{{ __('static.publish.fact_reach') }}</div>
|
||||
<div class="font-serif text-[26px] lg:text-[28px] font-semibold leading-none text-ink tracking-[-0.4px]">DACH</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">Deutschland · Österreich · Schweiz</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">{{ __('static.publish.fact_reach_sub') }}</div>
|
||||
</div>
|
||||
<div class="py-5 pl-5 border-t lg:border-t-0 border-bg-rule">
|
||||
<div class="eyebrow muted text-[10px] mb-2 inline-flex items-center gap-1.5">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-brand pulse-dot"></span>Heute
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-brand pulse-dot"></span>{{ __('static.publish.fact_today') }}
|
||||
</div>
|
||||
<div class="font-serif text-[26px] lg:text-[28px] font-semibold leading-none text-ink tracking-[-0.4px]">{{ (int) $publishedToday }} / {{ (int) $inReview }}</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">veröffentlicht / in Prüfung — Stand {{ $referenceNow->translatedFormat('j. M') }}</div>
|
||||
<div class="mt-2 text-[12px] leading-[1.4] text-ink-3">{{ __('static.publish.fact_today_sub', ['date' => $referenceNow->translatedFormat('j. M')]) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- RIGHT — Beispiel-Mitteilung --}}
|
||||
<aside class="lg:sticky lg:top-6">
|
||||
<div class="text-[11px] tracking-[0.14em] uppercase text-ink-3 font-semibold mb-2.5">So sieht eine veröffentlichte Mitteilung aus</div>
|
||||
<div class="text-[11px] tracking-[0.14em] uppercase text-ink-3 font-semibold mb-2.5">{{ __('static.publish.example_heading') }}</div>
|
||||
<article class="bg-bg-elev border border-bg-rule px-6 py-6">
|
||||
<div class="flex items-center justify-between mb-3.5">
|
||||
<span class="bp-cat text-[10.5px]">{{ $exampleCategory ?? 'Industrie · Maschinenbau' }}</span>
|
||||
<span class="bp-cat text-[10.5px]">{{ $exampleCategory ?? __('static.publish.example_category_fallback') }}</span>
|
||||
<span class="inline-flex items-center gap-1.5 text-[10.5px] text-ok font-semibold">
|
||||
<svg width="11" height="11" viewBox="0 0 11 11" aria-hidden="true"><path d="M2 5.5l2.2 2.2L9 3" stroke="currentColor" stroke-width="1.7" fill="none" stroke-linecap="round"/></svg>
|
||||
Geprüft
|
||||
{{ __('static.publish.example_verified') }}
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="font-serif m-0 text-[22px] leading-[1.2] font-semibold text-ink tracking-[-0.3px]">
|
||||
@if ($example)
|
||||
<a href="{{ $example->slug ? route('release.detail', ['slug' => $example->slug]) : '#' }}" class="hover:text-brand transition-colors">{{ $example->title }}</a>
|
||||
@else
|
||||
Mittelständischer Fertiger eröffnet Werk und schafft 84 Arbeitsplätze
|
||||
{{ __('static.publish.example_title_fallback') }}
|
||||
@endif
|
||||
</h3>
|
||||
<p class="font-serif mt-3.5 mb-0 text-[14px] leading-[1.55] text-ink-2">
|
||||
{{ $example?->subtitle
|
||||
?? \Illuminate\Support\Str::limit(strip_tags((string) $example?->text), 180)
|
||||
?: 'Coesfeld · Die Brinkmann Präzisionstechnik GmbH hat einen Erweiterungsbau in Betrieb genommen. Investitionsvolumen: 9,4 Mio. Euro.' }}
|
||||
?: __('static.publish.example_text_fallback') }}
|
||||
</p>
|
||||
<hr class="rule my-4" />
|
||||
<div class="flex flex-wrap text-[11.5px] text-ink-3 gap-y-2 gap-x-[18px]">
|
||||
<span>{{ $exampleCompany ?? 'Brinkmann Präzisionstechnik GmbH' }}</span>
|
||||
<span>{{ $exampleCompany ?? __('static.publish.example_company_fallback') }}</span>
|
||||
<span class="text-ink-4">·</span>
|
||||
<span class="font-mono">{{ $examplePublishedAt ? $examplePublishedAt->translatedFormat('j. M Y, H:i') : '14. Mai 2026, 09:30' }}</span>
|
||||
<span class="text-ink-4">·</span>
|
||||
<span>{{ $exampleReadMinutes }} Min. Lesezeit</span>
|
||||
<span>{{ __('static.publish.example_read_time', ['minutes' => $exampleReadMinutes]) }}</span>
|
||||
</div>
|
||||
</article>
|
||||
<div class="mt-3.5 text-[11.5px] text-ink-3 leading-[1.5]">
|
||||
Beispiel. Jede Mitteilung erhält eine permanente URL, ein strukturiertes Datenblatt und bleibt im durchsuchbaren Archiv.
|
||||
{{ __('static.publish.example_note') }}
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
|
@ -172,16 +200,16 @@
|
|||
@if (! empty($newsroomNames))
|
||||
<section class="bg-bg border-t border-bg-rule">
|
||||
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-6 grid items-baseline gap-4 lg:gap-7 grid-cols-1 lg:grid-cols-[auto_1fr_auto]">
|
||||
<span class="eyebrow muted text-[10.5px] flex-shrink-0">Aktive Newsrooms zuletzt</span>
|
||||
<span class="eyebrow muted text-[10.5px] flex-shrink-0">{{ __('static.publish.newsrooms_recent') }}</span>
|
||||
<p class="m-0 text-[13.5px] leading-[1.6] text-ink-2">
|
||||
@foreach ($newsroomNames as $name)
|
||||
<span class="text-ink font-medium">{{ $name }}</span>@if (! $loop->last)<span class="text-ink-4"> · </span>@endif
|
||||
@endforeach
|
||||
@if ($newsroomTotalLabel > 0)
|
||||
<span class="text-ink-3"> — und {{ number_format($newsroomTotalLabel, 0, ',', '.') }} weitere veröffentlichende Unternehmen.</span>
|
||||
<span class="text-ink-3"> — {{ __('static.publish.newsrooms_more', ['count' => number_format($newsroomTotalLabel, 0, ',', '.')]) }}</span>
|
||||
@endif
|
||||
</p>
|
||||
<a href="{{ route('newsrooms') }}" class="text-[12px] text-brand font-medium border-b border-brand pb-px flex-shrink-0 justify-self-start">Alle Newsrooms →</a>
|
||||
<a href="{{ route('newsrooms') }}" class="text-[12px] text-brand font-medium border-b border-brand pb-px flex-shrink-0 justify-self-start">{{ __('static.publish.newsrooms_all') }} →</a>
|
||||
</div>
|
||||
</section>
|
||||
@endif
|
||||
|
|
@ -192,18 +220,13 @@
|
|||
<div class="flex flex-col gap-3.5 mb-9">
|
||||
<span class="font-mono text-[11px] text-ink-4 tracking-[0.1em]">§ 01</span>
|
||||
<div>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">Was uns ausmacht</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">Vier Prinzipien, die diese Plattform tragen</h2>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">{{ __('static.publish.trust_eyebrow') }}</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">{{ __('static.publish.trust_heading') }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 border-t border-bg-rule-strong">
|
||||
@foreach ([
|
||||
['k' => 'Qualität', 't' => 'Geprüfte Mitteilungen', 'd' => 'Jede Mitteilung durchläuft eine Qualitätsprüfung, bevor sie online geht. Keine SEO-Spam-Texte, keine reinen Werbeanzeigen.'],
|
||||
['k' => 'Auffindbarkeit', 't' => 'Dauerhaft im Archiv', 'd' => 'Pressemitteilungen bleiben im Archiv – auch nach Jahren. Mitteilungen aus mehr als einem Jahrzehnt sind weiterhin abrufbar.'],
|
||||
['k' => 'Konditionen', 't' => 'Faire Preise, keine Bindung', 'd' => 'Transparente Preise, kein Abo-Zwang, keine Vertragsfallen. Sie zahlen, was Sie einreichen.'],
|
||||
['k' => 'Umgang mit Fehlern', 't' => 'Korrektur statt Löschung', 'd' => 'Fehler in einer Mitteilung? Wir korrigieren statt zu löschen – damit Verweise und Verlinkungen bestehen bleiben.'],
|
||||
] as $i => $p)
|
||||
@foreach ($trustPrinciples as $i => $p)
|
||||
<div class="py-7 {{ $i % 4 !== 3 ? 'lg:border-r' : '' }} {{ $i % 2 === 0 ? 'sm:border-r lg:border-r' : '' }} border-bg-rule {{ $i > 0 ? 'border-t sm:border-t-0' : '' }} {{ $i >= 2 ? 'lg:border-t-0 sm:border-t' : '' }} px-0 sm:px-6 first:sm:pl-0 lg:first:pl-0 lg:pr-6">
|
||||
<div class="eyebrow muted text-[10px] mb-3.5">{{ $p['k'] }}</div>
|
||||
<h3 class="font-serif m-0 text-[22px] leading-[1.2] font-semibold tracking-[-0.3px]">{{ $p['t'] }}</h3>
|
||||
|
|
@ -221,19 +244,15 @@
|
|||
<div class="flex flex-col gap-3.5">
|
||||
<span class="font-mono text-[11px] text-ink-4 tracking-[0.1em]">§ 02</span>
|
||||
<div>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">Ablauf</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">So funktioniert's — drei Schritte</h2>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">{{ __('static.publish.flow_eyebrow') }}</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">{{ __('static.publish.flow_heading') }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-[12.5px] text-ink-3 max-w-[280px] lg:text-right leading-[1.55]">Keine Magic-Sprache. Was hier passiert, passiert sichtbar.</div>
|
||||
<div class="text-[12.5px] text-ink-3 max-w-[280px] lg:text-right leading-[1.55]">{{ __('static.publish.flow_note') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-px bg-bg-rule border-y border-bg-rule-strong">
|
||||
@foreach ([
|
||||
['n' => '01', 'meta' => '≈ 2 Minuten', 't' => 'Konto anlegen', 'd' => 'Mit E-Mail-Adresse und Passwort — Anmeldung wahlweise auch passwortlos per Magic-Link. Konto und Abrechnung liegen im zentralen Publisher-Bereich — ein Konto für beide Portale.'],
|
||||
['n' => '02', 'meta' => 'werktags · innerhalb 24 h', 't' => 'Mitteilung einreichen', 'd' => 'Text, Bild, Ansprechpartner. Die automatisierte Inhaltsprüfung läuft direkt beim Einreichen mit.'],
|
||||
['n' => '03', 'meta' => 'permanent · indexiert', 't' => 'Veröffentlichung', 'd' => 'Nach Freigabe online und im Archiv. Bei Bedarf jederzeit korrigierbar — die URL bleibt stabil, Verweise bestehen weiter.'],
|
||||
] as $step)
|
||||
@foreach ($flowSteps as $step)
|
||||
<div class="bg-bg-elev px-7 pt-8 pb-9">
|
||||
<div class="flex items-baseline justify-between mb-[22px]">
|
||||
<span class="font-mono text-[13px] text-brand font-semibold">{{ $step['n'] }}</span>
|
||||
|
|
@ -246,8 +265,7 @@
|
|||
</div>
|
||||
|
||||
<p class="mt-[18px] mb-0 text-[12px] text-ink-3">
|
||||
Die Veröffentlichung erfolgt über den zentralen Publisher-Bereich und erscheint ohne Mehrkosten
|
||||
auf beiden Portalen — presseecho.de und businessportal24.com.
|
||||
{{ __('static.publish.flow_footnote') }}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -259,23 +277,16 @@
|
|||
<div class="flex flex-col gap-3.5">
|
||||
<span class="font-mono text-[11px] text-ink-4 tracking-[0.1em]">§ 03</span>
|
||||
<div>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">Für wen</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">Typische Anlässe einer Veröffentlichung</h2>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">{{ __('static.publish.occasions_eyebrow') }}</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">{{ __('static.publish.occasions_heading') }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-[12.5px] text-ink-3 max-w-[280px] lg:text-right leading-[1.55]">Anhaltspunkt für die Eignung. Eine Aufzählung, keine abschließende Liste.</div>
|
||||
<div class="text-[12.5px] text-ink-3 max-w-[280px] lg:text-right leading-[1.55]">{{ __('static.publish.occasions_note') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="grid items-start gap-12 lg:gap-16 grid-cols-1 lg:grid-cols-[1.05fr_1fr]">
|
||||
<ol class="list-none p-0 m-0">
|
||||
@foreach ([
|
||||
['t' => 'Neue Produkte oder Dienstleistungen', 'd' => 'Markteinführungen, Produktupdates, neue Services.'],
|
||||
['t' => 'Personalien und Geschäftsleitungs-Wechsel', 'd' => 'Berufungen, Bestellungen, Verabschiedungen.'],
|
||||
['t' => 'Auszeichnungen und Zertifizierungen', 'd' => 'Awards, ISO- und Branchen-Zertifikate, Audits.'],
|
||||
['t' => 'Standort-Eröffnungen, Expansionen, Aufträge', 'd' => 'Werke, Niederlassungen, Großaufträge, Investitionen.'],
|
||||
['t' => 'Veranstaltungs-Ankündigungen', 'd' => 'Tage der offenen Tür, Fachtage, Hauptversammlungen.'],
|
||||
['t' => 'Studien und Marktanalysen', 'd' => 'Eigene Erhebungen, Trendberichte, Branchenkennzahlen.'],
|
||||
] as $i => $anlass)
|
||||
@foreach ($occasions as $i => $anlass)
|
||||
<li class="grid items-start gap-4 py-[18px] {{ $loop->first ? 'border-t border-bg-rule-strong' : '' }} border-b border-bg-rule grid-cols-[44px_1fr]">
|
||||
<span class="font-mono text-[12px] text-ink-4 pt-1">{{ str_pad((string) ($i + 1), 2, '0', STR_PAD_LEFT) }}</span>
|
||||
<div>
|
||||
|
|
@ -287,31 +298,30 @@
|
|||
</ol>
|
||||
|
||||
<aside class="border border-bg-rule border-l-[3px] border-l-brand bg-bg-card-warm px-7 py-7 lg:px-8">
|
||||
<div class="eyebrow text-[10.5px] mb-3.5">Wichtig zur Eingrenzung</div>
|
||||
<div class="eyebrow text-[10.5px] mb-3.5">{{ __('static.publish.scope_eyebrow') }}</div>
|
||||
<h3 class="font-serif m-0 text-[20px] lg:text-[22px] leading-[1.25] font-semibold tracking-[-0.3px] text-ink">
|
||||
Nicht geeignet sind reine Werbeanzeigen, SEO-Linkbuilding-Texte oder Inhalte ohne nachvollziehbaren Pressewert.
|
||||
{{ __('static.publish.scope_heading') }}
|
||||
</h3>
|
||||
<p class="mt-[18px] mb-0 text-[13.5px] leading-[1.6] text-ink-2">
|
||||
Die Inhaltsprüfung sichert den Charakter der Plattform. Mitteilungen, die diese Schwelle nicht
|
||||
erreichen, werden mit einer kurzen Begründung zurückgegeben — meist mit einem konkreten Korrekturvorschlag.
|
||||
{{ __('static.publish.scope_text') }}
|
||||
</p>
|
||||
<hr class="rule my-5" />
|
||||
<div class="grid gap-2.5 text-[13px]">
|
||||
<div class="flex items-start gap-2.5">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" class="mt-[3px] flex-shrink-0 text-ok" aria-hidden="true"><path d="M3 7l3 3 5-6" stroke="currentColor" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
<span class="text-ink">Mitteilungen mit klarem Anlass und Quelle</span>
|
||||
<span class="text-ink">{{ __('static.publish.scope_ok_1') }}</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2.5">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" class="mt-[3px] flex-shrink-0 text-ok" aria-hidden="true"><path d="M3 7l3 3 5-6" stroke="currentColor" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
<span class="text-ink">Ansprechpartner mit Funktion und Kontakt</span>
|
||||
<span class="text-ink">{{ __('static.publish.scope_ok_2') }}</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2.5">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" class="mt-[3px] flex-shrink-0 text-ink-3" aria-hidden="true"><path d="M3.5 3.5l7 7M10.5 3.5l-7 7" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
|
||||
<span class="text-ink-3">Reine Verkaufs- und Rabatt-Texte</span>
|
||||
<span class="text-ink-3">{{ __('static.publish.scope_no_1') }}</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2.5">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" class="mt-[3px] flex-shrink-0 text-ink-3" aria-hidden="true"><path d="M3.5 3.5l7 7M10.5 3.5l-7 7" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
|
||||
<span class="text-ink-3">Anonyme oder Quellen-lose Inhalte</span>
|
||||
<span class="text-ink-3">{{ __('static.publish.scope_no_2') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
|
@ -325,41 +335,41 @@
|
|||
<div class="flex flex-col gap-3.5 mb-9">
|
||||
<span class="font-mono text-[11px] text-ink-4 tracking-[0.1em]">§ 04</span>
|
||||
<div>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">Preise</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">Sie zahlen, was Sie einreichen.</h2>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">{{ __('static.publish.pricing') }}</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">{{ __('static.publish.pricing_heading') }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-[1.3fr_1fr_1fr] border-y border-bg-rule-strong">
|
||||
<div class="pt-7 pb-8 lg:pr-8 lg:border-r border-bg-rule">
|
||||
<div class="eyebrow muted text-[10px] mb-3">Logik</div>
|
||||
<div class="eyebrow muted text-[10px] mb-3">{{ __('static.publish.pricing_logic') }}</div>
|
||||
<p class="font-serif m-0 text-[18px] lg:text-[19px] leading-[1.5] text-ink tracking-[-0.1px]">
|
||||
Einzeln ohne Abo veröffentlichen oder im Monats-Tarif — Inhaltsprüfung und beide Portale sind immer enthalten.
|
||||
{{ __('static.publish.pricing_logic_text') }}
|
||||
</p>
|
||||
<ul class="list-none p-0 mt-5 text-[13px] text-ink-2 grid gap-2.5">
|
||||
<li class="flex items-start gap-2.5"><span class="w-1.5 h-px bg-brand mt-2.5 flex-shrink-0"></span><span>Beide Portale ohne Mehrkosten.</span></li>
|
||||
<li class="flex items-start gap-2.5"><span class="w-1.5 h-px bg-brand mt-2.5 flex-shrink-0"></span><span>Abgelehnte Mitteilungen kosten kein Kontingent.</span></li>
|
||||
<li class="flex items-start gap-2.5"><span class="w-1.5 h-px bg-brand mt-2.5 flex-shrink-0"></span><span>Alle Tarife monatlich kündbar.</span></li>
|
||||
<li class="flex items-start gap-2.5"><span class="w-1.5 h-px bg-brand mt-2.5 flex-shrink-0"></span><span>{{ __('static.publish.pricing_point_1') }}</span></li>
|
||||
<li class="flex items-start gap-2.5"><span class="w-1.5 h-px bg-brand mt-2.5 flex-shrink-0"></span><span>{{ __('static.publish.pricing_point_2') }}</span></li>
|
||||
<li class="flex items-start gap-2.5"><span class="w-1.5 h-px bg-brand mt-2.5 flex-shrink-0"></span><span>{{ __('static.publish.pricing_point_3') }}</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pt-7 pb-8 lg:px-8 border-t lg:border-t-0 lg:border-r border-bg-rule flex flex-col justify-between">
|
||||
<div>
|
||||
<div class="eyebrow muted text-[10px] mb-3">Anker</div>
|
||||
<div class="font-serif text-[16px] leading-[1.4] text-ink-2">Eine Veröffentlichung ohne Abo</div>
|
||||
<div class="eyebrow muted text-[10px] mb-3">{{ __('static.publish.pricing_anchor') }}</div>
|
||||
<div class="font-serif text-[16px] leading-[1.4] text-ink-2">{{ __('static.publish.pricing_single') }}</div>
|
||||
<div class="mt-2 font-serif text-[40px] lg:text-[48px] font-semibold leading-none text-ink tracking-[-1.5px]">{{ $singlePmLabel }} €</div>
|
||||
<div class="mt-2.5 text-[12px] text-ink-3">netto · zzgl. USt. · voller Leistungsumfang.</div>
|
||||
<div class="mt-2.5 text-[12px] text-ink-3">{{ __('static.publish.pricing_single_note') }}</div>
|
||||
</div>
|
||||
@if ($cheapestPlanPriceLabel)
|
||||
<div class="mt-5 text-[11.5px] text-ink-3 leading-[1.5]">Regelmäßig veröffentlichen: Tarife ab {{ $cheapestPlanPriceLabel }} € / Monat mit {{ $cheapestPlan->press_release_quota }} Mitteilungen.</div>
|
||||
<div class="mt-5 text-[11.5px] text-ink-3 leading-[1.5]">{{ __('static.publish.pricing_plans_note', ['price' => $cheapestPlanPriceLabel, 'quota' => $cheapestPlan->press_release_quota]) }}</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="pt-7 pb-8 lg:pl-8 border-t lg:border-t-0 border-bg-rule flex flex-col justify-between">
|
||||
<div>
|
||||
<div class="eyebrow muted text-[10px] mb-3">Vollständige Übersicht</div>
|
||||
<p class="m-0 text-[14px] leading-[1.6] text-ink-2">Alle Tarife, Extra-Kontingente, Boost-Platzierungen und Agentur-Konditionen finden Sie in der Preisübersicht.</p>
|
||||
<div class="eyebrow muted text-[10px] mb-3">{{ __('static.publish.pricing_overview') }}</div>
|
||||
<p class="m-0 text-[14px] leading-[1.6] text-ink-2">{{ __('static.publish.pricing_overview_text') }}</p>
|
||||
</div>
|
||||
<a href="{{ route('preise') }}" class="mt-5 inline-flex items-center gap-2 text-[13.5px] font-semibold text-brand border-b border-brand self-start pb-0.5">
|
||||
Zur Preisübersicht
|
||||
{{ __('static.publish.pricing_overview_cta') }}
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M3 6h6M6 3l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -374,27 +384,21 @@
|
|||
<div class="flex flex-col gap-3.5">
|
||||
<span class="font-mono text-[11px] text-ink-4 tracking-[0.1em]">§ 05</span>
|
||||
<div>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">Häufige Fragen</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">Kurz beantwortet</h2>
|
||||
<div class="eyebrow text-[10.5px] mb-2.5">{{ __('static.publish.faq_eyebrow') }}</div>
|
||||
<h2 class="font-serif m-0 text-[28px] lg:text-[36px] font-semibold leading-[1.1] text-ink max-w-[720px] tracking-[-0.6px] text-balance">{{ __('static.publish.faq_heading') }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid items-start gap-10 lg:gap-16 grid-cols-1 lg:grid-cols-[1fr_1.6fr]">
|
||||
<div class="lg:sticky lg:top-6 pt-2">
|
||||
<p class="font-serif m-0 text-[16px] leading-[1.55] text-ink-2">Sie finden hier keine Antwort?</p>
|
||||
<a href="mailto:{{ config('domains.domains.'.config('app.theme').'.brand.contact_email') ?? 'info@businessportal24.com' }}" class="mt-3.5 inline-flex items-center gap-1.5 text-[13.5px] font-medium text-brand border-b border-brand pb-0.5">Direkt Kontakt aufnehmen</a>
|
||||
<div class="mt-3.5 text-[12px] text-ink-3 leading-[1.55]">Antwort werktags per E-Mail</div>
|
||||
<p class="font-serif m-0 text-[16px] leading-[1.55] text-ink-2">{{ __('static.publish.faq_no_answer') }}</p>
|
||||
<button type="button" x-data @click="$dispatch('open-contact-modal')" class="mt-3.5 inline-flex items-center gap-1.5 text-[13.5px] font-medium text-brand border-b border-brand pb-0.5 cursor-pointer">{{ __('static.publish.faq_contact') }}</button>
|
||||
<div class="mt-3.5 text-[12px] text-ink-3 leading-[1.55]">{{ __('static.publish.faq_response_note') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-bg-rule-strong">
|
||||
@foreach ([
|
||||
['q' => 'Wie schnell wird meine Mitteilung veröffentlicht?', 'a' => 'Werktags üblicherweise innerhalb von 24 Stunden nach Einreichung. Bei zeitkritischen Mitteilungen ist eine Vorab-Absprache möglich.'],
|
||||
['q' => 'Bleibt meine Mitteilung dauerhaft online?', 'a' => 'Ja. Mitteilungen werden nicht gelöscht. Korrekturen sind jederzeit möglich — die URL bleibt erhalten.'],
|
||||
['q' => 'Kann ich auch auf presseecho.de veröffentlichen?', 'a' => 'Ja — jede Mitteilung erscheint automatisch auf beiden Portalen, presseecho.de und businessportal24.com, ohne Mehrkosten und ohne doppelte Eingabe.'],
|
||||
['q' => 'Brauche ich ein Abo?', 'a' => 'Nein. Eine Einzel-Pressemitteilung buchen Sie ohne Abo zum Festpreis; für regelmäßige Veröffentlichungen lohnen sich die monatlich kündbaren Tarife.'],
|
||||
['q' => 'Was passiert bei einem Fehler in der Mitteilung?', 'a' => 'Korrektur statt Löschung: Inhalte werden aktualisiert, die URL bleibt erhalten, Verlinkungen und Verweise bestehen weiter.'],
|
||||
] as $i => $faq)
|
||||
@foreach ($publishFaqs as $i => $faq)
|
||||
<details class="group border-b border-bg-rule" {{ $i === 0 ? 'open' : '' }}>
|
||||
<summary class="grid items-center gap-4 py-[22px] cursor-pointer list-none grid-cols-[44px_1fr_24px] [&::-webkit-details-marker]:hidden">
|
||||
<span class="font-mono text-[12px] text-ink-4">{{ str_pad((string) ($i + 1), 2, '0', STR_PAD_LEFT) }}</span>
|
||||
|
|
@ -417,21 +421,20 @@
|
|||
<div class="relative overflow-hidden grid items-end text-ink-on-dark bg-topbar-grad gap-8 lg:gap-14 grid-cols-1 lg:grid-cols-[1.3fr_1fr] px-7 py-10 lg:px-14 lg:py-14">
|
||||
<span class="absolute left-0 top-0 bottom-0 w-1 bg-brand" aria-hidden="true"></span>
|
||||
<div>
|
||||
<div class="eyebrow mb-3.5 text-[10.5px] text-brand-soft">Mitteilung einreichen · Schritt eins</div>
|
||||
<h2 class="font-serif m-0 text-[34px] lg:text-[48px] font-semibold leading-[1.08] text-ink-on-dark max-w-[700px] tracking-[-0.9px] text-balance">Bereit, Ihre Mitteilung einzureichen?</h2>
|
||||
<div class="eyebrow mb-3.5 text-[10.5px] text-brand-soft">{{ __('static.publish.cta_eyebrow') }}</div>
|
||||
<h2 class="font-serif m-0 text-[34px] lg:text-[48px] font-semibold leading-[1.08] text-ink-on-dark max-w-[700px] tracking-[-0.9px] text-balance">{{ __('static.publish.cta_heading') }}</h2>
|
||||
<p class="font-serif mt-5 mb-0 text-[16px] lg:text-[17px] leading-[1.55] text-ink-on-dark-2 max-w-[580px]">
|
||||
Konto in zwei Minuten anlegen, Text und Bild einreichen, nach bestandener Inhaltsprüfung veröffentlicht.
|
||||
Einmaliges Konto — beide Portale (businessportal24 & presseecho.de) nutzbar.
|
||||
{{ __('static.publish.cta_text') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-start gap-3.5">
|
||||
<a href="{{ $publisherUrl }}/register"
|
||||
class="inline-flex items-center gap-2 px-7 py-4 text-[15px] font-semibold text-white bg-brand hover:bg-brand-deep transition-colors">
|
||||
Zum Publisher-Bereich
|
||||
{{ __('static.publish.hub_cta') }}
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M4 8L8.5 3.5M8.5 3.5H5M8.5 3.5V7" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
<span class="text-[12px] text-ink-on-dark-2">Login per Magic-Link · ohne Vertragsbindung</span>
|
||||
<a href="{{ route('web.home') }}" class="mt-1.5 text-[13px] text-ink-on-dark border-b border-white/35 pb-0.5">Oder zuerst Beispiele ansehen →</a>
|
||||
<span class="text-[12px] text-ink-on-dark-2">{{ __('static.publish.hub_note') }}</span>
|
||||
<a href="{{ route('web.home') }}" class="mt-1.5 text-[13px] text-ink-on-dark border-b border-white/35 pb-0.5">{{ __('static.publish.cta_examples') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||