/* ─── View Selector (sticky bottom bar) ───────────────────────────────── */
/* 4 view tab を画面下端に常設。 mobile-first、 desktop でも継続。 */

.view-selector {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  background: var(--t-surface);
  border-top: 1px solid var(--t-border);
  padding-bottom: env(safe-area-inset-bottom, 0);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* 🔴 `role="tablist"` を持つのは内側の `.vs-tabs` (4 tab だけ) — Me chip は tab ではなく
   `aria-pressed` のトグルなので同じ tablist に入れない (2026-09-07 で 2 層化)。
   ⚠ 見た目は据え置き: `.vs-tabs` は「残り幅を取り、4 tab を等分する」だけの器で、
   bar の fixed / 高さ (実効 54px) / 上境界 / 背景は `.view-selector` が持ったまま。
   ⚠ `min-width: 0` は置かない — 置くと狭幅で `.vs-tabs` だけが縮んで tab が
   `.vs-sep` / Me chip へ重なる。既定 (auto) なら現行どおり「縮まずに bar ごと溢れる」。 */
.vs-tabs {
  flex: 1;
  display: flex;
}

.vs-tab {
  flex: 1;
  padding: 0.65rem 0.5rem;
  background: transparent;
  border: none;
  color: var(--dim, #9090b0);
  font-size: 0.78rem;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  border-top: 2px solid transparent;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}

.vs-tab .vs-icon {
  font-size: 1.15rem;
  line-height: 1;
}

.vs-tab:hover {
  color: var(--text, #e8e8f5);
  background: color-mix(in srgb, var(--t-accent) 6%, transparent);
}

.vs-tab.is-active {
  color: var(--accent, var(--t-accent));
  border-top-color: var(--accent, var(--t-accent));
  background: color-mix(in srgb, var(--t-accent) 8%, transparent);
}
/* v=66: light theme は accent text on light tinted bg で 2.80 contrast → fg に override */
:where(html, body)[data-theme="light"] .vs-tab.is-active {
  color: var(--t-fg);
}


/* compare basket は selector の上に乗せる。
   🔴 **bar の高さは `--dm-bar-h` (実測値) を読む** (2026-09-11)。旧 54px literal は
      **bar の実高と違っていた** — 実測 = 63px (390) / 70.6px (1440) なので、かごの下端が
      8.6px ぶん bar の帯へ入り込み、かご (z-index 1800) が bar (50) のタブ上端を覆っていた。
      値の正 = `DomainMapPage` の ResizeObserver が `.view-selector` を測って
      `document.documentElement` へ publish する `--dm-bar-h` (`--dm-basket-h` と同型)。
      fallback 54px は bar がまだ描かれていない初回 frame 用。
   🔴 **かご / 同意バナーは bar の項を持ち、`.timebar` は持たない — この非対称は position の
      違い**: かご・バナーは `position: fixed` (viewport 基準) なので自分で bar を避ける必要が
      あるが、`.timebar` は `position: absolute` で基準の `.domain-map__plot-wrap` の下端が
      `body[data-view] .domain-map__body` の `padding-bottom: calc(var(--dm-bar-h) + env(…))`
      で**既に bar のぶん持ち上がっている** (足すと二重計上になる)。
   ⚠ `--dm-bar-h` は safe-area の padding を除いた内側の高さなので、`env()` は別に足すのが正。 */
.compare-basket {
  bottom: calc(var(--dm-bar-h, 54px) + env(safe-area-inset-bottom, 0) + 8px) !important;
}

/* timebar も。
   🔴 **bar の項 (54px + env) を持たないのが正** (2026-09-11 で二重計上を解消)。上のかご /
      同意バナーとの非対称の理由は position の違い — `.timebar` は `position: absolute`
      (`shared/css/components/plot.css` の `.timebar`) で、基準の `.domain-map__plot-wrap`
      (`ui/domain/domain-map.css` = `position: relative`) の下端は
      `body[data-view] .domain-map__body` の `padding-bottom: calc(var(--dm-bar-h) + env(…))`
      によって**既に bar のぶん持ち上がっている**。そこへ再び足していたため、意図 (「bar の
      6px 上」) に対して **viewport 下端から 114.4px (390) / 114.2px (1440)** も浮いていた。
      ⇒ 器の座標で `6px` と書けば、viewport 座標では `bar + env + 6` になる。
   🔴 **`--dm-basket-h` は残す** (2026-09-08) — かご (`bottom: bar + env + 8`) の**上**に
      居るのがこの規則の意図だが、**かごが折り返して背が高くなると追い抜かれる**。実測 =
      390 で 2 件のかごは 97px 高 (768 以上は 41px) で、かごの z-index 1800 > timebar 40 の
      ため `.timebar-range` の中心がかごに隠れた。
   ⚠ **バナーの有無に関わらず起きる** — 下の同意バナー用の規則は `:has(#ts-consent-banner)`
     条件なので、バナーが出ていない通常時はこちらが担当する。
   ⚠ かご不在なら `0px` に落ちる。実高は `DomainMapPage` の ResizeObserver が焼き直す
     (固定値だと折返しで破綻する)。
   ⚠ archive 32 §3.1 A-14 の「かご × 年代バー」の半分をここで閉じる
     (残る「かご × FAB」は別 unit の預かり)。 */
.timebar {
  bottom: calc(var(--dm-basket-h, 0px) + 6px) !important;
}

/* 🔴 **同意バナーが出ている間は、bar の上に載る 2 つも バナーの分だけ上げる**
   (2026-09-07 / batch 3 E-1)。バナーは `body[data-page="domain"]` で **bar の高さ (54px)
   だけ持ち上げて bar の上に接地**する (`ui/settings/consent-banner.css`) ので、その上に
   居た `.compare-basket` (62+SA・VS と削除ボタンを持つ) と `.timebar` (再生 / reset /
   range を持つ) が **バナーの帯の内側に入って押せなくなる** — bar を救ってこの 2 つを
   埋めるのでは欠陥を移しただけになる。
   ⚠ **高さは token 値 (120px) で組み、上振れ側へ倒す** — desktop にはバナーの高さ契約が
     無く実高は内容依存 (1440×900 匿名の実測 = 69px / 折返しで locale ごとに変わる)。
     51px 余分に上げると 2 つが少し高く浮くが、**下回ると押せない**。同じ判断と同じ実測の
     出所 = `apps/web/src/pages/profile/profile.css:252-264` (desktop の被り手当て)。
   ⚠ 浮きが目に付かないのは、この 2 つが**画面の縁に接地する chrome ではなく plot の上に
     浮く chrome** だから (bar 自身を上げると縁から離れて「宙に浮く」= 元の裁定が避けた形)。
   ⚠ `!important` 同士なので詳細度で勝たせる ((0,3,1) > (0,1,0))。`:has()` 非対応の環境では
     規則ごと落ち、バナーが出ている間だけこの 2 つが埋まる = **この規則を入れる前と同じ**で
     悪化しない。
   ⚠ バナーは同意済みだと **DOM ごと出ない** (`ConsentBanner.tsx`) ので `:has()` が外れ、
     持ち上げも同時に消える (残らない)。
   🔴 **bar の高さは `--dm-bar-h` (実測値) を読む** (2026-09-11)。旧注記「54px は token 化
     しない」は、design token 化 (= 固定値に名前を付ける) を禁じる趣旨だった。ここで入れる
     のは token ではなく **`--dm-basket-h` と同型の実測値の publish** (ResizeObserver が
     `.view-selector` を測る) で、literal を散らすのをやめて**値の正を publish 側 1 箇所へ
     集約**する。⇒ bar の高さの見えを変える時に直すのは `DomainMapPage` の publish だけ。
     ⚠ `apps/web/test/app/list-view-structure.test.ts` が `domain-map.css` の
       `padding-bottom: calc(var(--dm-bar-h, 54px) + env(…))` を**逐語で pin している** —
       2026-09-11 に pin も var 経路へ追随済み (assert の意図「下端余白が宣言されている」は
       不変で、var の書き手が消えた時も落ちる向きに強くなっている)。 */
body[data-page="domain"]:has(#ts-consent-banner) .compare-basket {
  bottom: calc(var(--dm-bar-h, 54px) + var(--t-consent-h, 120px) + env(safe-area-inset-bottom, 0) + 8px) !important;
}
/* 🔴 **`.timebar` だけ式が違う — bar の 54px と safe-area を足さない** (実測で確定)。
   `.compare-basket` は `position: fixed` (viewport 基準) だが、**`.timebar` は
   `position: absolute`** (`shared/css/components/plot.css` の `.timebar`) で、基準は
   **`.domain-map__plot-wrap`** (`ui/domain/domain-map.css:407-411` = `position: relative`)。
   ⚠ `plot.css` の `.canvas-wrap` は **legacy の器で React はこの面に描かない** (実測 =
     `apps/web/src` に `canvas-wrap` の描画は 0 件) — 基準を取り違えないこと。その器の下端は
   `body[data-view] .domain-map__body` の
   `padding-bottom: calc(var(--dm-bar-h, 54px) + env(...))` (上の規則) によって
   **既に viewport 下端から bar + safe-area の位置**にある。
   ⇒ 器の座標で `X` は viewport 座標の `bar + env + X` を意味し、バナー上端も
     `bar + env + バナー高` (`consent-banner.css` の `bottom: calc(var(--dm-bar-h, 54px) +
     env(…))` + 自身の高さ) なので、**必要なのは「バナーの高さぶん」だけ** (bar と env は相殺)。
   ✅ **2026-09-11 の var 化後もこの式は正しいまま** — 器の padding とバナーの `bottom` が
     同じ `var(--dm-bar-h, 54px) + env(…)` を使うので、相殺の前提が崩れない
     (54 → 63 のように値が動いても両辺が同じだけ動く)。
   ⚠ bar の項を足すと二重計上で浮く (実測で確認して外した = 390 で viewport 下端から 234px)。
   ✅ 上の基底規則にあった同じ二重計上 (archive 32 §3.1 A-14 の「親の padding-bottom と
     自身の offset を二重に足して 114px 浮く」) も 2026-09-11 に解消済み。 */
/* 🔴 **比較かごの上へ積む** (2026-09-07)。同意バナー表示中は `.timebar` が viewport から
   約 180px・`.compare-basket` が 182px で、z-index は basket 1800 > timebar 40 →
   **かごが年代操作を覆う**。390 では開いた timebar が左右 8px まで広がる
   (`mobile.css` の A5) ので水平にも必ず交差する。
   ⚠ かごの実高は折返しで変わる (390 で 2 件 = 97px / 768 以上 = 41px 実測) ので固定値を
     焼かず、`DomainMapPage` の ResizeObserver が `--dm-basket-h` を焼き直す
     (`--dm-top-offset` と同じ idiom)。⚠ かごが無い時は 0px = **在る時だけ持ち上がる**。
   ⚠ この式は**閉じたボタンにも要る** — `.timebar` の底辺位置を決める式そのものだから。
   🔴 **末尾は `6px` ではなく `14px`** — かご自身が `+ 8px` の位置から始まる (上の規則) ので、
     `--dm-basket-h` を足しただけでは **年代バーの下端 2px がかごの下に残る**
     (かごの z-index 1800 > timebar 40)。⇒ **かごの offset 8 + 間隔 6 = 14** を足して、
     かごの上端 (`--dm-bar-h + C + env + かご占有`) を 6px 上回らせる。
     ✅ 2026-09-11: かご自身の offset 8px は **`--dm-basket-h` の publish 側**が持つように
       なったので、ここの末尾は基底規則と同じ `+ 6px` (= 「かごの 6px 上」) で足りる。
     ⚠ 基底規則の `6px` は「bar の上に 6px 空ける」意味で、こちらは「かごの上に空ける」= 別の量。 */
body[data-page="domain"]:has(#ts-consent-banner) .timebar {
  bottom: calc(var(--t-consent-h, 120px) + var(--dm-basket-h, 0px) + 6px) !important;
}

@media (max-width: 480px) {
  .vs-tab {
    font-size: 0.7rem;
    padding: 0.55rem 0.4rem;
  }
  .vs-tab .vs-icon {
    font-size: 1rem;
  }
}

/* ── Taste Overlay chip (sticky bottom 右端) ──────────────────────── */
/* v=51: Me chip を強調 — gold gradient border + 大きめ icon + 強めの separator */
.vs-sep {
  width: 1px;
  align-self: center;
  height: 70%;
  background: linear-gradient(180deg, transparent 0%, var(--border-strong, rgba(255,255,255,0.18)) 30%, var(--border-strong, rgba(255,255,255,0.18)) 70%, transparent 100%);
  margin: 0 0.5rem 0 0.3rem;
  flex-shrink: 0;
}
.vs-me {
  flex: 0 0 auto;
  padding: 0.55rem 1rem;
  /* off 状態でも subtle gold tint で primary 感を出す */
  background:
    linear-gradient(color-mix(in srgb, var(--t-accent-warm) 6%, transparent), color-mix(in srgb, var(--t-accent-warm) 6%, transparent)) padding-box,
    var(--t-accent-grad) border-box;
  border: 1.5px solid transparent;
  border-radius: 999px;
  color: var(--t-accent-warm);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  margin: 0.25rem 0.5rem 0.25rem 0;
  transition: all 0.18s;
  box-shadow: 0 2px 8px rgba(212,160,23,0.18);
}
.vs-me .vs-icon { font-size: 1.35rem; line-height: 1; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.3)); }
.vs-me:hover:not(.is-disabled) {
  filter: brightness(1.15);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(212,160,23,0.32);
}
.vs-me.is-on {
  background: color-mix(in srgb, var(--t-accent) 22%, transparent) padding-box,
    var(--t-accent) border-box;
  color: var(--t-on-accent);
  box-shadow: var(--t-shadow-sm);
}
/* light: 半透明 accent bg (alpha 0.2-0.28) は淡色化して white text が読めない → fg に (v=66 規約) */
:where(html, body)[data-theme="light"] .vs-me.is-on { color: var(--t-fg); }
.vs-me.is-on .vs-icon { filter: drop-shadow(0 1px 3px rgba(0,0,0,0.4)); }
/* 未サインイン (disabled) = 低強調だが可読に。 opacity で文字ごと潰すと light で
   背景に沈む (user 報告「文字と背景色がかぶる」) → muted 色 + solid surface で表現。 */
.vs-me.is-disabled {
  cursor: not-allowed;
  background: var(--t-surface-hover);
  border-color: var(--t-border-strong);
  color: var(--t-muted);
  box-shadow: none;
}
.vs-me.is-disabled:hover { transform: none; filter: none; }
@media (max-width: 480px) {
  .vs-me { font-size: 0.7rem; padding: 0.45rem 0.7rem; margin: 0.2rem 0.4rem 0.2rem 0; }
  .vs-me .vs-icon { font-size: 1.2rem; }
}
