diff --git a/App.tsx b/App.tsx index 9a72f0f..6d921ea 100644 --- a/App.tsx +++ b/App.tsx @@ -18,7 +18,7 @@ import { initialisiereBenachrichtigungen } from './src/services/erinnerungen'; import { holeConsent } from './src/services/storage'; import { AppSchutz } from './src/components/AppSchutz'; import { Ikone } from './src/components/Ikone'; -import { farben, schrift } from './src/theme'; +import { farben, schrift, schriftart } from './src/theme'; import { FristenScreen } from './src/screens/FristenScreen'; import { ArchivScreen } from './src/screens/ArchivScreen'; import { ConsentScreen } from './src/screens/ConsentScreen'; @@ -67,10 +67,11 @@ function HauptTabs() { headerShown: false, tabBarActiveTintColor: farben.primaer, tabBarInactiveTintColor: farben.textTertiaer, - tabBarLabelStyle: { fontSize: 11, fontWeight: '600' }, + tabBarLabelStyle: { fontFamily: schriftart.serif, fontSize: 12, fontWeight: '700' }, tabBarStyle: { - backgroundColor: farben.flaeche, - borderTopColor: farben.rand, + backgroundColor: farben.hintergrund, + borderTopColor: farben.tinte, + borderTopWidth: 2, height: 56 + insets.bottom, paddingTop: 6, paddingBottom: insets.bottom, @@ -120,7 +121,7 @@ export default function App() { headerStyle: { backgroundColor: farben.hintergrund }, headerShadowVisible: false, headerTintColor: farben.primaer, - headerTitleStyle: { fontSize: schrift.gross, fontWeight: '700', color: farben.text }, + headerTitleStyle: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.text }, headerBackTitle: 'Zurück', contentStyle: { backgroundColor: farben.hintergrund }, }} @@ -149,12 +150,9 @@ const styles = StyleSheet.create({ backgroundColor: farben.primaerFuellung, alignItems: 'center', justifyContent: 'center', - borderWidth: 3, - borderColor: farben.flaeche, - shadowColor: '#000', - shadowOffset: { width: 0, height: 3 }, - shadowOpacity: 0.2, - shadowRadius: 5, - elevation: 5, + // Wie die Knöpfe der Webseite: Amtsblau, Tinten-Rahmen, harter Schatten + borderWidth: 2, + borderColor: farben.tinte, + boxShadow: '3px 4px 0px #21211D', }, }); diff --git a/src/components/Ampel.tsx b/src/components/Ampel.tsx index fadb538..5ed4608 100644 --- a/src/components/Ampel.tsx +++ b/src/components/Ampel.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { AmpelStatus } from '../utils/ampel'; -import { abstand, schrift } from '../theme'; +import { abstand, schrift, schriftart, ecke } from '../theme'; import { Ikone, IkonenName } from './Ikone'; const IKONE: Record = { rot: 'warnung', gelb: 'wecker', gruen: 'info' }; @@ -28,9 +28,9 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', borderLeftWidth: 6, - borderRadius: 12, + borderRadius: ecke, padding: abstand.m, gap: abstand.s, }, - text: { flex: 1, fontSize: schrift.gross, fontWeight: '700' }, + text: { fontFamily: schriftart.serif, flex: 1, fontSize: schrift.gross, fontWeight: '700' }, }); diff --git a/src/components/AppSchutz.tsx b/src/components/AppSchutz.tsx index 63a6c17..a8e4054 100644 --- a/src/components/AppSchutz.tsx +++ b/src/components/AppSchutz.tsx @@ -14,7 +14,7 @@ import { AppState, AppStateStatus, StyleSheet, Text, View } from 'react-native'; import * as LocalAuthentication from 'expo-local-authentication'; import { holeAppSperre } from '../services/storage'; import { GrossButton } from './GrossButton'; -import { farben, schrift, abstand } from '../theme'; +import { farben, schrift, abstand, schriftart } from '../theme'; export function AppSchutz({ children }: { children: React.ReactNode }) { const [entsperrt, setEntsperrt] = useState(false); @@ -97,14 +97,14 @@ const styles = StyleSheet.create({ gap: abstand.m, }, sichtschutz: { justifyContent: 'center', alignItems: 'center' }, - symbol: { fontSize: 56, textAlign: 'center' }, - titel: { + symbol: { fontFamily: schriftart.serif, fontSize: 56, textAlign: 'center' }, + titel: { fontFamily: schriftart.serif, fontSize: schrift.titel, fontWeight: '700', color: farben.text, textAlign: 'center', }, - text: { + text: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.textSekundaer, textAlign: 'center', diff --git a/src/components/GrossButton.tsx b/src/components/GrossButton.tsx index 20e1851..eab79dc 100644 --- a/src/components/GrossButton.tsx +++ b/src/components/GrossButton.tsx @@ -8,7 +8,7 @@ */ import React from 'react'; import { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native'; -import { farben, schrift, abstand, TOUCH_TARGET } from '../theme'; +import { farben, schrift, abstand, TOUCH_TARGET, schriftart, ecke } from '../theme'; import { Ikone, IkonenName } from './Ikone'; interface Props { @@ -30,8 +30,8 @@ export function GrossButton({ }: Props) { const istPrimaer = variante === 'primaer'; const istGefahr = variante === 'gefahr'; - // Sekundär: dunkles Bronze statt hellem Gold — auf grauer Fläche gut lesbar - const inhaltsFarbe = istPrimaer || istGefahr ? farben.primaerText : farben.primaerFuellung; + // Wie `.cta` der Webseite: Amtsblau gefüllt bzw. weißes Blatt mit blauer Schrift + const inhaltsFarbe = istPrimaer ? farben.primaerText : istGefahr ? farben.fehler : farben.primaer; return ( {laedt ? ( @@ -62,17 +62,19 @@ export function GrossButton({ const styles = StyleSheet.create({ button: { minHeight: TOUCH_TARGET, - borderRadius: 14, + borderRadius: ecke, justifyContent: 'center', alignItems: 'center', paddingHorizontal: abstand.l, paddingVertical: abstand.s, }, zeile: { flexDirection: 'row', alignItems: 'center', gap: abstand.xs + 2 }, - primaer: { backgroundColor: farben.primaerFuellung }, - sekundaer: { backgroundColor: farben.flaecheSekundaer }, - gefahr: { backgroundColor: farben.fehler }, - deaktiviert: { opacity: 0.4 }, - gedrueckt: { opacity: 0.65 }, - text: { fontSize: schrift.gross, fontWeight: '600', textAlign: 'center' }, + // Tinten-Rahmen + harter Versatz-Schatten wie `.cta` auf der Webseite; + // beim Drücken rutscht der Knopf in den Schatten (wie dort beim Hover) + primaer: { backgroundColor: farben.primaerFuellung, borderWidth: 2, borderColor: farben.tinte, boxShadow: '4px 4px 0px #21211D' }, + sekundaer: { backgroundColor: farben.flaeche, borderWidth: 2, borderColor: farben.tinte, boxShadow: '4px 4px 0px #21211D' }, + gefahr: { backgroundColor: farben.flaeche, borderWidth: 2, borderColor: farben.fehler }, + deaktiviert: { opacity: 0.4, boxShadow: 'none' }, + gedrueckt: { transform: [{ translateX: 2 }, { translateY: 2 }], boxShadow: '2px 2px 0px #21211D' }, + text: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', textAlign: 'center' }, }); diff --git a/src/screens/AnalyseScreen.tsx b/src/screens/AnalyseScreen.tsx index 413f60a..fbc68b4 100644 --- a/src/screens/AnalyseScreen.tsx +++ b/src/screens/AnalyseScreen.tsx @@ -24,7 +24,7 @@ import { terminZumKalender } from '../services/kalender'; import { berechneAmpel, naechsteFrist, formatiereLangDatum } from '../utils/ampel'; import { GrossButton } from '../components/GrossButton'; import { Ikone } from '../components/Ikone'; -import { farben, schrift, abstand, TOUCH_TARGET } from '../theme'; +import { farben, schrift, abstand, TOUCH_TARGET, schriftart, ecke, kartenSchatten } from '../theme'; type Props = NativeStackScreenProps; @@ -343,66 +343,66 @@ const styles = StyleSheet.create({ zentriert: { flex: 1, justifyContent: 'center', alignItems: 'center' }, // Frist-Karte - fristKarte: { borderRadius: 16, borderWidth: 1, padding: abstand.l }, + fristKarte: { borderRadius: ecke, borderWidth: 1, padding: abstand.l }, fristKopf: { flexDirection: 'row', alignItems: 'center', gap: 8, marginBottom: 10 }, - fristKicker: { fontSize: 12, letterSpacing: 0.6, textTransform: 'uppercase', fontWeight: '700' }, - grosseZahl: { fontSize: 64, lineHeight: 64, fontWeight: '800', fontVariant: ['tabular-nums'] }, - zahlEinheit: { fontSize: 22, fontWeight: '700', lineHeight: 24 }, - zahlUnter: { fontSize: 13, color: farben.textSekundaer }, + fristKicker: { fontFamily: schriftart.mono, fontSize: 12, letterSpacing: 0.6, textTransform: 'uppercase', fontWeight: '700' }, + grosseZahl: { fontFamily: schriftart.serif, fontSize: 64, lineHeight: 64, fontWeight: '800', fontVariant: ['tabular-nums'] }, + zahlEinheit: { fontFamily: schriftart.serif, fontSize: 22, fontWeight: '700', lineHeight: 24 }, + zahlUnter: { fontFamily: schriftart.serif, fontSize: 13, color: farben.textSekundaer }, trenner: { height: 1, backgroundColor: farben.rand, marginVertical: 14 }, datenZeile: { flexDirection: 'row', justifyContent: 'space-between', gap: 12, marginTop: 5 }, - datenLabel: { fontSize: schrift.klein, color: farben.textSekundaer }, - datenWert: { fontSize: schrift.klein, fontWeight: '700', color: farben.text }, + datenLabel: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer }, + datenWert: { fontFamily: schriftart.serif, fontSize: schrift.klein, fontWeight: '700', color: farben.text }, keineFrist: { flexDirection: 'row', gap: abstand.s, alignItems: 'center', - backgroundColor: farben.ampelGruenHintergrund, borderRadius: 12, + backgroundColor: farben.ampelGruenHintergrund, borderRadius: ecke, borderLeftWidth: 4, borderLeftColor: farben.ampelGruen, padding: abstand.m, }, - keineFristTitel: { fontSize: schrift.basis, fontWeight: '700', color: farben.text }, - keineFristText: { fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2 }, + keineFristTitel: { fontFamily: schriftart.serif, fontSize: schrift.basis, fontWeight: '700', color: farben.text }, + keineFristText: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2 }, // Werkzeuge werkzeugZeile: { flexDirection: 'row', gap: abstand.s, marginTop: abstand.m }, - werkzeug: { + werkzeug: { ...kartenSchatten, flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 7, - backgroundColor: farben.flaeche, borderRadius: 12, minHeight: 48, paddingHorizontal: abstand.s, + backgroundColor: farben.flaeche, borderRadius: ecke, minHeight: 48, paddingHorizontal: abstand.s, }, - werkzeugText: { fontSize: schrift.klein, fontWeight: '600', color: farben.primaerFuellung }, + werkzeugText: { fontFamily: schriftart.serif, fontSize: schrift.klein, fontWeight: '600', color: farben.primaerFuellung }, - kicker: { + kicker: { fontFamily: schriftart.mono, fontSize: 12, letterSpacing: 1.1, textTransform: 'uppercase', - color: farben.primaer, fontWeight: '700', marginTop: abstand.l, marginBottom: abstand.xs, + color: farben.textSekundaer, fontWeight: '700', marginTop: abstand.l, marginBottom: abstand.xs, }, - kernaussage: { fontSize: schrift.gross, color: farben.text, lineHeight: 29, fontWeight: '600' }, - erklaerung: { fontSize: schrift.basis, color: farben.textSekundaer, lineHeight: 27, marginTop: abstand.s }, + kernaussage: { fontFamily: schriftart.serif, fontSize: schrift.gross, color: farben.text, lineHeight: 29, fontWeight: '600' }, + erklaerung: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.textSekundaer, lineHeight: 27, marginTop: abstand.s }, dünnerTrenner: { height: 1, backgroundColor: farben.rand, marginTop: abstand.l }, // To-do todoZeile: { flexDirection: 'row', gap: abstand.s, alignItems: 'flex-start', minHeight: 40 }, todoKreis: { - width: 28, height: 28, borderRadius: 14, borderWidth: 1.5, borderColor: farben.primaer, + width: 28, height: 28, borderRadius: ecke, borderWidth: 1.5, borderColor: farben.primaer, alignItems: 'center', justifyContent: 'center', marginTop: 1, }, todoKreisFertig: { backgroundColor: farben.ampelGruen, borderColor: farben.ampelGruen }, - todoNummer: { fontSize: schrift.klein, fontWeight: '700', color: farben.primaerFuellung, fontVariant: ['tabular-nums'] }, - todoText: { flex: 1, fontSize: schrift.basis, color: farben.text, lineHeight: 25, paddingTop: 3 }, + todoNummer: { fontFamily: schriftart.serif, fontSize: schrift.klein, fontWeight: '700', color: farben.primaerFuellung, fontVariant: ['tabular-nums'] }, + todoText: { fontFamily: schriftart.serif, flex: 1, fontSize: schrift.basis, color: farben.text, lineHeight: 25, paddingTop: 3 }, durchgestrichen: { textDecorationLine: 'line-through', color: farben.textSekundaer }, // Fachbegriffe - begriffKarte: { backgroundColor: farben.flaeche, borderRadius: 12, padding: abstand.m }, - begriff: { fontSize: schrift.basis, fontWeight: '700', color: farben.text, marginBottom: 3 }, - begriffText: { fontSize: schrift.klein, color: farben.textSekundaer, lineHeight: 23 }, + begriffKarte: { ...kartenSchatten, backgroundColor: farben.flaeche, borderRadius: ecke, padding: abstand.m }, + begriff: { fontFamily: schriftart.serif, fontSize: schrift.basis, fontWeight: '700', color: farben.text, marginBottom: 3 }, + begriffText: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, lineHeight: 23 }, schutzZeile: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 6, marginTop: abstand.l }, - schutzText: { fontSize: 11.5, color: farben.textTertiaer }, + schutzText: { fontFamily: schriftart.serif, fontSize: 11.5, color: farben.textTertiaer }, - text: { fontSize: schrift.basis, color: farben.text, lineHeight: 27 }, + text: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.text, lineHeight: 27 }, // Modal modalHintergrund: { flex: 1, backgroundColor: 'rgba(0,0,0,0.45)', justifyContent: 'center', padding: abstand.l }, - modalKarte: { backgroundColor: farben.flaeche, borderRadius: 14, padding: abstand.m, maxHeight: '75%' }, - modalTitel: { fontSize: schrift.gross, fontWeight: '700', color: farben.text, marginBottom: abstand.xs }, + modalKarte: { ...kartenSchatten, backgroundColor: farben.flaeche, borderRadius: ecke, padding: abstand.m, maxHeight: '75%' }, + modalTitel: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.text, marginBottom: abstand.xs }, sprachZeile: { minHeight: TOUCH_TARGET, justifyContent: 'center' }, - sprachZeileText: { fontSize: schrift.gross, color: farben.text }, + sprachZeileText: { fontFamily: schriftart.serif, fontSize: schrift.gross, color: farben.text }, }); diff --git a/src/screens/AntwortScreen.tsx b/src/screens/AntwortScreen.tsx index 020a72a..06f3382 100644 --- a/src/screens/AntwortScreen.tsx +++ b/src/screens/AntwortScreen.tsx @@ -26,7 +26,7 @@ import { generiereAntwort } from '../services/antwort'; import { ClaudeFehler } from '../services/claudeClient'; import { GrossButton } from '../components/GrossButton'; import { Ikone, IkonenName } from '../components/Ikone'; -import { farben, schrift, abstand } from '../theme'; +import { farben, schrift, abstand, schriftart, ecke, kartenSchatten } from '../theme'; type Props = NativeStackScreenProps; @@ -258,28 +258,28 @@ function escapeHtml(s: string): string { const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: farben.hintergrund }, zentriert: { flex: 1, justifyContent: 'center', alignItems: 'center' }, - text: { fontSize: schrift.basis, color: farben.text }, + text: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.text }, - schrittLabel: { fontSize: schrift.klein, color: farben.textSekundaer, fontWeight: '600', marginBottom: abstand.xs }, + schrittLabel: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, fontWeight: '600', marginBottom: abstand.xs }, fortschritt: { flexDirection: 'row', gap: 6, marginBottom: abstand.l }, balken: { flex: 1, height: 5, borderRadius: 3 }, - titel: { fontSize: schrift.titel, fontWeight: '800', color: farben.text, marginBottom: 4 }, - unterTitel: { fontSize: schrift.klein, color: farben.textSekundaer, lineHeight: 22, marginBottom: abstand.s }, + titel: { fontFamily: schriftart.serif, fontSize: schrift.titel, fontWeight: '800', color: farben.text, marginBottom: 4 }, + unterTitel: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, lineHeight: 22, marginBottom: abstand.s }, // Schritt 1 — Karten - typKarte: { + typKarte: { ...kartenSchatten, flexDirection: 'row', alignItems: 'center', gap: abstand.s, - backgroundColor: farben.flaeche, borderRadius: 14, padding: abstand.m, + backgroundColor: farben.flaeche, borderRadius: ecke, padding: abstand.m, }, typIkone: { - width: 44, height: 44, borderRadius: 12, borderWidth: 1, borderColor: farben.primaer, + width: 44, height: 44, borderRadius: ecke, borderWidth: 1, borderColor: farben.primaer, alignItems: 'center', justifyContent: 'center', flexShrink: 0, }, - typTitel: { fontSize: schrift.basis, fontWeight: '700', color: farben.text }, - typBeschreibung: { fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2, lineHeight: 20 }, + typTitel: { fontFamily: schriftart.serif, fontSize: schrift.basis, fontWeight: '700', color: farben.text }, + typBeschreibung: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2, lineHeight: 20 }, empfohlenTag: { backgroundColor: farben.hervorhebung, borderRadius: 6, paddingHorizontal: 8, paddingVertical: 2 }, - empfohlenText: { fontSize: 11, fontWeight: '700', color: farben.primaerFuellung }, + empfohlenText: { fontFamily: schriftart.serif, fontSize: 11, fontWeight: '700', color: farben.primaerFuellung }, // Schritt 2/3 wahlPill: { @@ -287,19 +287,19 @@ const styles = StyleSheet.create({ borderWidth: 1, borderColor: farben.primaer, borderRadius: 9999, paddingHorizontal: 12, paddingVertical: 6, marginBottom: abstand.m, }, - wahlPillText: { fontSize: schrift.klein, color: farben.primaerFuellung, fontWeight: '600' }, - feldLabel: { fontSize: schrift.klein, color: farben.textSekundaer, fontWeight: '600', marginTop: abstand.s, marginBottom: 6 }, - eingabe: { - borderWidth: 1, borderColor: farben.rand, borderRadius: 12, padding: abstand.s, + wahlPillText: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.primaerFuellung, fontWeight: '600' }, + feldLabel: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, fontWeight: '600', marginTop: abstand.s, marginBottom: 6 }, + eingabe: { fontFamily: schriftart.serif, + borderWidth: 1, borderColor: farben.rand, borderRadius: ecke, padding: abstand.s, fontSize: schrift.basis, color: farben.text, backgroundColor: farben.flaeche, minHeight: 52, }, mehrzeilig: { minHeight: 110 }, briefText: { minHeight: 300, lineHeight: 26 }, infoBox: { flexDirection: 'row', gap: abstand.s, alignItems: 'flex-start', - backgroundColor: farben.hervorhebung, borderRadius: 12, padding: abstand.m, marginTop: abstand.m, + backgroundColor: farben.hervorhebung, borderRadius: ecke, padding: abstand.m, marginTop: abstand.m, }, - infoBoxText: { flex: 1, fontSize: schrift.klein, color: farben.text, lineHeight: 21 }, + infoBoxText: { fontFamily: schriftart.serif, flex: 1, fontSize: schrift.klein, color: farben.text, lineHeight: 21 }, zurueck: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 6, marginTop: abstand.m, paddingVertical: abstand.s }, - zurueckText: { fontSize: schrift.klein, color: farben.primaerFuellung, fontWeight: '600' }, + zurueckText: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.primaerFuellung, fontWeight: '600' }, }); diff --git a/src/screens/ArchivScreen.tsx b/src/screens/ArchivScreen.tsx index 2f08119..a234d32 100644 --- a/src/screens/ArchivScreen.tsx +++ b/src/screens/ArchivScreen.tsx @@ -13,7 +13,7 @@ import { berechneAmpel } from '../utils/ampel'; import { formatiereDatum } from '../services/erinnerungen'; import { Ikone } from '../components/Ikone'; import { GrossButton } from '../components/GrossButton'; -import { farben, schrift, abstand, TOUCH_TARGET } from '../theme'; +import { farben, schrift, abstand, TOUCH_TARGET, schriftart, ecke, kartenSchatten } from '../theme'; type Nav = NativeStackNavigationProp; @@ -161,39 +161,39 @@ export function ArchivScreen() { const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: farben.hintergrund }, - kicker: { + kicker: { fontFamily: schriftart.mono, fontSize: 12, letterSpacing: 1.3, textTransform: 'uppercase', - color: farben.primaer, fontWeight: '600', marginBottom: 4, + color: farben.textSekundaer, fontWeight: '600', marginBottom: 4, }, - titel: { fontSize: schrift.riesig, fontWeight: '800', color: farben.text, marginBottom: abstand.m }, - sucheBox: { + titel: { fontFamily: schriftart.serif, fontSize: schrift.riesig, fontWeight: '800', color: farben.text, marginBottom: abstand.m }, + sucheBox: { ...kartenSchatten, flexDirection: 'row', alignItems: 'center', gap: 8, - backgroundColor: farben.flaeche, borderRadius: 12, + backgroundColor: farben.flaeche, borderRadius: ecke, paddingHorizontal: abstand.s, marginBottom: abstand.s, minHeight: 48, }, - sucheFeld: { flex: 1, fontSize: schrift.basis, color: farben.text, paddingVertical: abstand.s }, + sucheFeld: { fontFamily: schriftart.serif, flex: 1, fontSize: schrift.basis, color: farben.text, paddingVertical: abstand.s }, chip: { borderRadius: 9999, borderWidth: 1, borderColor: farben.rand, backgroundColor: farben.flaeche, paddingHorizontal: 14, paddingVertical: 8, }, chipAktiv: { borderColor: farben.primaer, backgroundColor: farben.hervorhebung }, - chipText: { fontSize: schrift.klein, color: farben.textSekundaer }, + chipText: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer }, chipTextAktiv: { color: farben.primaer, fontWeight: '600' }, - zahlZeile: { + zahlZeile: { fontFamily: schriftart.mono, fontSize: 12, letterSpacing: 1, textTransform: 'uppercase', color: farben.textTertiaer, marginBottom: abstand.s, }, - zeile: { + zeile: { ...kartenSchatten, flexDirection: 'row', alignItems: 'center', gap: abstand.s, - backgroundColor: farben.flaeche, borderRadius: 12, + backgroundColor: farben.flaeche, borderRadius: ecke, padding: abstand.m, marginBottom: abstand.s, minHeight: TOUCH_TARGET, }, punkt: { width: 10, height: 10, borderRadius: 5 }, - zeileTyp: { flex: 1, fontSize: schrift.basis, fontWeight: '700', color: farben.text }, - datum: { fontSize: schrift.klein, color: farben.textTertiaer, fontVariant: ['tabular-nums'] }, - zeileMeta: { fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2 }, - ampelText: { fontSize: schrift.klein, fontWeight: '600', marginTop: 2 }, + zeileTyp: { fontFamily: schriftart.serif, flex: 1, fontSize: schrift.basis, fontWeight: '700', color: farben.text }, + datum: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textTertiaer, fontVariant: ['tabular-nums'] }, + zeileMeta: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2 }, + ampelText: { fontFamily: schriftart.serif, fontSize: schrift.klein, fontWeight: '600', marginTop: 2 }, leerBox: { alignItems: 'center', gap: abstand.s, marginTop: abstand.xl }, - leerTitel: { fontSize: schrift.gross, fontWeight: '700', color: farben.text }, - leerText: { fontSize: schrift.basis, color: farben.textSekundaer, textAlign: 'center', lineHeight: 26 }, + leerTitel: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.text }, + leerText: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.textSekundaer, textAlign: 'center', lineHeight: 26 }, }); diff --git a/src/screens/ConsentScreen.tsx b/src/screens/ConsentScreen.tsx index d266782..0551bac 100644 --- a/src/screens/ConsentScreen.tsx +++ b/src/screens/ConsentScreen.tsx @@ -8,7 +8,7 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack'; import { RootStackParamList } from '../types'; import { speichereConsent } from '../services/storage'; import { GrossButton } from '../components/GrossButton'; -import { farben, schrift, abstand } from '../theme'; +import { farben, schrift, abstand, schriftart, ecke, kartenSchatten } from '../theme'; type Props = NativeStackScreenProps; @@ -60,18 +60,18 @@ export function ConsentScreen({ navigation }: Props) { const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: farben.hintergrund }, inhalt: { padding: abstand.l }, - titel: { + titel: { fontFamily: schriftart.serif, fontSize: schrift.titel, fontWeight: '700', color: farben.text, marginBottom: abstand.l, }, - karte: { + karte: { ...kartenSchatten, backgroundColor: farben.flaeche, - borderRadius: 14, + borderRadius: ecke, padding: abstand.m, marginBottom: abstand.xl, gap: abstand.m, }, - punkt: { fontSize: schrift.basis, color: farben.text, lineHeight: 27 }, + punkt: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.text, lineHeight: 27 }, }); diff --git a/src/screens/EinstellungenScreen.tsx b/src/screens/EinstellungenScreen.tsx index b14ce76..857ba3e 100644 --- a/src/screens/EinstellungenScreen.tsx +++ b/src/screens/EinstellungenScreen.tsx @@ -33,7 +33,7 @@ import { import { NUTZT_PROXY } from '../services/claudeClient'; import { useAppStore } from '../store/useAppStore'; import { GrossButton } from '../components/GrossButton'; -import { farben, schrift, abstand } from '../theme'; +import { farben, schrift, abstand, schriftart, ecke, kartenSchatten } from '../theme'; type Props = NativeStackScreenProps; @@ -268,30 +268,30 @@ export function EinstellungenScreen({ navigation }: Props) { const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: farben.hintergrund }, - abschnittTitel: { + abschnittTitel: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.primaer, marginBottom: abstand.s, }, - text: { fontSize: schrift.basis, color: farben.text, lineHeight: 27 }, - hinweis: { + text: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.text, lineHeight: 27 }, + hinweis: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, lineHeight: 22, marginVertical: abstand.s, }, - eingabe: { + eingabe: { fontFamily: schriftart.serif, borderWidth: 1, borderColor: farben.rand, - borderRadius: 12, + borderRadius: ecke, padding: abstand.s, fontSize: schrift.basis, color: farben.text, minHeight: 56, marginBottom: abstand.s, }, - karte: { backgroundColor: farben.flaeche, borderRadius: 14, padding: abstand.m }, + karte: { ...kartenSchatten, backgroundColor: farben.flaeche, borderRadius: ecke, padding: abstand.m }, trenner: { height: 1, backgroundColor: farben.rand, marginVertical: abstand.l }, schalterZeile: { flexDirection: 'row', @@ -301,7 +301,7 @@ const styles = StyleSheet.create({ option: { borderWidth: 1, borderColor: farben.rand, - borderRadius: 12, + borderRadius: ecke, padding: abstand.s, minHeight: 56, justifyContent: 'center', diff --git a/src/screens/FristenScreen.tsx b/src/screens/FristenScreen.tsx index 08c159e..0f061c5 100644 --- a/src/screens/FristenScreen.tsx +++ b/src/screens/FristenScreen.tsx @@ -21,7 +21,7 @@ import { NaechsteFrist, } from '../utils/ampel'; import { Ikone } from '../components/Ikone'; -import { farben, schrift, abstand, TOUCH_TARGET } from '../theme'; +import { farben, schrift, abstand, TOUCH_TARGET, schriftart, ecke, kartenSchatten, formularRahmen } from '../theme'; type Nav = NativeStackNavigationProp; @@ -93,8 +93,10 @@ export function FristenScreen() { {/* Kopf */} - - BehördenKlar + + + BehördenKlar by Webklar + navigation.navigate('Glossar')} /> @@ -104,7 +106,9 @@ export function FristenScreen() { Fristen-Übersicht - Ihre Fristen + + Ihre Fristen + Nach Dringlichkeit geordnet. Kümmern Sie sich zuerst um das Oberste. @@ -238,44 +242,55 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', - paddingHorizontal: abstand.m, - marginBottom: abstand.m, + marginHorizontal: abstand.m, + paddingBottom: abstand.s, + marginBottom: abstand.l, + // Briefkopf wie auf der Webseite: Tinten-Linie unter Absender + borderBottomWidth: 2, + borderBottomColor: farben.tinte, }, - marke: { fontSize: schrift.gross, fontWeight: '700', color: farben.text }, + markeZusatz: { fontFamily: schriftart.serif, fontSize: 12, fontWeight: '400', color: farben.textSekundaer }, + // gelber Textmarker — das Erkennungszeichen der Webseite + markiert: { backgroundColor: farben.marker }, + marke: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.text }, kopfKnopf: { width: 40, height: 40, - borderRadius: 20, + borderRadius: ecke, backgroundColor: farben.flaeche, + borderWidth: 1.5, + borderColor: farben.tinte, alignItems: 'center', justifyContent: 'center', }, - kicker: { + kicker: { fontFamily: schriftart.mono, fontSize: 12, letterSpacing: 1.3, textTransform: 'uppercase', - color: farben.primaer, + color: farben.textSekundaer, fontWeight: '600', marginBottom: 4, }, - titel: { fontSize: schrift.riesig, fontWeight: '800', color: farben.text, marginBottom: 4 }, - unterTitel: { fontSize: schrift.klein, color: farben.textSekundaer, marginBottom: abstand.l }, + titel: { fontFamily: schriftart.serif, fontSize: schrift.riesig, fontWeight: '800', color: farben.text, marginBottom: 4 }, + unterTitel: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, marginBottom: abstand.l }, + // wichtigste Frist wie ein Formular der Webseite: Tinten-Rahmen, harter Schatten heldKarte: { - borderRadius: 16, - borderLeftWidth: 5, + ...formularRahmen, + borderRadius: ecke, + borderLeftWidth: 7, padding: abstand.l, marginBottom: abstand.l, }, heldKopf: { flexDirection: 'row', alignItems: 'center', gap: 8, marginBottom: 12 }, punkt: { width: 9, height: 9, borderRadius: 5 }, - heldKicker: { fontSize: 12, letterSpacing: 0.6, textTransform: 'uppercase', fontWeight: '700' }, - grosseZahl: { fontSize: 68, lineHeight: 68, fontWeight: '800', fontVariant: ['tabular-nums'] }, - zahlEinheit: { fontSize: 22, fontWeight: '700', lineHeight: 24 }, - zahlDatum: { fontSize: 13, color: farben.textSekundaer, marginTop: 2 }, + heldKicker: { fontFamily: schriftart.mono, fontSize: 12, letterSpacing: 0.6, textTransform: 'uppercase', fontWeight: '700' }, + grosseZahl: { fontFamily: schriftart.serif, fontSize: 68, lineHeight: 68, fontWeight: '800', fontVariant: ['tabular-nums'] }, + zahlEinheit: { fontFamily: schriftart.serif, fontSize: 22, fontWeight: '700', lineHeight: 24 }, + zahlDatum: { fontFamily: schriftart.serif, fontSize: 13, color: farben.textSekundaer, marginTop: 2 }, trenner: { height: 1, backgroundColor: farben.rand, marginVertical: 15 }, - briefTyp: { fontSize: schrift.gross, fontWeight: '700', color: farben.text, marginBottom: 3 }, - briefMeta: { fontSize: schrift.klein, color: farben.textSekundaer }, - abschnitt: { + briefTyp: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.text, marginBottom: 3 }, + briefMeta: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer }, + abschnitt: { fontFamily: schriftart.mono, fontSize: 12, letterSpacing: 1.1, textTransform: 'uppercase', @@ -284,42 +299,42 @@ const styles = StyleSheet.create({ marginTop: abstand.l, marginBottom: abstand.s, }, - zeile: { + zeile: { ...kartenSchatten, flexDirection: 'row', alignItems: 'center', gap: abstand.m, backgroundColor: farben.flaeche, - borderRadius: 12, + borderRadius: ecke, borderLeftWidth: 4, padding: abstand.m, }, zahlBox: { width: 54, alignItems: 'center' }, - zahlKlein: { fontSize: 30, fontWeight: '800', fontVariant: ['tabular-nums'], lineHeight: 32 }, - zahlBoxLabel: { fontSize: 10, letterSpacing: 0.5, textTransform: 'uppercase', color: farben.textTertiaer }, - zeileTyp: { fontSize: schrift.basis, fontWeight: '700', color: farben.text }, - zeileMeta: { fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2 }, + zahlKlein: { fontFamily: schriftart.serif, fontSize: 30, fontWeight: '800', fontVariant: ['tabular-nums'], lineHeight: 32 }, + zahlBoxLabel: { fontFamily: schriftart.mono, fontSize: 10, letterSpacing: 0.5, textTransform: 'uppercase', color: farben.textTertiaer }, + zeileTyp: { fontFamily: schriftart.serif, fontSize: schrift.basis, fontWeight: '700', color: farben.text }, + zeileMeta: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2 }, tag: { alignSelf: 'flex-start', borderRadius: 5, paddingHorizontal: 9, paddingVertical: 3, marginTop: 7 }, - tagText: { fontSize: 11, fontWeight: '600' }, - infoZeile: { + tagText: { fontFamily: schriftart.serif, fontSize: 11, fontWeight: '600' }, + infoZeile: { ...kartenSchatten, flexDirection: 'row', alignItems: 'center', gap: abstand.s, backgroundColor: farben.flaeche, - borderRadius: 12, + borderRadius: ecke, padding: abstand.m, minHeight: TOUCH_TARGET, }, - schutz: { + schutz: { ...kartenSchatten, flexDirection: 'row', gap: abstand.s, alignItems: 'flex-start', backgroundColor: farben.flaeche, - borderRadius: 12, + borderRadius: ecke, padding: abstand.m, marginTop: abstand.l, }, - schutzText: { flex: 1, fontSize: 12.5, lineHeight: 19, color: farben.textSekundaer }, + schutzText: { fontFamily: schriftart.serif, flex: 1, fontSize: 12.5, lineHeight: 19, color: farben.textSekundaer }, leerBox: { alignItems: 'center', gap: abstand.s, marginTop: abstand.xl, marginBottom: abstand.l }, - leerTitel: { fontSize: schrift.gross, fontWeight: '700', color: farben.text }, - leerText: { fontSize: schrift.basis, color: farben.textSekundaer, textAlign: 'center', lineHeight: 26 }, + leerTitel: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.text }, + leerText: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.textSekundaer, textAlign: 'center', lineHeight: 26 }, }); diff --git a/src/screens/GlossarScreen.tsx b/src/screens/GlossarScreen.tsx index 616c41d..f9f399c 100644 --- a/src/screens/GlossarScreen.tsx +++ b/src/screens/GlossarScreen.tsx @@ -4,7 +4,7 @@ import React, { useState } from 'react'; import { FlatList, StyleSheet, Text, TextInput, View } from 'react-native'; import { GLOSSAR } from '../data/glossar'; -import { farben, schrift, abstand } from '../theme'; +import { farben, schrift, abstand, schriftart, ecke, kartenSchatten } from '../theme'; export function GlossarScreen() { const [suche, setSuche] = useState(''); @@ -44,30 +44,30 @@ export function GlossarScreen() { const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: farben.hintergrund }, - suche: { + suche: { fontFamily: schriftart.serif, margin: abstand.m, borderWidth: 1, borderColor: farben.rand, - borderRadius: 12, + borderRadius: ecke, padding: abstand.s, fontSize: schrift.basis, color: farben.text, minHeight: 48, }, - karte: { + karte: { ...kartenSchatten, backgroundColor: farben.flaeche, - borderRadius: 14, + borderRadius: ecke, padding: abstand.m, marginBottom: abstand.s, }, - begriff: { fontSize: schrift.gross, fontWeight: '700', color: farben.primaer }, - erklaerung: { + begriff: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.primaer }, + erklaerung: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.text, lineHeight: 27, marginTop: abstand.xs, }, - leer: { + leer: { fontFamily: schriftart.serif, textAlign: 'center', fontSize: schrift.basis, color: farben.textSekundaer, diff --git a/src/screens/ScanScreen.tsx b/src/screens/ScanScreen.tsx index ebadad0..330f982 100644 --- a/src/screens/ScanScreen.tsx +++ b/src/screens/ScanScreen.tsx @@ -22,7 +22,7 @@ import { import { planeErinnerungen } from '../services/erinnerungen'; import { useAppStore, neueId } from '../store/useAppStore'; import { GrossButton } from '../components/GrossButton'; -import { farben, schrift, abstand } from '../theme'; +import { farben, schrift, abstand, schriftart } from '../theme'; type Props = NativeStackScreenProps; @@ -204,7 +204,7 @@ const styles = StyleSheet.create({ gap: abstand.m, justifyContent: 'center', }, - anleitung: { + anleitung: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.textSekundaer, textAlign: 'center', @@ -219,14 +219,14 @@ const styles = StyleSheet.create({ padding: abstand.xl, gap: abstand.m, }, - kontingent: { + kontingent: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, textAlign: 'center', marginTop: abstand.m, }, - ladeText: { fontSize: schrift.gross, fontWeight: '700', color: farben.text }, - ladeHinweis: { + ladeText: { fontFamily: schriftart.serif, fontSize: schrift.gross, fontWeight: '700', color: farben.text }, + ladeHinweis: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.textSekundaer, textAlign: 'center', diff --git a/src/screens/VerbindenScreen.tsx b/src/screens/VerbindenScreen.tsx index 85292a4..6f8e43c 100644 --- a/src/screens/VerbindenScreen.tsx +++ b/src/screens/VerbindenScreen.tsx @@ -20,7 +20,7 @@ import { holeAusUebergabe, loescheUebergabe, oeffneUebergabe, sendeAnUebergabe } import { briefZuWebPaket, leseUebergabeLink, webPaketZuBrief, WebPaket } from '../utils/uebergabeFormat'; import { GrossButton } from '../components/GrossButton'; import { Ikone } from '../components/Ikone'; -import { farben, schrift, abstand } from '../theme'; +import { farben, schrift, abstand, schriftart, ecke, kartenSchatten } from '../theme'; type Props = NativeStackScreenProps; @@ -173,19 +173,19 @@ export function VerbindenScreen({ navigation, route }: Props) { const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: farben.hintergrund }, - titel: { fontSize: schrift.titel, fontWeight: '700', color: farben.text, marginBottom: abstand.s }, - text: { fontSize: schrift.basis, color: farben.text, lineHeight: 26 }, - klein: { fontSize: schrift.klein, color: farben.textSekundaer, marginBottom: abstand.s }, + titel: { fontFamily: schriftart.serif, fontSize: schrift.titel, fontWeight: '700', color: farben.text, marginBottom: abstand.s }, + text: { fontFamily: schriftart.serif, fontSize: schrift.basis, color: farben.text, lineHeight: 26 }, + klein: { fontFamily: schriftart.serif, fontSize: schrift.klein, color: farben.textSekundaer, marginBottom: abstand.s }, kameraRahmen: { - marginTop: abstand.m, height: 300, borderRadius: 16, overflow: 'hidden', + marginTop: abstand.m, height: 300, borderRadius: ecke, overflow: 'hidden', backgroundColor: farben.flaecheSekundaer, }, kameraLeer: { flex: 1, justifyContent: 'center', padding: abstand.m, gap: abstand.m }, - meldung: { marginTop: abstand.m, gap: abstand.m, padding: abstand.m, borderRadius: 16, backgroundColor: farben.flaeche }, + meldung: { ...kartenSchatten, marginTop: abstand.m, gap: abstand.m, padding: abstand.m, borderRadius: ecke, backgroundColor: farben.flaeche }, schutzZeile: { flexDirection: 'row', alignItems: 'center', gap: 6, marginTop: abstand.m }, - schutzText: { fontSize: 13, color: farben.textTertiaer }, - feld: { - backgroundColor: farben.flaeche, borderRadius: 12, padding: 14, fontSize: schrift.klein, + schutzText: { fontFamily: schriftart.serif, fontSize: 13, color: farben.textTertiaer }, + feld: { fontFamily: schriftart.serif, + backgroundColor: farben.flaeche, borderRadius: ecke, padding: 14, fontSize: schrift.klein, color: farben.text, borderWidth: 1, borderColor: farben.rand, marginBottom: abstand.s, }, }); diff --git a/src/theme.ts b/src/theme.ts index e04b758..fc77e66 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -1,38 +1,51 @@ /** - * Design-System: ruhig, vertrauenswürdig, barrierefrei. + * Design-System — wie die Webseite behoerdenklar.de: ein Amtsbrief, der + * endlich verständlich ist. Papier, Tinte, Amtsblau, gelber Textmarker, + * Georgia-Serifenschrift, Etiketten in Schreibmaschinenschrift. + * * - Große Schrift (Basis 18) für die Zielgruppe - * - Hoher Kontrast (dunkles Blau auf Weiß, WCAG AA) + * - Hoher Kontrast (Tinte auf Papier, WCAG AA) * - Große Touch-Targets (min. 56px Höhe) + * + * Die Werte entsprechen den CSS-Variablen der Webseite (--papier, --tinte, + * --amtsblau, --marker, --stempelrot …). Ändert sich dort etwas, hier mitziehen. */ +import { Platform, TextStyle, ViewStyle } from 'react-native'; + export const farben = { - // Warme, ruhige Palette nach dem Claude-Design-Entwurf ("Postklar/Classical") - // und passend zur Website: Papier-Beige, Gold-Akzent, dunkle Tinte. - // Gut lesbar (hoher Kontrast bei Fließtext), nur die Schrift bleibt - // die klare System-Schrift statt der dünnen Serifenschrift. - hintergrund: '#F1EFE9', // warmes Off-White (Grund) - flaeche: '#FBFAF6', // warme, fast weiße Karten - flaecheSekundaer: '#EAE7E0', // gedämpfte Fläche (graue Taste) - primaer: '#B68235', // Gold-Akzent (Icons, aktive Tabs, Rahmen, Punkte) - primaerFuellung: '#7D5411', // dunkles Bronze — Hintergrund gefüllter Buttons (weiße Schrift lesbar) - primaerText: '#FBF7EF', // warmes Weiß (Text auf gefüllten Buttons) - text: '#201F1D', // dunkle Tinte - textSekundaer: '#6B675E', // warmes Grau (wie --grau der Website) - textTertiaer: '#A8A29A', // helles warmes Grau (Chevrons) - rand: '#E2DED6', // warme Trennlinie - // Dezente Gold-Hervorhebung (z. B. aktive Filter-Chips) - hervorhebung: '#F7EFE0', - hervorhebungRand: '#E9D8BC', + hintergrund: '#FAF7F0', // Papier (--papier) + flaeche: '#FFFFFF', // weißes Formularblatt (Karten, Felder) + flaecheSekundaer: '#F1ECDF', // dunkleres Papier (--papier-dunkel) + primaer: '#1D4E89', // Amtsblau (Icons, aktive Tabs, Links) + primaerFuellung: '#1D4E89', // Amtsblau — gefüllte Knöpfe + primaerText: '#FFFFFF', // Text auf gefüllten Knöpfen + text: '#21211D', // Tinte + textSekundaer: '#6B675E', // Grau (--grau) + textTertiaer: '#9A958A', // helles Grau (Platzhalter, Chevrons) + rand: 'rgba(33,33,29,0.22)', // dünne Linie wie auf der Webseite + tinte: '#21211D', // harte Rahmen und Schatten + marker: '#FFE66B', // gelber Textmarker (Signatur der Marke) + stempelrot: '#B3372B', + // Hervorhebung = Textmarker (z. B. aktive Filter) + hervorhebung: '#FFE66B', + hervorhebungRand: '#21211D', - // Dringlichkeits-Ampel in den warmen Design-Tönen — als Text auf hellem - // Tint gut lesbar (WCAG): Backstein-Rot, Bronze-Gold, Salbei-Grün. - ampelRot: '#A23B2B', - ampelGelb: '#8A5E14', - ampelGruen: '#3F5A4C', - ampelRotHintergrund: '#F5E9E5', - ampelGelbHintergrund: '#F5EEDF', - ampelGruenHintergrund: '#E8EFEA', + // Dringlichkeits-Ampel wie auf der Webseite (--rot, --gelb, --gruen), + // Gelb etwas dunkler, damit es als Text auf hellem Grund WCAG AA erreicht. + ampelRot: '#B3372B', + ampelGelb: '#8A5A00', + ampelGruen: '#2E7D4F', + ampelRotHintergrund: '#FDF1EF', + ampelGelbHintergrund: '#FFF6D6', + ampelGruenHintergrund: '#E7F4EA', - fehler: '#A23B2B', + fehler: '#B3372B', +}; + +/** Schriften der Webseite: Georgia (Text) und Courier (Etiketten). */ +export const schriftart = { + serif: Platform.select({ ios: 'Georgia', android: 'serif', default: 'Georgia' }) as string, + mono: Platform.select({ ios: 'Courier New', android: 'monospace', default: 'Courier New' }) as string, }; export const schrift = { @@ -54,9 +67,27 @@ export const abstand = { /** Mindesthöhe für alle interaktiven Elemente (Barrierefreiheit). */ export const TOUCH_TARGET = 56; -/** - * Bewusst leer: Nach Apple-Vorbild heben sich weiße Karten allein durch - * den grauen System-Hintergrund ab — ohne Schatten und Rahmen. - * (Als No-Op behalten, damit bestehende Spreads harmlos bleiben.) - */ -export const kartenSchatten = {} as const; +/** Papier hat (fast) keine runden Ecken. */ +export const ecke = 2; + +/** Karte wie `.brief-karte` der Webseite: weißes Blatt, feine Linie, flacher Schatten. */ +export const kartenSchatten: ViewStyle = { + borderWidth: 1, + borderColor: 'rgba(33,33,29,0.28)', + boxShadow: '4px 5px 0px rgba(33,33,29,0.08)', +}; + +/** Formular wie `.antrag`: Tinten-Rahmen mit hartem Versatz-Schatten. */ +export const formularRahmen: ViewStyle = { + borderWidth: 2, + borderColor: farben.tinte, + boxShadow: '6px 7px 0px rgba(33,33,29,0.9)', +}; + +/** Etikett wie `h2`/`.karten-label` der Webseite: Schreibmaschine, Versalien. */ +export const etikett: TextStyle = { + fontFamily: schriftart.mono, + fontSize: 13, + letterSpacing: 1.4, + textTransform: 'uppercase', +};