diff --git a/changelog/_8471.md b/changelog/_8471.md
new file mode 100644
index 0000000000..840a99f657
--- /dev/null
+++ b/changelog/_8471.md
@@ -0,0 +1,16 @@
+### Fixed
+
+- fixed linting in: `project_bplan_detail.html`, `project_detail.html`, `module_detail.html`, `base.html`
+
+### Changed
+
+- moved `/components/_alert.scss` to components_dashboard folder
+
+### Added
+- introduced a reusable snippet `alerts.html` to enhance consistency and maintainability across alerts and prevent code duplication.
+- added snippet to `project_detail.html`, `module_detail.html`, `base.html`
+- added alert__headline, .alert__content and alert__text to `/components_user_facing/_alert.scss`
+
+### Removed
+
+- removed messages class, @use "sass:color", $messages-margin-bottom form `/components_user_facing/_alert.scss`
\ No newline at end of file
diff --git a/meinberlin/apps/contrib/templates/meinberlin_contrib/components/alert.html b/meinberlin/apps/contrib/templates/meinberlin_contrib/components/alert.html
new file mode 100644
index 0000000000..bbc94195b5
--- /dev/null
+++ b/meinberlin/apps/contrib/templates/meinberlin_contrib/components/alert.html
@@ -0,0 +1,13 @@
+{% load i18n %}
+
+
-
- {# As bplan projects don't set the information and the result field, the default project detail, which is shown prior to the first phase, looks bad. #}
- {# This replaces the default project detail by a simple notice that the participation has not started yet. #}
-
-
{% translate 'Participation is not possible at the moment.' %}
-
- {% html_date project.modules.first.future_phases.first.start_date 'DATE_FORMAT' as start_date %}
- {% blocktranslate with date=start_date %}It starts on {{ date }}.{% endblocktrans %}
-
-
-
-{% endblock %}
+{% extends "meinberlin_projects/project_detail.html" %}
+{% load i18n rules react_follows thumbnail wagtailcore_tags meinberlin_project_tags offlineevent_tags contrib_tags ckeditor_tags %}
+
+{% block title %}{{ project.name }} — {{ block.super }}{% endblock title %}
+
+{% block breadcrumbs %}
+
+{% endblock breadcrumbs %}
+
+{% block content %}
+
+
+ {# As bplan projects don't set the information and the result field, the default project detail, which is shown prior to the first phase, looks bad. #}
+ {# This replaces the default project detail by a simple notice that the participation has not started yet. #}
+
+
{% translate 'Participation is not possible at the moment.' %}
+
+ {% html_date project.modules.first.future_phases.first.start_date 'DATE_FORMAT' as start_date %}
+ {% blocktranslate with date=start_date %}It starts on {{ date }}.{% endblocktrans %}
+
+
+
+{% endblock content %}
diff --git a/meinberlin/apps/projects/templates/meinberlin_projects/project_detail.html b/meinberlin/apps/projects/templates/meinberlin_projects/project_detail.html
index 426d7e2c65..4097c88eec 100644
--- a/meinberlin/apps/projects/templates/meinberlin_projects/project_detail.html
+++ b/meinberlin/apps/projects/templates/meinberlin_projects/project_detail.html
@@ -1,247 +1,240 @@
-{% extends "base.html" %}
-{% load i18n rules react_follows thumbnail wagtailcore_tags meinberlin_project_tags offlineevent_tags contrib_tags ckeditor_tags static %}
-
-{% block extra_css %}
- {{ block.super }}
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ project.name }}
-
-
{{ project.description }}
- {% if project.image_copyright %}
-
- {% translate "Image" %}: {{ project.image_copyright }}
-
- {% else %}
-
- {% translate "Image: copyright missing" %}
-
- {% endif %}
-
-
-
- {% react_follows project %}
-
-
-
-
-
-
-
- {% has_perm 'a4projects.change_project' request.user view.project as user_may_change %}
- {% if user_may_change %}
-
- {% endif %}
-
-
-
- {% translate "Information" %}
-
-
-
-
-
- {% translate "Participation" %}
-
-
-
-
- {% translate "Results" %}
-
-
-
-
-
-
-
- {% translate "Participate" %}
- {% if event %}
-
- {{ event.name }}
-
- {% html_date event.date 'DATETIME_FORMAT' %}
-
- {{ event.description | safe | transform_collapsibles | richtext }}
-
- {% elif view.is_project_view %}
-
-
-
- {% for module in modules %}
- {% include "meinberlin_projects/includes/project_module_tile.html" with project=project module=module %}
- {% endfor %}
-
-
-
- {% else %}
-
-
-
- {% include "a4modules/includes/module_detail_phase.html" %}
-
-
-
- {% block project_action %}{% endblock project_action %}
-
-
- {% endif %}
- {% block voting_token_field %}{% endblock voting_token_field %}
- {% block phase_content %}{% endblock phase_content %}
-
-
- {% translate "Result" %}
- {% if project.result %}
-
- {{ project.result | transform_collapsibles | disable_iframes | richtext }}
-
- {% else %}
- {% translate "No results yet." %}
- {% endif %}
-
-
-{% endblock content %}
+{% extends "base.html" %}
+{% load i18n rules react_follows thumbnail wagtailcore_tags meinberlin_project_tags offlineevent_tags contrib_tags ckeditor_tags static %}
+
+{% block extra_css %}
+ {{ block.super }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ project.name }}
+
+
{{ project.description }}
+ {% if project.image_copyright %}
+
+ {% translate "Image" %}: {{ project.image_copyright }}
+
+ {% else %}
+
+ {% translate "Image: copyright missing" %}
+
+ {% endif %}
+
+
+
+ {% react_follows project %}
+
+
+
+
+
+
+
+ {% has_perm 'a4projects.change_project' request.user view.project as user_may_change %}
+ {% if user_may_change %}
+
+ {% endif %}
+
+
+
+ {% translate "Information" %}
+
+
+
+
+
+ {% translate "Participation" %}
+
+
+
+
+ {% translate "Results" %}
+
+
+
+
+
+
+
+ {% translate "Participate" %}
+ {% if event %}
+
+ {{ event.name }}
+
+ {% html_date event.date 'DATETIME_FORMAT' %}
+
+ {{ event.description | safe | transform_collapsibles | richtext }}
+
+ {% elif view.is_project_view %}
+
+
+
+ {% for module in modules %}
+ {% include "meinberlin_projects/includes/project_module_tile.html" with project=project module=module %}
+ {% endfor %}
+
+
+
+ {% else %}
+
+
+
+ {% include "a4modules/includes/module_detail_phase.html" %}
+
+
+
+ {% block project_action %}{% endblock project_action %}
+
+
+ {% endif %}
+ {% block voting_token_field %}{% endblock voting_token_field %}
+ {% block phase_content %}{% endblock phase_content %}
+
+
+ {% translate "Result" %}
+ {% if project.result %}
+
+ {{ project.result | transform_collapsibles | disable_iframes | richtext }}
+
+ {% else %}
+ {% translate "No results yet." %}
+ {% endif %}
+
+
+{% endblock content %}
diff --git a/meinberlin/assets/scss/components/_alert.scss b/meinberlin/assets/scss/components_dashboard/_alert.scss
similarity index 100%
rename from meinberlin/assets/scss/components/_alert.scss
rename to meinberlin/assets/scss/components_dashboard/_alert.scss
diff --git a/meinberlin/assets/scss/components_user_facing/_alert.scss b/meinberlin/assets/scss/components_user_facing/_alert.scss
index 5599371526..98dd9f2a05 100644
--- a/meinberlin/assets/scss/components_user_facing/_alert.scss
+++ b/meinberlin/assets/scss/components_user_facing/_alert.scss
@@ -1,63 +1,47 @@
-@use "sass:color";
-
-$messages-margin-bottom: 25px;
-
-.messages {
- margin: 0 0 $messages-margin-bottom;
- padding: 0;
-
- li {
- display: block;
- }
-
- + .messages {
- margin-top: -$messages-margin-bottom;
- }
-}
-
-.alert {
- margin: 0;
- padding: $padding * 1.2 0;
- background-color: $message-light-blue;
- color: $text-base;
- text-align: center;
-}
-
-.alert--success {
- background-color: $message-light-green;
- color: $text-base;
-}
-
-.alert--error,
-.alert--danger {
- background-color: $message-light-red;
- color: $text-error;
-}
-
-.alert--warning {
- background-color: $message-light-yellow;
- color: $text-base;
-}
-
-.alert__close {
- float: right;
- color: inherit;
-}
-
-.alert--small {
- padding: 0.5em;
-}
-
-// If this directly follows the dialog box (see header.scss), add 16px
-// additional padding to the default value (see above).
-.messages:first-child > :first-child {
- padding-top: calc(16px + #{$padding * 1.2});
-}
-
-// compensate for margin-bottom on messages
-.project-header,
-.hero-unit {
- .messages + & {
- margin-top: -$messages-margin-bottom;
- }
-}
+.alert {
+ margin: $padding 0;
+ background-color: $message-light-blue;
+ display: flex;
+ justify-content: space-between;
+}
+
+.alert__content {
+ padding: $padding * 1.375 $padding * 1.125;
+}
+
+.alert__headline {
+ margin: 0;
+ padding: 0;
+ color: inherit;
+}
+
+.alert__text {
+ margin: 0;
+ padding: 0;
+}
+
+.alert__close {
+ padding: $padding * 0.625;
+ height: fit-content;
+ color: inherit;
+}
+
+.alert--success {
+ background-color: $message-light-green;
+ color: $text-base;
+}
+
+.alert--error,
+.alert--danger {
+ background-color: $message-light-red;
+ color: $text-error;
+}
+
+.alert--warning {
+ background-color: $message-light-yellow;
+ color: $text-base;
+}
+
+.alert--small {
+ padding: 0.5em;
+}
\ No newline at end of file
diff --git a/meinberlin/assets/scss/style_dashboard.scss b/meinberlin/assets/scss/style_dashboard.scss
index 8f128ea712..593f663915 100644
--- a/meinberlin/assets/scss/style_dashboard.scss
+++ b/meinberlin/assets/scss/style_dashboard.scss
@@ -27,7 +27,7 @@
@import "components/action";
// @import "components/accordion";
-@import "components/alert";
+@import "components_dashboard/alert";
@import "components/blocks";
@import "components_dashboard/breadcrumbs";
@import "components_dashboard/button";
diff --git a/meinberlin/templates/a4modules/module_detail.html b/meinberlin/templates/a4modules/module_detail.html
index 43bfd10822..cfda7ce777 100644
--- a/meinberlin/templates/a4modules/module_detail.html
+++ b/meinberlin/templates/a4modules/module_detail.html
@@ -1,124 +1,117 @@
-{% extends "base.html" %}
-{% load i18n rules react_follows thumbnail wagtailcore_tags meinberlin_project_tags offlineevent_tags contrib_tags ckeditor_tags static %}
-
-
-{% block extra_css %}
- {{ block.super }}
-
- {% if module.is_in_module_cluster %}
-
- {% endif %}
-
-
- {% for phase in module.phases %}
- {% if phase == module.active_phase and live_stream %}
-
- {{ live_stream.live_stream | disable_iframes | richtext }}
- •{% translate ' Live now' %}
-
- {% endif %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
- {% include "a4modules/includes/module_detail_phase.html" %}
-
-
- {% block project_action %}{% endblock %}
-
-
-
- {% block voting_token_field %}{% endblock %}
- {% block phase_content %}{% endblock %}
- {% if module.is_in_module_cluster %}
-
-
-
-
- {% for other_module in module.module_cluster %}
- {% if not other_module == module %}
- {% include "meinberlin_projects/includes/project_module_tile.html" with project=project module=other_module %}
- {% endif %}
- {% endfor %}
-
-
-
- {% endif %}
-
-{% endblock %}
+{% extends "base.html" %}
+{% load i18n rules react_follows thumbnail wagtailcore_tags meinberlin_project_tags offlineevent_tags contrib_tags ckeditor_tags static %}
+
+
+{% block extra_css %}
+ {{ block.super }}
+
+ {% if module.is_in_module_cluster %}
+
+ {% endif %}
+
+
+ {% for phase in module.phases %}
+ {% if phase == module.active_phase and live_stream %}
+
+ {{ live_stream.live_stream | disable_iframes | richtext }}
+ •{% translate ' Live now' %}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+ {% include "a4modules/includes/module_detail_phase.html" %}
+
+
+ {% block project_action %}{% endblock project_action %}
+
+
+
+ {% block voting_token_field %}{% endblock voting_token_field %}
+ {% block phase_content %}{% endblock phase_content %}
+ {% if module.is_in_module_cluster %}
+
+
+
+
+ {% for other_module in module.module_cluster %}
+ {% if not other_module == module %}
+ {% include "meinberlin_projects/includes/project_module_tile.html" with project=project module=other_module %}
+ {% endif %}
+ {% endfor %}
+
+
+
+ {% endif %}
+
+{% endblock content %}
diff --git a/meinberlin/templates/base.html b/meinberlin/templates/base.html
index f734a01947..373e0bc165 100644
--- a/meinberlin/templates/base.html
+++ b/meinberlin/templates/base.html
@@ -1,89 +1,84 @@
-
-{% load i18n userindicator static contrib_tags wagtailuserbar %}
-{% get_current_language as LANGUAGE_CODE %}
-
-
-