/* TASTEOME Design Tokens (Variant G: A base + F hybrid) */
/* owner approved 2026-06-02 / 詳細: BRANDING.md §3 */
/* Consistency Overhaul (2026-06-03): canonical source-of-truth for ALL design tokens */

/* Universal box-sizing for tokens-loading pages (hub/legal/start/tier/daily/domain) */
* { box-sizing: border-box; }

/* ── Display font: Bricolage Grotesque (self-host, latin variable。 ART_DIRECTION.md §1) ──
   見出し・ロゴ・数値のみ。 JA 見出しは stack で Noto Sans JP に fallback。 */
@font-face {
  font-family: 'Bricolage Grotesque';
  /* 絶対パス必須: domain page は css symlink (/manga/css→/shared/css) 経由で読むため
     相対パスだと /manga/fonts/ に解決されて 404 (session 42c〜52 の e2e FAIL 要因) */
  src: url('/shared/fonts/BricolageGrotesque-variable.woff2') format('woff2');
  font-weight: 400 800; font-style: normal; font-display: swap;
}

:root {
  /* ── Brand colors (軸 signature) ─────────────────────── */
  --t-cog: #ff6b7e;       /* 認知負荷 — red */
  --t-emo: #2dd4bf;       /* 感情(composite) — teal */
  --t-sem: #fbbf24;       /* 主題負荷 — gold */
  --t-vis: #f97316;       /* 視覚 — orange */
  --t-length: #a78bfa;    /* 長さ — purple */
  --t-mass: #60a5fa;      /* 大衆性 — blue */
  --t-polish: #f472b6;    /* 完成度 — pink */
  /* taxonomy v2 感情3軸 (emo を granular 分解。 weight は 6軸バーで emo を置換) */
  --t-weight: #2dd4bf;    /* 感情の重さ — teal (旧 emo を継承) */
  --t-arousal: #fb7185;   /* テンション arousal (静↔激) — rose */
  --t-valence: #38bdf8;   /* 陰陽 valence (陰↔陽) — sky。 diverging colormap/コンパスで方向表示 */
  /* taxonomy v3 コア新軸 (2026-06-11。 data/*.json metrics の colorDark と整合) */
  --t-structure: #a3e635; /* 構成 (craft 構成軸、 polish 後継) — lime */
  --t-open: #e879f9;      /* 解釈開放度 — fuchsia */
  /* taxonomy v4 コア新軸 (2026-07-17。 craft 三元目。 vis=orange/structure=lime と区別する cyan) */
  --t-world: #06b6d4;     /* 世界観構築 (craft) — cyan */

  /* ── 軸ラベル用 ink ───────────────────────────────────
     🔴 軸色は **dark なら文字にできる (最悪 6.86:1) が light は全 12 軸が AA 未達** (最悪 1.41:1)。
     点や帯 (var(--t-<axis>)) は意味を担うのでそのまま、**文字だけ** theme ごとの ink を使う。
     ⚠ 混色比を var() で渡すと color-mix が解決できず **全軸が --t-fg に落ちる** (無彩化)。
        literal で theme ごとに書く。 */
  --t-cog-ink: var(--t-cog);
  --t-emo-ink: var(--t-emo);
  --t-sem-ink: var(--t-sem);
  --t-vis-ink: var(--t-vis);
  --t-length-ink: var(--t-length);
  --t-mass-ink: var(--t-mass);
  --t-weight-ink: var(--t-weight);
  --t-arousal-ink: var(--t-arousal);
  --t-valence-ink: var(--t-valence);
  --t-structure-ink: var(--t-structure);
  --t-open-ink: var(--t-open);
  --t-world-ink: var(--t-world);

  /* ドメイン固有補助軸 (per-domain 分析の ridgeline で選択ドメイン時のみ表示、2026-07-01)。
     コア軸と同時表示されるため未使用の hue から採る (polish は既存)。 */
  --t-skill: #10b981;     /* 技量 (game) — emerald */
  --t-freedom: #6366f1;   /* 自由度 (game) — indigo */
  --t-motion: #059669;    /* 動き (anime) — deep green */
  --t-audio: #a855f7;     /* 音 (anime/movie/game/drama/variety) — violet */
  --t-acting: #ec4899;    /* 演技 (movie/drama) — magenta */
  /* variety (サテライト第 1 号) の新設 aux 2 軸 (DOMAIN_ADR_variety §5)。
     ⚠ 色は variety の metricOrder 内で hue が空いている帯から採る —
       cast = structure(lime 84°) と weight(teal 172°) の間 / info = open(fuchsia 292°) と
       cog(red 353°) の間。data/variety.json の colorDark と同値。
     ⚠ `--t-info` は `--t-acting` と同値 — aux は **選択ドメインの分だけ**描かれるので
       (acting = movie/drama / info = variety) 同時表示されない。空いた hue が無い中で
       悪い色域へ逃げるより、同値であることを明示するほうが安全。
     🔴 2026-08-17 修正: 本コメントは W1 でコメント終端記号が途中に混入して 2 つに割れており、
       後段が **宣言列の中に生テキストとして落ちていた** — CSS のエラー回復は次の `;` まで
       読み飛ばすので、直後の `--t-cast` が丸ごと 1 宣言として捨てられていた (静かな欠落)。
       ⚠ コメント本文にコメント終端記号を書かない (この注記自身がその罠を踏んだ)。 */
  --t-cast: #22c55e;      /* 出演者力 (variety) — green */
  --t-info: #ec4899;      /* 情報・学び (variety) — pink (= --t-acting と同値、上記) */
  /* musician / album (サテライト第 2 陣) の新設 aux 4 軸
     (DOMAIN_ADR_musician §5 / DOMAIN_ADR_album §5)。
     ⚠ hue は **そのドメインの metricOrder 内**で空いている帯から採る (aux は選択ドメインの
       分だけ描かれるので、衝突が起きるのは同一ドメインの軸どうしだけ)。
       musician は craft コア 3 軸が nullAxes で落ちるため sem(43°)→weight(172°) が 129° の
       大穴になる — songcraft 75° / performance 105° をそこへ、innovation は
       open(292°)→arousal(350°) の帯へ置いて 3 本を散らす。
       album は structure(83°)→weight(172°) の穴の中点へ sound 127°。
     ⚠ performance(105°) と sound(127°) は 22° しか離れていないが **musician と album で
       同時表示されない** (info = acting と同値にした W1 の判断と同型)。
     ⚠ data/musician.json · data/album.json の colorDark と同値に保つ。 */
  --t-songcraft: #b6df3a;    /* 作家性 (musician) — chartreuse */
  --t-performance: #54c62f;  /* 実演力 (musician) — green */
  --t-innovation: #ee4fb9;   /* 革新性 (musician) — magenta */
  --t-sound: #2eb83e;        /* 音響・プロダクション (album) — deep green */

  /* Domain accent (Landing card で使用、 軸色の中から代表色) */
  --t-domain-manga: var(--t-cog);
  --t-domain-anime: var(--t-emo);
  --t-domain-movie: var(--t-sem);
  --t-domain-game:  var(--t-vis);
  --t-domain-drama: var(--t-length);
  /* book: 既存 5 色 (red / teal / gold / orange / purple) が使っていない青系から採る。
     ⚠ 隣り合う色域を選ぶと Step 1 の domain accent と root カードで 2 ドメインが混同される。 */
  --t-domain-book:  var(--t-mass);
  /* variety (サテライト第 1 号): 既存 6 色 (red / teal / gold / orange / purple / blue) から
     最も離れた lime 帯。⚠ musician / album (第 2 陣) 用に cyan / rose を空けてある。 */
  --t-domain-variety: var(--t-structure);
  /* musician / album (サテライト第 2 陣): W1 で予約した cyan / rose をそのまま使う
     (DOMAIN_ADR_musician §1 / DOMAIN_ADR_album §1)。⚠ 音楽 2 ドメインは root カードで
     隣り合うので、同系色にせず **cyan と rose** で色域を割る。 */
  --t-domain-musician: var(--t-world);
  --t-domain-album: var(--t-arousal);

  /* ── Surface (dark base) ───────────────────────────────── */
  /* 🔴 native の form 部品 (チェックボックス・select・scrollbar・autofill) の描画を theme に揃える。
     無いと dark でも UA が light で描き、未チェックのチェックボックスが白い素の四角で出る
     (`accent-color` はチェック済みにしか効かない)。theme ごとに下の 3 ブロックで再宣言する。 */
  color-scheme: dark;
  /* Switch (`ui/shared/Switch.tsx`) — ON の地。dark の ink (`--t-accent`) はほぼ白で白いつまみが消えるので、
     dark は `--t-muted` (mobile の `SwitchRow` と同じ裁定)。つまみは両 theme で白。 */
  --t-switch-on: var(--t-muted);
  --t-switch-thumb: #ffffff;
  --t-bg: #0b0e1a;
  --t-bg-elev: rgba(255,255,255,0.04);
  --t-bg-elev-2: rgba(255,255,255,0.06);
  --t-surface: #14141f;          /* solid card / panel */
  --t-surface-hover: #1c1c2c;    /* hover / second-elevation */
  --t-bg-grad: var(--t-bg);
  --t-bg-radial-accents: none;

  /* ── Foreground ────────────────────────────────────────── */
  --t-fg: #e8eaf2;
  --t-fg-soft: #b8bdd0;
  --t-muted: #8a8fa3;
  /* 破壊的操作 / 失敗の色。⚠ light は #ff6b7e だと白地 2.74:1 で沈むため別値 */
  --t-danger: #ff6b7e;
  /* v=66: --t-dim was #5a5f73 (3.04:1 on --t-bg, WCAG AA fail)。
     大文字 button bg なら 3.0 (large) で OK だが、 tagline / section-label /
     vs-icon-off 等 small text で頻用されるため、 contrast 4.5 を確実に満たす値に。 */
  --t-dim: #8e94aa;

  /* ── Border ────────────────────────────────────────────── */
  --t-border: rgba(255,255,255,0.08);
  --t-border-strong: rgba(255,255,255,0.15);
  /* 押せる部品 (枠の pill 等) の境界 — 対 bg / surface で 3:1 (WCAG 1.4.11)。`--t-border-strong` (約 1.5:1) は箱の縁用で操作の境界には足りない (MOBILE-PILL-OUTLINE-CONTRAST)。 */
  --t-border-control: color-mix(in srgb, var(--t-fg) 40%, transparent);
  --t-border-hover: color-mix(in srgb, var(--t-fg) 38%, transparent);

  /* ── Rule (面を区切る罫線) / Press (押下の面) — C' (ART_DIRECTION.md §0) ──
     C' でフィードや一覧の**面の分離を担うのは罫線**になった (カードと影の多用をやめる)。
     ⚠ `--t-border` とは役割が違う — border は「箱そのものの縁」、rule は「面を区切る線」。
       構造を担う分だけ border より一段強い (実測 dark 1.70:1 / light 1.35:1 vs `--t-bg`。
       `--t-border` は dark 1.20:1 / light 1.17:1)。
     `--t-press-bg` は **押している間**の面。hover / 選択 (`--t-active-bg`) より一段強い —
     ⚠ touch には hover が無いので、押下の面が**唯一の即時反応**になる。
     ⚠ この面の上に `--t-muted` の文字を置かない (light で 4.61:1 → 3.64:1 まで落ちる)。
     ⚠ 濃度は theme で非対称 (light の減光は同じ割合でも強く出る) — `--t-active-bg` の
       9% / 7% と同じ流儀で theme ごとに宣言する。 */
  --t-rule: color-mix(in srgb, var(--t-fg) 20%, transparent);
  --t-press-bg: color-mix(in srgb, var(--t-fg) 16%, transparent);

  /* ── 精度メーター (onboarding の「いまの解像度」帯。ONBOARDING_DESIGN.md §6) ──────
     🔴 **無彩で描く** — 量は区画の個数が運ぶ (ART_DIRECTION §0「色は意味にだけ使う」/
       §4b「凡例なしに色で意味を運ばない」)。軸色も accent も使わない。
     ⚠ **theme ごとに再宣言しない** — 参照先 (`--t-fg` / `--t-fg-soft`) が theme で
       切り替わるので 1 宣言でそのまま追随する。 */
  --t-measure-track: color-mix(in srgb, var(--t-fg) 12%, transparent);  /* 未達 = 地に近い抜き (§5) */
  --t-measure-fill: var(--t-fg-soft);   /* 達成 = 本文より一段静かな ink (主行動より軽く) */

  /* ── Accent (primary CTA, links) ───────────────────────── */
  --t-accent: #eef0f7;        /* monochrome ink (dark)。 ART_DIRECTION.md */
  --t-accent-warm: #d4a017;
  --t-accent-grad: var(--t-accent);   /* グラデ撤去 → solid */
  /* accent / danger 塗り背景上の文字色 (dark = 暗色・light = white は light の block。半透明 accent bg 上では
     light theme で var(--t-fg) override が必要 — `docs/reference/CSS_COLOR_RULES.md`) */
  --t-on-accent: #0b0e1a;

  /* ── Tier (Badges) ─────────────────────────────────────── */
  /* domain ごとのバッジ (BADGES-V2) の段の色 = 徽章の塗り (`apps/web/src/ui/badges/badges.css`)。
     ⚠ **theme で変える** (tier list の --t-tier-sss 等とは逆) — 徽章は地の上の UI 部品で、
       light の地 (#f6f7fb / #fff) に dark の値を載せると silver 1.8:1 / gold 2.4:1 で消える。
       light の値は light の 2 block が持つ (地と 4.5:1 以上・中の白い icon とも 4.5:1 以上)。
     ⚠ 色だけで段を伝えない — 段の語と点の数 (`.badge-pips`) が同じ情報を運ぶ。 */
  --t-tier-bronze: #cd7f32;
  --t-tier-silver: #c0c0c0;
  --t-tier-gold:   #d4a017;

  /* ── custom tierlist の行 palette ───────────────────────
     UGC が行の色を選ぶ唯一の集合。自由入力の hex を受けない理由 = 本 token 規約を
     外れる / 文字とのコントラストを保証できない (docs/design/CUSTOM_TIERLIST_DESIGN.md §9.1)。
     ⚠ 正本 = scripts/lib/tier_palette.json。TS 側 (app/tierlist/palette.ts) と DB の
     allowlist (tier_palette_ok) との一致は drift test が固定する。
     ⚠ theme で変えない — canvas 書き出しが同じ hex を使うため (light/dark で別値にすると
     画像と画面で色が食い違う)。文字色は背景から導出する (一覧に手書きしない)。 */
  --t-tl-crimson:    #ff5757;
  --t-tl-orange:     #ff9f43;
  --t-tl-amber:      #fbbf24;
  --t-tl-green:      #5cb85c;
  --t-tl-teal:       #4f9a94;
  --t-tl-azure:      #3e7c93;
  --t-tl-periwinkle: #7c8ed9;
  --t-tl-slate:      #345a86;
  --t-tl-maroon:     #a63d4a;
  --t-tl-graphite:   #4e5560;

  /* ── Tier (TASTEOME tier list の段) ──────────────────────
     🔴 値は --t-tl-* の **id 参照**。並び順ではなく id で結ぶ。
     ⚠ SSS/SS/S は work.css の現行 hex と byte 一致 (色は変えていない)。
     ⚠ A/B は tier 正本 `packages/app/src/local/tiers.ts` の TIERS_BEST と一致させる。
     ⚠ theme で変えない (--t-tl-* を継承 = canvas 書き出しと同値を保つ)。 */
  --t-tier-sss: var(--t-tl-crimson);    /* #ff5757 */
  --t-tier-ss:  var(--t-tl-orange);     /* #ff9f43 */
  --t-tier-s:   var(--t-tl-amber);      /* #fbbf24 */
  --t-tier-a:   var(--t-tl-green);      /* #5cb85c */
  --t-tier-b:   var(--t-tl-periwinkle); /* #7c8ed9 */

  /* ── User list 状態色 (read/favorite/wishlist バッジ。 modal/sidebar/dashboard 共通) ──
     値は軸色と同じだが意味は別系統 — 軸の配色変更でリストバッジを巻き添えにしないため独立 token */
  --t-list-read: #60a5fa;
  --t-list-fav:  #fbbf24;
  --t-list-wish: #f472b6;
  /* negative 状態色 (dislike / delete / 警告的 destructive。 modal/views/tier/mypage 共通) */
  --t-negative: #f87171;

  /* ── Plot / Domain-specific tokens (3D scatter aux) ────── */
  --t-legend-bg: rgba(15,15,25,0.92);
  --t-legend-bar-border: rgba(255,255,255,0.15);
  --t-dot-border: rgba(255,255,255,0.15);
  --t-modebar-bg: rgba(20,20,30,0.7);
  --t-active-bg: color-mix(in srgb, var(--t-fg) 9%, transparent);
  --t-active-border: color-mix(in srgb, var(--t-fg) 28%, transparent);

  /* ── Typography ───────────────────────────────────────── */
  --t-font-sans: -apple-system, BlinkMacSystemFont, 'Hiragino Sans', 'Noto Sans JP', sans-serif;
  --t-font-display: 'Bricolage Grotesque', -apple-system, 'Hiragino Sans', 'Noto Sans JP', sans-serif;
  --t-font-mono: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
  --t-font-serif: 'Hiragino Mincho ProN', 'Yu Mincho', Georgia, serif;

  /* ── Spacing scale (4px base) ──────────────────────────── */
  --t-sp-1: 0.25rem;   /* 4 */
  --t-sp-2: 0.5rem;    /* 8 */
  --t-sp-3: 0.75rem;   /* 12 */
  --t-sp-4: 1rem;      /* 16 */
  --t-sp-5: 1.25rem;   /* 20 */
  --t-sp-6: 1.5rem;    /* 24 */
  --t-sp-8: 2rem;      /* 32 */
  --t-sp-10: 2.5rem;   /* 40 */
  --t-sp-12: 3rem;     /* 48 */

  /* ── 本文の最大幅 (owner 指摘 2026-09-05「左右の余白幅がバラバラ」) ─────────
     🔴 **1 値に潰さず「内容の型」で 2 値**にする — `../../..//docs/design/ART_DIRECTION.md §0`
     「本文幅と列数は面が決めず、**内容の型 (読み物 / 一覧 / ツール) が決める**」。
     実測 (1440・常設 drawer の右 1125px) で不揃いだったのは**同じ型の中**だった:
       読み物 / 一覧 = work 680 / search 680 / profile 760 / post 600  ← バラバラ
       ツール        = me 1100 / mypage 1080                          ← ほぼ揃っている
     ⇒ 前者を 960 に統一 (左右余白 223 → 82 = 「すこし狭める」)、後者を 1100 に統一。
     🔴 **型は 6 つ** (hub 裁定 2026-09-05 の 4 型 + owner 裁定 2026-09-06 [batch 3] で
     LP / 盤面 の 2 型を追加・面ごとに 1 行で分類した)。⚠ **token を当てるのは 4 型**
     (読み物 / 一覧・ツール・timeline・LP) で、**token の値は 5 つ** (LP だけ 2 値)。
     「盤面」と「フォーム」は当てない型 (`ART_DIRECTION.md §0` の「token 5 値」= この 5 値):
       **読み物 / 一覧 = `--t-page-max` 960** — work / post / search / profile /
         people / premium / support / legal / static-page (about・privacy・disclosure) /
         discover
         (⚠ `/discover/` は 2026-09-06 [batch 1 `/discover/` 案 A] に `.hub-main` の
          `/me/` との共有を割り、`.dc-main` [`pages/discover.css`] へ分離した。それまでは
          共有の副産物でツール側 1100 だった — 型で分類し直して一覧側 960 へ移した)
       **ツール = `--t-page-max-tool` 1100** — me / mypage / tierlist / quick / tier
         (tierlist・quick は `repeat(auto-fill, minmax(...))` の grid 主体、tier は
          盤面なのでツール側。⚠ `/tier/` の幅は `.tier-main` ではなく内側の
          `.tl-shell` が決める [`pages/tier-list.css`] — 面の外形だけ見ると漏れる)
       **timeline = `--t-page-max-timeline` 640** — feed / tag
         (`FeedCard` の設計幅。案 B v2.2 の中央列と同値)
       **フォーム = token を当てない** — account 420 / settings 540 は**狭いのが正**
         (入力欄は横に伸ばさない)。`/start/` の 768 も onboarding 専用で対象外。
       **LP = `--t-page-max-lp` 1100 + `--t-page-max-lp-hero` 700** — `/` root の
         hero (`header.hero` 700) と盤面 (`main` の domain カード grid / `.hub-quick` 1100)
         (owner 裁定 2026-09-06 [batch 3])。⚠ 1100 は `--t-page-max-tool` と**同値だが
          別の型**なので `var()` で連結しない — 連結するとツール幅を動かした時に LP が
          黙って動く (逆も同じ)。値が揃っているのは今の一致であって、同じ理由ではない。
       **盤面 = 全幅 (token を当てない)** — ドメイン 3D map **9 面** (manga / anime /
         movie / game / drama / book / variety / musician / album)。器は
         `apps/web/src/ui/domain/domain-map.css` の
         `body[data-page="domain"] .domain-map-main` で、**幅指定を持たず親 (AppShell) に
         追従するのが正** (owner 裁定 2026-09-06 [batch 3])。
     ⚠ `/messages/` (600) は **DM のリデザイン工程待ちで据え置き** — owner が評価済みの
       面を今は動かさない (hub 裁定 2026-09-05)。
     ⚠ 960 は次 unit とも整合する — 作品ページ 案 A v2 (archive 27 §6) の 1440 は
       本文 680 + 右 300 + gap で、**960 に収まる**。
     ⚠ **値はここ 1 箇所**。面ごとの CSS は必ずこの token を参照する
       (面ごとに数値を書くと、次に増えた面が必ず漏れる)。
     ⚠ `/feed/` は 640 + 右レールの仕様どおり**例外** (`components/feed.css`)。 */
  --t-page-max: 960px;
  --t-page-max-tool: 1100px;
  --t-page-max-timeline: 640px;
  --t-page-max-lp: 1100px;
  --t-page-max-lp-hero: 700px;

  /* ── Radii ─────────────────────────────────────────────── */
  --t-r-sm: 5px;
  --t-r-md: 8px;
  --t-r-lg: 10px;

  /* 作品カバーの下地 (contain 時の余白と読込前)。owner 裁定 2026-08-19: テーマ非追従の
     黒固定 (シアター風) — light/dark 両テーマで同値なので theme ブロックで再定義しない。 */
  --t-cover-plate: #0b0a09;
  /* 黒下地上のフォールバック標識色 (テーマ非追従 — 下地に対して決める)。 */
  --t-cover-plate-fg: #a9a196;
  /* 黒下地上の題名・帯の文字 (カバーなしのカード = 案 3「帯」・WEB-COVER-FALLBACK-CARD)。plate-fg より明るい側。 */
  --t-cover-plate-ink: #ece7df;
  --t-r-xl: 12px;
  --t-r-2xl: 16px;
  --t-r-pill: 999px;

  /* ── Shadows (elevation) ───────────────────────────────── */
  --t-shadow-sm: 0 2px 8px rgba(0,0,0,0.15);
  --t-shadow-md: 0 4px 16px rgba(0,0,0,0.25);
  --t-shadow-lg: 0 20px 60px rgba(0,0,0,0.4);
  --t-shadow-cta: 0 1px 2px rgba(0,0,0,0.18);

  /* ── Animation ─────────────────────────────────────────── */
  --t-trans-fast: 0.12s;
  --t-trans: 0.2s;
  --t-trans-slow: 0.3s;

  /* ── Breakpoints (Phase 4 consolidation: 3 canonical sizes) ─ */
  /* CSS custom media は brower support 不足、 number として保持 */
  --t-bp-mobile: 540px;
  --t-bp-tablet: 768px;
  --t-bp-wide: 1024px;

  /* ── Touch / mobile layout ─────────────────────────────── */
  /* 指で押す最小サイズ。Apple HIG / WCAG 2.5.5 の 44×44。
     ⚠ WCAG 2.2 の必須水準 (2.5.8) は 24×24 なので、本文中のテキストリンクまで
       44 を強制はしない — **主導線 (ナビ・ヘッダ・戻る・フォーム部品)** に効かせる。 */
  --t-tap-min: 44px;
  /* 副次の tap 床 (owner 裁定 2026-09-06 / batch 3 裁定 1-①)。
     🔴 **44px の床は一次動作だけ** — 副次の chip / タグ / 補助アイコンは 32 で足りる。
       44 を全部へ敷くと chip 行や card が伸びて、一覧の情報量が落ちる方が実害になる。
     ⚠ 32 は「**行間 8 = `--t-sp-2` を確保する**」とセットの値 (裁定の逐語)。副次要素が
       隣り合う行 / 列の gap がこれ未満なら 8 まで上げる — 誤爆は高さだけでは消えない。 */
  --t-tap-sub: 32px;
  /* ボトムナビ (モバイル専用) の実効高 = タブの min-height 52px + border-top 1px。
     🔴 **画面下に固定する要素はこの分だけ上げる** — 同意バナーがナビを覆って
       5 タブすべてが押せなくなっていた (2026-08-30 実測)。正は
       `shared/css/layout/bottom-nav.css` の `.bnav-tab { min-height }`。 */
  --t-bnav-h: 53px;
  /* 同意バナーの実効高。⚠ **観測値ではなく `min-height` として強制する値**
     (`ui/settings/consent-banner.css` が同じ token で `min-height` を敷く)。
     観測値を焼くと文言や locale で折返しが変わった時に静かにずれるので、
     「バナーは必ずこの高さ以上」という**契約**にして、余白を取る側と同じ数字を使う。
     🔴 画面下に主導線を置く面は、バナーが出ている間この分だけ避ける
       (2026-08-30 実測: `/start/` の主要ボタン 2 つが 360×780 の初期表示で押せなかった)。
     ⚠ 文言が伸びて実高がこれを超えた場合、避け幅は不足側に倒れる (安全側ではない) —
       文言を大きく増やす時はこの値も見直すこと。 */
  --t-consent-h: 120px;
}

/* 🔴 **desktop のバナー実高は別物** (2026-09-19 実測・5 言語 × 5 幅)。
   ⚠ 実測 = ≤767 は 120px (下の `min-height` の契約どおり) / 768〜1023 は **113〜118px**
     (言語で振れる) / **≥1024 は 69px で 5 言語とも同値** (ja / en / fr / ko / zh-Hant)。
   ⇒ 120px を desktop へそのまま使うと **51px 過剰に持ち上がる**。⇒ 幅で値を分け、
     `consent-banner.css` が `min-height` を**全幅**で効かせて **token を全幅で真にする**。
   ⚠ 72px は実測 69px に 3px の床余裕を足した値 (文言が伸びた時に不足側へ倒れないため)。
   ⚠ **観測値を JS から publish する形は採らない** — 既存が「観測値ではなく強制値」を
     選んでおり (`consent-banner.css:156-160`)、増やすと高さの source が 2 通りになる。 */
@media (min-width: 1024px) {
  :root { --t-consent-h: 72px; }
}

/* ── Legacy alias (旧 --bg/--text 系 — Domain も Hub も共用) ─────
   既存 component file (plot.css 等) が --bg / --surface 等を直参照しているため、
   alias で t-token に pass-through する。 新規 CSS は --t-* を直接使うこと。
   ⚠ 重要: page CSS で :root を上書きすると data-theme toggle が効かなくなるので禁止。
            必要な alias はここに追加すること。 */
:root {
  --bg: var(--t-bg);
  --surface: var(--t-surface);
  --surface2: var(--t-surface-hover);
  --border: var(--t-border);
  --border-strong: var(--t-border-strong);
  --text: var(--t-fg);
  --dim: var(--t-dim);
  --mid: var(--t-fg-soft);
  --accent: var(--t-accent);
  --muted: var(--t-muted);
  --fg: var(--t-fg);
  --gold: var(--t-accent-warm);
  --legend-bg: var(--t-legend-bg);
  --legend-bar-border: var(--t-legend-bar-border);
  --dot-border: var(--t-dot-border);
  --modebar-bg: var(--t-modebar-bg);
  --active-bg: var(--t-active-bg);
  --active-border: var(--t-active-border);
  /* Hub / Onboarding / Static page で使用 (旧 page CSS の :root 重複定義から集約) */
  --card-bg: var(--t-bg-elev);
  --card-border: var(--t-border);
  --hover-bg: var(--t-active-bg);
  --hover-border: var(--t-border-hover);
  --selected-bg: var(--t-active-bg);
  --selected-border: var(--t-accent);
}

/* Light mode (auto: prefers-color-scheme) — Hub / Legal / Root (toggle UI なし) ─ */
@media (prefers-color-scheme: light) {
  :root {
    --t-cog-ink: color-mix(in srgb, var(--t-cog) 45%, var(--t-fg));
    --t-emo-ink: color-mix(in srgb, var(--t-emo) 45%, var(--t-fg));
    --t-sem-ink: color-mix(in srgb, var(--t-sem) 45%, var(--t-fg));
    --t-vis-ink: color-mix(in srgb, var(--t-vis) 45%, var(--t-fg));
    --t-length-ink: color-mix(in srgb, var(--t-length) 45%, var(--t-fg));
    --t-mass-ink: color-mix(in srgb, var(--t-mass) 45%, var(--t-fg));
    --t-weight-ink: color-mix(in srgb, var(--t-weight) 45%, var(--t-fg));
    --t-arousal-ink: color-mix(in srgb, var(--t-arousal) 45%, var(--t-fg));
    --t-valence-ink: color-mix(in srgb, var(--t-valence) 45%, var(--t-fg));
    --t-structure-ink: color-mix(in srgb, var(--t-structure) 45%, var(--t-fg));
    --t-open-ink: color-mix(in srgb, var(--t-open) 45%, var(--t-fg));
    --t-world-ink: color-mix(in srgb, var(--t-world) 45%, var(--t-fg));

    color-scheme: light;
    --t-switch-on: var(--t-accent);
    --t-bg: #f6f7fb;
    --t-bg-elev: #ffffff;
    --t-bg-elev-2: rgba(0,0,0,0.03);
    --t-surface: #ffffff;
    --t-surface-hover: #f4f4f7;
    --t-fg: #1a1d2b;
    --t-fg-soft: #4a4e60;
    --t-muted: #6b7080;
    --t-danger: #c92a45;
    /* v=66: light theme の --t-dim は dark bg をなぞる必要なし、 dark gray で safe */
    --t-dim: #5a5f73;
    --t-border: #e3e6ef;
    --t-border-strong: #c5cad9;
    --t-border-control: color-mix(in srgb, var(--t-fg) 50%, transparent);
    --t-rule: color-mix(in srgb, var(--t-fg) 15%, transparent);
    --t-press-bg: color-mix(in srgb, var(--t-fg) 12%, transparent);
    --t-accent: #16181f;          /* monochrome ink (light) */
    --t-on-accent: #ffffff;
    --t-accent-grad: var(--t-accent);
    --t-legend-bg: rgba(255,255,255,0.95);
    --t-legend-bar-border: rgba(0,0,0,0.08);
    --t-dot-border: rgba(0,0,0,0.1);
    --t-modebar-bg: rgba(255,255,255,0.7);
    --t-active-bg: color-mix(in srgb, var(--t-fg) 7%, transparent);
    --t-active-border: color-mix(in srgb, var(--t-fg) 28%, transparent);
    --t-bg-grad: var(--t-bg);
    --t-bg-radial-accents: none;
    --t-tier-bronze: #9a5b25;
    --t-tier-silver: #6b7280;
    --t-tier-gold:   #8a6a00;
  }
}

/* Explicit theme toggle (Domain page の data-theme attribute / Phase 5 で Hub にも適用) ─ */
:where(html, body)[data-theme="dark"] {
  /* ⚠ @media(prefers-color-scheme: light) が上書きする token は **明示 dark でも再宣言する**。
     しないと OS が light の端末で dark を選んだとき light の値が残る (軸ラベルが暗い文字のまま
     dark 背景に載る)。同型は test/app/color-contrast.test.ts が全 token で検査する。 */
  --t-cog-ink: var(--t-cog);
  --t-emo-ink: var(--t-emo);
  --t-sem-ink: var(--t-sem);
  --t-vis-ink: var(--t-vis);
  --t-length-ink: var(--t-length);
  --t-mass-ink: var(--t-mass);
  --t-weight-ink: var(--t-weight);
  --t-arousal-ink: var(--t-arousal);
  --t-valence-ink: var(--t-valence);
  --t-structure-ink: var(--t-structure);
  --t-open-ink: var(--t-open);
  --t-world-ink: var(--t-world);

  color-scheme: dark;
  --t-switch-on: var(--t-muted);
  --t-bg: #0b0e1a;
  --t-bg-elev: rgba(255,255,255,0.04);
  --t-bg-elev-2: rgba(255,255,255,0.06);
  --t-surface: #14141f;
  --t-surface-hover: #1c1c2c;
  --t-fg: #e8eaf2;
  --t-fg-soft: #b8bdd0;
  --t-muted: #8a8fa3;
  --t-danger: #ff6b7e;
  /* v=66: contrast safe (5.83:1 on dark --t-bg) */
  --t-dim: #8e94aa;
  --t-border: rgba(255,255,255,0.08);
  --t-border-strong: rgba(255,255,255,0.15);
  --t-border-control: color-mix(in srgb, var(--t-fg) 40%, transparent);
  --t-rule: color-mix(in srgb, var(--t-fg) 20%, transparent);
  --t-press-bg: color-mix(in srgb, var(--t-fg) 16%, transparent);
  /* v=239: OS light + data-theme="dark" で @media(light) の accent が残らないよう明示 */
  --t-accent: #eef0f7;
  --t-on-accent: #0b0e1a;
  --t-accent-grad: var(--t-accent);
  --t-legend-bg: rgba(15,15,25,0.92);
  --t-legend-bar-border: rgba(255,255,255,0.15);
  --t-dot-border: rgba(255,255,255,0.15);
  --t-modebar-bg: rgba(20,20,30,0.7);
  --t-active-bg: color-mix(in srgb, var(--t-fg) 9%, transparent);
  --t-active-border: color-mix(in srgb, var(--t-fg) 28%, transparent);
  /* v=83: --t-bg-grad/--t-bg-radial-accents が OS light + data-theme="dark" の状況で
     light 版に上書きされる bug 修正。 dark override にも明示。 daily.css の `.daily-main`
     等で page header 以外が light 残る問題を解消。 */
  --t-bg-grad: var(--t-bg);
  --t-bg-radial-accents: none;
  --t-tier-bronze: #cd7f32;
  --t-tier-silver: #c0c0c0;
  --t-tier-gold:   #d4a017;
}
:where(html, body)[data-theme="light"] {
  --t-cog-ink: color-mix(in srgb, var(--t-cog) 45%, var(--t-fg));
  --t-emo-ink: color-mix(in srgb, var(--t-emo) 45%, var(--t-fg));
  --t-sem-ink: color-mix(in srgb, var(--t-sem) 45%, var(--t-fg));
  --t-vis-ink: color-mix(in srgb, var(--t-vis) 45%, var(--t-fg));
  --t-length-ink: color-mix(in srgb, var(--t-length) 45%, var(--t-fg));
  --t-mass-ink: color-mix(in srgb, var(--t-mass) 45%, var(--t-fg));
  --t-weight-ink: color-mix(in srgb, var(--t-weight) 45%, var(--t-fg));
  --t-arousal-ink: color-mix(in srgb, var(--t-arousal) 45%, var(--t-fg));
  --t-valence-ink: color-mix(in srgb, var(--t-valence) 45%, var(--t-fg));
  --t-structure-ink: color-mix(in srgb, var(--t-structure) 45%, var(--t-fg));
  --t-open-ink: color-mix(in srgb, var(--t-open) 45%, var(--t-fg));
  --t-world-ink: color-mix(in srgb, var(--t-world) 45%, var(--t-fg));

  color-scheme: light;
  --t-switch-on: var(--t-accent);
  --t-bg: #f6f7fb;
  --t-bg-elev: #ffffff;
  --t-bg-elev-2: rgba(0,0,0,0.03);
  --t-surface: #ffffff;
  --t-surface-hover: #f4f4f7;
  --t-fg: #1a1d2b;
  --t-fg-soft: #4a4e60;
  --t-muted: #6b7080;
  --t-danger: #c92a45;
  /* v=66: dark gray on light bg (5.80:1 contrast、 WCAG AA) */
  --t-dim: #5a5f73;
  --t-border: #e3e6ef;
  --t-border-strong: #c5cad9;
  --t-border-control: color-mix(in srgb, var(--t-fg) 50%, transparent);
  --t-rule: color-mix(in srgb, var(--t-fg) 15%, transparent);
  --t-press-bg: color-mix(in srgb, var(--t-fg) 12%, transparent);
  --t-accent: #16181f;          /* monochrome ink (light) */
  --t-on-accent: #ffffff;
  --t-accent-grad: var(--t-accent);
  --t-legend-bg: rgba(255,255,255,0.95);
  --t-legend-bar-border: rgba(0,0,0,0.08);
  --t-dot-border: rgba(0,0,0,0.1);
  --t-modebar-bg: rgba(255,255,255,0.7);
  --t-active-bg: color-mix(in srgb, var(--t-fg) 7%, transparent);
  --t-active-border: color-mix(in srgb, var(--t-fg) 28%, transparent);
  --t-bg-grad: var(--t-bg);
  --t-bg-radial-accents: none;
  --t-tier-bronze: #9a5b25;
  --t-tier-silver: #6b7280;
  --t-tier-gold:   #8a6a00;
}

/* Universal body background — 全 page で token を反映 (旧 tier/daily の transparent 問題解消)。
   base.css (Domain) は body に flex/overflow を追加上書きするが background はここで統一。 */
html, body {
  background: var(--t-bg);
  color: var(--t-fg);
  /* 🔴 **UA 既定 `body { margin: 8px }` の reset も単一経路**にする (owner 面 = mobile との
     並置で発覚 / 2026-09-13)。⚠ 実測 (402 幅・全 41 面) で **10 面に 8px が残っていた**
     (feed / post / tag / work / search / people / mypage / messages / quick / tierlist) —
     本文幅が **386 / 402** になり、同じ幅の Expo 側 (418) と 16px ずれていた。
     ここに置く理由 = 書体と同じ (`core/base.css` の `* { margin: 0 }` は domain の 9 面しか
     link しない)。⇒ 救済していた 5 file (`tier-list` / `identity-hub` / `static-page` /
     `onboarding` / `pages/root/root.css`) の宣言はこの 1 行へ寄せて撤去した。 */
  margin: 0;
  /* 🔴 本文書体の単一経路 (C-2 根治・owner 裁定 2026-09-04)。**配信 35 面で body の書体を宣言
     するのはこの 1 行だけ** — 複製すると「どれが効いているか」が面ごとに変わる。
     ここに置く理由 = `core/base.css` は domain page 専用 file (`*` の margin/padding reset と
     Google Fonts の `@import` を持つ) で **9 面しか link しない**。残り 26 面のうち 15 面は
     `static-page.css` / `identity-hub.css` / `onboarding.css` / `root.css` が body 宣言を
     各々持って**偶然**救済していただけで、**11 面 (work / search / people / mypage / messages /
     quick / tierlist と、容器だけ持つ feed / post / tag / tier) は UA 既定 (desktop で serif)**
     に落ちていた。⇒ 根治後は救済側の 4 file から同宣言を消してこの 1 行へ寄せてある。
     ⚠ **webfont Noto Sans JP / JetBrains Mono の読込経路は無い** — かつて `base.css` (domain 9 面) に
     在った Google Fonts の `@import` は `_headers` の CSP (`style-src` / `font-src` に Google Fonts の
     host 無し) で導入以来ブロックされ続けていたため、2026-09-20 (owner 裁定 (a)) に撤去した。
     self-host は Bricolage Grotesque のみ (直下の `@font-face`)。⇒ `-apple-system` / `Hiragino Sans`
     が解決せず Noto Sans JP も入っていない環境 (Windows 等) は **全 35 面**が stack 末尾の generic
     `sans-serif` で描かれる (9 面と 26 面で差は無い)。webfont を配るかは別裁定 (self-host か CSP 許可か
     = request 追加 / security posture の変更・hub 預かり 2026-09-05)。 */
  font-family: var(--t-font-sans);
}

/* v=86: Universal button UA reset — 再発防止
   <button> は UA で background: buttonface (light gray) + color: black が default 適用される。
   author CSS で background: var(--t-bg-elev) 等を指定しても、 appearance: auto のままだと
   一部 browser (Chrome Mac、 iOS Safari) で UA styling が優先される現象がある。
   全 <button> に appearance: none を強制し、 各 component CSS は background/color/border
   を明示的に設定する pattern を強制する。
   font/border の reset は副作用が大きいため row reset せず、 visual neutralizing のみ。 */
button {
  appearance: none;
  -webkit-appearance: none;
}

/* ── Display typography (Bricolage Grotesque。 見出し・ロゴ・数値。 ART_DIRECTION.md §1) ── */
h1, h2, h3, .site-brand, .wordmark, .hero-title, .page-title, .hub-title {
  font-family: var(--t-font-display);
  letter-spacing: -0.01em;
}

/* ── Line icon (window.Icon / shared/js/ui/icons.js。 currentColor 描画。 ART_DIRECTION.md §4) ── */
svg.ic { vertical-align: -0.15em; flex: none; }
/* flex/grid な icon コンテナ内では中央寄せ (vertical-align は無視される) */
.bnav-icon, .drawer-icon, .sd-grid-icon, .tl-icon, .header-search, .acct-nav-bell {
  display: inline-flex; align-items: center; justify-content: center;
}
