diff --git a/app/lib/data/fixtures.dart b/app/lib/data/fixtures.dart index abf5685..3afdea3 100644 --- a/app/lib/data/fixtures.dart +++ b/app/lib/data/fixtures.dart @@ -90,12 +90,6 @@ class Fixtures { 'T (Tarif) T1 — DESTATIS Verdiensterhebung kaufm. Tätigkeit ~30 €/h; ' 'h (Zeitaufwand) T3 — eigene Schätzung ~30 min, NKR-Validierung ausstehend. ' 'Regel der niedrigsten Stufe: Gesamt → T3 (in der Demo konservativ als T4 markiert).', - componentSummary: const [ - 'P · T1 — DESTATIS Gewerbeanzeigen', - 'F · T1 — anlassbezogen, je Vorgang', - 'T · T1 — DESTATIS Verdiensterhebung', - 'h · T3 — eigene Schätzung ~30 min', - ], ); static final _kassenSichV = Evaluation( @@ -183,12 +177,6 @@ class Fixtures { 'Laufende Folgekosten (TSE-Ausfallmeldungen, Hardware-Erneuerung): T2 ' 'aus DIHK-Bürokratie-Index + DEHOGA-Gastronomie-Stichprobe. ' 'Hoher Frust-Score wegen Pluralität TSE-Hersteller × Finanzamt-Vollzug.', - componentSummary: const [ - 'P · T1 — Kassen-pflichtige Betriebe', - 'F · T1 — kontinuierlich + Ausfälle', - 'T · T2 — DIHK Bürokratie-Index', - 'h · T2 — DEHOGA-Stichprobe', - ], ); static final _dsgvoArt30 = Evaluation( @@ -284,13 +272,6 @@ class Fixtures { 'pro Unternehmen liegt im Streit zwischen BfDI-Position (gering, weil ' '<250-MA-Ausnahme) und DIHK-Position (hoch, weil 5-Abs.-Ausnahme ' 'praktisch nicht greift). Tier T2 für Magnitude.', - componentSummary: const [ - 'P · T1 — DESTATIS Unternehmensregister', - 'F · T1 — jährlich überprüfen', - 'T · T2 — DIHK-Position', - 'h · T2 — Streit BfDI ↔ DIHK', - 'EU-determiniert · Reform-Hebel Brüssel', - ], ); static final _berlinBauO60 = Evaluation( @@ -370,13 +351,6 @@ class Fixtures { '→ Genehmigung sind im Land getrennt geregelt). Höchster Frust-Score ' 'aus Verweistiefe + Behörden-Pluralität (Bezirksamt × SenStadt × ' 'Beteiligungsverfahren).', - componentSummary: const [ - 'P · T2 — Handwerkskammer Berlin', - 'F · T1 — pro Bauvorhaben', - 'T · T2 — Bauwirtschaft Berlin', - 'h · T3 — Verfahren mehrstufig', - 'Frust · T2 — Bezirk × Senat × Beteiligung', - ], ); static final _miLoG17 = Evaluation( @@ -454,12 +428,5 @@ class Fixtures { 'dokumentierte den initial-Erfüllungsaufwand; aktuelle Zahlen ' 'aus ZDH Bürokratiekosten-Handwerk. Bürokratieentlastungs-' 'gesetz IV adressierte den § 17 — Reform-Bewegung ist im Lauf.', - componentSummary: const [ - 'P · T1 — DESTATIS MiLoG-pflichtig', - 'F · T1 — arbeitstäglich', - 'T · T1 — DESTATIS Tariflohn', - 'h · T1 — NKR-Stellungnahme 2014', - 'Reform · BEG IV in Lauf', - ], ); } diff --git a/app/lib/data/models.dart b/app/lib/data/models.dart index d75f950..ae7caf2 100644 --- a/app/lib/data/models.dart +++ b/app/lib/data/models.dart @@ -142,7 +142,6 @@ class Evaluation { required this.sources, required this.auditEventId, this.notes, - this.componentSummary = const [], }); final Norm norm; @@ -173,10 +172,4 @@ class Evaluation { final String auditEventId; final String? notes; - - /// Compact lines for at-a-glance reading on list views. - /// One line per SKM-Komponente (P / F / T / h) plus optional - /// extras — each carries its tier-tag inline. Empty list ⇒ - /// fall back to the notes field for the list view. - final List componentSummary; } diff --git a/app/lib/pages/landing_page.dart b/app/lib/pages/landing_page.dart index 50fba50..0f19bac 100644 --- a/app/lib/pages/landing_page.dart +++ b/app/lib/pages/landing_page.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import '../data/repository.dart'; import '../theme/reclaim_theme.dart'; import '../theme/reclaim_tokens.dart'; -import '../widgets/brand_wordmark.dart'; import '../widgets/delta_mark.dart'; import 'shell_page.dart'; @@ -21,7 +20,7 @@ class LandingPage extends StatelessWidget { body: SafeArea( child: Center( child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 820), + constraints: const BoxConstraints(maxWidth: 720), child: Padding( padding: const EdgeInsets.symmetric( horizontal: ReclaimSpace.xxl, @@ -31,18 +30,9 @@ class LandingPage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - DeltaMark(size: 96), - SizedBox(width: ReclaimSpace.xl), - BrandWordmark( - size: 56, - letterSpacing: -1.0, - ), - ], - ), - const SizedBox(height: ReclaimSpace.xl), + const DeltaMark(size: 96), + const SizedBox(height: ReclaimSpace.xxl), + Text('Recl∆Im', style: t.displaySmall), const SizedBox(height: ReclaimSpace.sm), Text( 'Pflicht-basierte Wirkungsanalyse von Rechtsnormen — ' diff --git a/app/lib/pages/norms_list_page.dart b/app/lib/pages/norms_list_page.dart index d6156a4..189a1fb 100644 --- a/app/lib/pages/norms_list_page.dart +++ b/app/lib/pages/norms_list_page.dart @@ -107,42 +107,31 @@ class _NormRow extends StatelessWidget { color: ReclaimColors.mute, ), ), - const SizedBox(height: ReclaimSpace.sm), - TierBadge(tier: evaluation.tierLowest), ], ), ), const SizedBox(width: ReclaimSpace.lg), Expanded( - flex: 2, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _MetricColumn( - label: 'Schaden / Jahr', - value: _eur(evaluation.skmEurPerYear), - ), - const SizedBox(height: ReclaimSpace.sm), - _MetricColumn( - label: 'Nutzen', - value: - '${evaluation.benefitScore.toStringAsFixed(1)} / 5', - ), - const SizedBox(height: ReclaimSpace.sm), - _MetricColumn( - label: 'Betroffene', - value: _kmu(evaluation.affectedCount), - ), - ], + child: _MetricColumn( + label: 'Schaden / Jahr', + value: _eur(evaluation.skmEurPerYear), ), ), - const SizedBox(width: ReclaimSpace.lg), Expanded( - flex: 3, - child: _ComponentSummary( - summary: evaluation.componentSummary, + child: _MetricColumn( + label: 'Nutzen', + value: + '${evaluation.benefitScore.toStringAsFixed(1)} / 5', ), ), + Expanded( + child: _MetricColumn( + label: 'Betroffene', + value: _kmu(evaluation.affectedCount), + ), + ), + const SizedBox(width: ReclaimSpace.md), + TierBadge(tier: evaluation.tierLowest), ], ), ), @@ -163,44 +152,6 @@ class _NormRow extends StatelessWidget { } } -class _ComponentSummary extends StatelessWidget { - const _ComponentSummary({required this.summary}); - - final List summary; - - @override - Widget build(BuildContext context) { - final t = Theme.of(context).textTheme; - if (summary.isEmpty) { - return Text( - '—', - style: t.labelSmall?.copyWith(color: ReclaimColors.mute), - ); - } - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Komponenten', - style: t.labelSmall?.copyWith(color: ReclaimColors.mute), - ), - const SizedBox(height: 4), - for (final line in summary) - Padding( - padding: const EdgeInsets.only(bottom: 2), - child: Text( - line, - style: t.bodyLarge?.copyWith( - height: 1.35, - fontSize: 12.5, - ), - ), - ), - ], - ); - } -} - class _MetricColumn extends StatelessWidget { const _MetricColumn({required this.label, required this.value}); diff --git a/app/lib/pages/shell_page.dart b/app/lib/pages/shell_page.dart index 2f7b51a..5cf3da4 100644 --- a/app/lib/pages/shell_page.dart +++ b/app/lib/pages/shell_page.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import '../data/repository.dart'; import '../theme/reclaim_tokens.dart'; -import '../widgets/brand_wordmark.dart'; import '../widgets/delta_mark.dart'; import 'about_page.dart'; import 'heatmap_page.dart'; @@ -52,7 +51,14 @@ class _ShellPageState extends State { children: [ const DeltaMark(size: 36), const SizedBox(height: ReclaimSpace.sm), - const BrandWordmark(size: 18), + Text( + 'Recl∆Im', + style: t.labelLarge?.copyWith( + letterSpacing: 1.5, + color: ReclaimColors.signal, + fontWeight: FontWeight.w600, + ), + ), Text( 'F∆I', style: t.labelSmall?.copyWith( diff --git a/app/lib/widgets/brand_wordmark.dart b/app/lib/widgets/brand_wordmark.dart deleted file mode 100644 index 14d6783..0000000 --- a/app/lib/widgets/brand_wordmark.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../theme/reclaim_tokens.dart'; - -/// "Recl∆Im" wordmark with the ∆I glyphs petrol-coloured — the -/// brand rule of thumb in the fai_web universe: wherever the name -/// stands as a brand, the ∆I tinted petrol carries the F∆I-family -/// identity. As plain text it would all share the surrounding ink -/// colour. -/// -/// Pass [size] for the base font size; the ∆I scales relative. -class BrandWordmark extends StatelessWidget { - const BrandWordmark({ - super.key, - this.size = 24, - this.fontWeight = FontWeight.w600, - this.color, - this.letterSpacing = -0.5, - }); - - final double size; - final FontWeight fontWeight; - - /// Color of the non-∆I letters. Defaults to the surface's - /// onSurface so the wordmark reads against whichever ink/paper - /// backdrop it sits on. - final Color? color; - final double letterSpacing; - - @override - Widget build(BuildContext context) { - final base = color ?? Theme.of(context).colorScheme.onSurface; - final style = TextStyle( - fontSize: size, - fontWeight: fontWeight, - fontFamily: ReclaimTypography.display, - color: base, - letterSpacing: letterSpacing, - height: 1.0, - ); - return RichText( - text: TextSpan( - style: style, - children: [ - const TextSpan(text: 'Recl'), - TextSpan( - text: '∆I', - style: style.copyWith(color: ReclaimColors.signal), - ), - const TextSpan(text: 'm'), - ], - ), - ); - } -} diff --git a/app/test/widget_test.dart b/app/test/widget_test.dart index 30b5b41..eb83a95 100644 --- a/app/test/widget_test.dart +++ b/app/test/widget_test.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:reclaim_app/main.dart'; -import 'package:reclaim_app/widgets/brand_wordmark.dart'; void main() { // Generous surface so NavigationRail + Heatmap fit without @@ -21,7 +20,7 @@ void main() { await tester.binding.setSurfaceSize(surfaceSize); await tester.pumpWidget(const ReclaimApp()); await tester.pump(); - expect(find.byType(BrandWordmark), findsWidgets); + expect(find.text('Recl∆Im'), findsOneWidget); expect( find.widgetWithText(FilledButton, 'App öffnen (Demo-Modus)'), findsOneWidget,