# ダークモード視認性ガイドライン

## 目的
ダークモード実装時に「背景と同化して見えない」問題を防ぐための開発ガイドラインです。

## 基本原則

### 1. **色の明示的指定**
❌ **NG**: `Theme.of(context).primaryColor` をダークモードで直接使用
```dart
// NG例: ダークモードでは #8AB4F6 になり、暗い背景で見えにくい
color: Theme.of(context).primaryColor
```

✅ **OK**: brightness チェックで明示的に明るい色を指定
```dart
// OK例: ダークモードでは明るい青 (#64B5F6) を使用
color: Theme.of(context).brightness == Brightness.dark
    ? const Color(0xFF64B5F6)  // より明るい青
    : Theme.of(context).primaryColor  // #376495
```

### 2. **推奨カラーパレット**

#### アクセント色（選択状態、重要なUI要素）
| 用途 | ライトモード | ダークモード |
|------|------------|------------|
| プライマリ（通常） | `#376495` (AppTheme.posimaiBlue) | `#64B5F6` (明るい青) |
| プライマリ（強調） | `AppTheme.posimaiBlue` | `#8AB4F6` (Theme.primaryColor) |
| チェックマーク | `Theme.primaryColor` | `#64B5F6` |
| 選択中チップ | `AppTheme.posimaiBlue` | `colorScheme.primary` (#8AB4F6) |

#### テキスト色
| 用途 | ライトモード | ダークモード |
|------|------------|------------|
| 本文 | `Colors.black87` | `Colors.white` |
| 副見出し | `Colors.grey[600]` | `Colors.grey[300]` |
| 薄い表示 | `Colors.grey[400]` | `Colors.grey[500]` |

#### 背景・ボーダー
| 用途 | ライトモード | ダークモード |
|------|------------|------------|
| カード背景 | `Colors.white` | `#1E1E1E` |
| ダイアログ背景 | `Colors.white` | `#2C2C2C` |
| ボーダー（通常） | `Colors.grey[300]` | `Colors.grey[700]` |
| ボーダー（強調） | `Colors.grey[400]` | `Colors.grey[600]` |

### 3. **コンポーネント別パターン**

#### ダイアログ選択肢（SimpleDialogOption）
```dart
Icon(
  isSelected ? Icons.check : Icons.circle_outlined,
  color: isSelected
      ? (Theme.of(context).brightness == Brightness.dark
          ? const Color(0xFF64B5F6)  // ダークモード用の明るい青
          : Theme.of(context).primaryColor)
      : Colors.grey[400],
)
```

#### FilterChip（フィルタチップ）
```dart
FilterChip(
  selected: isSelected,
  selectedColor: Theme.of(context).brightness == Brightness.dark
      ? colorScheme.primary  // #8AB4F6
      : AppTheme.posimaiBlue,
  side: isSelected
      ? BorderSide(
          color: Theme.of(context).brightness == Brightness.dark
              ? colorScheme.primary
              : AppTheme.posimaiBlue,
          width: 1.5,
        )
      : null,
  // 非選択時の明示的なスタイル指定
  backgroundColor: isDark
      ? Colors.grey[800]?.withValues(alpha: 0.5)
      : null,
  side: BorderSide(
    color: isDark
        ? Colors.grey[700]!
        : colorScheme.outline.withValues(alpha: 0.5),
  ),
)
```

#### ボタン（AlertDialog内のElevatedButton）
```dart
ElevatedButton(
  style: ElevatedButton.styleFrom(
    // ダークモードでも見えるよう固定色を使用
    backgroundColor: AppTheme.posimaiBlue,  // #376495
    foregroundColor: Colors.white,
  ),
  child: const Text('確認'),
)
```

#### SnackBar
```dart
SnackBar(
  content: Text(
    'メッセージ',
    style: TextStyle(
      color: isDark ? Colors.white : Colors.white,  // 明示的に白を指定
    ),
  ),
  backgroundColor: isDark
      ? const Color(0xFF2C2C2C)  // ダーク背景
      : Colors.grey[850],
  behavior: SnackBarBehavior.floating,
)
```

#### バッジカウンター
```dart
Container(
  decoration: BoxDecoration(
    color: Theme.of(context).brightness == Brightness.dark
        ? const Color(0xFF64B5F6).withValues(alpha: 0.15)
        : Theme.of(context).primaryColor.withValues(alpha: 0.1),
    border: Border.all(
      color: Theme.of(context).brightness == Brightness.dark
          ? const Color(0xFF64B5F6).withValues(alpha: 0.4)
          : Theme.of(context).primaryColor.withValues(alpha: 0.3),
    ),
  ),
  child: Text(
    '2 / 3',
    style: TextStyle(
      color: Theme.of(context).brightness == Brightness.dark
          ? const Color(0xFF64B5F6)
          : Theme.of(context).primaryColor,
    ),
  ),
)
```

## 開発時のチェックリスト

### 新機能実装時
- [ ] ライトモードで表示確認
- [ ] **ダークモードで表示確認（必須）**
- [ ] 以下の要素が見えるか確認：
  - [ ] テキスト（タイトル、本文、ラベル）
  - [ ] アイコン（選択状態、非選択状態）
  - [ ] ボーダー・区切り線
  - [ ] ボタン（通常、選択、無効）
  - [ ] カウンター・バッジ表示

### コードレビュー時
- [ ] `Theme.of(context).primaryColor` の使用箇所でbrightness チェックがあるか
- [ ] `const TextStyle()` に明示的な color 指定があるか
- [ ] `Colors.grey` のような曖昧な色ではなく、明示的な階調（`Colors.grey[300]`等）を使用しているか

## よくある問題と解決策

### 問題1: チェックマークが見えない
**原因**: `Theme.of(context).primaryColor` がダークモードで薄くなる
**解決**: 明示的に `#64B5F6` を指定

### 問題2: バッジカウンターが見えない
**原因**: 背景色とテキスト色のコントラストが不足
**解決**: ダークモード用に明るい色 (`#64B5F6`) とアルファ値を調整した背景を使用

### 問題3: ボタンが見えない
**原因**: `Theme.of(context).primaryColor` が背景と同化
**解決**: 固定色 `AppTheme.posimaiBlue` (#376495) を使用

### 問題4: SnackBarメッセージが読めない
**原因**: テキスト色が明示されておらず、デフォルトが暗い色になる
**解決**: `color: Colors.white` を明示的に指定

## 色のコントラスト比基準

WCAG 2.1 AA基準（最低限）:
- 通常テキスト: **4.5:1** 以上
- 大きいテキスト（18pt以上、14pt太字以上）: **3:1** 以上

推奨ツール:
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
- [Coolors Contrast Checker](https://coolors.co/contrast-checker)

## 実装例リファレンス

実装済みファイル:
- `lib/screens/soul_screen.dart`: ダイアログチェックマーク
- `lib/widgets/gamification/badge_case.dart`: バッジカウンター
- `lib/widgets/settings/backup_settings_section.dart`: ダイアログボタン
- `lib/screens/camera_screen.dart`: SnackBarメッセージ
- `lib/widgets/home/sake_filter_chips.dart`: フィルタチップ

---

**更新日**: 2026-01-18
**バージョン**: 1.0
