// AUTO-GENERATED from tokens.json — do not edit directly // Run: node design/generate.js import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; /// inou Design System /// Single source of truth: design/tokens.json class InouTheme { InouTheme._(); // ============================================ // COLORS // ============================================ static const Color bg = Color(0xFFF8F7F6); static const Color bgCard = Color(0xFFFFFFFF); static const Color border = Color(0xFFE5E2DE); static const Color borderHover = Color(0xFFC4BFB8); static const Color text = Color(0xFF1C1917); static const Color textMuted = Color(0xFF78716C); static const Color textSubtle = Color(0xFFA8A29E); static const Color accent = Color(0xFFB45309); static const Color accentHover = Color(0xFF92400E); static const Color accentLight = Color(0xFFFEF3C7); static const Color danger = Color(0xFFDC2626); static const Color dangerLight = Color(0xFFFEF2F2); static const Color success = Color(0xFF059669); static const Color successLight = Color(0xFFECFDF5); // Indicator colors (data sections) static const Color indicatorImaging = Color(0xFFB45309); static const Color indicatorLabs = Color(0xFF059669); static const Color indicatorUploads = Color(0xFF6366F1); static const Color indicatorVitals = Color(0xFFEC4899); static const Color indicatorMedications = Color(0xFF8B5CF6); static const Color indicatorRecords = Color(0xFF06B6D4); static const Color indicatorJournal = Color(0xFFF59E0B); static const Color indicatorPrivacy = Color(0xFF64748B); static const Color indicatorGenetics = Color(0xFF10B981); // ============================================ // SPACING // ============================================ static const double spaceXs = 4.0; static const double spaceSm = 8.0; static const double spaceMd = 12.0; static const double spaceLg = 16.0; static const double spaceXl = 24.0; static const double spaceXxl = 32.0; static const double spaceXxxl = 48.0; // ============================================ // BORDER RADIUS // ============================================ static const double radiusSm = 4.0; static const double radiusMd = 6.0; static const double radiusLg = 8.0; static const double radiusXl = 12.0; static const double radiusFull = 9999.0; static BorderRadius get borderRadiusSm => BorderRadius.circular(radiusSm); static BorderRadius get borderRadiusMd => BorderRadius.circular(radiusMd); static BorderRadius get borderRadiusLg => BorderRadius.circular(radiusLg); // ============================================ // LAYOUT // ============================================ static const double maxWidth = 1200.0; static const double maxWidthNarrow = 800.0; static const double maxWidthForm = 360.0; // ============================================ // TYPOGRAPHY — matches inou.com/static/style.css // Base: 15px (body) // ============================================ static String get fontFamily => 'Sora'; // Page Title: 2.5rem / 700 = 37.5px static TextStyle get pageTitle => GoogleFonts.sora( fontSize: 37.5, fontWeight: FontWeight.w700, color: text, ); // h1: 2.25rem / 300 / -0.03em = 33.75px (used in forms, etc.) static TextStyle get h1 => GoogleFonts.sora( fontSize: 33.75, fontWeight: FontWeight.w300, color: text, letterSpacing: -0.45, // -0.03em × 15px ); // h1.small: 1.5rem / 300 = 22.5px static TextStyle get h1Small => GoogleFonts.sora( fontSize: 22.5, fontWeight: FontWeight.w300, color: text, ); // Section Title: 1.4rem / 600 = 21px (.privacy-container h2) static TextStyle get sectionTitle => GoogleFonts.sora( fontSize: 21.0, fontWeight: FontWeight.w600, color: text, ); // h2 (regular): 1.5rem / 300 / -0.02em = 22.5px static TextStyle get h2 => GoogleFonts.sora( fontSize: 22.5, fontWeight: FontWeight.w300, color: text, letterSpacing: -0.3, // -0.02em × 15px ); // Subsection Title: 1.1rem / 600 = 16.5px (.privacy-container h3) static TextStyle get subsectionTitle => GoogleFonts.sora( fontSize: 16.5, fontWeight: FontWeight.w600, color: text, ); // h3 (regular): 1.125rem / 500 = 16.875px static TextStyle get h3 => GoogleFonts.sora( fontSize: 16.875, fontWeight: FontWeight.w500, color: text, ); // Intro text: 1.15rem / 300 = 17.25px static TextStyle get intro => GoogleFonts.sora( fontSize: 17.25, fontWeight: FontWeight.w300, color: textMuted, height: 1.8, ); // Body light (long-form): 1rem / 300 = 15px static TextStyle get bodyLight => GoogleFonts.sora( fontSize: 15.0, fontWeight: FontWeight.w300, color: textMuted, height: 1.8, ); // Body regular (UI labels): 1rem / 400 = 15px static TextStyle get body => GoogleFonts.sora( fontSize: 15.0, fontWeight: FontWeight.w400, color: text, ); // Label / Category: 0.75rem / 600 / caps / 0.1em = 11.25px static TextStyle get label => GoogleFonts.sora( fontSize: 11.25, fontWeight: FontWeight.w600, color: textSubtle, letterSpacing: 1.125, // 0.1em × 11.25px ); // Small text: 0.85rem / 400 = 12.75px static TextStyle get small => GoogleFonts.sora( fontSize: 12.75, fontWeight: FontWeight.w400, color: textMuted, ); // Mono (SF Mono fallback) static TextStyle get mono => const TextStyle( fontFamily: 'SF Mono', fontFamilyFallback: ['Monaco', 'Consolas', 'monospace'], fontSize: 12.75, color: text, ); // Legacy aliases for compatibility static TextStyle get h1Large => pageTitle; static TextStyle get bodyLarge => intro; static TextStyle get bodyMedium => body; static TextStyle get bodySmall => small; static TextStyle get labelLarge => GoogleFonts.sora( fontSize: 15.0, fontWeight: FontWeight.w500, color: text, ); static TextStyle get labelSmall => label; // ============================================ // THEME DATA // ============================================ static ThemeData get light => ThemeData( useMaterial3: true, brightness: Brightness.light, scaffoldBackgroundColor: bg, colorScheme: ColorScheme.light( primary: accent, onPrimary: Colors.white, secondary: accentLight, onSecondary: accent, surface: bgCard, onSurface: text, error: danger, onError: Colors.white, outline: border, ), textTheme: TextTheme( displayLarge: pageTitle, displayMedium: h1, headlineMedium: sectionTitle, headlineSmall: subsectionTitle, bodyLarge: intro, bodyMedium: body, bodySmall: small, labelLarge: labelLarge, labelSmall: label, ), appBarTheme: AppBarTheme( backgroundColor: bg, foregroundColor: text, elevation: 0, centerTitle: false, ), cardTheme: CardTheme( color: bgCard, elevation: 0, shape: RoundedRectangleBorder( borderRadius: borderRadiusLg, side: BorderSide(color: border), ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: accent, foregroundColor: Colors.white, elevation: 0, padding: EdgeInsets.symmetric(horizontal: spaceLg, vertical: spaceMd), shape: RoundedRectangleBorder(borderRadius: borderRadiusMd), textStyle: labelLarge, ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: text, side: BorderSide(color: border), padding: EdgeInsets.symmetric(horizontal: spaceLg, vertical: spaceMd), shape: RoundedRectangleBorder(borderRadius: borderRadiusMd), textStyle: labelLarge, ), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: bgCard, border: OutlineInputBorder( borderRadius: borderRadiusMd, borderSide: BorderSide(color: border), ), enabledBorder: OutlineInputBorder( borderRadius: borderRadiusMd, borderSide: BorderSide(color: border), ), focusedBorder: OutlineInputBorder( borderRadius: borderRadiusMd, borderSide: BorderSide(color: accent, width: 2), ), contentPadding: EdgeInsets.symmetric(horizontal: spaceMd, vertical: spaceMd), ), dividerTheme: DividerThemeData( color: border, thickness: 1, ), ); }