FP_POC / apps /web /src /fp.css
github-actions[bot]
Space-Deploy aus GitHub main
9de795a
Raw History Blame Contribute Delete
8.5 kB
/* Future Planning – globales Stylesheet (UI-Redesign Etappe A, Bryan-Konzept).
*
* Hier lebt ALLES, was Pseudoklassen (:hover/:active), Media-Queries oder
* Keyframes braucht – Inline-Styles in React können das nicht. Statische
* JS-Tokens (Farben, Kartenobjekt, Pill) bleiben in theme.ts, damit
* Inline-Reste sie weiter konsumieren. Die Klassennamen sind zusätzlich als
* Konstanten in theme.ts (`CSS`) gespiegelt.
*
* Quelle/Vorgabe: Bryans UI-Konzept + Brain Corporate-Identity.md.
*/
:root {
/* Farbrollen (Bryan-Vorgabe). Dunkelgrün = Navigation/Titel/Text/Icons/
Rahmen/Sekundär-Buttons · Orange = die EINE Hauptaktion pro Ansicht,
aktiver Schritt, Fortschritt, Auswahl · Salbei = inaktiv/Tags/ruhige
Flächen. */
--fp-primary: #243d35;
--fp-primary-dark: #123845;
--fp-accent: #d6914f;
--fp-muted: #9ba494;
--fp-soft: #f0f7f2; /* Off-White NUR für Felder, Auswahl, Infoboxen,
Sekundärkarten, Ladezustände – NICHT als App-Grund. */
--fp-background: #ffffff; /* App-Body reinweiss. */
--fp-text: #123845;
/* Typografie. Schriftdateien werden BEWUSST NICHT eingebettet – die Lizenz
für «Accidental Presidency» (Display) und «GeosansLight» (Body) ist laut
Brain (Corporate-Identity.md §Offene Punkte) noch offen. Bis zur Klärung
nur Fallback-Ketten; sobald geklärt, hier @font-face ergänzen. */
--fp-font-display:
"Accidental Presidency", "Arial Narrow", "Helvetica Neue Condensed", sans-serif;
--fp-font-body: "GeosansLight", "Century Gothic", "Futura", system-ui, sans-serif;
/* Vereinheitlichter Kartenstil: harter Schlagschatten OHNE Blur (gleiche
Richtung/Stärke überall) + weisser Innenschein. Der Innenschein (inset)
ist bewusst kräftiger als der Schlagschatten – Bryan: «Schein nach innen
überall UND stärker» (2026-07-08). Rand etwas kräftiger grün eingefärbt,
damit die CI-Farbe auch im Ruhezustand sichtbar bleibt. */
--fp-card-border: 1px solid rgba(36, 61, 53, 0.3);
--fp-card-radius: 12px;
--fp-card-shadow:
7px 7px 0 rgba(36, 61, 53, 0.18), inset 0 0 30px rgba(240, 247, 242, 0.95),
inset 0 0 8px rgba(255, 255, 255, 0.7);
/* Innenschein allein (für Flächen ohne Schlagschatten, z. B. .fp-card-flach,
.fp-soft). */
--fp-inner-glow: inset 0 0 26px rgba(240, 247, 242, 0.95), inset 0 0 8px rgba(255, 255, 255, 0.7);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--fp-background);
color: var(--fp-text);
font-family: var(--fp-font-body);
}
/* Display-Font nur für Titel/grosse Zahlen/kurze Aussagen (UPPERCASE +
leichte Sperrung). Als Utility, falls Inline-`titel` nicht reicht. */
.fp-titel {
font-family: var(--fp-font-display);
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--fp-primary);
font-weight: 400;
}
/* ---------- Karten ---------- */
.fp-card {
background: #fff;
border: var(--fp-card-border);
border-radius: var(--fp-card-radius);
box-shadow: var(--fp-card-shadow);
}
/* Unterelemente flacher: Rahmen + Radius + Innenschein, aber kein
Schlagschatten (bewusst flacher als .fp-card). */
.fp-card-flach {
background: #fff;
border: var(--fp-card-border);
border-radius: var(--fp-card-radius);
box-shadow: var(--fp-inner-glow);
}
/* Aktive/ausgewählte Karte: oranger Rand (gleiche Schattenrichtung), Innenschein
ebenfalls verstärkt. */
.fp-card-aktiv {
border-color: var(--fp-accent);
box-shadow:
7px 7px 0 rgba(214, 145, 79, 0.22),
inset 0 0 30px rgba(240, 247, 242, 0.95),
inset 0 0 8px rgba(255, 255, 255, 0.7);
}
/* Sekundärfläche/Infobox/Ladefläche – Off-White ist hier erlaubt. Innenschein
in Weiss, damit er auf dem Off-White-Grund sichtbar bleibt. */
.fp-soft {
background: var(--fp-soft);
border-radius: var(--fp-card-radius);
box-shadow:
inset 0 0 22px rgba(255, 255, 255, 0.85),
inset 0 0 0 1px rgba(36, 61, 53, 0.08);
}
/* ---------- Buttons ---------- */
/* Farbige Objekte (Buttons/Chips/Karten mit CI-Farbe) tragen die CI-Grafik-
sprache: harter Schlagschatten (kleiner als Karten) + Schein nach innen. */
.fp-farbig {
box-shadow:
4px 4px 0 rgba(36, 61, 53, 0.22),
inset 0 0 18px rgba(255, 255, 255, 0.55),
inset 0 0 5px rgba(255, 255, 255, 0.8);
}
.fp-button {
transition:
transform 140ms ease,
box-shadow 140ms ease,
background 140ms ease;
}
.fp-button:active:not(:disabled) {
transform: scale(0.97);
}
.fp-button:disabled {
cursor: not-allowed;
opacity: 0.45;
}
/* Auswählbare Karte: hebt leicht an; der orange Rand kommt über
.fp-card-aktiv dazu. Im Hover/Fokus wird der Rand kräftig CI-grün, damit
Interaktion klar als «unsere Farbe» erkennbar ist (Bryan: mehr Grüntöne). */
.fp-auswahl {
transition:
transform 140ms ease,
box-shadow 140ms ease,
border-color 140ms ease;
}
.fp-auswahl:hover,
.fp-auswahl:focus-visible {
transform: translateY(-2px);
border-color: var(--fp-primary);
}
.fp-auswahl:not(.fp-card-aktiv):hover {
box-shadow:
7px 7px 0 rgba(36, 61, 53, 0.15),
inset 0 0 30px rgba(240, 247, 242, 0.95),
inset 0 0 8px rgba(255, 255, 255, 0.7),
0 0 0 2px rgba(36, 61, 53, 0.18);
}
/* Fokus allgemein (Tastatur): grüner Ring statt Browser-Default, konsistent
zur CI. */
.fp-button:focus-visible {
outline: 2px solid var(--fp-primary);
outline-offset: 2px;
}
/* ---------- Schrittwechsel-Einblendung (einmalig via CSS-Animation) ---------- */
@keyframes fp-einblenden {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fp-schritt-neu {
animation: fp-einblenden 200ms ease-out both;
}
/* ---------- Stil-Swipe: Karte gleitet weg (Like rechts, Dislike links) ------ */
@keyframes fp-swipe-like {
to {
transform: translateX(60%) rotate(4deg);
opacity: 0;
}
}
@keyframes fp-swipe-dislike {
to {
transform: translateX(-60%) rotate(-4deg);
opacity: 0;
}
}
/* Like = oranger Akzent, Dislike = neutrales Dunkelgrün. ~220 ms, dann kommt
per State das nächste Bild frisch (ohne Animation). */
.fp-swipe-like {
border-radius: 8px;
box-shadow: 0 0 0 3px rgba(214, 145, 79, 0.9);
animation: fp-swipe-like 220ms ease-in both;
}
.fp-swipe-dislike {
border-radius: 8px;
box-shadow: 0 0 0 3px rgba(36, 61, 53, 0.55);
animation: fp-swipe-dislike 220ms ease-in both;
}
/* ---------- Ladezustand: sanft pulsierendes Piktogramm ---------- */
@keyframes fp-puls {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.5;
transform: scale(0.9);
}
}
.fp-piktogramm-puls {
animation: fp-puls 1.4s ease-in-out infinite;
}
/* ---------- Ladezustand: Fortschrittsbalken (Ladezustand.tsx) ----------
Standard = unbestimmt (kein bekannter Endpunkt, meist ein KI-Call);
bestimmter Balken kommt über eine feste Füllungs-Breite (kein CSS nötig,
nur Inline-`width` per Prop `fortschritt`). */
.fp-fortschrittsbalken {
position: relative;
width: min(220px, 70%);
height: 6px;
border-radius: 999px;
background: rgba(36, 61, 53, 0.12);
overflow: hidden;
}
.fp-fortschrittsbalken-fuellung {
position: absolute;
top: 0;
left: 0;
height: 100%;
border-radius: 999px;
background: var(--fp-accent);
transition: width 200ms ease;
}
@keyframes fp-balken-unbestimmt {
0% {
left: -45%;
width: 40%;
}
50% {
width: 55%;
}
100% {
left: 100%;
width: 40%;
}
}
.fp-fortschrittsbalken-unbestimmt {
width: 40%;
transition: none;
animation: fp-balken-unbestimmt 1.3s ease-in-out infinite;
}
/* ---------- Responsive-Helfer ---------- */
.fp-two-column {
display: grid;
grid-template-columns: minmax(0, 1.6fr) minmax(300px, 0.8fr);
gap: 24px;
}
.fp-drei-karten {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
@media (max-width: 820px) {
.fp-two-column {
grid-template-columns: 1fr;
}
.fp-drei-karten {
grid-template-columns: 1fr;
}
}
/* Fortschrittsweg: auf kleinen Screens horizontal scrollbar statt Umbruch. */
.fp-fortschritt {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
/* Barrierefreiheit: Bewegung reduzieren, wenn das System es wünscht. */
@media (prefers-reduced-motion: reduce) {
.fp-schritt-neu,
.fp-piktogramm-puls,
.fp-swipe-like,
.fp-swipe-dislike,
.fp-button,
.fp-auswahl,
.fp-fortschrittsbalken-unbestimmt {
animation: none;
transition: none;
}
}