diff --git a/DESIGN.md b/DESIGN.md
index 1951e09d..a6fe2095 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -40,14 +40,14 @@ RoastPlus の主軸は「現場オペレーション重視」です。明るく
優先順位は次の順に固定します。
-| 優先 | 原則 | 内容 |
-|------|------|------|
-| 1 | 現場で迷わない | 画面を開いた瞬間に、今の状態と次の操作が分かる。 |
-| 2 | ページごとの型を揃える | 同じ目的の画面は、ヘッダー、余白、最大幅、主要アクション位置、空状態を揃える。 |
-| 3 | iPadで押しやすい | 現場iPad、タブレット、補助端末でのPWA利用を前提にし、44px以上のタッチ領域を確保する。 |
-| 4 | 情報が一目で読める | 時間、担当、状態、次アクションは本文より強く見せる。 |
-| 5 | コーヒーらしさは控えめに効かせる | コーヒーらしい色や演出は、業務理解を邪魔しない範囲で使う。 |
-| 6 | 毎日使って疲れない | 強いアニメーション、過度なグラデーション、重い装飾は限定する。 |
+| 優先 | 原則 | 内容 |
+| ---- | -------------------------------- | ------------------------------------------------------------------------------------- |
+| 1 | 現場で迷わない | 画面を開いた瞬間に、今の状態と次の操作が分かる。 |
+| 2 | ページごとの型を揃える | 同じ目的の画面は、ヘッダー、余白、最大幅、主要アクション位置、空状態を揃える。 |
+| 3 | iPadで押しやすい | 現場iPad、タブレット、補助端末でのPWA利用を前提にし、44px以上のタッチ領域を確保する。 |
+| 4 | 情報が一目で読める | 時間、担当、状態、次アクションは本文より強く見せる。 |
+| 5 | コーヒーらしさは控えめに効かせる | コーヒーらしい色や演出は、業務理解を邪魔しない範囲で使う。 |
+| 6 | 毎日使って疲れない | 強いアニメーション、過度なグラデーション、重い装飾は限定する。 |
---
@@ -55,14 +55,14 @@ RoastPlus の主軸は「現場オペレーション重視」です。明るく
RoastPlus のページは、見た目ではなく「ユーザーが何をする画面か」で分類します。新しい画面を作るときは、まずこの6タイプのどれに当たるかを決めます。
-| タイプ | 主な用途 | 対象ページ例 | 推奨レイアウト | ヘッダー | 最大幅 | 主要アクション位置 | 使う共通UI | 避けること |
-|--------|----------|--------------|----------------|----------|--------|--------------------|------------|------------|
-| ホーム / ハブ | 機能選択 | ホーム | 2列中心の機能カード | ブランドヘッダー | `max-w-6xl` | カード全体を入口にする | `Card`, `ActionCard` | カード内説明を増やしすぎる |
-| 一覧 / 管理 | 探す、追加、編集 | 担当表、スケジュール、欠点豆、生産記録、試飲一覧 | iPadではカード、広い画面はテーブルやグリッド | `FloatingNav` + タイトル | `max-w-4xl` から `max-w-7xl` | 上部右側、または下部固定 | `Card`, `Button`, `Tabs`, `EmptyState` | 検索、絞り込み、追加を離れた場所に置く |
-| フォーム / 編集 | 入力して保存 | レシピ作成、試飲作成、設定入力、お問い合わせ | 縦積みフォーム | `FloatingNav` + タイトル | `max-w-2xl` または `max-w-lg` | 下部、右下、固定フッターのいずれか | `Input`, `Textarea`, `Select`, `Button`, `Card` | 危険操作を保存ボタンの近くに置く |
-| 集中操作 / 実行 | 作業中に状態と次操作を見る | ドリップガイド、時計 | 固定または準固定画面 | 最小ナビ、固定ヘッダー | 画面全体 | 下部操作、中央に主要状態 | `Button`, `IconButton`, `ProgressBar` | 説明文やカードを増やしすぎる |
-| 詳細 / 参照 | 読む、判断材料を見る | 欠点豆詳細、開発秘話、規約、履歴詳細 | 読み物レイアウト | `FloatingNav` + タイトル | `max-w-3xl` 前後 | 必要な場合のみ本文末尾 | `Card`, `Badge`, `Accordion` | 操作ボタンを主役にする |
-| モーダル / 確認 | 短い判断、設定、確認 | 削除確認、フィルター、OCR確認、詳細設定 | 中央ダイアログ、またはモバイル下寄せ | モーダル内タイトル | `max-w-sm` から `max-w-md` | 下部にキャンセル、実行 | `Modal`, `Dialog`, `Button` | 長い内容や複雑な設定を詰め込む |
+| タイプ | 主な用途 | 対象ページ例 | 推奨レイアウト | ヘッダー | 最大幅 | 主要アクション位置 | 使う共通UI | 避けること |
+| --------------- | -------------------------- | ------------------------------------------------ | -------------------------------------------- | ------------------------ | ----------------------------- | ---------------------------------- | ----------------------------------------------- | -------------------------------------- |
+| ホーム / ハブ | 機能選択 | ホーム | 2列中心の機能カード | ブランドヘッダー | `max-w-6xl` | カード全体を入口にする | `Card`, `ActionCard` | カード内説明を増やしすぎる |
+| 一覧 / 管理 | 探す、追加、編集 | 担当表、スケジュール、欠点豆、生産記録、試飲一覧 | iPadではカード、広い画面はテーブルやグリッド | `FloatingNav` + タイトル | `max-w-4xl` から `max-w-7xl` | 上部右側、または下部固定 | `Card`, `Button`, `Tabs`, `EmptyState` | 検索、絞り込み、追加を離れた場所に置く |
+| フォーム / 編集 | 入力して保存 | レシピ作成、試飲作成、設定入力、お問い合わせ | 縦積みフォーム | `FloatingNav` + タイトル | `max-w-2xl` または `max-w-lg` | 下部、右下、固定フッターのいずれか | `Input`, `Textarea`, `Select`, `Button`, `Card` | 危険操作を保存ボタンの近くに置く |
+| 集中操作 / 実行 | 作業中に状態と次操作を見る | ドリップガイド、時計 | 固定または準固定画面 | 最小ナビ、固定ヘッダー | 画面全体 | 下部操作、中央に主要状態 | `Button`, `IconButton`, `ProgressBar` | 説明文やカードを増やしすぎる |
+| 詳細 / 参照 | 読む、判断材料を見る | 欠点豆詳細、開発秘話、規約、履歴詳細 | 読み物レイアウト | `FloatingNav` + タイトル | `max-w-3xl` 前後 | 必要な場合のみ本文末尾 | `Card`, `Badge`, `Accordion` | 操作ボタンを主役にする |
+| モーダル / 確認 | 短い判断、設定、確認 | 削除確認、フィルター、OCR確認、詳細設定 | 中央ダイアログ、またはモバイル下寄せ | モーダル内タイトル | `max-w-sm` から `max-w-md` | 下部にキャンセル、実行 | `Modal`, `Dialog`, `Button` | 長い内容や複雑な設定を詰め込む |
---
@@ -117,83 +117,83 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ
### 5.2 テーマ概要
-| 項目 | 内容 |
-|------|------|
-| テーマ数 | 7テーマ(`default`, `christmas`, `dark-roast`, `light-roast`, `matcha`, `caramel`, `dark`) |
-| テーマ切替方法 | `` でCSS変数が自動切替 |
-| カラー方針 | セマンティックトークン必須。ハードコードカラーは禁止 |
-| スタイリング | Tailwind CSS v4 + CSS変数 |
+| 項目 | 内容 |
+| -------------- | ------------------------------------------------------------------------------------------- |
+| テーマ数 | 7テーマ(`default`, `christmas`, `dark-roast`, `light-roast`, `matcha`, `caramel`, `dark`) |
+| テーマ切替方法 | `` でCSS変数が自動切替 |
+| カラー方針 | セマンティックトークン必須。ハードコードカラーは禁止 |
+| スタイリング | Tailwind CSS v4 + CSS変数 |
### 5.3 背景色
-| Tailwindクラス | CSS変数 | default値 | 用途 |
-|--------------|---------|-----------|------|
-| `bg-page` | `--page` | `#F7F7F5` | ページ全体背景 |
-| `bg-surface` | `--surface` | `#FFFFFF` | カード・セクション背景 |
-| `bg-overlay` | `--overlay` | `#FFFFFF` | モーダル・ダイアログ。不透明必須 |
-| `bg-ground` | `--ground` | `#F5F5F5` | テーブルヘッダー・セクション背景 |
-| `bg-field` | `--field` | `#FFFFFF` | 入力フィールド背景 |
-| `bg-spot` | `--spot` | `#E48003` | アクセント背景 |
-| `bg-spot-subtle` | `--spot-subtle` | `#f0f0f0` | アクセント薄背景 |
-| `bg-spot-surface` | `--spot-surface` | `#f7f7f7` | アクセント極薄背景 |
-| `bg-btn-primary` | `--btn-primary` | `#E48003` | プライマリボタン背景 |
-| `bg-btn-primary-hover` | `--btn-primary-hover` | `#C56604` | プライマリボタンホバー |
-| `bg-header-bg` | `--header-bg` | `#261a14` | ヘッダー背景 |
+| Tailwindクラス | CSS変数 | default値 | 用途 |
+| ---------------------- | --------------------- | --------- | -------------------------------- |
+| `bg-page` | `--page` | `#F7F7F5` | ページ全体背景 |
+| `bg-surface` | `--surface` | `#FFFFFF` | カード・セクション背景 |
+| `bg-overlay` | `--overlay` | `#FFFFFF` | モーダル・ダイアログ。不透明必須 |
+| `bg-ground` | `--ground` | `#F5F5F5` | テーブルヘッダー・セクション背景 |
+| `bg-field` | `--field` | `#FFFFFF` | 入力フィールド背景 |
+| `bg-spot` | `--spot` | `#E48003` | アクセント背景 |
+| `bg-spot-subtle` | `--spot-subtle` | `#f0f0f0` | アクセント薄背景 |
+| `bg-spot-surface` | `--spot-surface` | `#f7f7f7` | アクセント極薄背景 |
+| `bg-btn-primary` | `--btn-primary` | `#E48003` | プライマリボタン背景 |
+| `bg-btn-primary-hover` | `--btn-primary-hover` | `#C56604` | プライマリボタンホバー |
+| `bg-header-bg` | `--header-bg` | `#261a14` | ヘッダー背景 |
### 5.4 テキスト色
-| Tailwindクラス | CSS変数 | default値 | 用途 |
-|--------------|---------|-----------|------|
-| `text-ink` | `--ink` | `#1f2937` | メインテキスト |
-| `text-ink-sub` | `--ink-sub` | `#4b5563` | 補助テキスト・説明文 |
-| `text-ink-muted` | `--ink-muted` | `#9ca3af` | プレースホルダー・薄いテキスト |
-| `text-spot` | `--spot` | `#E48003` | アクセントテキスト |
-| `text-spot-hover` | `--spot-hover` | `#C56604` | アクセントホバー |
-| `text-header-text` | `--header-text` | `#FFFFFF` | ヘッダーテキスト |
-| `text-header-accent` | `--header-accent` | `#EF8A00` | ヘッダーアクセント |
-| `text-danger` | `--danger` | `#dc2626` | エラー・削除 |
-| `text-success` | `--success` | `#16a34a` | 成功 |
-| `text-warning` | `--warning` | `#eab308` | 警告 |
-| `text-info` | `--info` | `#00b8d4` | 情報 |
-| `text-error` | `--error` | `#ef4444` | エラーテキスト |
+| Tailwindクラス | CSS変数 | default値 | 用途 |
+| -------------------- | ----------------- | --------- | ------------------------------ |
+| `text-ink` | `--ink` | `#1f2937` | メインテキスト |
+| `text-ink-sub` | `--ink-sub` | `#4b5563` | 補助テキスト・説明文 |
+| `text-ink-muted` | `--ink-muted` | `#9ca3af` | プレースホルダー・薄いテキスト |
+| `text-spot` | `--spot` | `#E48003` | アクセントテキスト |
+| `text-spot-hover` | `--spot-hover` | `#C56604` | アクセントホバー |
+| `text-header-text` | `--header-text` | `#FFFFFF` | ヘッダーテキスト |
+| `text-header-accent` | `--header-accent` | `#EF8A00` | ヘッダーアクセント |
+| `text-danger` | `--danger` | `#dc2626` | エラー・削除 |
+| `text-success` | `--success` | `#16a34a` | 成功 |
+| `text-warning` | `--warning` | `#eab308` | 警告 |
+| `text-info` | `--info` | `#00b8d4` | 情報 |
+| `text-error` | `--error` | `#ef4444` | エラーテキスト |
### 5.5 ボーダー色
-| Tailwindクラス | CSS変数 | default値 | 用途 |
-|--------------|---------|-----------|------|
-| `border-edge` | `--edge` | `#e5e7eb` | 通常ボーダー |
+| Tailwindクラス | CSS変数 | default値 | 用途 |
+| -------------------- | --------------- | --------- | -------------------- |
+| `border-edge` | `--edge` | `#e5e7eb` | 通常ボーダー |
| `border-edge-strong` | `--edge-strong` | `#d1d5db` | 強調ボーダー・ホバー |
-| `border-edge-subtle` | `--edge-subtle` | `#f3f4f6` | 薄いボーダー |
-| `border-error` | `--error` | `#ef4444` | エラーボーダー |
+| `border-edge-subtle` | `--edge-subtle` | `#f3f4f6` | 薄いボーダー |
+| `border-error` | `--error` | `#ef4444` | エラーボーダー |
### 5.6 ステータス薄背景
-| Tailwindクラス | default値 | 用途 |
-|--------------|-----------|------|
-| `bg-danger-subtle` | `#fee2e2` | エラー薄背景 |
-| `bg-success-subtle` | `#dcfce7` | 成功薄背景 |
-| `bg-warning-subtle` | `#fef9c3` | 警告薄背景 |
+| Tailwindクラス | default値 | 用途 |
+| ------------------- | --------- | ------------ |
+| `bg-danger-subtle` | `#fee2e2` | エラー薄背景 |
+| `bg-success-subtle` | `#dcfce7` | 成功薄背景 |
+| `bg-warning-subtle` | `#fef9c3` | 警告薄背景 |
### 5.7 シャドウ
-| クラス | 用途 |
-|--------|------|
-| `shadow-card` | カード通常シャドウ |
+| クラス | 用途 |
+| ------------------- | -------------------- |
+| `shadow-card` | カード通常シャドウ |
| `shadow-card-hover` | カードホバーシャドウ |
-| `shadow-card-glow` | 薄いシャドウ |
+| `shadow-card-glow` | 薄いシャドウ |
### 5.8 ブランド固定色
ブランド固定色は、通常画面では乱用しません。ロゴ、ホーム、テーマプレビュー、コーヒーらしい強調に限定します。
-| Tailwindクラス | 値 | 用途 |
-|--------------|-----|------|
+| Tailwindクラス | 値 | 用途 |
+| ----------------------------- | --------- | ---------------- |
| `text-primary` / `bg-primary` | `#EF8A00` | ブランドオレンジ |
-| `bg-primary-dark` | `#D67A00` | ダークオレンジ |
-| `text-primary-light` | `#FF9A1A` | ライトオレンジ |
-| `bg-dark` | `#211714` | ダークブラウン |
-| `bg-dark-light` | `#3A2F2B` | ライトブラウン |
-| `text-gold` | `#FFC107` | ゴールド |
+| `bg-primary-dark` | `#D67A00` | ダークオレンジ |
+| `text-primary-light` | `#FF9A1A` | ライトオレンジ |
+| `bg-dark` | `#211714` | ダークブラウン |
+| `bg-dark-light` | `#3A2F2B` | ライトブラウン |
+| `text-gold` | `#FFC107` | ゴールド |
### 5.9 カードヘッダーグラデーション
@@ -213,54 +213,82 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ
### 6.1 用途別の基本形
-| 用途 | 推奨クラス | 使う場所 |
-|------|------------|----------|
-| ページタイトル | `text-xl sm:text-2xl font-bold text-ink` | 通常ページのタイトル |
-| セクション見出し | `text-lg font-semibold text-ink` | カード内やフォーム区切り |
-| 本文 | `text-base text-ink` | 説明、本文 |
-| 補助文 | `text-sm text-ink-sub` | 説明、注記 |
-| ラベル | `text-xs font-medium text-ink-muted` | バッジ、補足情報 |
-| 大きな数値 | `text-3xl` から `text-4xl font-bold` | タイマー、進捗数値 |
+| 用途 | 推奨クラス | 使う場所 |
+| ---------------- | ---------------------------------------- | ------------------------ |
+| ページタイトル | `text-xl sm:text-2xl font-bold text-ink` | 通常ページのタイトル |
+| セクション見出し | `text-lg font-semibold text-ink` | カード内やフォーム区切り |
+| 本文 | `text-base text-ink` | 説明、本文 |
+| 補助文 | `text-sm text-ink-sub` | 説明、注記 |
+| ラベル | `text-xs font-medium text-ink-muted` | バッジ、補足情報 |
+| 大きな数値 | `text-3xl` から `text-4xl font-bold` | タイマー、進捗数値 |
### 6.2 フォントサイズ
-| クラス | px換算 | 主な用途 |
-|--------|--------|---------|
-| `text-xs` | 12px | バッジ・ラベル・補足情報 |
-| `text-sm` | 14px | 補助テキスト・フォームラベル |
-| `text-base` | 16px | 本文 |
-| `text-lg` | 18px | セクション見出し |
-| `text-xl` | 20px | ページタイトル(モバイル) |
-| `text-2xl` | 24px | ページタイトル(デスクトップ) |
-| `text-3xl` | 30px | 大きな数値 |
-| `text-4xl` | 36px | タイマーなどのヒーロー数値 |
+| クラス | px換算 | 主な用途 |
+| ----------- | ------ | ------------------------------ |
+| `text-xs` | 12px | バッジ・ラベル・補足情報 |
+| `text-sm` | 14px | 補助テキスト・フォームラベル |
+| `text-base` | 16px | 本文 |
+| `text-lg` | 18px | セクション見出し |
+| `text-xl` | 20px | ページタイトル(モバイル) |
+| `text-2xl` | 24px | ページタイトル(デスクトップ) |
+| `text-3xl` | 30px | 大きな数値 |
+| `text-4xl` | 36px | タイマーなどのヒーロー数値 |
### 6.3 フォントウェイト
-| クラス | 用途 |
-|--------|------|
-| `font-bold` | 見出し・強調 |
+| クラス | 用途 |
+| --------------- | ------------------------ |
+| `font-bold` | 見出し・強調 |
| `font-semibold` | サブ見出し・ボタンラベル |
-| `font-medium` | ラベル・タブ |
-| `font-normal` | 本文 |
+| `font-medium` | ラベル・タブ |
+| `font-normal` | 本文 |
-### 6.4 典型パターン
+### 6.4 フォントファミリー
-```tsx
-{/* ページタイトル */}
-
タイトル
+| クラス | フォント | 用途 |
+| ------------ | -------- | --------------------------------------------------------------------- |
+| (既定) | serif | 本文。`` の `font-serif` が効く |
+| `font-sans` | Inter 系 | サンセリフにしたい箇所 |
+| `font-brand` | Inter | ブランド表記(ホームのロゴ・スプラッシュ・ログイン/新規登録の見出し) |
+| `font-num` | Outfit | 数値表示 |
+| `font-mono` | 等幅 | コード・ID |
+
+ブランド表記は画面ごとに書体を変えず、`font-brand` に揃える。ロゴとタイトルで書体が違うと、同じアプリの画面に見えなくなる。
+
+書体を指定するときは、必ず上記のユーティリティクラスを使う。`font-` に CSS 変数を任意値として直接渡す書き方(角括弧・丸括弧のどちらの形でも)は、Tailwind v4 では **font-weight として解釈されて効かない**。font-family として扱わせるには `family-name:` の型ヒントが必要になる。
-{/* セクション見出し */}
-セクション名
+新しい書体を足すときは、クラス側で指定せず `app/globals.css` の `@theme` に `--font-*` を定義してユーティリティ化する。
-{/* 説明文 */}
-補足説明
+> なお Tailwind v4 は Markdown を含むプロジェクト内のファイルを走査してクラス名を拾うため、**このドキュメントや CSS のコメントに使っていないクラス名を書くと、未使用のCSSが生成される**。説明のために書くときは実在しない形に崩す。過去の計画・作業ログ(`docs/`・`.superpowers/`)は `app/globals.css` の `@source not` で除外済み。
-{/* 数値表示 */}
-00:00
+### 6.5 典型パターン
-{/* バッジ・ラベル */}
-ラベル
+```tsx
+{
+ /* ページタイトル */
+}
+タイトル
;
+
+{
+ /* セクション見出し */
+}
+セクション名
;
+
+{
+ /* 説明文 */
+}
+補足説明
;
+
+{
+ /* 数値表示 */
+}
+00:00;
+
+{
+ /* バッジ・ラベル */
+}
+ラベル;
```
---
@@ -271,58 +299,58 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ
### 7.1 基本スケール
-| 用途 | 推奨 |
-|------|------|
-| モバイル横余白 | `px-4` |
-| タブレット横余白 | `sm:px-6` |
-| 標準ページ | `max-w-4xl` |
-| フォーム | `max-w-2xl` または `max-w-lg` |
-| 詳細読み物 | `max-w-3xl` |
-| ホーム、広い一覧 | `max-w-6xl` から `max-w-7xl` |
-| カード内余白 | `p-4` から `p-6` |
-| セクション間 | `space-y-6` |
-| カード角丸 | `rounded-2xl` |
-| ボタン、入力 | `rounded-lg` |
+| 用途 | 推奨 |
+| ---------------- | ----------------------------- |
+| モバイル横余白 | `px-4` |
+| タブレット横余白 | `sm:px-6` |
+| 標準ページ | `max-w-4xl` |
+| フォーム | `max-w-2xl` または `max-w-lg` |
+| 詳細読み物 | `max-w-3xl` |
+| ホーム、広い一覧 | `max-w-6xl` から `max-w-7xl` |
+| カード内余白 | `p-4` から `p-6` |
+| セクション間 | `space-y-6` |
+| カード角丸 | `rounded-2xl` |
+| ボタン、入力 | `rounded-lg` |
### 7.2 垂直スペーシング
-| クラス | px | 用途 |
-|--------|----|------|
-| `space-y-2` | 8px | 密なリスト |
-| `space-y-4` | 16px | フォーム要素間 |
+| クラス | px | 用途 |
+| ----------- | ---- | -------------------- |
+| `space-y-2` | 8px | 密なリスト |
+| `space-y-4` | 16px | フォーム要素間 |
| `space-y-6` | 24px | セクション内グループ |
-| `space-y-8` | 32px | 主要セクション間 |
+| `space-y-8` | 32px | 主要セクション間 |
### 7.3 グリッド・フレックスギャップ
-| クラス | px | 用途 |
-|--------|----|------|
-| `gap-2` | 8px | アイコン+テキスト |
-| `gap-3` | 12px | モバイルグリッド |
+| クラス | px | 用途 |
+| ------- | ---- | -------------------- |
+| `gap-2` | 8px | アイコン+テキスト |
+| `gap-3` | 12px | モバイルグリッド |
| `gap-4` | 16px | デスクトップグリッド |
-| `gap-6` | 24px | 大きなグリッド |
+| `gap-6` | 24px | 大きなグリッド |
### 7.4 コンテナ余白
-| クラス | 値 | 用途 |
-|--------|----|------|
-| `px-4` | 16px | モバイル横余白 |
-| `sm:px-6` | 24px | タブレット横余白 |
-| `lg:px-8` | 32px | デスクトップ横余白 |
-| `py-4` | 16px | モバイル縦余白 |
-| `py-6` | 24px | タブレット縦余白 |
-| `p-4` | 16px | カード内余白 |
-| `p-6` | 24px | フォームカード内余白 |
+| クラス | 値 | 用途 |
+| --------- | ---- | -------------------- |
+| `px-4` | 16px | モバイル横余白 |
+| `sm:px-6` | 24px | タブレット横余白 |
+| `lg:px-8` | 32px | デスクトップ横余白 |
+| `py-4` | 16px | モバイル縦余白 |
+| `py-6` | 24px | タブレット縦余白 |
+| `p-4` | 16px | カード内余白 |
+| `p-6` | 24px | フォームカード内余白 |
### 7.5 角丸
-| クラス | px | 主な用途 |
-|--------|----|---------|
-| `rounded-lg` | 8px | ボタン・入力・小要素 |
-| `rounded-xl` | 12px | バッジ・中要素 |
-| `rounded-2xl` | 16px | カード・モーダル |
-| `rounded-3xl` | 24px | 大きな特殊要素 |
-| `rounded-full` | 50% | アイコンボタン・アバター・ピル型バッジ |
+| クラス | px | 主な用途 |
+| -------------- | ---- | -------------------------------------- |
+| `rounded-lg` | 8px | ボタン・入力・小要素 |
+| `rounded-xl` | 12px | バッジ・中要素 |
+| `rounded-2xl` | 16px | カード・モーダル |
+| `rounded-3xl` | 24px | 大きな特殊要素 |
+| `rounded-full` | 50% | アイコンボタン・アバター・ピル型バッジ |
---
@@ -339,20 +367,20 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ
### 8.2 使い分け
-| コンポーネント | 主な用途 | 注意 |
-|----------------|----------|------|
-| `Button` | 主要、補助、危険操作 | 主操作は1画面1つを目立たせる |
-| `IconButton` | 戻る、設定、閉じるなどの小操作 | 44px以上のタッチ領域を確保する |
-| `FloatingNav` | 通常ページの戻る導線 | ホームと集中画面では例外あり |
-| `Card` | 情報のまとまり | カードの入れ子は禁止 |
-| `Input`, `Textarea`, `Select` | フォーム入力 | ラベルと補足文を近くに置く |
-| `Checkbox`, `Switch` | ON/OFFや複数選択 | 生のinputを直接使わない |
-| セグメントコントロール | 3択以内の状態切替(「十分・残少・欠品」など) | `Tabs` との違い:ページコンテンツの切替ではなく値の状態変更に使う。`StatusToggle` パターン参照 |
-| `Modal` | 任意コンテンツのモーダル | `bg-overlay` 必須 |
-| `Dialog` | 確認ダイアログ | 削除は `danger` |
-| `Tabs` | 同階層の表示切替 | ページ遷移の代替にしすぎない |
-| `Accordion` | 補足情報の開閉 | 主要情報を隠しすぎない |
-| `EmptyState` | 空状態 | 次アクションを出す |
+| コンポーネント | 主な用途 | 注意 |
+| ----------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------- |
+| `Button` | 主要、補助、危険操作 | 主操作は1画面1つを目立たせる |
+| `IconButton` | 戻る、設定、閉じるなどの小操作 | 44px以上のタッチ領域を確保する |
+| `FloatingNav` | 通常ページの戻る導線 | ホームと集中画面では例外あり |
+| `Card` | 情報のまとまり | カードの入れ子は禁止 |
+| `Input`, `Textarea`, `Select` | フォーム入力 | ラベルと補足文を近くに置く |
+| `Checkbox`, `Switch` | ON/OFFや複数選択 | 生のinputを直接使わない |
+| セグメントコントロール | 3択以内の状態切替(「十分・残少・欠品」など) | `Tabs` との違い:ページコンテンツの切替ではなく値の状態変更に使う。`StatusToggle` パターン参照 |
+| `Modal` | 任意コンテンツのモーダル | `bg-overlay` 必須 |
+| `Dialog` | 確認ダイアログ | 削除は `danger` |
+| `Tabs` | 同階層の表示切替 | ページ遷移の代替にしすぎない |
+| `Accordion` | 補足情報の開閉 | 主要情報を隠しすぎない |
+| `EmptyState` | 空状態 | 次アクションを出す |
### 8.3 import例
@@ -389,18 +417,18 @@ import {
### 8.4 Button
-| variant | 用途 |
-|---------|------|
-| `primary` | 主要アクション |
-| `secondary` | 副次アクション |
-| `danger` | 削除・危険操作 |
-| `success` | 完了・承認 |
-| `warning` | 注意喚起 |
-| `info` | 情報系アクション |
-| `outline` | 軽量アクション |
-| `ghost` | ナビゲーション、控えめな操作 |
-| `coffee` | ブランド強調 |
-| `surface` | フィルター・補助 |
+| variant | 用途 |
+| ----------- | ---------------------------- |
+| `primary` | 主要アクション |
+| `secondary` | 副次アクション |
+| `danger` | 削除・危険操作 |
+| `success` | 完了・承認 |
+| `warning` | 注意喚起 |
+| `info` | 情報系アクション |
+| `outline` | 軽量アクション |
+| `ghost` | ナビゲーション、控えめな操作 |
+| `coffee` | ブランド強調 |
+| `surface` | フィルター・補助 |
```tsx
@@ -410,14 +438,14 @@ import {
### 8.5 Card
-| variant | 用途 |
-|---------|------|
-| `default` | 汎用カード |
-| `hoverable` | クリッカブルカード |
-| `action` | ホームグリッドカード |
-| `coffee` | ブランド強調カード |
-| `table` | テーブル外枠 |
-| `guide` | ガイド表示、空状態 |
+| variant | 用途 |
+| ----------- | -------------------- |
+| `default` | 汎用カード |
+| `hoverable` | クリッカブルカード |
+| `action` | ホームグリッドカード |
+| `coffee` | ブランド強調カード |
+| `table` | テーブル外枠 |
+| `guide` | ガイド表示、空状態 |
### 8.6 Modal / Dialog
@@ -494,7 +522,9 @@ import {
-
+
@@ -509,7 +539,9 @@ import {
```tsx
{items.map((item) => (
- ...
+
+ ...
+
))}
```
@@ -517,22 +549,30 @@ import {
### 9.5 ヘッダーパターン
```tsx
-{/* 通常ページ */}
+{
+ /* 通常ページ */
+}
タイトル
-
+;
-{/* スティッキー */}
+{
+ /* スティッキー */
+}
+;
-{/* 眉毛ラベル(eyebrow)付きタイトル — 機能名をアイコン+大文字英語で上段に添える */}
+{
+ /* 眉毛ラベル(eyebrow)付きタイトル — 機能名をアイコン+大文字英語で上段に添える */
+}
+;
-{/* セクション見出し + カウントバッジ — 件数を色変化(0件=グレー / 1件以上=赤)で示す */}
+{
+ /* セクション見出し + カウントバッジ — 件数を色変化(0件=グレー / 1件以上=赤)で示す */
+}
セクション名
{count}
-
+;
-{/* ホーム */}
+{
+ /* ホーム */
+}
+;
```
### 9.6 テーブルリスト
@@ -574,7 +620,9 @@ import {
一覧データを行で表示する際の基本形。モバイルで横スクロールが発生するHTMLテーブルの代わりに使う。`Card variant="table"` で外枠を作り、`divide-y divide-edge-subtle` で行を区切る。
```tsx
-{/* 通常リスト */}
+{
+ /* 通常リスト */
+}
{items.map((item) => (
@@ -585,26 +633,28 @@ import {
補足情報
{/* 右: 操作系(shrink-0 で縮まない) */}
-
- {/* IconButton など */}
-
+ {/* IconButton など */}
))}
-
+;
-{/* ローディング中 */}
+{
+ /* ローディング中 */
+}
読み込み中...
-
+;
-{/* 空状態(簡易メッセージ) */}
+{
+ /* 空状態(簡易メッセージ) */
+}
対象がありません。
-
+;
```
行内に `order-3 w-full sm:order-none sm:w-auto` を使うと、モバイルでは最下段に折り返し、タブレット以上では通常位置に戻るレスポンシブ配置ができる。
@@ -616,12 +666,10 @@ import {
3択以内の状態を切り替えるUI。`Tabs` がページ内コンテンツの切替に使うのに対し、こちらは「値の状態変更」に使う(例: 在庫の「十分 / 残少 / 欠品」)。
```tsx
-{/* セグメントコントロール外枠 */}
-
+{
+ /* セグメントコントロール外枠 */
+}
+
{options.map((opt) => {
const selected = opt.value === value;
return (
@@ -635,12 +683,15 @@ import {
selected ? `${opt.activeClass} shadow-sm` : 'bg-transparent text-ink-muted hover:text-ink-sub'
}`}
>
-
+
{opt.label}
);
})}
-
+
;
```
選択中ボタンの `activeClass` はセマンティック色(`bg-success-subtle text-success`、`bg-danger-subtle text-danger` など)を使い、未選択はすべてグレーに統一する。
@@ -664,42 +715,38 @@ lg : 1024px 大型デスクトップ
アニメーションは、状態変化を理解しやすくするために使います。装飾だけの強い動きは避けます。
-| 用途 | 方針 |
-|------|------|
-| ホーム | カードの順次出現は使用可 |
-| 集中操作画面 | タイマー、進捗、完了状態の演出は使用可 |
-| 一覧、フォーム | 控えめな hover / focus / loading を優先 |
-| モーダル | 短い fade / scale / slide に留める |
-| エラー、成功 | Toast やインラインメッセージで次の行動を示す |
+| 用途 | 方針 |
+| -------------- | -------------------------------------------- |
+| ホーム | カードの順次出現は使用可 |
+| 集中操作画面 | タイマー、進捗、完了状態の演出は使用可 |
+| 一覧、フォーム | 控えめな hover / focus / loading を優先 |
+| モーダル | 短い fade / scale / slide に留める |
+| エラー、成功 | Toast やインラインメッセージで次の行動を示す |
`prefers-reduced-motion` を尊重し、動きを減らす設定のユーザーには不要なアニメーションを見せません。
### 10.1 カスタムCSSアニメーション
-| クラス | 効果 | 用途 |
-|--------|------|------|
-| `animate-pulse-scale` | 2秒ループ、scale 1→1.05→1 | Newラベル |
-| `animate-home-page` | 左スライド + フェードイン | ホームページ入場 |
-| `animate-home-card` | 下スライド + フェードイン | グリッドカード順次出現 |
-| `new-label-gradient` | グラデーション流動 | ラベル装飾 |
+| クラス | 効果 | 用途 |
+| --------------------- | ------------------------- | ---------------------- |
+| `animate-pulse-scale` | 2秒ループ、scale 1→1.05→1 | Newラベル |
+| `animate-home-page` | 左スライド + フェードイン | ホームページ入場 |
+| `animate-home-card` | 下スライド + フェードイン | グリッドカード順次出現 |
+| `new-label-gradient` | グラデーション流動 | ラベル装飾 |
### 10.2 Tailwindトランジション
-| 用途 | クラス | 時間 |
-|------|--------|------|
-| ホバー色変化 | `transition-colors duration-200` | 200ms |
-| モーダル開閉 | `transition-all duration-300` | 300ms |
-| カードリフト | `hover:-translate-y-2 hover:shadow-card-hover transition-all duration-300` | 300ms |
-| テーマ変更 | `transition-colors duration-1000` | 1000ms |
+| 用途 | クラス | 時間 |
+| ------------ | -------------------------------------------------------------------------- | ------ |
+| ホバー色変化 | `transition-colors duration-200` | 200ms |
+| モーダル開閉 | `transition-all duration-300` | 300ms |
+| カードリフト | `hover:-translate-y-2 hover:shadow-card-hover transition-all duration-300` | 300ms |
+| テーマ変更 | `transition-colors duration-1000` | 1000ms |
### 10.3 Framer Motion
```tsx
-
+
...
```
@@ -790,13 +837,12 @@ UIを作る、または直す前に確認します。
## 13. 参照先
-| ドキュメント / ファイル | 内容 |
-|-------------------------|------|
-| `docs/steering/PRODUCT.md` | プロダクトの目的、ユーザー、コアバリュー |
-| `docs/steering/FEATURES.md` | 機能仕様、UI実装ルール、共通禁止事項 |
-| `docs/steering/TECH_SPEC.md` | 技術制約、テーマシステム、ADR |
-| `docs/steering/REPOSITORY.md` | ディレクトリ構成、依存方向 |
-| `docs/steering/GUIDELINES.md` | 実装、テスト、Git運用 |
-| `app/globals.css` | CSS変数、テーマ定義、カスタムアニメーション |
-| `/dev/design-lab` | 開発者向けデザイン確認ページ |
-
+| ドキュメント / ファイル | 内容 |
+| ----------------------------- | ------------------------------------------- |
+| `docs/steering/PRODUCT.md` | プロダクトの目的、ユーザー、コアバリュー |
+| `docs/steering/FEATURES.md` | 機能仕様、UI実装ルール、共通禁止事項 |
+| `docs/steering/TECH_SPEC.md` | 技術制約、テーマシステム、ADR |
+| `docs/steering/REPOSITORY.md` | ディレクトリ構成、依存方向 |
+| `docs/steering/GUIDELINES.md` | 実装、テスト、Git運用 |
+| `app/globals.css` | CSS変数、テーマ定義、カスタムアニメーション |
+| `/dev/design-lab` | 開発者向けデザイン確認ページ |
diff --git a/app/assignment/components/AssignmentSettingsModal.tsx b/app/assignment/components/AssignmentSettingsModal.tsx
index b5a5e440..03a9a014 100644
--- a/app/assignment/components/AssignmentSettingsModal.tsx
+++ b/app/assignment/components/AssignmentSettingsModal.tsx
@@ -196,7 +196,7 @@ export function AssignmentSettingsModal({
options={memberOptions}
placeholder="選択..."
disabled={isLoading}
- className="!text-sm !py-2"
+ className="text-sm! py-2!"
/>
@@ -247,7 +247,7 @@ export function AssignmentSettingsModal({
size="sm"
onClick={() => handleDelete(exclusion.id)}
disabled={isLoading}
- className="!p-1.5 !min-h-0 !text-red-500 hover:!text-red-700 hover:!bg-red-50"
+ className="!p-1.5 min-h-0! !text-red-500 hover:!text-red-700 hover:!bg-red-50"
aria-label="削除"
>
diff --git a/app/assignment/components/assignment-table/DesktopTableBody.tsx b/app/assignment/components/assignment-table/DesktopTableBody.tsx
index 580750af..ef954c62 100644
--- a/app/assignment/components/assignment-table/DesktopTableBody.tsx
+++ b/app/assignment/components/assignment-table/DesktopTableBody.tsx
@@ -116,10 +116,10 @@ export const DesktopTableBody: React.FC = ({
onTouchMove={handleCellTouchMove}
onClick={() => handleCellClick(team.id, label.id)}
className={`
- !min-h-0 w-full py-2 md:py-3 px-1 !rounded-lg text-sm md:text-base !font-bold text-center transition-all truncate select-none
+ min-h-0! w-full py-2 md:py-3 px-1 rounded-lg! text-sm md:text-base !font-bold text-center transition-all truncate select-none
${member && isSelected ? 'shadow-md scale-105' : ''} ${
- !member && isSelected ? '!bg-surface !border-spot' : ''
- } ${!member && !isSelected ? '!text-ink-muted !bg-ground !border-dashed !border-edge-strong hover:!bg-ground/80 !shadow-none' : ''}
+ !member && isSelected ? 'bg-surface! !border-spot' : ''
+ } ${!member && !isSelected ? '!text-ink-muted !bg-ground !border-dashed border-edge-strong! hover:!bg-ground/80 !shadow-none' : ''}
`}
>
{member ? member.name : '未割当'}
diff --git a/app/assignment/components/assignment-table/DesktopTableFooter.tsx b/app/assignment/components/assignment-table/DesktopTableFooter.tsx
index 7815753e..a4bb8360 100644
--- a/app/assignment/components/assignment-table/DesktopTableFooter.tsx
+++ b/app/assignment/components/assignment-table/DesktopTableFooter.tsx
@@ -49,7 +49,7 @@ export const DesktopTableFooter: React.FC = ({
if (e.key === 'Enter') handleAddTaskLabel();
}}
placeholder={`${headerLabels.left}を入力`}
- className="!p-2 !text-sm !min-h-0 !text-center"
+ className="!p-2 text-sm! min-h-0! !text-center"
/>
) : (
@@ -66,7 +66,7 @@ export const DesktopTableFooter: React.FC = ({
size="sm"
onClick={handleAddTaskLabel}
disabled={!newLeftLabel.trim()}
- className="!rounded-full !px-4 shadow-md active:scale-95"
+ className="rounded-full! px-4! shadow-md active:scale-95"
>
担当を追加
@@ -77,7 +77,7 @@ export const DesktopTableFooter: React.FC = ({
size="sm"
onClick={onShuffle}
disabled={isShuffleDisabled}
- className="!rounded-full !px-4 shadow-md active:scale-95"
+ className="rounded-full! px-4! shadow-md active:scale-95"
>
シャッフル
@@ -93,7 +93,7 @@ export const DesktopTableFooter: React.FC = ({
if (e.key === 'Enter') handleAddTaskLabel();
}}
placeholder={`${headerLabels.right}を入力`}
- className="!min-w-0 !p-2 !text-center !text-sm !min-h-0 w-full"
+ className="min-w-0! !p-2 !text-center text-sm! min-h-0! w-full"
/>
) : (
diff --git a/app/assignment/components/assignment-table/DesktopTableHeader.tsx b/app/assignment/components/assignment-table/DesktopTableHeader.tsx
index b14253b9..d7c843ae 100644
--- a/app/assignment/components/assignment-table/DesktopTableHeader.tsx
+++ b/app/assignment/components/assignment-table/DesktopTableHeader.tsx
@@ -71,7 +71,7 @@ export const DesktopTableHeader: React.FC = ({
if (e.key === 'Escape') setIsAddingTeam(false);
}}
variant="dark"
- className="!min-h-[30px] !w-20 !border-none !px-1 !py-1 !text-sm"
+ className="!min-h-[30px] !w-20 !border-none !px-1 py-1! text-sm!"
/>
@@ -142,7 +142,7 @@ export const DesktopTableHeader: React.FC = ({
variant="outline"
size="sm"
onClick={() => setIsAddingTeam(true)}
- className="!min-h-[34px] !text-sm md:!text-base !gap-1 !bg-transparent"
+ className="!min-h-[34px] text-sm! md:!text-base gap-1! !bg-transparent"
>
最初の班を追加
@@ -170,7 +170,7 @@ export const DesktopTableHeader: React.FC = ({
onKeyDown={(e) => e.key === 'Enter' && handleUpdateTeam(team.id)}
onBlur={() => handleUpdateTeam(team.id)}
variant="light"
- className="!text-sm md:!text-base"
+ className="text-sm! md:!text-base"
/>
) : (
= ({
value={editLeftLabel}
onChange={(e) => setEditLeftLabel(e.target.value)}
placeholder={headerLabels.left}
- className="!p-2 !text-lg !font-bold !min-h-0"
+ className="!p-2 !text-lg !font-bold min-h-0!"
/>
setEditRightLabel(e.target.value)}
placeholder={headerLabels.right}
- className="flex-1 !p-2 !text-sm !min-h-0"
+ className="flex-1 !p-2 text-sm! min-h-0!"
/>
@@ -89,7 +89,7 @@ export const MobileListView: React.FC = ({
variant="danger"
size="sm"
onClick={() => handleDeleteTaskLabel(label.id)}
- className="!p-2 !min-h-0 shrink-0"
+ className="!p-2 min-h-0! shrink-0"
>
@@ -144,15 +144,15 @@ export const MobileListView: React.FC = ({
onTouchEnd={handleCellTouchEnd}
onTouchMove={handleCellTouchMove}
onClick={() => handleCellClick(team.id, label.id)}
- className={`!min-h-0 !rounded-md !px-2 !py-3 !shadow-none truncate select-none ${
+ className={`min-h-0! rounded-md! !px-2 py-3! !shadow-none truncate select-none ${
member && isSelected
? '!border-spot !bg-spot !text-on-spot ring-2 ring-spot/20'
: member
- ? '!border-edge !bg-surface hover:!bg-spot-surface'
+ ? 'border-edge! bg-surface! hover:!bg-spot-surface'
: ''
} ${
- !member && isSelected ? '!bg-surface !border-spot' : ''
- } ${!member && !isSelected ? '!border-dashed !border-edge-strong !bg-surface !text-ink-muted' : ''}`}
+ !member && isSelected ? 'bg-surface! !border-spot' : ''
+ } ${!member && !isSelected ? '!border-dashed border-edge-strong! bg-surface! !text-ink-muted' : ''}`}
>
{member ? member.name : '未割当'}
diff --git a/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx b/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx
index fc78f351..af69fae9 100644
--- a/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx
+++ b/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx
@@ -67,7 +67,7 @@ export function ContextMenuModal({ data, state, setMemberMenu, callbacks }: Cont
setCurrent(null);
}
}}
- className="!py-2"
+ className="py-2!"
/>
削除
diff --git a/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx b/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx
index e5527155..dc01bd84 100644
--- a/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx
+++ b/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx
@@ -45,7 +45,7 @@ export function MemberSelectionModal({ data, state, callbacks }: MemberSelection
handleAddMember(current.taskLabelId, current.teamId);
}
}}
- className="!py-2 !text-sm"
+ className="py-2! text-sm!"
autoFocus
/>
@@ -71,7 +71,7 @@ export function MemberSelectionModal({ data, state, callbacks }: MemberSelection
callbacks.onUpdateMember(createEmptyAssignment(current.teamId, current.taskLabelId), member.id);
setCurrent(null);
}}
- className="flex-1 !justify-start !text-left !text-ink hover:!bg-ground"
+ className="flex-1 !justify-start text-left! !text-ink hover:bg-ground!"
>
{member.name}
diff --git a/app/assignment/components/assignment-table/modals/TeamActionModal.tsx b/app/assignment/components/assignment-table/modals/TeamActionModal.tsx
index a4f22783..e93ae669 100644
--- a/app/assignment/components/assignment-table/modals/TeamActionModal.tsx
+++ b/app/assignment/components/assignment-table/modals/TeamActionModal.tsx
@@ -151,7 +151,7 @@ function TeamActionModalContent({
size="sm"
fullWidth
onClick={handleDeleteTeamFromModal}
- className="!flex !items-center !justify-center !gap-1"
+ className="flex! items-center! !justify-center gap-1!"
>
削除
diff --git a/app/assignment/page.tsx b/app/assignment/page.tsx
index 8785e1a8..8650938b 100644
--- a/app/assignment/page.tsx
+++ b/app/assignment/page.tsx
@@ -73,7 +73,7 @@ export default function AssignmentPage() {
variant="outline"
size="sm"
onClick={() => setIsSettingsModalOpen(true)}
- className="!rounded-full !px-3 !py-2 shadow-md !bg-surface !text-ink-sub hover:!bg-ground !border !border-edge-strong"
+ className="rounded-full! px-3! py-2! shadow-md bg-surface! text-ink-sub! hover:bg-ground! border! border-edge-strong!"
title="詳細設定"
>
@@ -114,8 +114,8 @@ export default function AssignmentPage() {
variant={data.manager ? 'outline' : 'primary'}
size="md"
onClick={() => setIsManagerDialogOpen(true)}
- className={`!flex !items-center !gap-2 !px-4 !py-3 !rounded-lg shadow-lg ${
- data.manager ? '!bg-surface hover:!bg-ground !border-edge' : ''
+ className={`flex! items-center! gap-2! px-4! py-3! rounded-lg! shadow-lg ${
+ data.manager ? 'bg-surface! hover:bg-ground! border-edge!' : ''
}`}
>
{data.manager ? (
diff --git a/app/clock/page.tsx b/app/clock/page.tsx
index a2dfba73..54ee8278 100644
--- a/app/clock/page.tsx
+++ b/app/clock/page.tsx
@@ -258,7 +258,7 @@ export default function ClockPage() {
variant="primary"
size="sm"
onClick={enableAudio}
- className="col-span-2 mt-1 w-full !min-h-11 !px-4 sm:col-span-1 sm:mt-0 sm:w-auto"
+ className="col-span-2 mt-1 w-full !min-h-11 px-4! sm:col-span-1 sm:mt-0 sm:w-auto"
style={{
backgroundColor: colors.accent,
color: '#FFFFFF',
diff --git a/app/contact/page.tsx b/app/contact/page.tsx
index e5496045..65d95ca7 100644
--- a/app/contact/page.tsx
+++ b/app/contact/page.tsx
@@ -121,7 +121,7 @@ export default function ContactPage() {
{/* エラーメッセージ */}
{status === 'error' && errorMessage && (
-
+
エラーが発生しました
{errorMessage}
diff --git a/app/defect-beans/page.tsx b/app/defect-beans/page.tsx
index 01ce03f6..cc30a79a 100644
--- a/app/defect-beans/page.tsx
+++ b/app/defect-beans/page.tsx
@@ -190,7 +190,7 @@ export default function DefectBeansPage() {
size="sm"
onClick={toggleCompareMode}
title={compareMode ? '選択モード' : '比較モード'}
- className="!px-3 !py-2 gap-1.5"
+ className="px-3! py-2! gap-1.5"
>
{compareMode ? '選択モード' : '比較'}
@@ -201,7 +201,7 @@ export default function DefectBeansPage() {
size="sm"
onClick={handleShowCompare}
title="比較を表示"
- className="!px-3 !py-2 gap-1.5"
+ className="px-3! py-2! gap-1.5"
>
比較 ({selectedIds.size})
@@ -212,7 +212,7 @@ export default function DefectBeansPage() {
size="sm"
onClick={() => setShowAddForm(true)}
title="欠点豆を追加"
- className="!px-3 !py-2 gap-1.5"
+ className="px-3! py-2! gap-1.5"
>
追加
diff --git a/app/drip-guide/page.tsx b/app/drip-guide/page.tsx
index 1bbedcfc..a8426407 100644
--- a/app/drip-guide/page.tsx
+++ b/app/drip-guide/page.tsx
@@ -21,7 +21,7 @@ export default function DripGuidePage() {
right={
新規レシピ
diff --git a/app/error.tsx b/app/error.tsx
index c5ee7928..478c1ff0 100644
--- a/app/error.tsx
+++ b/app/error.tsx
@@ -16,7 +16,7 @@ export default function Error({ reset }: { error: Error & { digest?: string }; r
ホームへ
diff --git a/app/globals.css b/app/globals.css
index f07db0e1..a7ec5259 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,5 +1,10 @@
@import 'tailwindcss';
+/* 過去の仕様・計画・作業ログはクラス名の検出対象から外す。
+ 古いクラス名を拾って未使用CSSが生成されるのを防ぐ */
+@source not '../docs';
+@source not '../.superpowers';
+
:root {
--background: #fdf8f0;
--foreground: #171717;
@@ -480,6 +485,11 @@
--font-mono: var(--font-geist-mono);
--font-nunito: var(--font-nunito);
--font-num: var(--font-outfit);
+ /* ブランド表記(ロゴ・スプラッシュ・ログイン/新規登録の見出し)用。
+ 書体をクラス側の任意値で直接指定すると Tailwind v4 では font-weight として
+ 解釈され効かないため、ここでユーティリティ化する
+ (コメント内にクラス名を書くと Tailwind が拾ってしまうので書かない) */
+ --font-brand: var(--font-inter);
}
/* stylelint-enable at-rule-no-unknown */
diff --git a/app/inventory/page.tsx b/app/inventory/page.tsx
index 7075fccb..b789dfe3 100644
--- a/app/inventory/page.tsx
+++ b/app/inventory/page.tsx
@@ -131,7 +131,7 @@ export default function InventoryPage() {
setEditing(null);
setModalOpen(true);
}}
- className="!min-h-0 shrink-0 gap-1.5 !rounded-[10px] !px-4 !py-2 !text-sm"
+ className="min-h-0! shrink-0 gap-1.5 !rounded-[10px] px-4! py-2! text-sm!"
>
品目を追加
diff --git a/app/login/page.tsx b/app/login/page.tsx
index 62d9504b..914aaf26 100644
--- a/app/login/page.tsx
+++ b/app/login/page.tsx
@@ -92,7 +92,7 @@ function LoginForm() {
-
+
RoastPlus
diff --git a/app/page.tsx b/app/page.tsx
index a33e9664..19faee10 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -194,7 +194,7 @@ export default function HomePage(_props: HomePageProps = {}) {
return (
{isChristmasMode &&
}
@@ -212,7 +212,7 @@ export default function HomePage(_props: HomePageProps = {}) {
{/* メインコンテンツ */}
-
+
{visibleActions.map(({ key, title, label, description, href, icon: DefaultIcon, badge }, index) => {
const Icon = isChristmasMode ? CHRISTMAS_ICONS[key] || DefaultIcon : DefaultIcon;
diff --git a/app/schedule/page.tsx b/app/schedule/page.tsx
index 2dff4fe6..d2f2f9d1 100644
--- a/app/schedule/page.tsx
+++ b/app/schedule/page.tsx
@@ -67,7 +67,7 @@ export default function SchedulePage() {
size="sm"
onClick={moveToPreviousDay}
aria-label="前日"
- className="active:scale-90 transition-transform !min-h-0 !min-w-0 !h-8 !w-8 !p-1"
+ className="active:scale-90 transition-transform min-h-0! min-w-0! !h-8 !w-8 p-1!"
>
@@ -76,7 +76,7 @@ export default function SchedulePage() {
size="sm"
onClick={() => setIsDatePickerOpen(true)}
aria-label="日付を選択"
- className="!min-h-0 !px-2 !py-1"
+ className="min-h-0! !px-2 py-1!"
>
{formatDateString(selectedDate)}
@@ -88,7 +88,7 @@ export default function SchedulePage() {
onClick={moveToNextDay}
disabled={isMaxDate}
aria-label="翌日"
- className="active:scale-90 transition-transform !min-h-0 !min-w-0 !h-8 !w-8 !p-1"
+ className="active:scale-90 transition-transform min-h-0! min-w-0! !h-8 !w-8 p-1!"
>
@@ -96,7 +96,7 @@ export default function SchedulePage() {
{/* 日付ナビゲーション */}
-
+
{/* スマホレイアウト:FloatingNav右に統合済み */}
{/* タブレット・デスクトップレイアウト:横並び */}
@@ -117,7 +117,7 @@ export default function SchedulePage() {
aria-label="日付を選択"
className="gap-2 md:gap-2.5"
>
-
+
{formatDateString(selectedDate)}
@@ -133,16 +133,16 @@ export default function SchedulePage() {
-
+
-
+
{formatTime(currentTime)}
-
+
setIsOCROpen(true)} aria-label="画像から読み取り">
@@ -154,10 +154,10 @@ export default function SchedulePage() {
{/* タブナビゲーション(スマホ版:画面下部に固定) */}
-
+
本日のスケジュール
@@ -166,14 +166,14 @@ export default function SchedulePage() {
variant="primary"
size="md"
onClick={() => setIsOCROpen(true)}
- className="relative z-20 -my-3 mx-1 flex-shrink-0 !w-12 !h-12 !rounded-full shadow-lg !bg-spot !text-on-spot active:scale-95 transition-transform ring-4 ring-surface"
+ className="relative z-20 -my-3 mx-1 shrink-0 !w-12 !h-12 rounded-full! shadow-lg !bg-spot !text-on-spot active:scale-95 transition-transform ring-4 ring-surface"
aria-label="画像から読み取り"
>
ローストスケジュール
diff --git a/app/signup/page.tsx b/app/signup/page.tsx
index 376eb34b..63594283 100644
--- a/app/signup/page.tsx
+++ b/app/signup/page.tsx
@@ -57,7 +57,7 @@ function SignupForm() {
-
+
RoastPlus
diff --git a/app/tasting/page.tsx b/app/tasting/page.tsx
index 17aced77..c8e96f80 100644
--- a/app/tasting/page.tsx
+++ b/app/tasting/page.tsx
@@ -267,7 +267,7 @@ function TastingPageContent() {
size="sm"
onClick={() => router.push('/tasting/sessions/new')}
aria-label="新規セッション作成"
- className="!px-3 !py-2 gap-1.5 shadow-md"
+ className="px-3! py-2! gap-1.5 shadow-md"
>
セッションを作成
diff --git a/components/DefectBeanCard.tsx b/components/DefectBeanCard.tsx
index 2014e147..eb6e958c 100644
--- a/components/DefectBeanCard.tsx
+++ b/components/DefectBeanCard.tsx
@@ -61,7 +61,7 @@ export function DefectBeanCard({
>
{/* 画像 */}
{
e.stopPropagation(); // カードクリックを防ぐ
setShowImageModal(true);
@@ -72,7 +72,7 @@ export function DefectBeanCard({
{/* 内側の細い枠(上品なゴールド、光沢感) */}
{/* 画像コンテナ */}
-
+
{/* 名称 */}
-
+
{defectBean.name}
@@ -106,21 +106,21 @@ export function DefectBeanCard({
特徴
-
+
{defectBean.characteristics || 未入力}
味への影響
-
+
{defectBean.tasteImpact || 未入力}
省く理由
-
+
{defectBean.removalReason || 未入力}
@@ -129,29 +129,29 @@ export function DefectBeanCard({
{/* 設定切り替え */}
{onToggleSetting && (
e.stopPropagation()}
>
diff --git a/components/DefectBeanDetail.tsx b/components/DefectBeanDetail.tsx
index b6d63ed5..a1823124 100644
--- a/components/DefectBeanDetail.tsx
+++ b/components/DefectBeanDetail.tsx
@@ -52,8 +52,8 @@ export function DefectBeanDetail({
{/* 画像(拡大表示可能) */}
setShowImageModal(true)}
>
@@ -62,7 +62,7 @@ export function DefectBeanDetail({
{/* 内側の細い枠(上品なゴールド、光沢感) */}
{/* 画像コンテナ */}
-
+
{isLoading || !animationData ? (
-
+
) : (
diff --git a/components/OCRRoastScheduleEditor.tsx b/components/OCRRoastScheduleEditor.tsx
index c5c80da1..ffc3b0e8 100644
--- a/components/OCRRoastScheduleEditor.tsx
+++ b/components/OCRRoastScheduleEditor.tsx
@@ -130,27 +130,27 @@ export function OCRRoastScheduleEditor({
{schedule.beanName && (
-
+
豆: {schedule.beanName}
)}
{schedule.beanName2 && schedule.blendRatio && (
-
+
副豆 {schedule.beanName2}({schedule.blendRatio})
)}
{schedule.weight && (
-
+
{schedule.weight}g
)}
{schedule.roastLevel && (
-
+
{schedule.roastLevel}
)}
{schedule.bagCount && (
-
+
{schedule.bagCount}袋
)}
@@ -199,7 +199,7 @@ export function OCRRoastScheduleEditor({
})
)}
-