presseportale/resources/css/shared/hub-components.css
Kevin Adametz 79658bdf87 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>
2026-07-09 15:45:58 +00:00

1635 lines
46 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Hub-Components — Single Source of Truth für Hub-typische Layout-Bausteine
*
* Wird von BEIDEN Builds importiert:
* - resources/css/portal.css (FluxUI-Portal)
* - resources/css/web/shared-styles.css (Web/Hub-Frontend)
*
* Dadurch DRY für Customer-Dashboard (Phase 2), Admin-Dashboard (Phase 3),
* Listen/Detail-Pages (Phase 4) und perspektivisch auch die Hub-Landing.
*
* Tokens kommen aus shared/design-tokens.css — diese Datei darf KEINE
* Hex-Literale enthalten (außer wo bewusst alpha-overlays via `rgba`
* gegen White/Black gerechnet werden).
*
* Vorlage: dev/frontend/tailwind_v3/User Dashboard presseportale.html
* Dokumentation: dev/frontend/hub-flux/04-PHASE-2-CUSTOMER-DASHBOARD.md
*/
@layer components {
/* ============================================================
* Panels (Karten-Container mit Hub-Charakter)
* ============================================================ */
.panel {
background: var(--color-bg-card);
border: 1px solid var(--color-bg-rule);
border-radius: 6px;
}
.panel-warm {
background: var(--color-bg-elev);
border: 1px solid var(--color-bg-rule);
border-radius: 6px;
}
.panel-dark {
/* KONSTANTES Dark-Hub-Blau — bleibt auch im Dark Mode dunkel
(sonst würde `var(--color-hub)` zum hellen #5a78c2 werden).
Tokens `--color-panel-dark` und `--color-panel-dark-2` sind
in beiden Modi identisch. */
background: var(--color-panel-dark-2);
border: 1px solid var(--color-panel-dark);
border-radius: 6px;
color: var(--color-ink-on-dark);
}
.panel-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px 20px;
border-bottom: 1px solid var(--color-bg-rule);
}
.panel-dark .panel-head {
border-bottom-color: rgba(255, 255, 255, 0.1);
}
/* ============================================================
* Page-Header (Titel links, Aktionen rechts)
*
* Ersetzt das frühere Inline-Style `grid-template-columns:1fr auto`:
* Das starre Zwei-Spalten-Grid konnte auf schmalen Screens nicht
* umbrechen — die Aktions-Spalte (auto = Inhaltsbreite) quetschte
* die Titel-Spalte zusammen (Buchstaben-Umbrüche im Titel, Buttons
* liefen aus der Box). Unterhalb von lg stapeln die Bereiche.
* ============================================================ */
.page-header {
display: grid;
align-items: end;
gap: 20px;
}
@media (min-width: 1024px) {
.page-header {
grid-template-columns: 1fr auto;
gap: 32px;
}
}
/* Aktions-Zeilen (Buttons rechts) dürfen auf schmalen Screens
umbrechen, statt aus dem Header zu laufen. */
.page-header > .flex {
flex-wrap: wrap;
}
/* ============================================================
* PM-Inhalt (gerenderter Editor-HTML in Vorschau/Detail)
*
* Die Detailseiten nutzten `prose`-Klassen, aber das
* Tailwind-Typography-Plugin ist nicht installiert — der Text
* erschien deshalb unformatiert. Diese Klasse bildet die
* Editor-Typografie nach (Absätze, Listen, Zwischenüberschriften,
* Links), ohne eine neue Abhängigkeit einzuführen.
* ============================================================ */
.pr-content {
font-size: 14.5px;
line-height: 1.7;
color: var(--color-ink);
}
.pr-content p {
margin: 0 0 1em;
}
.pr-content p:last-child {
margin-bottom: 0;
}
.pr-content h2,
.pr-content h3,
.pr-content h4 {
color: var(--color-ink);
font-weight: 700;
letter-spacing: -0.2px;
line-height: 1.3;
margin: 1.6em 0 0.6em;
}
.pr-content h2 {
font-size: 19px;
}
.pr-content h3 {
font-size: 16.5px;
}
.pr-content h4 {
font-size: 15px;
}
.pr-content h2:first-child,
.pr-content h3:first-child,
.pr-content h4:first-child {
margin-top: 0;
}
.pr-content ul,
.pr-content ol {
margin: 0 0 1em;
padding-inline-start: 1.4em;
}
.pr-content ul {
list-style: disc;
}
.pr-content ol {
list-style: decimal;
}
.pr-content li {
margin: 0.3em 0;
}
.pr-content a {
color: var(--color-hub);
text-decoration: underline;
text-underline-offset: 2px;
}
.pr-content strong,
.pr-content b {
font-weight: 700;
color: var(--color-ink);
}
.pr-content blockquote {
margin: 1em 0;
padding: 0.2em 0 0.2em 1em;
border-left: 3px solid var(--color-hub-soft-2);
color: var(--color-ink-2);
font-style: italic;
}
.pr-content hr {
margin: 1.5em 0;
border: 0;
border-top: 1px solid var(--color-bg-rule);
}
/* ============================================================
* Stat-Cards (KPI-Karten mit farbigem Strip links)
* ============================================================ */
.stat-card {
position: relative;
background: var(--color-bg-card);
border: 1px solid var(--color-bg-rule);
border-radius: 6px;
padding: 18px 20px;
transition:
border-color 0.12s,
box-shadow 0.12s;
}
.stat-card .stat-strip {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 3px;
background: var(--color-hub-soft-2);
border-radius: 6px 0 0 6px;
}
.stat-card.is-primary .stat-strip {
background: var(--color-hub);
}
.stat-card.is-ok .stat-strip {
background: var(--color-ok);
}
.stat-card.is-warn .stat-strip {
background: var(--color-warn);
}
.stat-card.is-muted .stat-strip {
background: var(--color-ink-4);
}
.stat-label {
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--color-ink-3);
}
.stat-card.is-primary .stat-label {
color: var(--color-hub);
}
.stat-card.is-ok .stat-label {
color: var(--color-ok);
}
.stat-card.is-warn .stat-label {
color: var(--color-warn);
}
.stat-card.is-muted .stat-label {
color: var(--color-ink-4);
}
.stat-num {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
font-size: 36px;
font-weight: 600;
color: var(--color-ink);
letter-spacing: -0.5px;
line-height: 1.05;
margin-top: 14px;
/* Text-Werte (z. B. Portal-Name) dürfen die Karte nie sprengen. */
overflow-wrap: anywhere;
}
@media (max-width: 480px) {
.stat-num {
font-size: 26px;
}
}
.stat-card.is-ok .stat-num {
color: var(--color-ok);
}
.stat-card.is-warn .stat-num {
color: var(--color-warn);
}
.stat-card.is-muted .stat-num {
color: var(--color-ink-3);
}
.stat-meta {
font-family: var(--font-mono);
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--color-ink-3);
}
.stat-trend {
margin-top: 12px;
display: flex;
align-items: center;
gap: 8px;
font-size: 11.5px;
color: var(--color-ink-3);
}
/* ============================================================
* Hint-Cards (Datenqualitäts-Hinweise mit Progress-Bar)
* ============================================================ */
.hint-card {
display: grid;
gap: 14px;
grid-template-columns: auto 1fr;
align-items: start;
/* Im Light Mode warmes Buchpapier-elev; im Dark Mode der wärmere
Card-Ton (`--color-bg-card-warm` schaltet automatisch um). */
background: var(--color-bg-card-warm);
border: 1px solid var(--color-bg-rule);
/* `--color-accent-warm` bleibt KONSTANT Bernstein (Phase 5):
Im Portal mappt --color-accent auf Hub-Blau, hier wollen wir
aber den klassischen Bernstein-Border behalten. */
border-left: 3px solid var(--color-accent-warm);
border-radius: 5px;
padding: 16px 18px;
}
.hint-card .hint-ico {
width: 36px;
height: 36px;
border-radius: 4px;
background: var(--color-accent-soft);
color: var(--color-accent-deep);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.hint-card .hint-bar {
margin-top: 8px;
height: 4px;
width: 100%;
border-radius: 999px;
background: var(--color-bg-rule-2);
overflow: hidden;
}
.hint-card .hint-bar > span {
display: block;
height: 100%;
border-radius: 999px;
background: var(--color-accent-warm);
}
.hint-card .hint-action {
display: inline-flex;
align-items: center;
gap: 4px;
margin-top: 8px;
font-size: 11.5px;
font-weight: 600;
color: var(--color-accent-deep);
text-decoration: none;
text-underline-offset: 3px;
}
.hint-card .hint-action:hover {
text-decoration: underline;
text-decoration-color: color-mix(
in oklab,
var(--color-accent-deep),
transparent 60%
);
}
/* ============================================================
* Badges (Status-Pillen)
* ============================================================ */
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 3px 9px;
border-radius: 999px;
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
}
.badge.warn {
background: var(--color-warn-soft);
color: var(--color-accent-deep);
}
.badge.ok {
background: var(--color-ok-soft);
color: var(--color-gain-deep);
}
.badge.hub {
background: var(--color-hub-soft);
color: var(--color-hub);
}
.badge.err {
background: var(--color-err-soft);
color: var(--color-loss);
}
.badge.muted {
background: var(--color-bg-rule-2);
color: var(--color-ink-3);
}
.badge.dot::before {
content: "";
width: 6px;
height: 6px;
border-radius: 999px;
background: currentColor;
}
/* ============================================================
* Brand-Bridge (presseecho + businessportal24 Indikatoren)
* ============================================================ */
.bridge-row {
display: inline-flex;
align-items: center;
gap: 6px;
font-family: var(--font-mono);
font-size: 10.5px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--color-ink-3);
}
.dot-pe {
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--color-bridge-presseecho);
}
.dot-bp {
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--color-bridge-businessportal);
}
/* ============================================================
* Section-Eyebrow VARIANTE (für panel-head)
* ============================================================
* Die Basis-`.section-eyebrow` liegt in theme-pressekonto.css.
* Im Portal-Bundle haben wir die Klasse heute NOCH NICHT — hier
* eine portable Definition, die im Web-Build vom Original-Layer
* überschrieben wird (gleiche Werte → idempotent).
*/
.section-eyebrow {
display: inline-flex;
align-items: center;
gap: 10px;
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--color-hub);
}
.section-eyebrow::after {
content: "";
display: block;
width: 30px;
height: 1px;
background: var(--color-hub);
opacity: 0.45;
}
.section-eyebrow.on-dark {
color: var(--color-hub-line);
}
.section-eyebrow.on-dark::after {
background: var(--color-hub-line);
opacity: 0.55;
}
/* ============================================================
* Eyebrow VARIANTE (für Portal)
* ============================================================
* Basis liegt in theme-pressekonto.css. Hier portabel für Portal-Build.
*/
.eyebrow {
font-size: 11px;
font-weight: 700;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--color-hub);
}
.eyebrow.muted {
color: var(--color-ink-3);
letter-spacing: 0.16em;
font-weight: 600;
font-size: 10.5px;
}
.eyebrow.accent {
color: var(--color-accent-deep);
}
.eyebrow.on-dark {
color: var(--color-hub-line);
}
/* ============================================================
* Counter-Strip (Inline-Zähler unter H1)
* ============================================================
* Beispiel:
* 24 Mitteilungen · 18 veröffentlicht · 1 in Prüfung · …
*/
.counter-strip {
display: inline-flex;
align-items: center;
gap: 14px;
padding: 6px 0;
flex-wrap: wrap;
}
.counter-strip .seg {
display: inline-flex;
align-items: baseline;
gap: 6px;
font-size: 12.5px;
color: var(--color-ink-2);
}
.counter-strip .seg b {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
font-size: 13.5px;
font-weight: 600;
color: var(--color-ink);
letter-spacing: -0.2px;
}
.counter-strip .seg.is-ok b {
color: var(--color-gain-deep);
}
.counter-strip .seg.is-warn b {
color: var(--color-accent-deep);
}
.counter-strip .seg.is-err b {
color: var(--color-loss);
}
.counter-strip .seg.is-muted b {
color: var(--color-ink-3);
}
.counter-strip .sep {
width: 1px;
height: 11px;
background: var(--color-bg-rule);
}
/* ============================================================
* View-Tabs (Saved-Views — Tab-Leiste über Filter)
* ============================================================ */
.view-tabs {
display: flex;
align-items: center;
gap: 4px;
border-bottom: 1px solid var(--color-bg-rule);
}
.view-tab {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 7px 12px 9px;
font-size: 12.5px;
font-weight: 500;
color: var(--color-ink-3);
border-bottom: 2px solid transparent;
margin-bottom: -1px;
transition:
color 0.12s,
border-color 0.12s;
cursor: pointer;
background: transparent;
border-top: 0;
border-left: 0;
border-right: 0;
}
.view-tab:hover {
color: var(--color-hub);
}
.view-tab.is-active {
color: var(--color-hub);
font-weight: 600;
border-bottom-color: var(--color-hub);
}
.view-tab .cnt {
font-family: var(--font-mono);
font-size: 10.5px;
color: var(--color-ink-3);
background: var(--color-bg-rule-2);
padding: 1px 6px;
border-radius: 999px;
font-weight: 600;
letter-spacing: 0.04em;
}
.view-tab.is-active .cnt {
background: var(--color-hub);
color: var(--color-ink-on-dark);
}
/* ============================================================
* Filter-Chips (Dropdown-Buttons mit Caret)
* ============================================================ */
.filter-chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px 6px 14px;
background: var(--color-bg-card);
border: 1px solid var(--color-hub-soft-2);
border-radius: 4px;
font-size: 12.5px;
color: var(--color-hub);
font-weight: 500;
transition:
border-color 0.15s,
background 0.15s;
white-space: nowrap;
cursor: pointer;
}
.filter-chip:hover {
border-color: var(--color-hub);
background: var(--color-bg-elev);
}
.filter-chip.is-active {
background: var(--color-hub);
color: var(--color-ink-on-dark);
border-color: var(--color-hub);
}
.filter-chip.is-active:hover {
background: var(--color-hub-2);
}
.filter-chip .caret {
opacity: 0.55;
}
/* ============================================================
* Such-Feld (Icon + Input als Pille) – Toolbar-Suche
* Gleiche Optik wie .filter-chip (weißer Card-Hintergrund, Border),
* damit das Feld in der Filterleiste klar erkennbar ist.
* ============================================================ */
.search-wrap {
display: flex;
align-items: center;
gap: 7px;
flex: 1 1 240px;
padding: 6px 12px;
background: var(--color-bg-card);
border: 1px solid var(--color-hub-soft-2);
border-radius: 4px;
transition: border-color 0.15s;
}
.search-wrap:focus-within {
border-color: var(--color-hub);
}
.search-wrap .ico {
color: var(--color-ink-3);
flex-shrink: 0;
}
.search-wrap input {
flex: 1;
min-width: 0;
padding: 0;
border: 0;
background: transparent;
outline: none;
font-size: 12.5px;
color: var(--color-ink);
}
.search-wrap input::placeholder {
color: var(--color-ink-3);
}
/* ============================================================
* Active-Chips (entfernbare Filter-Anzeige)
* ============================================================ */
.active-chip {
display: inline-flex;
align-items: center;
gap: 7px;
padding: 4px 6px 4px 11px;
background: var(--color-bg-elev);
border: 1px solid var(--color-bg-rule);
border-radius: 999px;
font-size: 11.5px;
color: var(--color-ink-2);
font-weight: 500;
}
.active-chip strong {
color: var(--color-hub);
font-weight: 600;
}
.active-chip .x {
width: 16px;
height: 16px;
border-radius: 999px;
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--color-ink-3);
background: var(--color-bg-rule-2);
transition:
background 0.12s,
color 0.12s;
border: 0;
cursor: pointer;
}
.active-chip .x:hover {
background: var(--color-hub);
color: var(--color-ink-on-dark);
}
/* ============================================================
* Portal-Pills (presseecho / businessportal24 Indikator)
* ============================================================ */
.portal-pill {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 3px 8px;
border-radius: 999px;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.06em;
background: var(--color-bg-elev);
border: 1px solid var(--color-bg-rule);
color: var(--color-ink-2);
white-space: nowrap;
}
.portal-pill .pdot {
width: 6px;
height: 6px;
border-radius: 999px;
}
.portal-pill.pe .pdot {
background: var(--color-bridge-presseecho);
}
.portal-pill.bp .pdot {
background: var(--color-bridge-businessportal);
}
/* ============================================================
* Inline-Action (kleine Aktion direkt neben Status-Badge)
* ============================================================ */
.inline-action {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 11px;
font-weight: 600;
color: var(--color-hub);
background: transparent;
padding: 3px 6px;
margin-left: 4px;
border-radius: 3px;
border: 1px dashed transparent;
transition:
border-color 0.12s,
background 0.12s;
cursor: pointer;
}
.inline-action:hover {
background: var(--color-hub-soft);
border-color: var(--color-hub-soft-2);
}
.inline-action.warn {
color: var(--color-accent-deep);
}
.inline-action.warn:hover {
background: var(--color-warn-soft);
border-color: color-mix(
in oklab,
var(--color-warn),
transparent 60%
);
}
.inline-action.err {
color: var(--color-loss);
}
.inline-action.err:hover {
background: var(--color-err-soft);
border-color: color-mix(
in oklab,
var(--color-err),
transparent 60%
);
}
/* ============================================================
* Row-Tinting (für Status-Hover-Hervorhebung in Listen)
* ============================================================ */
.is-row-warn:hover,
tr.is-row-warn:hover td {
background: color-mix(
in oklab,
var(--color-warn-soft),
var(--color-bg-card) 50%
) !important;
}
.is-row-err:hover,
tr.is-row-err:hover td {
background: color-mix(
in oklab,
var(--color-err-soft),
var(--color-bg-card) 50%
) !important;
}
/* ============================================================
* Empty-Stage (große Empty-States in Panels/Tabellen)
* ============================================================ */
.empty-stage {
padding: 64px 24px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.empty-stage .empty-ico {
width: 64px;
height: 64px;
border-radius: 6px;
background: var(--color-hub-soft);
border: 1px solid var(--color-hub-soft-2);
color: var(--color-hub);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
}
.empty-stage .empty-ico.warm {
background: var(--color-accent-soft);
border-color: color-mix(
in oklab,
var(--color-accent-warm),
transparent 50%
);
color: var(--color-accent-deep);
}
.empty-stage .empty-ico.err {
background: var(--color-err-soft);
border-color: color-mix(
in oklab,
var(--color-err),
transparent 50%
);
color: var(--color-loss);
}
.empty-stage .empty-title {
font-size: 17px;
font-weight: 600;
color: var(--color-ink);
margin: 0;
letter-spacing: -0.2px;
}
.empty-stage .empty-sub {
font-size: 13px;
color: var(--color-ink-3);
line-height: 1.55;
margin: 8px 0 0;
max-width: 440px;
}
/* ============================================================
* SEG-TOGGLE (Karten- vs. Listenansicht)
* ============================================================ */
.seg-toggle {
display: inline-flex;
background: var(--color-bg-card);
border: 1px solid var(--color-hub-soft-2);
border-radius: 4px;
padding: 2px;
gap: 0;
}
.seg-toggle button {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 5px 11px;
font-size: 12px;
font-weight: 600;
color: var(--color-ink-3);
border-radius: 3px;
transition: background 0.12s, color 0.12s;
cursor: pointer;
}
.seg-toggle button:hover {
color: var(--color-hub);
}
.seg-toggle button.is-active {
background: var(--color-hub);
color: #fff;
}
.seg-toggle button svg {
opacity: 0.7;
}
.seg-toggle button.is-active svg {
opacity: 1;
}
/* ============================================================
* FIRM-CARD — Firmen-Karte im Card-Grid
* ============================================================ */
.firm-card {
background: var(--color-bg-card);
border: 1px solid var(--color-bg-rule);
border-radius: 6px;
padding: 18px;
transition: border-color 0.15s;
display: flex;
flex-direction: column;
gap: 14px;
min-height: 266px;
}
.firm-card:hover {
border-color: var(--color-hub-line);
}
.firm-card.is-self {
border-color: var(--color-bg-rule);
box-shadow: none;
}
.firm-card .logo {
width: 56px;
height: 56px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-mono);
font-weight: 700;
font-size: 18px;
letter-spacing: -0.5px;
flex-shrink: 0;
overflow: hidden;
}
.firm-card .logo img {
width: 100%;
height: 100%;
object-fit: cover;
}
.firm-card .name {
font-size: 16px;
font-weight: 700;
letter-spacing: -0.3px;
color: var(--color-ink);
line-height: 1.2;
margin: 0;
}
.firm-card .meta-line {
font-size: 11.5px;
color: var(--color-ink-3);
margin-top: 3px;
line-height: 1.4;
}
.firm-card .kpis {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border-top: 1px solid var(--color-bg-rule-2);
padding-top: 11px;
margin-top: auto;
}
.firm-card .kpi {
display: flex;
flex-direction: column;
gap: 2px;
padding: 0 4px;
border-right: 1px solid var(--color-bg-rule-2);
}
.firm-card .kpi:last-child {
border-right: 0;
}
.firm-card .kpi .k {
font-family: var(--font-mono);
font-size: 15.5px;
font-weight: 600;
color: var(--color-ink);
font-variant-numeric: tabular-nums;
line-height: 1.1;
letter-spacing: -0.3px;
}
.firm-card .kpi .l {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--color-ink-4);
}
/* ============================================================
* ROLE-PILL — Rolle innerhalb einer Firma
* ============================================================ */
.role-pill {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 2px 8px 2px 7px;
background: var(--color-bg-elev);
border: 1px dashed var(--color-hub-soft-2);
border-radius: 99px;
font-size: 10.5px;
color: var(--color-ink-3);
font-weight: 600;
letter-spacing: 0.04em;
}
.role-pill::before {
content: "";
width: 5px;
height: 5px;
border-radius: 99px;
background: var(--color-accent-warm);
}
.role-pill.admin {
color: var(--color-hub);
}
.role-pill.admin::before {
background: var(--color-hub);
}
/* ============================================================
* MINI-LOGO — Kleines Logo in Listen-Zeilen
* ============================================================ */
.mini-logo {
width: 30px;
height: 30px;
border-radius: 4px;
display: inline-flex;
align-items: center;
justify-content: center;
font-family: var(--font-mono);
font-size: 11px;
font-weight: 700;
letter-spacing: -0.3px;
flex-shrink: 0;
overflow: hidden;
}
.mini-logo img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* ============================================================
* LOGO-COLOR-TOKENS — Deterministische Avatar-Varianten
* ============================================================ */
.lg-brew {
background: linear-gradient(135deg, #3a4d2f 0%, #1f2e1a 100%);
color: var(--color-accent-soft);
}
.lg-mv {
background: linear-gradient(
135deg,
var(--color-hub) 0%,
var(--color-hub-2) 100%
);
color: #fff;
}
.lg-soft {
background: var(--color-accent-soft);
color: var(--color-accent-deep);
border: 1px solid
color-mix(in oklab, var(--color-accent-warm), transparent 50%);
}
.lg-warm {
background: linear-gradient(
135deg,
var(--color-accent-warm) 0%,
var(--color-accent-deep) 100%
);
color: #fff;
}
.lg-blank {
background: repeating-linear-gradient(
135deg,
var(--color-bg-elev) 0 6px,
var(--color-bg-rule-2) 6px 12px
);
color: var(--color-ink-4);
border: 1px dashed var(--color-hub-soft-2);
}
/* ============================================================
* CARD-ACTION — Aktion-Button auf einer Karte
* ============================================================ */
.card-action {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border: 1px solid var(--color-hub-soft-2);
background: var(--color-bg-card);
color: var(--color-hub);
border-radius: 4px;
font-size: 12px;
font-weight: 600;
transition: border-color 0.12s, background 0.12s;
white-space: nowrap;
}
.card-action:hover {
border-color: var(--color-hub);
background: var(--color-bg);
}
.card-action.primary {
background: var(--color-hub);
color: #fff;
border-color: var(--color-hub);
}
.card-action.primary:hover {
background: var(--color-hub-2);
}
/* ============================================================
* MENU-TRIGGER — 3-Dots Menu-Knopf
* ============================================================ */
.menu-trigger {
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
border-radius: 4px;
border: 1px solid transparent;
color: var(--color-ink-3);
background: transparent;
transition: background 0.12s, border-color 0.12s, color 0.12s;
cursor: pointer;
}
.menu-trigger:hover {
background: var(--color-bg);
border-color: var(--color-hub-soft-2);
color: var(--color-hub);
}
/* ============================================================
* PAGE-BTN — Pagination-Buttons
* ============================================================ */
.page-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 30px;
height: 30px;
padding: 0 9px;
border-radius: 4px;
border: 1px solid var(--color-hub-soft-2);
background: var(--color-bg-card);
font-size: 12px;
font-weight: 600;
color: var(--color-ink-2);
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.page-btn:hover {
border-color: var(--color-hub);
color: var(--color-hub);
}
.page-btn.is-current {
background: var(--color-hub);
border-color: var(--color-hub);
color: #fff;
}
.page-btn.is-disabled {
color: var(--color-ink-4);
border-color: var(--color-bg-rule-2);
background: var(--color-bg-elev);
cursor: default;
}
.page-btn.is-disabled:hover {
color: var(--color-ink-4);
border-color: var(--color-bg-rule-2);
}
/* ============================================================
* TABLE.LIST — Hub-styled Datentabelle (für reine HTML-Tabellen)
* ============================================================ */
table.list {
width: 100%;
border-collapse: separate;
border-spacing: 0;
font-size: 13px;
}
table.list thead th {
text-align: left;
font-weight: 700;
font-size: 10px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--color-ink-3);
padding: 11px 14px;
background: var(--color-bg-elev);
border-bottom: 1px solid var(--color-bg-rule);
white-space: nowrap;
}
table.list thead th:first-child {
padding-left: 18px;
}
table.list thead th:last-child {
padding-right: 18px;
}
table.list tbody td {
padding: 14px;
border-bottom: 1px solid var(--color-bg-rule-2);
vertical-align: middle;
}
table.list tbody td:first-child {
padding-left: 18px;
}
table.list tbody td:last-child {
padding-right: 18px;
}
table.list tbody tr:last-child td {
border-bottom: 0;
}
table.list tbody tr {
transition: background 0.1s;
}
table.list tbody tr:hover {
background: var(--color-bg-elev);
}
.row-title {
font-weight: 600;
color: var(--color-ink);
font-size: 13.5px;
line-height: 1.35;
letter-spacing: -0.1px;
display: inline-flex;
align-items: center;
gap: 9px;
}
.row-title:hover {
color: var(--color-hub);
}
.row-sub {
font-size: 11.5px;
color: var(--color-ink-3);
margin-top: 3px;
line-height: 1.4;
}
.row-num {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
font-size: 13px;
color: var(--color-ink);
font-weight: 600;
}
.row-num .sub {
font-family: var(--font-sans, "Inter Tight", sans-serif);
font-weight: 400;
font-size: 11px;
color: var(--color-ink-4);
margin-left: 4px;
letter-spacing: 0.02em;
}
/* ============================================================
* ADD-TILE — "Neue Firma anlegen" Karte im Card-Grid
* ============================================================ */
.add-tile {
border: 1.5px dashed var(--color-hub-soft-2);
background: var(--color-bg-elev);
border-radius: 6px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 24px;
min-height: 266px;
transition: border-color 0.15s, background 0.15s, color 0.15s;
cursor: pointer;
color: var(--color-ink-2);
}
.add-tile:hover {
border-color: var(--color-hub);
border-style: solid;
background: var(--color-bg-card);
color: var(--color-hub);
}
.add-tile .ico {
width: 48px;
height: 48px;
border-radius: 6px;
background: var(--color-hub-soft);
color: var(--color-hub);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 14px;
}
.add-tile:hover .ico {
background: var(--color-hub);
color: #fff;
}
.add-tile .lbl {
font-size: 14px;
font-weight: 600;
}
.add-tile .sub {
font-size: 11.5px;
color: var(--color-ink-3);
margin-top: 6px;
line-height: 1.5;
max-width: 200px;
}
}
/* ============================================================
* FluxUI-Tabellen im Hub-Panel-Kontext
* ============================================================
* FluxUI setzt per Default `first:ps-0 last:pe-0` auf alle
* Tabellen-Zellen/-Spalten — die Tabelle „klebt" am Rand des
* Containers. Im Hub-Stil wollen wir konsistente 18px
* Edge-Padding (wie im Mockup `table.list`).
*
* MUSS in `@layer utilities` stehen (gleicher Layer wie
* FluxUI's `first:ps-0`-Utility), sonst gewinnt FluxUI durch
* CSS-Cascade-Layer-Ordering, unabhängig von Spezifität.
*
* Greift überall, wo eine FluxUI-Tabelle innerhalb eines
* `.panel` oder `.panel-warm` sitzt. Tabellen in Modals,
* Dropdowns oder anderen Kontexten bleiben unangetastet.
*/
@layer utilities {
.panel [data-flux-table] [data-flux-column]:first-child,
.panel [data-flux-table] [data-flux-cell]:first-child,
.panel-warm [data-flux-table] [data-flux-column]:first-child,
.panel-warm [data-flux-table] [data-flux-cell]:first-child {
padding-inline-start: 18px;
}
.panel [data-flux-table] [data-flux-column]:last-child,
.panel [data-flux-table] [data-flux-cell]:last-child,
.panel-warm [data-flux-table] [data-flux-column]:last-child,
.panel-warm [data-flux-table] [data-flux-cell]:last-child {
padding-inline-end: 18px;
}
}
/* ============================================================
* Phase 7 — Press-Release-Form-Bausteine
* ============================================================
* Vorlage: dev/frontend/tailwind_v3/User Neue Mitteilung presseportale.html
* Bewusst eng auf den Form-Kontext gemünzt. Wird im Hub-Form für
* Counter-Pillen, KI-bald-Hints, Pre-Submit-Checks, Boilerplate-Box,
* Tag-Chips und Portal-/Veröffentlichungs-Optionen verwendet.
*/
@layer components {
/* Container-Query-Kontext: Das zweispaltige Editor-Layout richtet sich
nach dem real verfügbaren Inhaltsbereich, nicht nach dem Viewport.
So rutschen die rechten Cards automatisch nach unten, sobald die
Sidebar offen ist und der Platz knapp wird — unabhängig davon, bei
welcher Viewport-Breite die Sidebar gerade ein- oder ausfährt. */
.pr-editor-shell {
container-type: inline-size;
container-name: pr-editor;
}
.pr-editor-layout {
grid-template-columns: minmax(0, 1fr);
}
@container pr-editor (min-width: 960px) {
.pr-editor-layout {
grid-template-columns: minmax(0, 1fr) 360px;
}
.pr-editor-side {
position: sticky;
top: 1rem;
}
}
.pr-form-label {
display: flex;
align-items: center;
gap: 8px;
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--color-ink-3);
margin-bottom: 8px;
}
.pr-form-label .req {
color: var(--color-err);
font-weight: 700;
letter-spacing: 0;
}
.pr-form-help {
font-size: 11.5px;
color: var(--color-ink-4);
margin-top: 6px;
line-height: 1.5;
}
.pr-form-help.warn {
color: var(--color-warn);
}
/* Counter-Pille mit Bar (Titel-, Subline-, Body-Länge) */
.pr-meter {
display: inline-flex;
align-items: center;
gap: 6px;
font-family: var(--font-mono, ui-monospace, monospace);
font-size: 10.5px;
color: var(--color-ink-3);
font-variant-numeric: tabular-nums;
}
.pr-meter .bar {
position: relative;
width: 60px;
height: 4px;
background: var(--color-bg-rule-2);
border-radius: 99px;
overflow: hidden;
}
.pr-meter .bar i {
position: absolute;
inset: 0 auto 0 0;
background: var(--color-hub);
border-radius: 99px;
}
.pr-meter.good .bar i {
background: var(--color-ok);
}
.pr-meter.warn .bar i {
background: var(--color-warn);
}
.pr-meter.err .bar i {
background: var(--color-err);
}
/* KI-bald-Badge — gestrichelter Akzent-Ring */
.pr-bald-badge {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 2px 8px;
border-radius: 99px;
font-size: 9.5px;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
background: var(--color-accent-soft);
color: var(--color-accent-deep);
border: 1px dashed color-mix(in srgb, var(--color-accent) 60%, transparent);
}
.pr-bald-badge::before {
content: "";
width: 4px;
height: 4px;
border-radius: 99px;
background: var(--color-accent);
}
/* KI-Inline-Hint (z.B. KI-Lektorat unter dem Editor) */
.pr-ai-hint {
display: flex;
align-items: center;
gap: 9px;
padding: 8px 11px;
background: color-mix(in srgb, var(--color-accent-soft) 60%, var(--color-bg));
border: 1px dashed color-mix(in srgb, var(--color-accent) 50%, transparent);
border-radius: 4px;
font-size: 11.5px;
color: var(--color-accent-deep);
line-height: 1.45;
}
.pr-ai-hint .ico {
width: 22px;
height: 22px;
border-radius: 4px;
background: var(--color-accent-soft);
color: var(--color-accent-deep);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
/* Pre-Submit-Checkliste */
.pr-check-row {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 7px 0;
font-size: 12.5px;
}
.pr-check-row .ic {
width: 16px;
height: 16px;
border-radius: 99px;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-top: 1px;
}
.pr-check-row.ok .ic {
background: var(--color-ok-soft);
color: var(--color-ok);
}
.pr-check-row.warn .ic {
background: var(--color-warn-soft);
color: var(--color-warn);
}
.pr-check-row.err .ic {
background: var(--color-err-soft);
color: var(--color-err);
}
.pr-check-row .lbl {
flex: 1;
color: var(--color-ink);
line-height: 1.4;
}
.pr-check-row .lbl .sub {
display: block;
font-size: 11px;
color: var(--color-ink-3);
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);
border: 1px dashed var(--color-hub-soft-2);
border-radius: 5px;
padding: 14px 16px;
font-family: var(--font-serif, Georgia, serif);
font-size: 13.5px;
color: var(--color-ink-2);
line-height: 1.6;
}
/* Themen-Tag-Chip + Vorschlags-Buttons */
.pr-tag-chip {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 3px 4px 3px 9px;
background: var(--color-hub-soft);
color: var(--color-hub);
border-radius: 3px;
font-size: 11.5px;
font-weight: 500;
}
.pr-tag-chip .x {
width: 16px;
height: 16px;
border-radius: 2px;
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--color-hub);
transition: background 0.12s;
cursor: pointer;
}
.pr-tag-chip .x:hover {
background: var(--color-hub-soft-2);
}
.pr-tag-suggest {
padding: 3px 9px;
background: var(--color-bg-elev);
border: 1px dashed var(--color-hub-soft-2);
border-radius: 3px;
font-size: 11.5px;
color: var(--color-ink-2);
font-weight: 500;
transition: border-color 0.12s, background 0.12s, color 0.12s;
cursor: pointer;
}
.pr-tag-suggest:hover {
border-style: solid;
border-color: var(--color-hub);
background: var(--color-hub-soft);
color: var(--color-hub);
}
/* Veröffentlichungs-Optionen (RadioGroup-Cards) */
.pr-pub-opt {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 8px 12px;
border: 1px solid var(--color-bg-rule);
border-radius: 4px;
background: var(--color-bg-elev);
cursor: pointer;
transition: border-color 0.12s, background 0.12s;
}
.pr-pub-opt:hover {
border-color: var(--color-hub);
}
.pr-pub-opt.is-checked {
border-color: var(--color-hub);
background: var(--color-hub-soft);
box-shadow: inset 0 0 0 1px var(--color-hub);
}
.pr-pub-opt.is-disabled {
opacity: 0.7;
cursor: not-allowed;
}
.pr-pub-opt .dot-out {
width: 14px;
height: 14px;
border-radius: 99px;
border: 2px solid var(--color-ink-4);
flex-shrink: 0;
margin-top: 2px;
position: relative;
}
.pr-pub-opt.is-checked .dot-out {
border-color: var(--color-hub);
background: var(--color-hub);
}
.pr-pub-opt.is-checked .dot-out::after {
content: "";
position: absolute;
inset: 3px;
border-radius: 99px;
background: #fff;
}
}