/* CoSpark — 会員ページ共通のサイドバー
 *
 * PCではアイコンだけの細いバー（ラベルはホバー時に吹き出しで出す）、
 * スマホでは従来どおりラベル付きのドロワーとして開く。
 *
 * 各ページの <style> より前に読み込むこと。ページ側で上書きできるようにするため。
 * ページ側では .content の margin-left を 72px（スマホは 0）にしておく。
 */

.sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; width: 72px; z-index: 200;
  display: flex; flex-direction: column; align-items: center;
  padding: 18px 0 14px; gap: 4px;
  background: var(--card); border-right: 1px solid var(--border);
  transition: transform .25s ease;
}

/* ブランド（ロゴ） */
.sidebar .brand {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-size: 19px; font-weight: 700; letter-spacing: -0.02em;
  padding: 0; margin-bottom: 10px; height: 34px; flex-shrink: 0;
  /* 吹き出し（.side-text）の位置の基準にする。
     これが無いと .sidebar 基準になり、吹き出しが画面のずっと下に出てしまう */
  position: relative;
}
/* ブランドマーク：大文字のCと、そこから飛び出す星。トップページへ戻るボタンも兼ねる */
.logo-dot {
  width: 22px; height: 22px; flex-shrink: 0;
  background: url(/brand/cospark-mark.png) center/contain no-repeat;
}

/* プロフィール欄（アイコンのみ） */
.sidebar .side-user {
  display: flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; padding: 0; margin: 0 0 6px;
  background: none; border: none; border-radius: 50%; cursor: pointer;
  position: relative; flex-shrink: 0;
}
.sidebar .side-user .avatar {
  width: 34px; height: 34px; font-size: 13px;
  border: 2px solid transparent; transition: border-color .15s ease;
}
@media (hover: hover) and (pointer: fine) { .sidebar .side-user:hover .avatar { border-color: var(--red); } }
/* 編集の鉛筆アイコンは profile-edit.js が差し込む。PCでは幅がないので隠す */
.sidebar .side-user-edit { display: none; }

/* メニュー */
.side-nav {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  flex: 1; width: 100%;
  padding-top: 8px; margin-top: 4px; border-top: 1px solid var(--border);
  /* overflow は指定しない。指定すると、はみ出して表示するツールチップが切れてしまう */
}

.side-item {
  display: flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; padding: 0; border-radius: 14px;
  color: var(--text); cursor: pointer; position: relative; flex-shrink: 0;
  font-size: 14.5px; font-weight: 600;
  transition: background .15s ease, color .15s ease;
}
.side-item svg { width: 21px; height: 21px; flex-shrink: 0; color: var(--sub); }
@media (hover: hover) and (pointer: fine) { .side-item:hover { background: var(--surface); } }
@media (hover: hover) and (pointer: fine) { .side-item:hover svg { color: var(--text); } }
.side-item.active { background: var(--red-light); color: var(--red-dark); }
.side-item.active svg { color: var(--red-dark); }
.side-item.disabled { opacity: .45; cursor: default; }
@media (hover: hover) and (pointer: fine) { .side-item.disabled:hover { background: none; } }

/* ラベルはPCでは吹き出し（ホバーで表示）にする */
.side-text {
  position: absolute; left: calc(100% + 10px); top: 50%; transform: translateY(-50%);
  background: var(--text); color: var(--bg);
  font-size: 12.5px; font-weight: 700; white-space: nowrap;
  padding: 6px 11px; border-radius: 9px;
  opacity: 0; pointer-events: none; transition: opacity .14s ease;
  box-shadow: 0 4px 14px rgba(0,0,0,.16); z-index: 10;
}
@media (hover: hover) and (pointer: fine) {
  .side-item:hover .side-text,
  .side-user:hover .side-text,
  .brand:hover .side-text { opacity: 1; }
}

/* PCでは見出しラベルとバッジの数字を出さない（幅がないため） */
.side-label { display: none; }
.soon { display: none; }

/* 未読バッジはアイコンの右上に小さく重ねる（アイコンを隠さない大きさに抑える） */
.side-badge {
  position: absolute; top: 3px; right: 3px;
  box-sizing: border-box;
  min-width: 18px; height: 18px; padding: 0 4px;
  background: var(--red); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 14px; text-align: center;
  border-radius: 100px; border: 2px solid var(--card);
}

/* ※設定・ログアウトはサイドバーから外し、プロフィールページ（profile.html）
   へ集約した。そのため .side-foot は使っていない。
   メンバー検索・通知は右上の .top-actions に置く（検索バーがベルの左）。
   （フリートークは 2026-09-23 に廃止した） */

/* ===== 継続日数の炎バッジ =====
 * アイコンの右上に小さく重ねる。バッジを差し込むのは streak.js。
 * アイコンが出るページすべてで同じ見た目にするため、ここに置いている。
 *
 * .streak-wrap は streak.js がアイコンを包むために作る枠。
 * アイコン自体は overflow:hidden なことが多く、中に入れるとバッジが切れてしまう。 */
.streak-wrap {
  position: relative; display: inline-flex; flex-shrink: 0; vertical-align: middle;
}
/* 大きさはアイコンの直径に合わせて streak.js が3段階で付け替える。
   既定は中サイズ（40〜63pxのアイコン用）。 */
.streak-badge {
  position: absolute; top: -3px; right: -5px; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 4px;
  border-radius: 100px; border: 2px solid var(--card);
  background: linear-gradient(160deg, #ff9d00 0%, #f5580a 55%, #d81e12 100%);
  color: #fff; font-size: 10px; font-weight: 800; letter-spacing: -0.02em;
  box-shadow: 0 0 0 1px rgba(216, 30, 18,.10), 0 2px 8px rgba(245,88,10,.42);
  pointer-events: none; /* アイコンのタップ（プロフィールへ移動）を邪魔しない */
}
.streak-badge .flame {
  width: 9px; height: 9px; margin-right: 1px; flex-shrink: 0;
  /* 炎がゆらぐ演出。動きを減らす設定の人には出さない（下の@mediaで無効化） */
  animation: flame-flicker 1.5s ease-in-out infinite;
  transform-origin: 50% 85%;
}

/* 小さいアイコン（サイドバー・下部タブ・トークの吹き出しなど）。
   ここにも日数を出すので、文字と炎を詰めて高さを抑える。
   バッジはアイコンの右上から少し外へずらし、顔が隠れすぎないようにする。 */
.streak-badge-sm {
  top: -5px; right: -7px;
  min-width: 15px; height: 15px; padding: 0 3px; border-width: 1.5px;
  font-size: 8.5px;
  box-shadow: 0 2px 6px rgba(245,88,10,.4);
}
.streak-badge-sm .flame { width: 7px; height: 7px; margin-right: 0.5px; }

/* 大きいアイコン（メンバー一覧・プロフィール上部） */
.streak-badge-lg {
  top: -4px; right: -6px;
  min-width: 26px; height: 26px; padding: 0 5px; border-width: 2.5px;
  font-size: 11.5px;
  box-shadow: 0 0 0 1px rgba(216, 30, 18,.10), 0 3px 10px rgba(245,88,10,.45);
}
.streak-badge-lg .flame { width: 11px; height: 11px; }

@keyframes flame-flicker {
  0%, 100% { transform: scale(1) rotate(0deg); opacity: 1; }
  30%      { transform: scale(1.16) rotate(-5deg); opacity: .92; }
  65%      { transform: scale(.95) rotate(4deg); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .streak-badge .flame { animation: none; }
}

/* スマホ用トップバー（左上のロゴだけを置く。移動は下部タブバーで行う） */
.topbar {
  display: none; position: fixed; top: 0; left: 0; right: 0; z-index: 150;
  /* iOSアプリ(WebView)では画面最上部まで描画されるので、ステータスバーの下に
     バーの中身が来るよう安全領域ぶん内側に寄せる。ブラウザでは env() が0 */
  height: calc(58px + env(safe-area-inset-top));
  align-items: center;
  padding: env(safe-area-inset-top) calc(16px + env(safe-area-inset-right)) 0 calc(16px + env(safe-area-inset-left));
  background: var(--nav-bg); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
/* ロゴマーク＋文字を横に並べる。
   .logo-dot は span なので、flexにしないと幅0になってマークが出ない */
.topbar .brand {
  display: flex; align-items: center; gap: 8px;
  font-size: 19px; font-weight: 700; letter-spacing: -0.02em; color: var(--text);
}

/* ===== 右上のアクション（検索・通知ベル） =====
 * 以前はメンバーのボタンだけが単独で固定配置され、通知ベルはそのボタンの
 * 位置を毎回測って左隣に置いていた。行き先が増えると破綻するので、
 * 横並びの入れ物にまとめ、ベルもこの入れ物の中へ入れる。
 * 各ページの<style>に同じ指定が重複していたのをここへ集約した。
 *
 * 中身は、検索の丸ボタン（.top-icon。行き先は search.html）と、
 * 通知ベル（notify-bell.js が作るので、見た目の指定はあちらにある）。 */
.top-actions {
  position: fixed; top: calc(16px + env(safe-area-inset-top));
  right: calc(20px + env(safe-area-inset-right)); z-index: 161;
  display: flex; align-items: center; gap: 8px;
}
/* ベルは notify-bell.js が position:fixed で作るので、
   この中に入れたときだけ通常の並びに戻す。丸いので先頭（左端）に置く。 */
/* static ではなく relative にする。ガラスの層（::before / ::after）と件数の丸を、ベル自身に重ねるため */
.top-actions .cs-bell { position: relative; order: -1; flex-shrink: 0; }

/* アイコンだけの丸ボタン（検索）。ベルと同じ大きさ・同じ丸みにそろえる。
   ベルの左に置くので、ベル（order:-1）より前の -2 にする。
   文字を添えないのは、スマホで2つ並ぶと入力欄ぶんの幅が残らないため。
   何のボタンかは title と aria-label で伝える。 */
/* 丸の見た目（ガラス）は、下の「左上の戻るボタン」と共通（通知ベルも同じ） */
.top-icon {
  display: inline-flex; position: relative;
  flex-shrink: 0; order: -2;
  transition: transform .15s ease;
}
@media (hover: hover) and (pointer: fine) { .top-icon:hover { transform: translateY(-1px); } }
.top-icon svg { width: 19px; height: 19px; }
/* 今そのページにいるとき。ガラスの上に赤をうっすら重ねる */
.top-icon.current { background: rgba(216, 30, 18, .10); }
.top-icon.current svg { color: var(--red-dark); }

/* ===== スマホ：上部バーの出し入れと、画面最上部のぼかし =====
 * インスタの上部の画面録画をコマ送りで測り、同じ動きにした。
 * ・上部バー（左のCoSpark・右のベルなど）は背景を持たず、本文の上に浮かせる
 * ・下へスクロールすると、本文と同じ速さで上へ流れ、画面最上部のぼかしの中へ消える
 * ・上へスクロールしても途中では出ない。一番上まで戻ると、本文と一緒に下りてくる
 * ・画面最上部（ステータスバーの下まで）には常にぼかしの帯があり、
 *   その下を通るもの（上部バー自身も含む）は上へ行くほど強くぼける
 * 位置は sidebar.js が --hdr-y（ずらす量）と --hdr-o（濃さ）で渡す。 */
@media (max-width: 860px) {
  .topbar {
    background: transparent; border-bottom: 0;
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  /* 背景が無いぶん、下を通る本文と重なってもロゴが読めるよう白く縁取る */
  .topbar .brand { text-shadow: 0 0 6px #fff, 0 0 12px rgba(255, 255, 255, .9); }
  .topbar, .top-actions {
    transform: translate(var(--swipe-x, 0px), var(--hdr-y, 0px));
    opacity: var(--hdr-o, 1);
    will-change: transform;
  }
  /* 消えている間は、見えないボタンを押してしまわないようにする */
  .hdr-hidden .topbar, .hdr-hidden .top-actions { pointer-events: none; }

  /* 画面最上部のぼかしの帯（sidebar.js が差し込む .top-fog）。
     上へ行くほど強くぼかす。1枚では「急に切れる」ので、ぼかしの強さの違う3枚を
     下端をぼかしたマスクで重ね、上へ行くほどぼけが積み上がるようにしてある。
     iOS の Safari でも、マスクで切った backdrop-filter が効くことは確認済み。 */
  .top-fog {
    position: fixed; top: 0; left: 0; right: 0; z-index: 175;
    height: calc(env(safe-area-inset-top) + 14px);
    pointer-events: none;
    background: linear-gradient(to bottom, rgba(255, 255, 255, .72), rgba(255, 255, 255, 0));
  }
  .top-fog i { position: absolute; inset: 0; }
  .top-fog i:nth-child(1) {
    -webkit-backdrop-filter: blur(1.5px); backdrop-filter: blur(1.5px);
    -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
  }
  .top-fog i:nth-child(2) {
    -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
    -webkit-mask-image: linear-gradient(to bottom, #000 20%, transparent 70%);
    mask-image: linear-gradient(to bottom, #000 20%, transparent 70%);
  }
  .top-fog i:nth-child(3) {
    -webkit-backdrop-filter: blur(9px); backdrop-filter: blur(9px);
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 45%);
    mask-image: linear-gradient(to bottom, #000 0%, transparent 45%);
  }
}

@media (max-width: 860px) {
  .top-actions { top: calc(11px + env(safe-area-inset-top)); gap: 7px; }
}

/* ===== スマホ：上部バーの並び =====
 * 真ん中に「CoSpark」の文字だけを置く（ロゴマークは出さない）。
 * 検索は左上、通知ベルは右上に分け、画面の端から同じ距離に置いて左右対称にする。
 * 入れ物（.top-actions）を左右いっぱいに広げ、中の2つを両端に寄せている。
 * 検索だけを position:fixed で左へ出す形にしないのは、.top-actions がスクロールで
 * transform されていて、中の fixed がその入れ物基準になってしまうため。
 * 専用ページ（sub-page）は左上が戻るボタンなので、検索はこれまでどおりベルの左に置く。 */
@media (max-width: 860px) {
  .topbar { justify-content: center; }
  .topbar .logo-dot { display: none; }

  /* 「CoSpark」の文字は、ロゴの文字の絵（/brand/cospark-wordmark.png）に置き換える。
     絵は形（透明度）だけを使い、色は color で塗る（mask）。だから明るい画面では黒、
     ダークモードでは白に、はっきり切り替わる。
     HTMLの「CoSpark」の文字は残して大きさだけ0にしてある（読み上げではそのまま読まれる）。
     下を通る本文から浮かせる縁取りは、文字の影（text-shadow）では絵に効かないので、
     filter の drop-shadow で付ける（mask より先に描かれる親に掛けるので、縁取りは消えない）。
     字間は、もとのロゴ（1文字ずつ約20pxあき・幅677）を、絵の中で1文字ずつ切り出して
     10pxずつに詰め直してある（幅619）。左右の端の余白は同じ2pxなので、絵の真ん中が文字の真ん中。 */
  /* gap は 0 にする。大きさ0の文字と絵のあいだに、もとの文字用のすき間（8px）が残ると、
     絵が右へ4pxずれて真ん中に来ない */
  /* 大きさは、以前の高さ 21px の1.2倍（25.2px、幅は約108px）。
     縦は、最初の「C」の真ん中（絵の上から 61.65/144）を、両隣の丸ボタン
     （上から11px・高さ42px）の真ん中（上から32px）に合わせる。
     絵ごとの真ん中で合わせると、下に伸びる p の分だけ文字が上に寄って見える */
  .topbar .brand {
    --logo-h: calc(21px * 1.2);
    align-self: flex-start;
    margin-top: calc(32px - var(--logo-h) * 61.65 / 144);
    font-size: 0; gap: 0; color: #000; text-shadow: none;
    filter: drop-shadow(0 0 4px #fff) drop-shadow(0 0 8px rgba(255, 255, 255, .9));
  }
  .topbar .brand::after {
    content: ''; display: block;
    height: var(--logo-h); aspect-ratio: 619 / 144;
    background: currentColor;
    -webkit-mask: url(/brand/cospark-wordmark.png) center / contain no-repeat;
    mask: url(/brand/cospark-wordmark.png) center / contain no-repeat;
  }
  :root[data-theme="dark"] .topbar .brand {
    color: #fff; text-shadow: none;
    filter: drop-shadow(0 0 4px #111214) drop-shadow(0 0 8px rgba(17, 18, 20, .9));
  }
  body:not(.sub-page) .top-actions {
    left: calc(16px + env(safe-area-inset-left));
    right: calc(16px + env(safe-area-inset-right));
    justify-content: space-between;
    /* 広げた入れ物の真ん中（文字の上）は、押しても下へ通す */
    pointer-events: none;
  }
  body:not(.sub-page) .top-actions > * { pointer-events: auto; }
  /* 上部バーが隠れているあいだは、見えないボタンを押せないようにする（上の auto より強く） */
  .hdr-hidden body:not(.sub-page) .top-actions > * { pointer-events: none; }
}

/* ===== 専用ページ（検索・設定・プロフィール編集） =====
 * 行って、用が済んだら戻る場所。他所へ移るための並び（下部タブバー）は出さず、
 * 左上に戻るボタンだけを置く。<body class="sub-page"> を付けたページに効く。
 *
 * 戻るボタンは <body> の直下に置いてある。スマホ用の上部バー（.topbar）の中に
 * 入れると、PCではその上部バーごと display:none になって出てこないため。 */
body.sub-page .tabbar { display: none; }
/* スマホでは、右上の検索と通知ベルも出さない。上は左上の戻るボタンだけにする。
   下部タブバーの4つ（投稿・メッセージ・カレンダー・自分のプロフィール）以外のページは、すべてこの形。
   PCは左のサイドバーで行き来するので、検索と通知はこれまでどおり右上に出す。 */
@media (max-width: 860px) {
  body.sub-page .top-actions { display: none; }
}
/* 左上のロゴは戻るボタンと同じ場所に来るので、専用ページでは引っ込める */
body.sub-page .topbar .brand { display: none; }
/* 下部タブバーが無くなったぶん、本文の下の余白を詰める。
   各ページの<style>より強くするため、body から書いている */
@media (max-width: 860px) {
  body.sub-page .content { padding-bottom: calc(40px + env(safe-area-inset-bottom)); }
}

/* ===== 左上の戻るボタン（どのページでも同じ形・同じ場所） =====
 * 大きさと場所は、スマホのトップの左上にある検索の丸（.top-icon）と同じ：
 * 42pxの丸、画面の上から 11px＋安全領域、左から 16px＋安全領域。
 * 上部バーとは違い、スクロールしても動かず消えない（下部タブバーと同じく画面に固定）。
 * 大きさもスクロールで変えない（タブバーの .is-small のような縮みは入れない）。
 *
 * 見た目は下部タブバーと同じガラス（ぼかし・縁のレンズ・縁の光）。値も同じにしてある。
 * ・::before … ガラスの本体（白8%・ぼかし4px）。縁の光は内側の影で描く
 *   （タブバーの .tab-rim は横長のピル用の角度なので、丸には内側の影で同じ明るさの縁を付ける）
 * ・::after  … 縁のレンズ。外周だけ強くぼかして明るくする
 * ※ backdrop-filter を持つ要素の子は親の中しか透かせないので、ぼかしは「<」の親にしない。
 *
 * 同じ形の戻るボタンは、ほかに2つある（どちらもここでまとめて見た目を決める）：
 *   .thread-back … DMの会話の左上（dm.html）。会話の見出しの中に置いてある
 *   .mv-close    … 写真を1枚ずつ見る画面の左上（moments.js / moments.css）
 *   .dv-close    … カレンダーの日付を押した先の、その日のタイムラインの左上（day-view.js）
 *   .dp-back     … 投稿の写真から開く、その人のその日の記録の左上（day-peek.js）
 * 右上の検索（.top-icon）と通知ベル（.cs-bell。notify-bell.js が作る）も、丸の見た目だけ
 * ここで同じガラスにしている。こちらの動き（スクロールで上部バーと一緒に出入りする）は変えていない。
 * 登録・ログインの画面（/app/）は sidebar.css を読まないので、app.css に同じ指定がある。 */
.top-back {
  display: none;
  position: fixed; z-index: 180;
  top: 16px; left: 96px;
}
:is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell) {
  width: 42px; height: 42px; padding: 0; box-sizing: border-box;
  align-items: center; justify-content: center;
  border: 0; border-radius: 50%;
  background: transparent; color: #55504e; cursor: pointer;
  /* 浮いている影はタブバーと同じ */
  box-shadow:
    0 8px 24px rgba(40, 20, 10, .13),
    0 1px 3px rgba(40, 20, 10, .07),
    0 0 0 .5px rgba(40, 18, 14, .07);
  -webkit-tap-highlight-color: transparent;
}
:is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell)::before,
:is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell)::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none;
}
:is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell)::before {
  background: rgba(255, 255, 255, .08);
  -webkit-backdrop-filter: blur(4px) saturate(160%) brightness(1.05);
  backdrop-filter: blur(4px) saturate(160%) brightness(1.05);
  /* 縁の光。左上が一番明るく、右下にもう一度回り込む（タブバーの .tab-rim と同じ並び） */
  box-shadow:
    inset 1px 1.5px 0 rgba(255, 255, 255, .85),
    inset -1px -1px 0 rgba(255, 255, 255, .45),
    inset 0 0 0 1px rgba(255, 255, 255, .28);
}
:is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell)::after {
  -webkit-backdrop-filter: blur(9px) saturate(200%) brightness(1.12);
  backdrop-filter: blur(9px) saturate(200%) brightness(1.12);
  -webkit-mask-image: radial-gradient(circle closest-side, transparent 50%, rgba(0, 0, 0, .55) 76%, #000 100%);
  mask-image: radial-gradient(circle closest-side, transparent 50%, rgba(0, 0, 0, .55) 76%, #000 100%);
}
:is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell) svg { position: relative; z-index: 1; color: inherit; }
.top-back svg, .thread-back svg, .mv-close svg, .dv-close svg, .dp-back svg { width: 20px; height: 20px; }
/* ぼかせない環境では、透けたままだと本文と重なって読めないので下地を濃くする */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell) { background: rgba(255, 255, 255, .95); }
}
/* ダークモード（タブバーと同じ値） */
:root[data-theme="dark"] :is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell) {
  color: #b9bcc1;
  box-shadow:
    0 8px 24px rgba(0, 0, 0, .50),
    0 1px 3px rgba(0, 0, 0, .30),
    0 0 0 .5px rgba(0, 0, 0, .55);
}
:root[data-theme="dark"] :is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell)::before {
  background: rgba(255, 255, 255, .07);
  -webkit-backdrop-filter: blur(4px) saturate(150%) brightness(1.02);
  backdrop-filter: blur(4px) saturate(150%) brightness(1.02);
  box-shadow:
    inset 1px 1.5px 0 rgba(255, 255, 255, .42),
    inset -1px -1px 0 rgba(255, 255, 255, .22),
    inset 0 0 0 1px rgba(255, 255, 255, .14);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root[data-theme="dark"] :is(.top-back, .thread-back, .mv-close, .dv-close, .dp-back, .top-icon, .cs-bell) { background: rgba(26, 29, 33, .96); }
}
body.sub-page .top-back { display: flex; }

@media (min-width: 861px) {
  /* PCでは、左サイドバー（72px）の右隣、本文の始まりのあたりに置く。高さは右上の検索と同じ */
  .top-back { transition: transform .15s ease; }
  @media (hover: hover) and (pointer: fine) { .top-back:hover { transform: translateY(-1px); } }
}
@media (max-width: 860px) {
  .top-back {
    top: calc(11px + env(safe-area-inset-top));
    left: calc(16px + env(safe-area-inset-left));
  }
  /* スクロールでは動かさない（上部バーの --hdr-y・--hdr-o は入れない）。
     右へなぞって戻るときだけ、ページと一緒に指について動く。
     画面最上部のぼかしの帯（.top-fog・175）より手前に置くので、上を通る本文にぼかされない。 */
  .top-back { transform: translateX(var(--swipe-x, 0px)); }
}

/* ===== スマホ：右へなぞって戻る =====
 * 「戻る」のあるページで右へなぞると、今のページが丸ごと指について右へずれ、
 * その下に一つ前のページ（離れるときに残した写し）が見える。Instagram と同じ動き（sidebar.js）。
 *
 * 重なり（奥から）：
 *   .swipe-under  前のページの写し（iframe）。--under-x で少し左から寄ってくる
 *   .swipe-sheet  今のページの地の色。左端に影。--swipe-x で指につく
 *   それより手前は今のページそのもの（背景の火花・本文・上の並び・下のボタン）
 * 写しと地の色は z-index をマイナスにして、今のページの中身すべての奥に置く。
 * そのため、なぞっているあいだは body の背景色を消す（地の色は .swipe-sheet が持つ）。
 * html.swipe-armed … 右へ動きかけた（まだ動かしてはいない）。html.swipe-back … 動かしている。
 *
 * ずらし方：
 *   上の並び（.topbar / .top-actions / .top-back）… 上の translate に --swipe-x を入れてある
 *   本文（.content）… left。transform を付けると、本文の中の position:fixed
 *     （ToDoの追加ボタン等）がページ基準でなくなって飛ぶため
 *   ほかの画面に貼りついた部品（.swipe-mv。sidebar.js が拾って付ける）… translate。
 *     もともと持っている transform（中央寄せ等）と重ねがけできるので
 * 指を離したあと、行き切るか元へ戻るかへ流すときだけ transition を効かせる
 * （なぞっている最中は指に即つけたいので付けない）。長さは指の速さから --swipe-dur で渡す。 */
.swipe-under, .swipe-sheet { display: none; }
@media (max-width: 860px) {
  .swipe-under, .swipe-sheet {
    display: block; position: fixed; inset: 0;
    visibility: hidden; pointer-events: none;
    background: var(--bg, #fff);
  }
  .swipe-under { z-index: -2; overflow: hidden; }
  .swipe-under iframe { display: block; width: 100%; height: 100%; border: 0; background: var(--bg, #fff); }
  .swipe-sheet { z-index: -1; }
  /* 右へずらした本文がはみ出して、横にスクロールできるようになったり画面が縮んだりしないように */
  .swipe-back, .swipe-back body { overflow-x: clip; }
  .swipe-armed body, .swipe-back body { background: transparent; }
  /* 右へ動きかけた時点（.swipe-armed）で出しておく。まだ地の色がぴったり覆っているので見えない */
  .swipe-armed .swipe-under, .swipe-armed .swipe-sheet,
  .swipe-back .swipe-under, .swipe-back .swipe-sheet { visibility: visible; }
  .swipe-back .swipe-under {
    transform: translate3d(var(--under-x, 0px), 0, 0);
  }
  .swipe-back .swipe-sheet {
    transform: translate3d(var(--swipe-x, 0px), 0, 0);
    box-shadow: -1px 0 0 rgba(0, 0, 0, .04), -8px 0 24px rgba(0, 0, 0, .10);
  }
  .swipe-back .content { left: var(--swipe-x, 0px); }
  .swipe-back .swipe-mv { translate: var(--swipe-x, 0px) 0; }

  .swipe-settling .content { transition: left var(--swipe-dur, .3s) cubic-bezier(.22, .61, .36, 1); }
  .swipe-settling .topbar, .swipe-settling .top-actions, .swipe-settling .top-back,
  .swipe-settling .swipe-under, .swipe-settling .swipe-sheet {
    transition: transform var(--swipe-dur, .3s) cubic-bezier(.22, .61, .36, 1);
  }
  .swipe-settling .swipe-mv { transition: translate var(--swipe-dur, .3s) cubic-bezier(.22, .61, .36, 1); }
}
@media (prefers-reduced-motion: reduce) {
  .swipe-settling .content, .swipe-settling .topbar,
  .swipe-settling .top-actions, .swipe-settling .top-back,
  .swipe-settling .swipe-under, .swipe-settling .swipe-sheet, .swipe-settling .swipe-mv { transition: none; }
}

/* ===== スマホ：下部タブバー（Instagram等と同じ、主要ページへワンタップで移動） ===== */
/* タブバーはスマホ専用。PCでは左サイドバーが同じ役割を持つ。 */
.tabbar { display: none; }
/* タブバーは画面の下端に貼り付けず、少し浮かせたピル型にしてある。
   --tabbar-h はピル自体の高さ、--tabbar-gap は画面の下端との間。
   本文がピルの下に隠れないよう、この2つとiPhoneのホームバーぶん
   （安全領域）を足したものを --tabbar-total として配り、
   各ページはこれを使って下の余白を取る。
   ピルの実寸より8px多く取ってあるのは、チャットの入力欄のように
   「下いっぱいまで使う」画面で、入力欄とピルが接して見えないようにするため。 */
:root {
  --tabbar-h: 58px;
  --tabbar-gap: 10px;
  --tabbar-total: calc(58px + 10px + 8px + env(safe-area-inset-bottom));
}

@media (max-width: 860px) {
  /* 画面の幅いっぱいに敷かず、左右を空けて浮かせる。
     下の内容が透けて動くことで、バーが画面に載っているものだと伝わる。 */
  .tabbar {
    display: flex; position: fixed; z-index: 190;
    left: 14px; right: 14px;
    bottom: calc(var(--tabbar-gap) + env(safe-area-inset-bottom));
    height: var(--tabbar-h); padding: 0 8px; box-sizing: border-box;
    border-radius: 100px;
    /* ガラスそのもの（ぼかし）は ::before / ::after に持たせ、ここには付けない。
       backdrop-filter を持つ要素の子は、ページではなく親の中しか透かせなくなるため */
    background: transparent;
    /* 浮いている影。iPhone のガラスと同じく、ふわっと薄く広げる。
       縁の光の線は .tab-rim（sidebar.js が差し込む）に任せる */
    box-shadow:
      0 8px 24px rgba(40, 20, 10, .13),
      0 1px 3px rgba(40, 20, 10, .07),
      0 0 0 .5px rgba(40, 18, 14, .07);
    /* 下へスクロールすると小さくなり、上へ戻すと元の大きさに戻る（sidebar.js が
       .is-small を付け外しする）。インスタの録画から測った値：
       ・幅も高さもアイコンも一緒に約84%へ縮む
       ・縮む中心は真ん中より少し下（下端はほとんど動かず、上が下がってくる）
       ・約0.3秒で、始めが速く終わりがゆっくり
       押したときの「ふくらみ」は transform で別に動かすので、ここは scale を使う */
    scale: 1;
    transform-origin: 50% 60%;
    transition: scale .34s cubic-bezier(.32, .72, 0, 1);
  }
  .tabbar.is-small { scale: .84; }
  /* タブを押した瞬間、バー全体が少しふくらんで戻る（録画では約3%、0.3秒ほど） */
  .tabbar.is-pressed { animation: tabbar-press .32s cubic-bezier(.3, .7, .4, 1); }
  @keyframes tabbar-press {
    35%  { transform: scale(1.03); }
    100% { transform: scale(1); }
  }
  /* ===== ガラスの質感（iPhone のアプリライブラリの検索バーに合わせた） =====
     2026-10-06 の画面録画をコマごとに取り出し、ガラスの中と外の色を比べて決めた。
     ・白はほとんど重ねない。何も無い所では、下の色に白が約8%乗るだけ
     ・ぼかしは中くらい。細かい模様は消えるが、下を通るものの形と色は分かる
     ・色はほぼそのまま。少し明るく、少し鮮やかになるだけ
     ・左右の丸い端では、下の像が引き伸ばされて明るく光る（厚いガラスのレンズ）
     ・縁には細い光の線。上と左上が一番明るく、右下にもう一度光が回り込む
     iOS の Safari / アプリ内ブラウザは、下の像を「ずらす」表現（SVGフィルター）を
     描けない。使えるのはぼかし・明るさ・彩度だけなので、レンズは
     「端だけ強くぼかして明るくする」ことで、引き伸ばされて光る見え方に寄せている。
     ※backdrop-filter を持つ要素の子は、ページではなく親の中しか透かせなくなるので、
       ガラスの層はどれもアイコンの親にしない（::before・::after・.tab-rim）。 */
  .tabbar::before,
  .tabbar::after {
    content: ''; position: absolute; inset: 0; border-radius: inherit;
    pointer-events: none;
  }
  /* ガラスの本体。録画で測った「白が約8%」のまま */
  .tabbar::before {
    background: rgba(255, 255, 255, .08);
    -webkit-backdrop-filter: blur(4px) saturate(160%) brightness(1.05);
    backdrop-filter: blur(4px) saturate(160%) brightness(1.05);
  }
  /* 縁のレンズ。左右の丸い端は広く（22px）、上下は細く（6px）、内側へ向かって
     なだらかに消える帯にして、そこだけ強くぼかし、明るく鮮やかにする。
     ぼかしの強さが急に変わらないので、像が端へ向かって伸びていくように見える */
  .tabbar::after {
    /* 白は足さない。足すと、黒い写真の上で端だけ白く濁る（録画では下の色のまま光る） */
    -webkit-backdrop-filter: blur(9px) saturate(200%) brightness(1.12);
    backdrop-filter: blur(9px) saturate(200%) brightness(1.12);
    -webkit-mask-image:
      linear-gradient(to right, #000 0, rgba(0, 0, 0, .55) 10px, transparent 22px,
                      transparent calc(100% - 22px), rgba(0, 0, 0, .55) calc(100% - 10px), #000 100%),
      linear-gradient(to bottom, #000 0, transparent 6px, transparent calc(100% - 6px), #000 100%);
    mask-image:
      linear-gradient(to right, #000 0, rgba(0, 0, 0, .55) 10px, transparent 22px,
                      transparent calc(100% - 22px), rgba(0, 0, 0, .55) calc(100% - 10px), #000 100%),
      linear-gradient(to bottom, #000 0, transparent 6px, transparent calc(100% - 6px), #000 100%);
  }
  /* 縁の光の線（sidebar.js がバーの先頭に差し込む）。
     1.5px の枠だけを残して、ふちに沿って明るさを変える。
     角度はピルの真ん中から見た向きで、0deg が真上。横長のピルなので、
     上の辺はおよそ -80〜80deg、右の丸い端が 80〜100deg、下の辺が 100〜260deg、
     左の丸い端が 260〜280deg にあたる */
  .tab-rim {
    position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
    border: 1.5px solid transparent; box-sizing: border-box;
    background: conic-gradient(from 0deg,
      rgba(255, 255, 255, .80) 0deg,
      rgba(255, 255, 255, .55) 60deg,
      rgba(255, 255, 255, .22) 84deg,
      rgba(255, 255, 255, .70) 100deg,
      rgba(255, 255, 255, .30) 130deg,
      rgba(255, 255, 255, .16) 180deg,
      rgba(255, 255, 255, .22) 240deg,
      rgba(255, 255, 255, .35) 262deg,
      rgba(255, 255, 255, .95) 280deg,
      rgba(255, 255, 255, .80) 360deg) border-box;
    -webkit-mask: linear-gradient(#000 0 0) padding-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) padding-box exclude, linear-gradient(#000 0 0);
  }
  /* ぼかしに対応していない環境では、透けたままだと文字と重なって読めない。
     ぼかせないぶん、下地を濃くする */
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .tabbar { background: rgba(255, 255, 255, .95); }
  }

  /* ピルの足元（sidebar.js が差し込む .bottom-fog）。
     ピルは浮いているので、下端との隙間と左右の余白からは本文がそのまま見える。
     コマ（写真）が流れてくると、そこだけ写真が生のまま画面の端で切れて、
     ピルが写真の上に落ちているように見えた。画面の下端へ向かって白くぼかし、
     写真が溶けていく帯を敷くと、ピルの下に置き場ができて落ち着く。
     白い本文の上では何も起きない（白に白を重ねるだけ）。
     高さは各ページが下に空けている余白（--tabbar-total）と同じにしてある。
     これより高くすると、チャットの入力欄のように余白のすぐ上に置いたものまで
     かすませてしまう。
     ぼかしは上部の帯（.top-fog）と同じく、強さの違う3枚を重ねる。
     以前は1枚で、ピルの下の隙間から4pxで消していたため、上部のように
     徐々にではなく、そこで急に切れて見えた。下端へ行くほどぼけが積み上がる。
     白（地の色）も同じく、帯の高さ全体を使って上へ向かって薄くする。
     ピルの裏は薄くしか塗らないので、ガラス越しの下の色は残る。 */
  .bottom-fog {
    --fog-solid: calc(var(--tabbar-gap) + env(safe-area-inset-bottom));
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 189;
    height: var(--tabbar-total);
    pointer-events: none;
    background: linear-gradient(to top,
      rgba(255, 255, 255, .85) 0, rgba(255, 255, 255, .55) var(--fog-solid),
      rgba(255, 255, 255, .18) 60%, rgba(255, 255, 255, 0) 100%);
  }
  .bottom-fog i { position: absolute; inset: 0; }
  .bottom-fog i:nth-child(1) {
    -webkit-backdrop-filter: blur(1.5px); backdrop-filter: blur(1.5px);
    -webkit-mask-image: linear-gradient(to top, #000 40%, transparent 100%);
    mask-image: linear-gradient(to top, #000 40%, transparent 100%);
  }
  .bottom-fog i:nth-child(2) {
    -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
    -webkit-mask-image: linear-gradient(to top, #000 20%, transparent 70%);
    mask-image: linear-gradient(to top, #000 20%, transparent 70%);
  }
  .bottom-fog i:nth-child(3) {
    -webkit-backdrop-filter: blur(9px); backdrop-filter: blur(9px);
    -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 45%);
    mask-image: linear-gradient(to top, #000 0%, transparent 45%);
  }

  /* アイコンの下に、そのタブの名前を小さく添える（カメラだけは添えない） */
  .tab-item {
    flex: 1; display: flex; flex-direction: column; gap: 3px;
    align-items: center; justify-content: center; min-width: 0;
    /* ガラス越しの下地は、白い本文の上と写真の上とで明るさが変わる。
       --sub（#6f6f6f）のままだと写真の上で沈むので、少し濃い灰にしてある */
    color: #55504e; position: relative;
    transition: color .25s ease;
  }
  /* 選んでいるところの光。タブごとに持たせず、バーに1つだけ置いて横へ滑らせる
     （各ページの <span class="tab-glow"> がこれ）。どのタブの下に置くかは、
     何番目のタブが .active かで決める。タブの枠いっぱいに敷くと、両端のタブで
     ピルの丸い角からはみ出すので、タブの中央に決まった大きさで置く。
     left は「左の余白8px ＋ タブ幅 ×（番号＋0.5）− 光の幅の半分」。
     並びは5枠で、真ん中（3番目）はカメラのボタン。カメラはページではないので
     光は止まらず、カメラより右のタブは1枠ずらした位置に光を置く。 */
  .tab-glow {
    --i: 0;
    position: absolute; top: 50%;
    /* アイコンと名前の両方を包む大きさ */
    width: 66px; height: 48px; margin-top: -24px;
    left: calc(8px + (100% - 16px) / 5 * (var(--i) + .5) - 33px);
    border-radius: 14px; pointer-events: none;
    background: rgba(253, 236, 235, .92);
    box-shadow: inset 0 0 0 1px rgba(216, 30, 18, .1);
    opacity: 0;
    /* 録画をコマ送りで測ると、約0.23秒で滑り、行き過ぎずに止まる
       （動き出しが速く、最後の3割をゆっくり寄せる） */
    transition: left .26s cubic-bezier(.2, .8, .2, 1), opacity .15s ease,
                background .2s ease, box-shadow .2s ease;
  }
  .tabbar:has(> .tab-item:nth-of-type(1).active) .tab-glow { --i: 0; opacity: 1; }
  .tabbar:has(> .tab-item:nth-of-type(2).active) .tab-glow { --i: 1; opacity: 1; }
  .tabbar:has(> .tab-item:nth-of-type(3).active) .tab-glow { --i: 3; opacity: 1; }
  .tabbar:has(> .tab-item:nth-of-type(4).active) .tab-glow { --i: 4; opacity: 1; }
  /* :has に対応していない古い端末（iOS 15.3 以前）では光の位置を決められないので、
     滑らせるのはあきらめて、選択中のタブの下地として出す */
  @supports not selector(:has(a)) {
    .tab-glow { display: none; }
    .tab-item.active::before {
      content: ''; position: absolute; top: 50%; left: 50%;
      width: 66px; height: 48px; margin: -24px 0 0 -33px; border-radius: 14px;
      background: rgba(253, 236, 235, .92);
      box-shadow: inset 0 0 0 1px rgba(216, 30, 18, .1);
    }
  }
  /* 光より前に出す。光はバーの最後の子なので、何もしないとアイコンの上に重なる。
     バッジは自前で absolute なので、ここには入れず z-index だけ上げる */
  .tab-item svg, .tab-item .tab-av, .tab-label { position: relative; z-index: 1; }
  /* 名前。タブの幅に収まるよう、小さく詰めてある */
  .tab-label {
    font-size: 9.5px; font-weight: 700; line-height: 1.1;
    letter-spacing: -0.03em; white-space: nowrap;
  }
  /* 幅の狭い端末（iPhone SE など）では、隣の名前とぶつからないようもう一回り小さく */
  @media (max-width: 350px) {
    .tab-label { font-size: 8.5px; }
  }
  /* 以前はアイコンの周りに白い影を回り込ませていた。ガラスが薄く、暗い写真が
     来るとアイコンが沈んだため。いまはガラス自体が下地を作るので、影は入れない
     （白い影は、写真の上では輪郭のまわりが白くにじんで、かえって汚れて見えた） */
  .tab-item svg { width: 24px; height: 24px; }
  /* ガラス越しの真下が暗いところでは白、明るいところでは濃い灰にする（sidebar.js が
     タブごとに data-tone を付ける）。iPhone のガラスと同じく、少し時間をかけて移す
     （.tab-item の transition） */
  .tab-item[data-tone="dark"]:not(.active) { color: rgba(255, 255, 255, .96); }
  .tab-item[data-tone="light"]:not(.active) { color: #55504e; }
  .tab-item.active { color: var(--red-dark); }
  /* 一番右のタブは、人型アイコンではなく自分のプロフィール画像を出す（Instagram等と同じ）。
     中身（画像 or 名前の頭文字）は sidebar.js がサイドバーのアイコンから写してくる。 */
  .tab-av {
    width: 26px; height: 26px; border-radius: 50%; overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    background: var(--red-light); color: var(--red-dark);
    font-size: 11px; font-weight: 800; line-height: 1;
    border: 1.5px solid transparent; box-sizing: border-box;
  }
  .tab-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
  /* 自分のプロフィールを見ているときは、アイコンを枠で囲って選択中だと分かるようにする */
  .tab-item.active .tab-av { border-color: var(--red-dark); }
  /* 真ん中のカメラ。押すとその場で「コマを撮る」のカメラが開く（sidebar.js）。
     ページへ移るタブと見分けがつくよう、撮るボタンと同じ赤い丸に白いカメラを置く */
  .tab-cam {
    flex: 1; display: flex; align-items: center; justify-content: center;
    padding: 0; border: 0; background: none; cursor: pointer;
    position: relative; z-index: 1;
    -webkit-tap-highlight-color: transparent;
  }
  .tab-cam-disc {
    width: 42px; height: 42px; border-radius: 50%;
    display: grid; place-items: center; color: #fff;
    background: linear-gradient(150deg, #ff8a3d 0%, #ef4a24 48%, #d81e12 100%);
    box-shadow: 0 0 0 2.5px rgba(255, 255, 255, .9), 0 0 0 4px rgba(216, 30, 18, .55),
                0 4px 10px rgba(216, 30, 18, .28);
    transition: transform .14s ease;
  }
  .tab-cam:active .tab-cam-disc { transform: scale(.9); }
  .tab-cam svg { width: 22px; height: 22px; }
  .tab-badge {
    /* 名前を添えたぶんアイコンが上へ寄ったので、バッジも合わせて上げてある */
    position: absolute; z-index: 1; top: 3px; right: calc(50% - 22px);
    min-width: 16px; height: 16px; padding: 0 4px;
    background: var(--red); color: #fff; font-size: 9.5px; font-weight: 700;
    line-height: 16px; text-align: center; border-radius: 100px; border: 2px solid var(--card);
  }
}
@media (prefers-reduced-motion: reduce) {
  .tabbar, .tab-glow { transition: none; }
  .tabbar.is-pressed { animation: none; }
}

/* ===== スマホ：左サイドバーは出さない ===== */
/* 移動はすべて下部タブバー（と左上のロゴ・右上の検索）で完結させる。
   要素自体はDOMに残す。各ページのJSが /me の結果をここのアイコンへ描き、
   sidebar.js がそれを下部タブバーの一番右へ写しているため。 */
@media (max-width: 860px) {
  .sidebar { display: none; }
  .topbar { display: flex; }
}

/* ===== ページを移るときの切り替え =====
 *
 * タブを押すとページを開き直すので、切り替えの瞬間に白が入る。
 * iOSのSafari（アプリ内も同じ）は、ページをまたぐ切り替えを短く重ねて
 * 見せられるので、それに任せる。対応していない端末では何も起きない。
 *
 * 前に試したときは、下部バーに view-transition-name を付けたせいで
 * ガラスのぼかしが崩れた。今回はバーに名前を付けず、画面全体を
 * ごく短く重ねるだけにしてある。
 *
 * ※ここで見た目が崩れるようなら、この一かたまりを消せば元に戻る。 */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .16s;
  animation-timing-function: ease;
}

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* ===== 押したら、すぐ返す =====
 *
 * 押してから次のページが出るまでには少し間がある。そのあいだ画面が何も
 * 変わらないと、効いていないと思ってもう一度押してしまう。アプリでは
 * その2回目が1回目の移動を取り消して「接続できませんでした」になっていた
 * （いきさつは sidebar.js の「移動は、一度にひとつだけ」）。
 * だから、受け付けた時点で2つ返す。付け外しは sidebar.js。
 *
 * 1) 押したもの（.is-tapped）
 *    指のすぐ下で変わるのが一番伝わる。行・ボタン・アイコンのどれに付いても
 *    崩れないよう、形や位置には触らず、濃さだけを落とす。
 *    下部タブバーには付けない（あちらは光とふくらみで自分で返している）。
 *
 * 2) 画面の一番上の細い帯（.nav-prog）
 *    いま読んでいるという印。すぐ着いたときに一瞬ちらつかないよう、
 *    0.12秒だけ待ってから出す。最後まで伸ばさず9割で止める
 *    （いつ着くかは分からないので、満ちたのに変わらない見え方にしない）。 */
.is-tapped { opacity: .5; }

.nav-prog {
  position: fixed; top: env(safe-area-inset-top); left: 0; right: 0;
  height: 2.5px; z-index: 300; pointer-events: none;
  opacity: 0; transition: opacity .15s ease .12s;
}
.nav-prog b {
  display: block; width: 0; height: 100%;
  background: var(--red); border-radius: 0 2px 2px 0;
}
.is-leaving .nav-prog { opacity: 1; }
.is-leaving .nav-prog b { animation: nav-prog 2.2s cubic-bezier(.15,.85,.25,1) forwards; }

@keyframes nav-prog {
  from { width: 0; }
  to   { width: 90%; }
}

/* 動きを控える設定のときは、伸ばさずに出すだけにする */
@media (prefers-reduced-motion: reduce) {
  .is-tapped { opacity: .62; }
  .nav-prog { transition: none; }
  .is-leaving .nav-prog b { animation: none; width: 35%; }
}
