feat(design): Projector Noir theme - tungsten amber on film-black

Full visual refonte replacing the generic neon-blue glass look:

- palette: warm film-black surface ladder, tungsten amber primary,
  warm taupe secondary, verdigris teal tertiary; semantic and
  category colors retuned to match (coral live, gold movies)
- typography: Syne (display/headlines) + Instrument Sans (body/UI)
  replace Space Grotesk/Inter/Outfit across all screens
- glassmorphism tokens warmed (amber inner glow, warm-white borders)
- web player theme.css + index.html loader mirror the new tokens
- hardcoded Colors.blue* in streaming settings and recordings tabs
  now use AppColors tokens
- DESIGN_SYSTEM.md updated to v3.0 Projector Noir

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Fable 5 committed 2026-06-10 14:52:45 +02:00
1 parent 9595afcc99
commit e332895d7d
33 files changed
+392 -397

No files matched your search

+38 -44
View File
@@ -1,12 +1,12 @@
# XtremFlow Apple TV Modern Design System
# XtremFlow Projector Noir Design System
## Overview
XtremFlow has been completely redesigned with a **premium Apple TV modern aesthetic** inspired by tvOS 18+. The new design system prioritizes:
XtremFlow uses a **Projector Noir aesthetic**: warm tungsten light cutting through a dark screening room. The design system prioritizes:
- **Sophisticated Glassmorphism** - Elegant blur effects with subtle gradients
- **Premium Color Palette** - Vibrant accents (Cyan, Mint, Red) on pure black
- **Cinematic Typography** - Bold headlines (Outfit) + refined UI text (Inter)
- **Sophisticated Glassmorphism** - Elegant blur effects with warm-tinted borders
- **Tungsten Palette** - Amber projector-beam accents on deep film-black
- **Art-House Typography** - Geometric headlines (Syne) + refined UI text (Instrument Sans)
- **Focus-Driven Interactions** - TV-friendly hover states and animations
- **Responsive Layouts** - Seamless adaptation from web to mobile
@@ -14,46 +14,40 @@ XtremFlow has been completely redesigned with a **premium Apple TV modern aesthe
## Color Palette
### Backgrounds
- **`background`** (#000000) - Pure black, OLED optimized
- **`surface`** (#1C1C1E) - Primary dark surface
- **`surfaceVariant`** (#2A2A2E) - Secondary surface for hierarchy
- **`surfaceTertiary`** (#383838) - Tertiary depth layer
### Backgrounds (warm film-black ladder)
- **`baseLevel0`** (#0B0A08) - Deepest black, OLED optimized
- **`background` / `surface`** (#14110C) - Primary dark surface
- **`surfaceContainerLow`** (#1B1812) to **`surfaceContainerHighest`** (#363027) - Warm charcoal hierarchy
### Primary Accents
- **`primary`** (#00D4FF) - Main brand color (Cyan/Sky Blue)
- **`secondary`** (#FF6B6B) - Secondary accent (Soft Red)
- **`tertiary`** (#00E5BB) - Highlight accent (Mint)
- **`accent`** - Alias for primary (for consistency)
- **`primary`** (#FFB35C) - Tungsten amber (main brand color)
- **`primaryContainer`** (#F39A1F) - Vivid amber (buttons, focus rings)
- **`secondary`** (#D3C6B2) - Warm taupe
- **`tertiary`** (#A4CCBE) - Verdigris teal (counterpoint accent)
### Semantic Colors
- **`success`** (#34C759) - Success/completed state
- **`warning`** (#FF9500) - Warning/caution state
- **`error`** (#FF3B30) - Error/danger state
- **`info`** (#30B0C0) - Information state
- **`disabled`** (#8E8E93) - Disabled/inactive state
- **`success`** (#6BD89B) - Success/completed state
- **`warning`** (#FFAB00) - Warning/caution state
- **`error`** (#FFB4AB) - Error/danger state (Material 3 dark)
- **`info`** (#64B6AC) - Information state (soft teal)
### Text Hierarchy
- **`textPrimary`** (#FFFFFF) - Main text (white)
- **`textSecondary`** (#999999) - Secondary text (60% grey)
- **`textTertiary`** (#666666) - Tertiary text (40% grey)
- **`textQuaternary`** (#404040) - Subtle text (25% grey)
### Text Hierarchy (warm ivory)
- **`textPrimary`** (#ECE6DA) - Main text
- **`textSecondary`** (#CDC4B4) - Secondary text
- **`textTertiary`** (#998F7C) - Tertiary text
### Category Colors
- **`live`** (#FF3B30) - Live streams (red)
- **`movies`** (#00B4E8) - Movie content (blue)
- **`series`** (#00E5BB) - Series content (mint)
- **`sports`** (#BF5AF0) - Sports content (purple)
- **`news`** (#FFC300) - News content (yellow)
- **`music`** (#FF2D55) - Music content (pink)
- **`live`** (#FF6E5E) - Live streams (signal coral)
- **`movies`** (#E8B64C) - Movie content (warm gold)
- **`series`** (#5FC9AE) - Series content (teal)
---
## Typography
### Font Stack
1. **Outfit** (headings/display) - Bold, geometric, premium feel
2. **Inter** (UI/body) - Clean, readable, high contrast
1. **Syne** (headings/display) - Geometric, art-house, distinctive
2. **Instrument Sans** (UI/body) - Clean, readable, characterful
3. Fallback to system fonts
### Sizes & Weights
@@ -287,14 +281,14 @@ TvSideNav(
## Usage Guidelines
### Color Usage
- **Primary (Cyan):** Call-to-action buttons, focus states, active indicators
- **Secondary (Red):** Alerts, favorite toggles, urgent actions
- **Tertiary (Mint):** Accent highlights, success states, featured badges
- **Primary (Tungsten Amber):** Call-to-action buttons, focus states, active indicators
- **Secondary (Warm Taupe):** Alerts, favorite toggles, urgent actions
- **Tertiary (Verdigris Teal):** Accent highlights, success states, featured badges
- **White/Grey text:** Maintain WCAG AA contrast ratio (4.5:1 minimum)
### Typography
- **Outfit:** Only for headings/hero text (sizes 20px and above)
- **Inter:** All UI, buttons, body text
- **Syne:** Only for headings/hero text (sizes 20px and above)
- **Instrument Sans:** All UI, buttons, body text
- **Letter spacing:** Increase for larger sizes (hero titles: -1.0 to -1.5), decrease for body text
### Spacing
@@ -319,8 +313,8 @@ TvSideNav(
## Mobile Adaptations
### Touch Targets
- **Minimum button size:** 48×48px
- **Minimum tap area:** 44×44px
- **Minimum button size:** 48x48px
- **Minimum tap area:** 44x44px
- **Between buttons:** 16px spacing minimum
### Typography Scaling
@@ -349,7 +343,7 @@ TvSideNav(
2. Extend with custom styling if needed
3. Follow spacing/animation guidelines
4. Test hover states on desktop, tap on mobile
5. Ensure text contrast ≥ 4.5:1
5. Ensure text contrast >= 4.5:1
### Color Customization
- Never override `AppColors` constants directly
@@ -378,7 +372,7 @@ TvSideNav(
## Accessibility
- **Text Contrast:** All text must meet WCAG AA (4.5:1)
- **Touch Targets:** 48×48px minimum on mobile
- **Touch Targets:** 48x48px minimum on mobile
- **Focus States:** Always visible with 2px border or scale change
- **Semantic HTML:** Use proper widget hierarchy
- **Tooltips:** Always add for icon-only buttons
@@ -435,6 +429,6 @@ Curve animCurve = AppTheme.curveDefault;
---
**Design System Version:** 2.0 Apple TV Modern
**Last Updated:** 2026-03-26
**Status:** Production Ready ✅
**Design System Version:** 3.0 Projector Noir
**Last Updated:** 2026-06-10
**Status:** Production Ready OK
+80 -79
View File
@@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
/// Cyber-Cinematic Glass Design System — Material 3 Token Palette
/// Projector Noir Design System — Material 3 Token Palette
///
/// Extracted from the Stitch design system for XtremFlow.
/// Warm tungsten light on deep film-black, like a projector beam cutting
/// through a dark screening room. Verdigris teal as the counterpoint accent.
/// Optimized for OLED displays and low-light environments.
/// Primary accent: Neon blue (#4b8eff / #adc6ff)
/// Primary accent: Tungsten amber (#F39A1F / #FFB35C)
class AppColors {
AppColors._();
@@ -13,58 +14,58 @@ class AppColors {
static Color get border => outlineVariant;
// ============ SURFACE / ON SURFACE ============
static const Color onSurface = Color(0xFFe3e2e7);
static const Color onSurfaceVariant = Color(0xFFc1c6d7);
static const Color onSurface = Color(0xFFECE6DA);
static const Color onSurfaceVariant = Color(0xFFCDC4B4);
// ============ BASE LEVEL 0 ============
static const Color baseLevel0 = Color(0xFF0F1014);
static const Color baseLevel0 = Color(0xFF0B0A08);
// ============ BACKGROUNDS ============
static const Color background = Color(0xFF121317);
static const Color onBackground = Color(0xFFe3e2e7);
static const Color background = Color(0xFF14110C);
static const Color onBackground = Color(0xFFECE6DA);
static const Color surface = Color(0xFF121317);
static const Color surfaceDim = Color(0xFF121317);
static const Color surfaceBright = Color(0xFF38393d);
static const Color surface = Color(0xFF14110C);
static const Color surfaceDim = Color(0xFF14110C);
static const Color surfaceBright = Color(0xFF3E382C);
// Surface Containers (Material 3 hierarchy)
static const Color surfaceContainerLowest = Color(0xFF0d0e12);
static const Color surfaceContainerLow = Color(0xFF1a1b20);
static const Color surfaceContainer = Color(0xFF1f1f24);
static const Color surfaceContainerHigh = Color(0xFF292a2e);
static const Color surfaceContainerHighest = Color(0xFF343439);
static const Color surfaceVariant = Color(0xFF343439);
static const Color surfaceContainerLowest = Color(0xFF0E0C09);
static const Color surfaceContainerLow = Color(0xFF1B1812);
static const Color surfaceContainer = Color(0xFF211D16);
static const Color surfaceContainerHigh = Color(0xFF2B261E);
static const Color surfaceContainerHighest = Color(0xFF363027);
static const Color surfaceVariant = Color(0xFF363027);
// ============ PRIMARY (Neon Blue) ============
static const Color primary = Color(0xFFadc6ff);
static const Color onPrimary = Color(0xFF002e69);
static const Color primaryContainer = Color(0xFF4b8eff);
static const Color onPrimaryContainer = Color(0xFF00285c);
static const Color inversePrimary = Color(0xFF005bc1);
static const Color primaryFixed = Color(0xFFd8e2ff);
static const Color primaryFixedDim = Color(0xFFadc6ff);
static const Color onPrimaryFixed = Color(0xFF001a41);
static const Color onPrimaryFixedVariant = Color(0xFF004493);
// ============ PRIMARY (Tungsten Amber) ============
static const Color primary = Color(0xFFFFB35C);
static const Color onPrimary = Color(0xFF452800);
static const Color primaryContainer = Color(0xFFF39A1F);
static const Color onPrimaryContainer = Color(0xFF2E1B00);
static const Color inversePrimary = Color(0xFF8F5B00);
static const Color primaryFixed = Color(0xFFFFDDB3);
static const Color primaryFixedDim = Color(0xFFFFB35C);
static const Color onPrimaryFixed = Color(0xFF2A1700);
static const Color onPrimaryFixedVariant = Color(0xFF6B4300);
// ============ SECONDARY ============
static const Color secondary = Color(0xFFc6c5cf);
static const Color onSecondary = Color(0xFF2f3037);
static const Color secondaryContainer = Color(0xFF4a4b53);
static const Color onSecondaryContainer = Color(0xFFbcbbc4);
static const Color secondaryFixed = Color(0xFFe3e1eb);
static const Color secondaryFixedDim = Color(0xFFc6c5cf);
static const Color onSecondaryFixed = Color(0xFF1a1b22);
static const Color onSecondaryFixedVariant = Color(0xFF46464e);
// ============ SECONDARY (Warm Taupe) ============
static const Color secondary = Color(0xFFD3C6B2);
static const Color onSecondary = Color(0xFF382F21);
static const Color secondaryContainer = Color(0xFF504535);
static const Color onSecondaryContainer = Color(0xFFD8CCB9);
static const Color secondaryFixed = Color(0xFFF0E4D0);
static const Color secondaryFixedDim = Color(0xFFD3C6B2);
static const Color onSecondaryFixed = Color(0xFF231B0E);
static const Color onSecondaryFixedVariant = Color(0xFF4D4232);
// ============ TERTIARY ============
static const Color tertiary = Color(0xFFc6c6c7);
static const Color onTertiary = Color(0xFF2f3131);
static const Color tertiaryContainer = Color(0xFF909191);
static const Color onTertiaryContainer = Color(0xFF282a2a);
static const Color tertiaryFixed = Color(0xFFe2e2e2);
static const Color tertiaryFixedDim = Color(0xFFc6c6c7);
static const Color onTertiaryFixed = Color(0xFF1a1c1c);
static const Color onTertiaryFixedVariant = Color(0xFF454747);
// ============ TERTIARY (Verdigris Teal) ============
static const Color tertiary = Color(0xFFA4CCBE);
static const Color onTertiary = Color(0xFF0F352B);
static const Color tertiaryContainer = Color(0xFF2F5A4C);
static const Color onTertiaryContainer = Color(0xFFC0E8D9);
static const Color tertiaryFixed = Color(0xFFC0E8D9);
static const Color tertiaryFixedDim = Color(0xFFA4CCBE);
static const Color onTertiaryFixed = Color(0xFF04201A);
static const Color onTertiaryFixedVariant = Color(0xFF274B40);
// ============ ERROR ============
static const Color error = Color(0xFFffb4ab);
@@ -73,61 +74,61 @@ class AppColors {
static const Color onErrorContainer = Color(0xFFffdad6);
// ============ OUTLINE ============
static const Color outline = Color(0xFF8b90a0);
static const Color outlineVariant = Color(0xFF414755);
static const Color outline = Color(0xFF998F7C);
static const Color outlineVariant = Color(0xFF4A4334);
// ============ INVERSE SURFACE ============
static const Color inverseSurface = Color(0xFFe3e2e7);
static const Color inverseOnSurface = Color(0xFF2f3035);
static const Color inverseSurface = Color(0xFFECE6DA);
static const Color inverseOnSurface = Color(0xFF332F26);
// ============ SURFACE TINT ============
static const Color surfaceTint = Color(0xFFadc6ff);
static const Color surfaceTint = Color(0xFFFFB35C);
// ============ TEXT / CONTENT COLORS ============
static const Color textPrimary = Color(0xFFe3e2e7);
static const Color textSecondary = Color(0xFFc1c6d7);
static const Color textTertiary = Color(0xFF8b90a0);
static const Color textPrimary = Color(0xFFECE6DA);
static const Color textSecondary = Color(0xFFCDC4B4);
static const Color textTertiary = Color(0xFF998F7C);
// ============ STATUS COLORS ============
static const Color success = Color(0xFF00E676);
static const Color success = Color(0xFF6BD89B);
static const Color warning = Color(0xFFFFAB00);
static const Color info = Color(0xFF2979FF);
static const Color info = Color(0xFF64B6AC);
// ============ CATEGORY COLORS (kept for semantic meaning) ============
static const Color live = Color(0xFFFF5252);
static const Color movies = Color(0xFF448AFF);
static const Color series = Color(0xFF69F0AE);
static const Color live = Color(0xFFFF6E5E);
static const Color movies = Color(0xFFE8B64C);
static const Color series = Color(0xFF5FC9AE);
// ============ RATING / PREMIUM ============
static const Color ratingGold = Color(0xFFFFD700);
static const Color ratingGold = Color(0xFFFFD166);
static const Color premiumGold = Color(0xFFFFA000);
// ============ GLASSMORPHISM LEVELS ============
static const Color glassLevel1Bg = Color(0x66121317); // 40% opacity
static const Color glassLevel1Border = Color(0x1AFFFFFF); // 10% white
static const Color glassLevel1Bg = Color(0x6614110C); // 40% opacity
static const Color glassLevel1Border = Color(0x1AFFE9C9); // 10% warm white
static const Color glassLevel2Bg = Color(0x99121317); // 60% opacity
static const Color glassLevel2Border = Color(0x1AFFFFFF); // 10% white
static const Color glassLevel2InnerGlow = Color(0x33adc6ff); // 20% primary top-left
static const Color glassLevel2Bg = Color(0x9914110C); // 60% opacity
static const Color glassLevel2Border = Color(0x1AFFE9C9); // 10% warm white
static const Color glassLevel2InnerGlow = Color(0x33FFB35C); // 20% primary top-left
// ============ GRADIENTS ============
static const LinearGradient primaryGradient = LinearGradient(
colors: [Color(0xFF007AFF), Color(0xFF00C6FF)],
colors: [Color(0xFFE8941A), Color(0xFFFFC36A)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
);
static const LinearGradient backgroundGradient = LinearGradient(
colors: [Color(0xFF0F1014), Color(0xFF121317)],
colors: [Color(0xFF0B0A08), Color(0xFF14110C)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
);
// ============ GLOW / SHADOWS ============
static Color glowPrimary(double opacity) =>
const Color(0xFF007AFF).withOpacity(opacity);
const Color(0xFFF39A1F).withOpacity(opacity);
static Color glowPrimaryDim(double opacity) =>
const Color(0xFFadc6ff).withOpacity(opacity);
const Color(0xFFFFB35C).withOpacity(opacity);
// ============ COLOR SCHEMES ============
static ColorScheme get darkColorScheme => const ColorScheme.dark(
@@ -162,24 +163,24 @@ class AppColors {
brightness: Brightness.dark,
);
// Light scheme is minimal — Stitch is dark-only
// Light scheme is minimal — Projector Noir is dark-first
static ColorScheme get lightColorScheme => const ColorScheme.light(
primary: Color(0xFF005bc1),
primary: Color(0xFF8F5B00),
onPrimary: Colors.white,
primaryContainer: Color(0xFFd8e2ff),
onPrimaryContainer: Color(0xFF001a41),
secondary: Color(0xFF5e5c68),
primaryContainer: Color(0xFFFFDDB3),
onPrimaryContainer: Color(0xFF2A1700),
secondary: Color(0xFF6F6353),
onSecondary: Colors.white,
secondaryContainer: Color(0xFFe3e1eb),
onSecondaryContainer: Color(0xFF1a1b22),
secondaryContainer: Color(0xFFF0E4D0),
onSecondaryContainer: Color(0xFF231B0E),
error: Color(0xFFba1a1a),
onError: Colors.white,
errorContainer: Color(0xFFFFdad6),
onErrorContainer: Color(0xFF410002),
surface: Color(0xFFF9F9FF),
onSurface: Color(0xFF1a1b22),
outline: Color(0xFF757680),
outlineVariant: Color(0xFFc5c6d0),
surface: Color(0xFFFFF8F0),
onSurface: Color(0xFF1E1B15),
outline: Color(0xFF7F766A),
outlineVariant: Color(0xFFD0C5B4),
brightness: Brightness.light,
);
}
+42 -42
View File
@@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'app_colors.dart';
/// XtremFlow Cyber-Cinematic Glass Theme
/// XtremFlow Projector Noir Theme
///
/// Design system extracted from Google Stitch.
/// Fonts: Space Grotesk (headlines) + Inter (body/labels)
/// Style: Dark-only glassmorphism with neon blue accents.
/// Warm tungsten light on deep film-black.
/// Fonts: Syne (headlines, art-house geometric) + Instrument Sans (body/labels)
/// Style: Dark-first glassmorphism with tungsten amber accents.
class AppTheme {
AppTheme._();
@@ -39,14 +39,14 @@ class AppTheme {
static const Curve curveSmooth = Curves.fastOutSlowIn;
// ============ TYPOGRAPHY HELPERS ============
static TextStyle _spaceGrotesk({
static TextStyle _syne({
required double fontSize,
required FontWeight fontWeight,
double? letterSpacing,
double? height,
Color color = AppColors.onSurface,
}) {
return GoogleFonts.spaceGrotesk(
return GoogleFonts.syne(
fontSize: fontSize,
fontWeight: fontWeight,
letterSpacing: letterSpacing,
@@ -55,14 +55,14 @@ class AppTheme {
);
}
static TextStyle _inter({
static TextStyle _instrumentSans({
required double fontSize,
required FontWeight fontWeight,
double? letterSpacing,
double? height,
Color color = AppColors.onSurface,
}) {
return GoogleFonts.inter(
return GoogleFonts.instrumentSans(
fontSize: fontSize,
fontWeight: fontWeight,
letterSpacing: letterSpacing,
@@ -81,85 +81,85 @@ class AppTheme {
// Typography
textTheme: TextTheme(
// Display / Headline (Space Grotesk)
displayLarge: _spaceGrotesk(
// Display / Headline (Syne)
displayLarge: _syne(
fontSize: 48,
fontWeight: FontWeight.w700,
letterSpacing: -0.02,
height: 1.1,
),
displayMedium: _spaceGrotesk(
displayMedium: _syne(
fontSize: 32,
fontWeight: FontWeight.w600,
letterSpacing: -0.01,
height: 1.2,
),
displaySmall: _spaceGrotesk(
displaySmall: _syne(
fontSize: 24,
fontWeight: FontWeight.w500,
height: 1.3,
),
headlineLarge: _spaceGrotesk(
headlineLarge: _syne(
fontSize: 32,
fontWeight: FontWeight.w600,
letterSpacing: -0.01,
height: 1.2,
),
headlineMedium: _spaceGrotesk(
headlineMedium: _syne(
fontSize: 24,
fontWeight: FontWeight.w500,
height: 1.3,
),
headlineSmall: _spaceGrotesk(
headlineSmall: _syne(
fontSize: 20,
fontWeight: FontWeight.w500,
height: 1.3,
),
titleLarge: _spaceGrotesk(
titleLarge: _syne(
fontSize: 20,
fontWeight: FontWeight.w600,
),
titleMedium: _inter(
titleMedium: _instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w600,
),
titleSmall: _inter(
titleSmall: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
),
// Body (Inter)
bodyLarge: _inter(
// Body (Instrument Sans)
bodyLarge: _instrumentSans(
fontSize: 18,
fontWeight: FontWeight.w400,
height: 1.6,
color: AppColors.onSurfaceVariant,
),
bodyMedium: _inter(
bodyMedium: _instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w400,
height: 1.5,
color: AppColors.onSurfaceVariant,
),
bodySmall: _inter(
bodySmall: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w400,
height: 1.4,
color: AppColors.onSurfaceVariant,
),
// Labels (Inter with tracking)
labelLarge: _inter(
// Labels (Instrument Sans with tracking)
labelLarge: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
letterSpacing: 0.05,
height: 1.2,
),
labelMedium: _inter(
labelMedium: _instrumentSans(
fontSize: 12,
fontWeight: FontWeight.w500,
letterSpacing: 0.02,
height: 1.2,
),
labelSmall: _inter(
labelSmall: _instrumentSans(
fontSize: 11,
fontWeight: FontWeight.w500,
letterSpacing: 0.02,
@@ -174,13 +174,13 @@ class AppTheme {
elevation: 0,
centerTitle: true,
scrolledUnderElevation: 0,
titleTextStyle: _spaceGrotesk(
titleTextStyle: _syne(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
// Inputs: Dark filled with blue glow on focus
// Inputs: Dark filled with amber glow on focus
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: AppColors.surfaceContainerLow,
@@ -204,12 +204,12 @@ class AppTheme {
borderRadius: BorderRadius.circular(radiusMd),
borderSide: const BorderSide(color: AppColors.error, width: 1),
),
hintStyle: _inter(
hintStyle: _instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w400,
color: AppColors.outline,
),
labelStyle: _inter(
labelStyle: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColors.onSurfaceVariant,
@@ -226,7 +226,7 @@ class AppTheme {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radiusMd),
),
textStyle: _inter(
textStyle: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
letterSpacing: 0.05,
@@ -253,7 +253,7 @@ class AppTheme {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radiusMd),
),
textStyle: _inter(
textStyle: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
letterSpacing: 0.05,
@@ -266,7 +266,7 @@ class AppTheme {
style: TextButton.styleFrom(
foregroundColor: AppColors.primary,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
textStyle: _inter(
textStyle: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
),
@@ -292,11 +292,11 @@ class AppTheme {
borderRadius: BorderRadius.circular(radiusXl),
side: const BorderSide(color: AppColors.glassLevel2Border, width: 1),
),
titleTextStyle: _spaceGrotesk(
titleTextStyle: _syne(
fontSize: 20,
fontWeight: FontWeight.w600,
),
contentTextStyle: _inter(
contentTextStyle: _instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w400,
color: AppColors.onSurfaceVariant,
@@ -314,7 +314,7 @@ class AppTheme {
// Snackbars
snackBarTheme: SnackBarThemeData(
backgroundColor: AppColors.surfaceContainerHigh,
contentTextStyle: _inter(
contentTextStyle: _instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColors.onSurface,
@@ -336,12 +336,12 @@ class AppTheme {
shape: StadiumBorder(
side: BorderSide(color: AppColors.primary.withOpacity(0.3)),
),
labelStyle: _inter(
labelStyle: _instrumentSans(
fontSize: 12,
fontWeight: FontWeight.w500,
color: AppColors.onSurface,
),
secondaryLabelStyle: _inter(
secondaryLabelStyle: _instrumentSans(
fontSize: 12,
fontWeight: FontWeight.w600,
color: AppColors.onPrimaryContainer,
@@ -353,8 +353,8 @@ class AppTheme {
labelColor: AppColors.onSurface,
unselectedLabelColor: AppColors.outline,
indicatorColor: AppColors.primaryContainer,
labelStyle: _inter(fontSize: 14, fontWeight: FontWeight.w600),
unselectedLabelStyle: _inter(fontSize: 14, fontWeight: FontWeight.w500),
labelStyle: _instrumentSans(fontSize: 14, fontWeight: FontWeight.w600),
unselectedLabelStyle: _instrumentSans(fontSize: 14, fontWeight: FontWeight.w500),
),
// Divider
@@ -389,10 +389,10 @@ class AppTheme {
);
}
// Light theme is minimal — Stitch is dark-only
// Light theme is minimal — Projector Noir is dark-first
static ThemeData get lightTheme => ThemeData.light(useMaterial3: true).copyWith(
colorScheme: AppColors.lightColorScheme,
scaffoldBackgroundColor: AppColors.lightColorScheme.surface,
textTheme: GoogleFonts.interTextTheme(ThemeData.light().textTheme),
textTheme: GoogleFonts.instrumentSansTextTheme(ThemeData.light().textTheme),
);
}
@@ -1,4 +1,4 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
@@ -140,7 +140,7 @@ class _HeroCarouselState extends State<HeroCarousel> {
children: [
Text(
item.title,
style: GoogleFonts.spaceGrotesk(
style: GoogleFonts.syne(
fontSize: 32,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -152,7 +152,7 @@ class _HeroCarouselState extends State<HeroCarousel> {
const SizedBox(height: 8),
Text(
item.subtitle!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
color: AppColors.onSurface,
),
@@ -245,7 +245,7 @@ class _HeroButtonState extends State<_HeroButton> {
const SizedBox(width: 8),
Text(
widget.label,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontWeight: FontWeight.w600,
),
@@ -149,7 +149,7 @@ class _GradientButtonState extends State<GradientButton>
],
Text(
widget.label,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
@@ -253,7 +253,7 @@ class LiveBadge extends StatelessWidget {
const SizedBox(width: 4),
Text(
'LIVE',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontSize: 10,
fontWeight: FontWeight.w700,
@@ -302,7 +302,7 @@ class CategoryChip extends StatelessWidget {
),
child: Text(
label,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 13,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
color: isSelected ? AppColors.primary : AppColors.onSurfaceVariant,
@@ -458,7 +458,7 @@ class _MediaCardState extends State<MediaCard>
const SizedBox(width: 4),
Text(
widget.rating!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontSize: 10,
fontWeight: FontWeight.w700,
@@ -502,7 +502,7 @@ class _MediaCardState extends State<MediaCard>
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: _isHovered
? AppColors.primary
: AppColors.onSurface,
@@ -518,7 +518,7 @@ class _MediaCardState extends State<MediaCard>
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant,
fontSize: 11,
),
+2 -2
View File
@@ -1,4 +1,4 @@
import 'dart:async';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
@@ -38,7 +38,7 @@ class _DigitalClockState extends State<DigitalClock> {
),
child: Text(
timeString,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600,
fontSize: 16,
color: AppColors.onSurface,
+6 -6
View File
@@ -1,4 +1,4 @@
import 'dart:async';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../theme/app_colors.dart';
@@ -220,7 +220,7 @@ class _HeroCarouselState extends State<HeroCarousel>
),
child: Text(
item.badge!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 12,
fontWeight: FontWeight.w700,
color: AppColors.primary,
@@ -233,7 +233,7 @@ class _HeroCarouselState extends State<HeroCarousel>
item.title,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
fontSize: 48,
fontWeight: FontWeight.w800,
color: AppColors.textPrimary,
@@ -247,7 +247,7 @@ class _HeroCarouselState extends State<HeroCarousel>
item.subtitle!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w400,
color: AppColors.textSecondary,
@@ -292,7 +292,7 @@ class _HeroCarouselState extends State<HeroCarousel>
const SizedBox(width: 8),
Text(
'Play',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.primary,
@@ -330,7 +330,7 @@ class _HeroCarouselState extends State<HeroCarousel>
const SizedBox(width: 8),
Text(
'More Info',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.textPrimary,
+2 -2
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../theme/app_colors.dart';
@@ -30,7 +30,7 @@ class ThemedLoading extends StatelessWidget {
const SizedBox(height: 16),
Text(
'Loading...',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant,
fontSize: 14,
fontWeight: FontWeight.w500,
+1 -1
View File
@@ -152,7 +152,7 @@ class _AdminContentState extends ConsumerState<AdminContent>
const SizedBox(width: 8),
Text(
label,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600,
fontSize: 14,
color: isSelected ? AppColors.textPrimary : AppColors.textSecondary,
+7 -7
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -144,7 +144,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
// Title
Text(
'XtremFlow',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 42,
fontWeight: FontWeight.w700,
color: AppColors.textPrimary,
@@ -154,7 +154,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
const SizedBox(height: 8),
Text(
'Sign in to sync your playlists',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 18,
color: AppColors.textSecondary,
fontWeight: FontWeight.w400,
@@ -266,7 +266,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
)
: Text(
'Sign In',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.primary,
fontSize: 18,
fontWeight: FontWeight.w600,
@@ -282,7 +282,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
const SizedBox(height: 32),
Text(
'Default: admin / admin',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
color: AppColors.textTertiary,
),
@@ -310,13 +310,13 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
return TextFormField(
controller: controller,
obscureText: obscureText,
style: GoogleFonts.inter(fontSize: 18, color: AppColors.textPrimary),
style: GoogleFonts.instrumentSans(fontSize: 18, color: AppColors.textPrimary),
autofocus: autofocus,
textInputAction: nextFocus ? TextInputAction.next : TextInputAction.done,
onFieldSubmitted: isLast ? (_) => onSubmitted?.call() : null,
decoration: InputDecoration(
labelText: label,
labelStyle: GoogleFonts.inter(color: AppColors.textSecondary),
labelStyle: GoogleFonts.instrumentSans(color: AppColors.textSecondary),
prefixIcon: Icon(icon, color: AppColors.textSecondary),
suffixIcon: suffix,
filled: true,
+10 -10
View File
@@ -535,7 +535,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
'Unknown')
.toString()
: widget.title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: AppColors.textPrimary,
fontSize: 18,
fontWeight: FontWeight.w600,
@@ -544,7 +544,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
),
Text(
'Live TV',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.primary,
fontSize: 12,
fontWeight: FontWeight.bold,
@@ -706,7 +706,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
Expanded(
child: Text(
widget.title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Colors.white,
@@ -747,7 +747,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
seconds: _currentPosition.toInt(),
),
),
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white70,
),
),
@@ -799,7 +799,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
seconds: _totalDuration.toInt(),
),
),
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white70,
),
),
@@ -1060,7 +1060,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
widget.channels != null
? widget.channels![_currentIndex].name
: widget.title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
@@ -1110,7 +1110,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
children: [
Text(
currentProgram.title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontSize: 15,
fontWeight: FontWeight.w600,
@@ -1121,7 +1121,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
if (currentProgram.description.isNotEmpty)
Text(
currentProgram.description,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white60,
fontSize: 12,
),
@@ -1156,7 +1156,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
widget.channels != null
? widget.channels![_currentIndex].name
: widget.title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
@@ -1168,7 +1168,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
widget.channels != null
? widget.channels![_currentIndex].name
: widget.title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -97,7 +97,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
const SizedBox(height: 16),
Text(
'Error loading playlists',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
fontSize: 18,
color: AppColors.textSecondary,
),
@@ -109,7 +109,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
backgroundColor: AppColors.primary,
foregroundColor: AppColors.textPrimary,
),
child: Text('Retry', style: GoogleFonts.inter()),
child: Text('Retry', style: GoogleFonts.instrumentSans()),
),
],
),
@@ -128,7 +128,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
const SizedBox(height: 16),
Text(
'No playlists available',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
fontSize: 18,
color: Colors.white60,
),
@@ -138,7 +138,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
currentUser?.isAdmin ?? false
? 'Add playlists in Admin Panel'
: 'Contact administrator',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
color: Colors.white38,
),
@@ -269,7 +269,7 @@ class _PlaylistCardState extends State<_PlaylistCard> {
const SizedBox(height: 20),
Text(
widget.playlist.name,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.white,
@@ -281,7 +281,7 @@ class _PlaylistCardState extends State<_PlaylistCard> {
const SizedBox(height: 8),
Text(
Uri.tryParse(widget.playlist.dns)?.host ?? widget.playlist.dns,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 13,
color: Colors.white38,
letterSpacing: 0.5,
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -143,7 +143,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
// Title
Text(
_seriesInfo!.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -178,7 +178,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
// Season selector
Text(
'Seasons',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
@@ -200,7 +200,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
},
selectedColor: AppColors.primaryContainer,
backgroundColor: AppColors.surfaceContainer,
labelStyle: GoogleFonts.inter(
labelStyle: GoogleFonts.instrumentSans(
color: isSelected ? AppColors.onPrimary : AppColors.onSurfaceVariant,
fontSize: 12,
),
@@ -224,7 +224,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
padding: const EdgeInsets.all(16),
child: Text(
'Season $_selectedSeason - ${currentEpisodes.length} Episodes',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
@@ -323,7 +323,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
? const Icon(Icons.check, color: AppColors.onSurface, size: 20)
: Text(
'${episode.episodeNum}',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
+2 -2
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../../core/models/playlist_config.dart';
@@ -99,7 +99,7 @@ class _EPGWidgetState extends ConsumerState<EPGWidget> {
),
child: Text(
'LIVE',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 9,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
+12 -12
View File
@@ -137,7 +137,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
: _showFavoritesOnly
? 'Favorites'
: _selectedCategory ?? 'Live TV',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 24,
fontWeight: FontWeight.w700,
color: Colors.white,
@@ -157,10 +157,10 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
),
child: TextField(
controller: _searchController,
style: GoogleFonts.inter(color: Colors.white),
style: GoogleFonts.instrumentSans(color: Colors.white),
decoration: InputDecoration(
hintText: 'Search channels...',
hintStyle: GoogleFonts.inter(color: Colors.white54),
hintStyle: GoogleFonts.instrumentSans(color: Colors.white54),
prefixIcon:
const Icon(Icons.search, color: Colors.white54),
border: InputBorder.none,
@@ -235,7 +235,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
const SizedBox(height: 16),
Text(
'No channels found',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white54,
fontSize: 18,
),
@@ -319,7 +319,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
child: Text(
category,
textAlign: TextAlign.center,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white,
@@ -331,7 +331,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
const SizedBox(height: 4),
Text(
'$count Channels',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 13,
color: Colors.white54,
),
@@ -406,7 +406,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
)
: Text(
channel.name.characters.first.toUpperCase(),
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
fontSize: 40,
fontWeight: FontWeight.bold,
color: Colors.white24,
@@ -427,7 +427,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
children: [
Text(
channel.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white,
fontSize: 13,
fontWeight: FontWeight.w500,
@@ -452,7 +452,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
if (epgList.isEmpty) {
return Text(
'No Info',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white54,
fontSize: 10,
),
@@ -480,7 +480,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
return Text(
currentProgram.title,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.ratingGold,
fontSize: 10,
fontWeight: FontWeight.w600,
@@ -491,14 +491,14 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
},
loading: () => Text(
'...',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white24,
fontSize: 10,
),
),
error: (_, __) => Text(
'Err',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.red,
fontSize: 10,
),
+8 -8
View File
@@ -1,4 +1,4 @@
import 'dart:async';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -219,7 +219,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
children: [
Text(
'Movies',
style: GoogleFonts.spaceGrotesk(
style: GoogleFonts.syne(
fontSize: 24,
fontWeight: FontWeight.w700,
color: AppColors.onSurface,
@@ -251,14 +251,14 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
Expanded(
child: TextField(
controller: _searchController,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
color: AppColors.onSurface,
),
decoration: InputDecoration(
hintText: 'Search movies...',
hintStyle:
GoogleFonts.inter(color: AppColors.outline),
GoogleFonts.instrumentSans(color: AppColors.outline),
border: InputBorder.none,
isDense: true,
contentPadding:
@@ -311,7 +311,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
title: m.name,
imageUrl: _getProxiedImageUrl(m.streamIcon),
subtitle: m.rating != null
? '${_formatRating(m.rating)} ★'
? '${_formatRating(m.rating)} ★'
: null,
onPlay: () => _playMovie(m),
onTap: () => _playMovie(m),
@@ -426,7 +426,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
const SizedBox(width: 4),
Text(
_formatRating(movie.rating)!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 10,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -448,7 +448,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
children: [
Text(
movie.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontSize: 13,
fontWeight: FontWeight.w600,
@@ -467,7 +467,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
padding: const EdgeInsets.only(top: 4),
child: Text(
'WATCHED',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.primary,
fontSize: 10,
fontWeight: FontWeight.bold,
@@ -64,7 +64,7 @@ class QualitySelectorButton extends StatelessWidget {
Text(
q.label,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.textPrimary,
fontWeight: FontWeight.w600,
fontSize: 14,
@@ -73,7 +73,7 @@ class QualitySelectorButton extends StatelessWidget {
Text(
q.description,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.textTertiary,
fontSize: 11,
),
+12 -12
View File
@@ -106,7 +106,7 @@ class _RecordingModalState extends State<RecordingModal> {
Expanded(
child: Text(
'Programmer un enregistrement',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 20,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -120,12 +120,12 @@ class _RecordingModalState extends State<RecordingModal> {
// Informations Chaine
Text(
'Chaîne ciblée :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14),
style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
),
const SizedBox(height: 8),
Text(
widget.channel.name,
style: GoogleFonts.inter(color: AppColors.onSurface, fontSize: 18),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface, fontSize: 18),
),
const SizedBox(height: 24),
@@ -139,7 +139,7 @@ class _RecordingModalState extends State<RecordingModal> {
children: [
Text(
'Date :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14),
style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
),
const SizedBox(height: 8),
TvFocusableCard(
@@ -173,7 +173,7 @@ class _RecordingModalState extends State<RecordingModal> {
Expanded(
child: Text(
'${_startTime.day.toString().padLeft(2, '0')}/${_startTime.month.toString().padLeft(2, '0')}/${_startTime.year}',
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
overflow: TextOverflow.ellipsis,
),
),
@@ -193,7 +193,7 @@ class _RecordingModalState extends State<RecordingModal> {
children: [
Text(
'Heure :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14),
style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
),
const SizedBox(height: 8),
TvFocusableCard(
@@ -236,7 +236,7 @@ class _RecordingModalState extends State<RecordingModal> {
Expanded(
child: Text(
'${_startTime.hour.toString().padLeft(2, '0')}:${_startTime.minute.toString().padLeft(2, '0')}',
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
),
),
],
@@ -255,7 +255,7 @@ class _RecordingModalState extends State<RecordingModal> {
children: [
Text(
'Durée (min) :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14),
style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
),
const SizedBox(height: 8),
GlassContainer.glass(
@@ -277,7 +277,7 @@ class _RecordingModalState extends State<RecordingModal> {
child: Text(
'$_durationMinutes',
textAlign: TextAlign.center,
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
),
),
IconButton(
@@ -308,7 +308,7 @@ class _RecordingModalState extends State<RecordingModal> {
onPressed: _isLoading ? null : () => Navigator.of(context).pop(),
child: Text(
'Annuler',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
),
),
const SizedBox(width: 16),
@@ -328,7 +328,7 @@ class _RecordingModalState extends State<RecordingModal> {
)
: Text(
'Enregistrer de suite',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontWeight: FontWeight.bold,
),
@@ -352,7 +352,7 @@ class _RecordingModalState extends State<RecordingModal> {
)
: Text(
'Programmer',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontWeight: FontWeight.bold,
),
+24 -24
View File
@@ -183,7 +183,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
children: [
Text(
'GROUPES',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white38,
fontSize: 10,
fontWeight: FontWeight.bold,
@@ -217,7 +217,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
),
child: Text(
cat,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: isSelected
? Colors.white
: Colors.white60,
@@ -331,7 +331,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
Expanded(
child: Text(
ch.name,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: isSelected
? Colors.white
: Colors.white70,
@@ -370,7 +370,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
Text(
'Sélectionnez une chaîne\npour voir son guide des programmes',
textAlign: TextAlign.center,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white38,
fontSize: 15,
),
@@ -385,7 +385,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
children: [
Text(
_selectedChannel!.name,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
@@ -425,7 +425,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
child: Text(
'Aucun programme EPG disponible\npour cette chaîne',
textAlign: TextAlign.center,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white38,
),
),
@@ -525,7 +525,7 @@ class _ProgrammeCard extends StatelessWidget {
Expanded(
child: Text(
'Enregistrer',
style: GoogleFonts.outfit(color: Colors.white),
style: GoogleFonts.syne(color: Colors.white),
),
),
],
@@ -536,7 +536,7 @@ class _ProgrammeCard extends StatelessWidget {
children: [
Text(
title.isEmpty ? channel.name : title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
@@ -658,7 +658,7 @@ class _ProgrammeCard extends StatelessWidget {
),
child: Text(
'LIVE',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontSize: 8,
fontWeight: FontWeight.bold,
@@ -668,7 +668,7 @@ class _ProgrammeCard extends StatelessWidget {
else
Text(
_fmt(_start),
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: isPast ? Colors.white24 : Colors.white70,
fontSize: 13,
fontWeight: FontWeight.w600,
@@ -678,14 +678,14 @@ class _ProgrammeCard extends StatelessWidget {
Text(
_fmt(_end),
style:
GoogleFonts.outfit(color: Colors.white24, fontSize: 10),
GoogleFonts.syne(color: Colors.white24, fontSize: 10),
),
],
),
),
title: Text(
_title.isEmpty ? '—' : _title,
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: isPast ? Colors.white38 : Colors.white,
fontWeight: isNow ? FontWeight.bold : FontWeight.normal,
),
@@ -827,7 +827,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
backgroundColor: AppColors.surfaceContainer,
title: Text(
title,
style: GoogleFonts.outfit(color: Colors.white, fontSize: 14),
style: GoogleFonts.syne(color: Colors.white, fontSize: 14),
),
content: SizedBox(
width: 500,
@@ -863,7 +863,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
'recording' => Colors.redAccent,
'completed' => Colors.green,
'failed' => Colors.orangeAccent,
_ => Colors.blueAccent,
_ => AppColors.primaryContainer,
};
String _statusLabel(String status) => switch (status) {
@@ -924,7 +924,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
const SizedBox(height: 16),
Text(
'Aucun enregistrement',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white38,
fontSize: 16,
),
@@ -962,7 +962,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
),
title: Text(
rec['title'] ?? '—',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontWeight: FontWeight.w600,
),
@@ -1039,7 +1039,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
IconButton(
icon: const Icon(
Icons.description_outlined,
color: Colors.blueAccent,
color: AppColors.primaryContainer,
size: 20,
),
tooltip: 'Logs',
@@ -1132,7 +1132,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
const SizedBox(width: 8),
Text(
'Nouveau Season Pass',
style: GoogleFonts.outfit(color: Colors.white),
style: GoogleFonts.syne(color: Colors.white),
),
],
),
@@ -1143,7 +1143,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
children: [
Text(
'Enregistre automatiquement toutes les nouvelles diffusions d\'une émission.',
style: GoogleFonts.outfit(color: Colors.white54, fontSize: 13),
style: GoogleFonts.syne(color: Colors.white54, fontSize: 13),
),
const SizedBox(height: 16),
_buildField(
@@ -1231,7 +1231,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
children: [
Text(
'Enregistrements automatiques',
style: GoogleFonts.outfit(color: Colors.white54, fontSize: 13),
style: GoogleFonts.syne(color: Colors.white54, fontSize: 13),
),
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
@@ -1262,7 +1262,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
Expanded(
child: Text(
'Scanne l\'EPG toutes les 4h et programme automatiquement les nouvelles diffusions. Seuls les nouveaux épisodes sont enregistrés.',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.purpleAccent.shade100,
fontSize: 12,
),
@@ -1288,7 +1288,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
const SizedBox(height: 16),
Text(
'Aucun Season Pass actif',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white38,
fontSize: 16,
),
@@ -1296,7 +1296,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
const SizedBox(height: 8),
Text(
'Créez-en un pour enregistrer automatiquement vos émissions préférées',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white24,
fontSize: 12,
),
@@ -1325,7 +1325,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
),
title: Text(
p['show_title'] ?? '—',
style: GoogleFonts.outfit(
style: GoogleFonts.syne(
color: Colors.white,
fontWeight: FontWeight.w600,
),
+5 -5
View File
@@ -199,7 +199,7 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
children: [
Text(
'TV Series',
style: GoogleFonts.spaceGrotesk(
style: GoogleFonts.syne(
fontSize: 24,
fontWeight: FontWeight.w700,
color: AppColors.onSurface,
@@ -229,14 +229,14 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
Expanded(
child: TextField(
controller: _searchController,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
color: AppColors.onSurface,
),
decoration: InputDecoration(
hintText: 'Search series...',
hintStyle:
GoogleFonts.inter(color: AppColors.outline),
GoogleFonts.instrumentSans(color: AppColors.outline),
border: InputBorder.none,
isDense: true,
contentPadding:
@@ -397,7 +397,7 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
bottom: 12,
child: Text(
serie.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontSize: 13,
fontWeight: FontWeight.w600,
@@ -440,7 +440,7 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
const SizedBox(width: 4),
Text(
_formatRating(serie.rating)!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 10,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
+18 -18
View File
@@ -155,7 +155,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
const SizedBox(width: 12),
Text(
'Thème',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
@@ -212,7 +212,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
),
title: Text(
'Mode actuel',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w500,
color: AppColors.onSurface,
),
@@ -279,7 +279,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
children: [
Text(
title,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600,
color: isSelected
? colorScheme.primary
@@ -288,7 +288,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
),
Text(
subtitle,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 12,
color: colorScheme.onSurfaceVariant,
),
@@ -327,11 +327,11 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.person, color: AppColors.onSurface),
title: Text(
'Connecté en tant que',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
),
subtitle: Text(
currentUser?.username ?? 'Unknown',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
),
@@ -340,7 +340,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
? Chip(
label: Text(
'Admin',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 11,
color: AppColors.onPrimaryContainer,
),
@@ -355,7 +355,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
// Category filters section
Text(
'Filtres de Catégories',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.bold,
fontSize: 16,
color: AppColors.onSurface,
@@ -364,7 +364,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
const SizedBox(height: 4),
Text(
'Seules les catégories contenant un de ces mots-clés seront affichées. Séparez par des virgules.',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 12,
color: AppColors.onSurfaceVariant,
),
@@ -430,7 +430,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.playlist_play, color: AppColors.onSurface),
title: Text(
'Changer de Playlist',
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
),
trailing: const Icon(Icons.chevron_right, color: AppColors.onSurfaceVariant),
onTap: () => context.go('/playlists'),
@@ -449,11 +449,11 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.info_outline, color: AppColors.onSurface),
title: Text(
'À propos',
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
),
subtitle: Text(
'XtremFlow IPTV v1.0.0',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
),
),
),
@@ -470,11 +470,11 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.cleaning_services, color: AppColors.warning),
title: Text(
'Maintenance',
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
),
subtitle: Text(
'En cas de problèmes d\'affichage ou de mise à jour',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
),
trailing: FilledButton.icon(
onPressed: () {
@@ -573,7 +573,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
const SizedBox(width: 8),
Text(
title,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600,
fontSize: 13,
color: AppColors.onSurface,
@@ -587,7 +587,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
decoration: InputDecoration(
hintText: 'Ex: FR,FRANCE,HD,SPORT',
hintStyle:
GoogleFonts.inter(fontSize: 12, color: AppColors.outline),
GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.outline),
filled: true,
fillColor: AppColors.surfaceContainerHigh,
border: OutlineInputBorder(
@@ -612,7 +612,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
)
: null,
),
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurface),
onChanged: onChanged,
),
if (keywords.isNotEmpty) ...[
@@ -633,7 +633,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
child: Text(
keyword,
style:
GoogleFonts.inter(fontSize: 11, color: AppColors.onSurface),
GoogleFonts.instrumentSans(fontSize: 11, color: AppColors.onSurface),
),
);
}).toList(),
@@ -19,7 +19,7 @@ class StreamingSettingsTab extends ConsumerWidget {
// Header
Text(
'Paramètres Streaming Live TV',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -28,7 +28,7 @@ class StreamingSettingsTab extends ConsumerWidget {
const SizedBox(height: 8),
Text(
'Ces paramètres s\'appliquent uniquement aux flux TV en direct.',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 12,
color: AppColors.onSurfaceVariant,
),
@@ -105,14 +105,14 @@ class StreamingSettingsTab extends ConsumerWidget {
SwitchListTile(
title: Text(
'Reconnexion automatique',
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
),
subtitle: Text(
'Se reconnecter en cas de coupure',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
),
value: settings.autoReconnect,
activeThumbColor: Colors.blueAccent,
activeThumbColor: AppColors.primaryContainer,
onChanged: (v) => notifier.setAutoReconnect(v),
),
],
@@ -141,14 +141,14 @@ class StreamingSettingsTab extends ConsumerWidget {
SwitchListTile(
title: Text(
'Préférer lecture directe',
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
),
subtitle: Text(
'Utiliser le flux original si compatible',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
),
value: settings.preferDirectPlay,
activeThumbColor: Colors.blueAccent,
activeThumbColor: AppColors.primaryContainer,
onChanged: (v) => notifier.setPreferDirectPlay(v),
),
],
@@ -186,11 +186,11 @@ class StreamingSettingsTab extends ConsumerWidget {
SwitchListTile(
title: Text(
'Accélération NVIDIA GPU',
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
),
subtitle: Text(
'Utiliser NVENC/NVDEC pour le transcodage (requiert GPU NVIDIA)',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
),
value: settings.enableNvidiaGpu,
activeThumbColor: Colors.green,
@@ -204,20 +204,20 @@ class StreamingSettingsTab extends ConsumerWidget {
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
color: AppColors.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.blue.withOpacity(0.3)),
border: Border.all(color: AppColors.primary.withOpacity(0.3)),
),
child: Row(
children: [
const Icon(Icons.info_outline, color: Colors.blue),
const Icon(Icons.info_outline, color: AppColors.primary),
const SizedBox(width: 12),
Expanded(
child: Text(
'Les changements prennent effet immédiatement pour les nouveaux flux.',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 12,
color: Colors.blue.shade700,
color: AppColors.primary,
),
),
),
@@ -247,11 +247,11 @@ class StreamingSettingsTab extends ConsumerWidget {
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(icon, size: 20, color: Colors.blueAccent),
Icon(icon, size: 20, color: AppColors.primaryContainer),
const SizedBox(width: 8),
Text(
title,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
@@ -278,11 +278,11 @@ class StreamingSettingsTab extends ConsumerWidget {
return ListTile(
title: Text(
title,
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
),
subtitle: Text(
subtitle,
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
),
trailing: DropdownButton<T>(
value: value,
@@ -293,12 +293,12 @@ class StreamingSettingsTab extends ConsumerWidget {
value: item,
child: Text(
labelBuilder(item),
style: GoogleFonts.inter(fontSize: 13, color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(fontSize: 13, color: AppColors.onSurface),
),
);
}).toList(),
onChanged: onChanged,
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
iconEnabledColor: AppColors.onSurfaceVariant,
),
);
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -124,7 +124,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
const SizedBox(height: 24),
Text(
'XtremFlow',
style: GoogleFonts.spaceGrotesk(
style: GoogleFonts.syne(
fontSize: 32,
fontWeight: FontWeight.w700,
color: AppColors.onSurface,
@@ -133,7 +133,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
),
Text(
'Mobile Edition',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
color: AppColors.onSurfaceVariant,
letterSpacing: 0.5,
@@ -173,7 +173,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
),
child: Text(
authState.errorMessage!,
style: GoogleFonts.inter(color: AppColors.error, fontSize: 13),
style: GoogleFonts.instrumentSans(color: AppColors.error, fontSize: 13),
textAlign: TextAlign.center,
),
),
@@ -213,7 +213,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
)
: Text(
'Sign In',
style: GoogleFonts.inter(fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white),
style: GoogleFonts.instrumentSans(fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white),
),
),
),
@@ -243,10 +243,10 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
return TextFormField(
controller: controller,
obscureText: obscureText,
style: GoogleFonts.inter(color: AppColors.onSurface),
style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
decoration: InputDecoration(
labelText: label,
labelStyle: GoogleFonts.inter(color: AppColors.onSurfaceVariant),
labelStyle: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
prefixIcon: Icon(icon, color: AppColors.onSurfaceVariant),
suffixIcon: isPassword
? IconButton(
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../../features/iptv/providers/xtream_provider.dart';
@@ -70,7 +70,7 @@ class MobilePlaylistSelectionScreen extends ConsumerWidget {
color: AppColors.error,
),
const SizedBox(height: 16),
Text('Error loading playlists', style: GoogleFonts.inter()),
Text('Error loading playlists', style: GoogleFonts.instrumentSans()),
TextButton(
onPressed: () => ref.refresh(playlistsProvider),
child: const Text('Retry'),
@@ -92,7 +92,7 @@ class MobilePlaylistSelectionScreen extends ConsumerWidget {
const SizedBox(height: 16),
Text(
'No playlists available',
style: GoogleFonts.inter(color: AppColors.textSecondary),
style: GoogleFonts.instrumentSans(color: AppColors.textSecondary),
),
],
),
@@ -177,7 +177,7 @@ class _MobilePlaylistCard extends StatelessWidget {
children: [
Text(
playlist.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
@@ -188,7 +188,7 @@ class _MobilePlaylistCard extends StatelessWidget {
const SizedBox(height: 4),
Text(
Uri.tryParse(playlist.dns)?.host ?? playlist.dns,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 13,
color: AppColors.textSecondary,
),
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -110,7 +110,7 @@ class _MobileSeriesDetailScreenState
const SizedBox(height: 16),
Text(
'Error: $_error',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant),
style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
),
TextButton(
onPressed: _loadSeriesInfo,
@@ -186,7 +186,7 @@ class _MobileSeriesDetailScreenState
children: [
Text(
_seriesInfo!.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 24,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -204,7 +204,7 @@ class _MobileSeriesDetailScreenState
const SizedBox(width: 4),
Text(
_formatRating(_seriesInfo!.rating!)!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant,
fontSize: 13,
),
@@ -213,7 +213,7 @@ class _MobileSeriesDetailScreenState
],
Text(
'${_seriesInfo!.episodes.keys.length} Seasons',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant,
fontSize: 13,
),
@@ -235,7 +235,7 @@ class _MobileSeriesDetailScreenState
padding: const EdgeInsets.all(16.0),
child: Text(
_seriesInfo!.plot!,
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, height: 1.4),
style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, height: 1.4),
maxLines: 4,
overflow: TextOverflow.ellipsis,
),
@@ -262,7 +262,7 @@ class _MobileSeriesDetailScreenState
},
backgroundColor: AppColors.surfaceContainer,
selectedColor: AppColors.primary,
labelStyle: GoogleFonts.inter(
labelStyle: GoogleFonts.instrumentSans(
color: isSelected ? AppColors.onPrimary : AppColors.onSurfaceVariant,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
),
@@ -357,7 +357,7 @@ class _MobileSeriesDetailScreenState
children: [
Text(
'E${episode.episodeNum} - ${episode.title}',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
@@ -369,7 +369,7 @@ class _MobileSeriesDetailScreenState
episode.durationSecs! > 0)
Text(
_formatDuration(episode.durationSecs!),
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant,
fontSize: 12,
),
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../../../features/iptv/providers/xtream_provider.dart';
@@ -80,7 +80,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
const SizedBox(height: 16),
Text(
'Failed to load channels',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
@@ -153,11 +153,11 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
Expanded(
child: TextField(
controller: _searchController,
style: GoogleFonts.inter(color: Colors.white),
style: GoogleFonts.instrumentSans(color: Colors.white),
decoration: InputDecoration(
hintText: 'Search channels...',
hintStyle:
GoogleFonts.inter(color: Colors.white54),
GoogleFonts.instrumentSans(color: Colors.white54),
border: InputBorder.none,
prefixIcon: const Icon(
Icons.search,
@@ -207,7 +207,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
),
child: Text(
category,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color:
isSelected ? Colors.black : Colors.white70,
fontWeight: isSelected
@@ -233,7 +233,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
: _showFavoritesOnly
? 'Favorites'
: _selectedCategory ?? 'Channels',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
@@ -285,7 +285,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
const SizedBox(height: 16),
Text(
'No channels found',
style: GoogleFonts.inter(color: Colors.white38),
style: GoogleFonts.instrumentSans(color: Colors.white38),
),
],
),
@@ -382,7 +382,7 @@ class _MobileChannelTile extends StatelessWidget {
Expanded(
child: Text(
channel.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 14,
@@ -1,4 +1,4 @@
import 'dart:async';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -180,7 +180,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
id: m.streamId,
title: m.name,
imageUrl: _getProxiedImageUrl(m.streamIcon, ref),
subtitle: m.rating != null ? '${_formatRating(m.rating)} ★' : null,
subtitle: m.rating != null ? '${_formatRating(m.rating)} ★' : null,
onMoreInfo: () => _playMovie(m, displayMovies),
),
)
@@ -206,13 +206,13 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
Expanded(
child: TextField(
controller: _searchController,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
color: AppColors.onSurface,
),
decoration: InputDecoration(
hintText: 'Search Movies...',
hintStyle: GoogleFonts.inter(color: AppColors.onSurfaceVariant),
hintStyle: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
border: InputBorder.none,
isDense: true,
contentPadding: const EdgeInsets.only(bottom: 11),
@@ -346,7 +346,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
children: [
Text(
movie.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontSize: 13,
fontWeight: FontWeight.w600,
@@ -357,7 +357,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
if (isWatched)
Text(
'WATCHED',
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.primary,
fontSize: 10,
fontWeight: FontWeight.bold,
@@ -389,7 +389,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
const SizedBox(width: 4),
Text(
_formatRating(movie.rating)!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 10,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -1,4 +1,4 @@
import 'dart:async';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -171,7 +171,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
id: s.seriesId.toString(),
title: s.name,
imageUrl: _getProxiedImageUrl(s.cover, ref),
subtitle: s.rating != null ? '${_formatRating(s.rating)} ★' : null,
subtitle: s.rating != null ? '${_formatRating(s.rating)} ★' : null,
onMoreInfo: () => _openSeries(s),
),
)
@@ -197,13 +197,13 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
Expanded(
child: TextField(
controller: _searchController,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
color: AppColors.onSurface,
),
decoration: InputDecoration(
hintText: 'Search Series...',
hintStyle: GoogleFonts.inter(color: AppColors.onSurfaceVariant),
hintStyle: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
border: InputBorder.none,
isDense: true,
contentPadding: const EdgeInsets.only(bottom: 11),
@@ -332,7 +332,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
right: 12,
child: Text(
series.name,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
color: AppColors.onSurface,
fontSize: 13,
fontWeight: FontWeight.w600,
@@ -364,7 +364,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
const SizedBox(width: 4),
Text(
_formatRating(series.rating)!,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 10,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -398,7 +398,7 @@ class _SectionHeader extends StatelessWidget {
padding: const EdgeInsets.only(left: 8, bottom: 8),
child: Text(
title,
style: GoogleFonts.inter(
style: GoogleFonts.instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.onSurfaceVariant,
+17 -17
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../core/theme/app_colors.dart';
@@ -32,69 +32,69 @@ class MobileTheme {
// Typography: Scaled down for mobile
textTheme: TextTheme(
displayLarge: GoogleFonts.spaceGrotesk(
displayLarge: GoogleFonts.syne(
fontSize: 32,
fontWeight: FontWeight.w700,
letterSpacing: -0.02,
height: 1.1,
color: AppColors.onSurface,
),
displayMedium: GoogleFonts.spaceGrotesk(
displayMedium: GoogleFonts.syne(
fontSize: 28,
fontWeight: FontWeight.w600,
letterSpacing: -0.01,
height: 1.2,
color: AppColors.onSurface,
),
displaySmall: GoogleFonts.spaceGrotesk(
displaySmall: GoogleFonts.syne(
fontSize: 22,
fontWeight: FontWeight.w500,
height: 1.3,
color: AppColors.onSurface,
),
headlineMedium: GoogleFonts.spaceGrotesk(
headlineMedium: GoogleFonts.syne(
fontSize: 20,
fontWeight: FontWeight.w500,
height: 1.3,
color: AppColors.onSurface,
),
titleLarge: GoogleFonts.spaceGrotesk(
titleLarge: GoogleFonts.syne(
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
),
titleMedium: GoogleFonts.inter(
titleMedium: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
),
bodyLarge: GoogleFonts.inter(
bodyLarge: GoogleFonts.instrumentSans(
fontSize: 16,
fontWeight: FontWeight.w400,
height: 1.5,
color: AppColors.onSurfaceVariant,
),
bodyMedium: GoogleFonts.inter(
bodyMedium: GoogleFonts.instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w400,
height: 1.5,
color: AppColors.onSurfaceVariant,
),
labelLarge: GoogleFonts.inter(
labelLarge: GoogleFonts.instrumentSans(
fontSize: 14,
fontWeight: FontWeight.w600,
letterSpacing: 0.05,
height: 1.2,
color: AppColors.onSurface,
),
labelMedium: GoogleFonts.inter(
labelMedium: GoogleFonts.instrumentSans(
fontSize: 12,
fontWeight: FontWeight.w500,
letterSpacing: 0.02,
height: 1.2,
color: AppColors.onSurface,
),
labelSmall: GoogleFonts.inter(
labelSmall: GoogleFonts.instrumentSans(
fontSize: 11,
fontWeight: FontWeight.w500,
letterSpacing: 0.02,
@@ -110,7 +110,7 @@ class MobileTheme {
elevation: 0,
centerTitle: true,
scrolledUnderElevation: 0,
titleTextStyle: GoogleFonts.spaceGrotesk(
titleTextStyle: GoogleFonts.syne(
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
@@ -122,11 +122,11 @@ class MobileTheme {
backgroundColor: AppColors.surfaceContainerLow.withOpacity(0.9),
selectedItemColor: AppColors.onSurface,
unselectedItemColor: AppColors.outline,
selectedLabelStyle: GoogleFonts.inter(
selectedLabelStyle: GoogleFonts.instrumentSans(
fontSize: 11,
fontWeight: FontWeight.w600,
),
unselectedLabelStyle: GoogleFonts.inter(
unselectedLabelStyle: GoogleFonts.instrumentSans(
fontSize: 11,
fontWeight: FontWeight.w500,
),
@@ -157,7 +157,7 @@ class MobileTheme {
width: 2,
),
),
hintStyle: GoogleFonts.inter(
hintStyle: GoogleFonts.instrumentSans(
color: AppColors.outline,
fontSize: 14,
),
@@ -173,7 +173,7 @@ class MobileTheme {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radiusMd),
),
textStyle: GoogleFonts.inter(
textStyle: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600,
fontSize: 14,
),
+3 -3
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../core/theme/app_colors.dart';
@@ -60,9 +60,9 @@ class MobileScaffold extends ConsumerWidget {
selectedItemColor: AppColors.primary,
unselectedItemColor: AppColors.textSecondary,
selectedLabelStyle:
GoogleFonts.inter(fontWeight: FontWeight.w600, fontSize: 11),
GoogleFonts.instrumentSans(fontWeight: FontWeight.w600, fontSize: 11),
unselectedLabelStyle:
GoogleFonts.inter(fontWeight: FontWeight.w500, fontSize: 11),
GoogleFonts.instrumentSans(fontWeight: FontWeight.w500, fontSize: 11),
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.live_tv_rounded),
+4 -4
View File
@@ -27,7 +27,7 @@
}
body {
background: linear-gradient(135deg, #0F1014 0%, #181920 100%);
background: linear-gradient(135deg, #0B0A08 0%, #1B1812 100%);
display: flex;
justify-content: center;
align-items: center;
@@ -55,7 +55,7 @@
.logo {
font-size: 48px;
font-weight: 700;
background: linear-gradient(135deg, #007AFF 0%, #00C6FF 100%);
background: linear-gradient(135deg, #E8941A 0%, #FFC36A 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
@@ -67,8 +67,8 @@
width: 40px;
height: 40px;
margin: 0 auto 16px;
border: 3px solid rgba(0, 122, 255, 0.2);
border-top-color: #007AFF;
border: 3px solid rgba(243, 154, 31, 0.2);
border-top-color: #F39A1F;
border-radius: 50%;
animation: spin 1s linear infinite;
}
+9 -9
View File
@@ -1,14 +1,14 @@
/* XtremFlow web player theme tokens.
Mirrors lib/core/theme/app_colors.dart (Cyber-Cinematic Glass).
Mirrors lib/core/theme/app_colors.dart (Projector Noir).
Keep both files in sync when the palette changes. */
:root {
--color-bg: #0F1014; /* AppColors.baseLevel0 */
--color-surface: #121317; /* AppColors.surface */
--color-text: #e3e2e7; /* AppColors.textPrimary */
--color-text-secondary: #c1c6d7;/* AppColors.textSecondary */
--color-accent: #adc6ff; /* AppColors.primary */
--color-accent-strong: #4b8eff; /* AppColors.primaryContainer */
--color-bg: #0B0A08; /* AppColors.baseLevel0 */
--color-surface: #14110C; /* AppColors.surface */
--color-text: #ECE6DA; /* AppColors.textPrimary */
--color-text-secondary: #CDC4B4;/* AppColors.textSecondary */
--color-accent: #FFB35C; /* AppColors.primary */
--color-accent-strong: #F39A1F; /* AppColors.primaryContainer */
--color-error: #ffb4ab; /* AppColors.error */
--color-overlay: rgba(15, 16, 20, 0.6);
--color-border: rgba(255, 255, 255, 0.1); /* glassLevel1Border */
--color-overlay: rgba(11, 10, 8, 0.6);
--color-border: rgba(255, 233, 201, 0.1); /* glassLevel1Border */
}