175 lines
6.3 KiB
Dart
175 lines
6.3 KiB
Dart
/// Design tokens extracted from "The Sacred Horizon" Stitch design system.
|
||
/// These are the canonical color, typography, spacing, and styling constants.
|
||
library;
|
||
|
||
import 'package:flutter/material.dart';
|
||
|
||
// ──────────────────────────────────────────────
|
||
// COLOR TOKENS — "Masjid Twilight" palette
|
||
// ──────────────────────────────────────────────
|
||
|
||
class SacredColors {
|
||
SacredColors._();
|
||
|
||
// Core
|
||
static const Color primary = Color(0xFF88D982); // Living Green
|
||
static const Color primaryContainer = Color(0xFF004F11);
|
||
static const Color onPrimaryContainer = Color(0xFF72C36E);
|
||
|
||
static const Color secondary = Color(0xFFE9C349); // Sacred Gold
|
||
static const Color secondaryContainer = Color(0xFFAF8D11);
|
||
|
||
static const Color tertiary = Color(0xFFE9C400);
|
||
static const Color tertiaryContainer = Color(0xFFC8A900);
|
||
|
||
// Background & Surface hierarchy
|
||
static const Color background = Color(0xFF131313); // The Void
|
||
static const Color surface = Color(0xFF131313);
|
||
static const Color surfaceDim = Color(0xFF131313);
|
||
static const Color surfaceContainerLowest = Color(0xFF0E0E0E);
|
||
static const Color surfaceContainerLow = Color(0xFF1C1B1B);
|
||
static const Color surfaceContainer = Color(0xFF201F1F);
|
||
static const Color surfaceContainerHigh = Color(0xFF2A2A2A);
|
||
static const Color surfaceContainerHighest = Color(0xFF353534);
|
||
static const Color surfaceBright = Color(0xFF393939);
|
||
static const Color surfaceVariant = Color(0xFF353534);
|
||
|
||
// On‑ tokens
|
||
static const Color onSurface = Color(0xFFE5E2E1);
|
||
static const Color onSurfaceVariant = Color(0xFFBFC9C4);
|
||
static const Color onBackground = Color(0xFFE5E2E1);
|
||
static const Color onPrimary = Color(0xFF003909);
|
||
static const Color onSecondary = Color(0xFF3C2F00);
|
||
|
||
// Outline
|
||
static const Color outline = Color(0xFF89938F);
|
||
static const Color outlineVariant = Color(0xFF3F4945);
|
||
|
||
// Error
|
||
static const Color error = Color(0xFFFFB4AB);
|
||
static const Color errorContainer = Color(0xFF93000A);
|
||
|
||
// Inverse
|
||
static const Color inverseSurface = Color(0xFFE5E2E1);
|
||
static const Color inversePrimary = Color(0xFF1B6D24);
|
||
|
||
// Special
|
||
static const Color blackScreen = Color(0xFF000000);
|
||
|
||
// Convenience: transparent glass for overlays
|
||
static Color get glass70 => surfaceVariant.withValues(alpha: 0.70);
|
||
static Color get glass60 => surfaceVariant.withValues(alpha: 0.60);
|
||
static Color get glass35 => surfaceVariant.withValues(alpha: 0.35);
|
||
}
|
||
|
||
// ──────────────────────────────────────────────
|
||
// TYPOGRAPHY
|
||
// ──────────────────────────────────────────────
|
||
|
||
class SacredTypography {
|
||
SacredTypography._();
|
||
|
||
static const String headlineFamily = 'Plus Jakarta Sans';
|
||
static const String bodyFamily = 'Manrope';
|
||
|
||
// Display — The Clock (heartbeat of the system)
|
||
static TextStyle clockDisplay(double fontSize) => TextStyle(
|
||
fontFamily: headlineFamily,
|
||
fontSize: fontSize,
|
||
fontWeight: FontWeight.w800,
|
||
letterSpacing: -0.02 * fontSize,
|
||
color: SacredColors.onSurface,
|
||
height: 1.0,
|
||
);
|
||
|
||
// Headline — Prayer Names
|
||
static TextStyle headline(double fontSize) => TextStyle(
|
||
fontFamily: headlineFamily,
|
||
fontSize: fontSize,
|
||
fontWeight: FontWeight.w700,
|
||
letterSpacing: -0.01 * fontSize,
|
||
color: SacredColors.onSurface,
|
||
);
|
||
|
||
// Title — Timings
|
||
static TextStyle title(double fontSize) => TextStyle(
|
||
fontFamily: bodyFamily,
|
||
fontSize: fontSize,
|
||
fontWeight: FontWeight.w600,
|
||
color: SacredColors.onSurface,
|
||
);
|
||
|
||
// Body
|
||
static TextStyle body(double fontSize) => TextStyle(
|
||
fontFamily: bodyFamily,
|
||
fontSize: fontSize,
|
||
fontWeight: FontWeight.w400,
|
||
color: SacredColors.onSurface,
|
||
);
|
||
|
||
// Label — metadata
|
||
static TextStyle label(double fontSize) => TextStyle(
|
||
fontFamily: bodyFamily,
|
||
fontSize: fontSize,
|
||
fontWeight: FontWeight.w500,
|
||
letterSpacing: 0.05 * fontSize,
|
||
color: SacredColors.onSurfaceVariant,
|
||
);
|
||
|
||
// Label caps (for TRACKING-WIDEST uppercase captions)
|
||
static TextStyle labelCaps(double fontSize) => TextStyle(
|
||
fontFamily: bodyFamily,
|
||
fontSize: fontSize,
|
||
fontWeight: FontWeight.w700,
|
||
letterSpacing: 0.2 * fontSize,
|
||
color: SacredColors.onSurfaceVariant,
|
||
);
|
||
}
|
||
|
||
// ──────────────────────────────────────────────
|
||
// SPACING — 8px grid
|
||
// ──────────────────────────────────────────────
|
||
|
||
class SacredSpacing {
|
||
SacredSpacing._();
|
||
|
||
static const double xs = 8;
|
||
static const double sm = 16;
|
||
static const double md = 24;
|
||
static const double lg = 32;
|
||
static const double xl = 48;
|
||
static const double xxl = 64;
|
||
static const double screenEdge = 64; // 4rem minimum from edges
|
||
}
|
||
|
||
// ──────────────────────────────────────────────
|
||
// RADII
|
||
// ──────────────────────────────────────────────
|
||
|
||
class SacredRadii {
|
||
SacredRadii._();
|
||
|
||
static const double sm = 4;
|
||
static const double md = 8;
|
||
static const double lg = 12;
|
||
static const double xl = 16;
|
||
static const double full = 9999;
|
||
}
|
||
|
||
// ──────────────────────────────────────────────
|
||
// TV SCALING
|
||
// ──────────────────────────────────────────────
|
||
|
||
class TVScale {
|
||
TVScale._();
|
||
|
||
/// Scale factor relative to 1920px baseline
|
||
static double of(BuildContext context) {
|
||
return MediaQuery.of(context).size.width / 1920;
|
||
}
|
||
|
||
static double fontSize(BuildContext context, double base) {
|
||
return base * of(context);
|
||
}
|
||
}
|