/* ===== CoSpark 会員ページの装飾レイヤー =====
 *
 * 会員ページ7枚（community / dm / todo / habits / members /
 * profile / mypage）が共通で読み込む、見た目だけのファイル。
 *
 * 各ページの <style> の「あと」に読み込むこと。
 * 同じ強さのセレクタならこちらが勝つようにして、ページ側の素の見た目
 * （枠線だけのカード、べた塗りのカレンダー）を上書きしている。
 *
 * 中身の役割はここだけに閉じている：
 *   - 火花（ブランド名の由来）を色と動きの語彙にした装飾
 *   - 奥行き（影）と登場アニメーションで、情報のまとまりを見やすくする
 *   - 押した・できた瞬間の手応え
 * 機能には一切触れない。読み込まなくてもページは同じように動く。
 *
 * 動きを減らす設定（prefers-reduced-motion）の人には、
 * ファイル末尾でアニメーションをまとめて止めている。
 */

:root {
  /* 火花の色。炎バッジ（sidebar.css）と同じ並びに揃えてある */
  --spark-hot: #ff9d00;
  --spark-mid: #f5580a;
  --spark-deep: #d81e12;
  --ember: linear-gradient(150deg, #ff8a3d 0%, #ef4a24 48%, #d81e12 100%);

  --ease-out: cubic-bezier(.22, .68, .24, 1);
  --ease-pop: cubic-bezier(.34, 1.42, .5, 1);

  /* 白地に薄い枠線だけだと平坦なので、影で階層を作る */
  --lift-1: 0 1px 2px rgba(40, 18, 14, .04), 0 5px 16px -8px rgba(40, 18, 14, .12);
  --lift-2: 0 2px 6px rgba(40, 18, 14, .06), 0 18px 34px -16px rgba(216, 30, 18, .26);
}

/* ============================================================
 * 1. 背景の火花
 * 白一色だと画面が広いほど寒々しいので、動かない程度にゆっくり漂う
 * 暖色のにじみを敷く。文字の下に来るが、濃さは数%なので読みは妨げない。
 * 要素は app-ui.js が body の先頭に差し込む。
 * ========================================================== */
.app-amb {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: strict;
}
.app-amb i {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(72px);
  will-change: transform;
}
.app-amb i:nth-child(1) {
  width: 46vw; height: 46vw; min-width: 320px; min-height: 320px;
  top: -14vw; left: -8vw;
  background: radial-gradient(circle, rgba(255, 157, 0, .16), rgba(255, 157, 0, 0) 70%);
  animation: ambDrift1 34s ease-in-out infinite;
}
.app-amb i:nth-child(2) {
  width: 40vw; height: 40vw; min-width: 300px; min-height: 300px;
  bottom: -16vw; right: -6vw;
  background: radial-gradient(circle, rgba(216, 30, 18, .13), rgba(216, 30, 18, 0) 70%);
  animation: ambDrift2 42s ease-in-out infinite;
}
.app-amb i:nth-child(3) {
  width: 30vw; height: 30vw; min-width: 240px; min-height: 240px;
  top: 42%; right: 22%;
  background: radial-gradient(circle, rgba(245, 88, 10, .09), rgba(245, 88, 10, 0) 70%);
  animation: ambDrift3 52s ease-in-out infinite;
}
@keyframes ambDrift1 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(6vw, 5vh, 0) scale(1.12); }
}
@keyframes ambDrift2 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(-7vw, -6vh, 0) scale(1.08); }
}
@keyframes ambDrift3 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(-4vw, 7vh, 0) scale(.88); }
}

/* 背景を敷いたぶん、本文は必ずその上に置く。
   サイドバー・下部タブ・トップバーは sidebar.css で z-index 済み。 */
.content { position: relative; z-index: 1; }

/* ============================================================
 * 2. 見出し
 * 題と本文のあいだに火花色の短い線を入れて、話の区切りを目で分かるようにする。
 * ========================================================== */
.page-title,
.page-head h1,
.dm-head h1 {
  position: relative;
  padding-bottom: 10px;
}
.page-title::after,
.page-head h1::after,
.dm-head h1::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 34px; height: 3px;
  border-radius: 2px;
  background: var(--ember);
  transform-origin: left center;
  animation: ruleGrow .7s var(--ease-out) both;
}
@keyframes ruleGrow {
  from { transform: scaleX(0); opacity: 0; }
  to   { transform: scaleX(1); opacity: 1; }
}

/* 説明文が題にくっついて見えないよう、少しだけ間を空ける */
.page-sub,
.page-head p,
.dm-head p { margin-top: 8px; }

/* ============================================================
 * 3. カードの奥行き
 * 1pxの枠線だけだった箱に、薄い影と持ち上がるホバーを足す。
 * ========================================================== */
.card,
.post,
.member-card,
.progress-card,
.todo-card,
.cal-card,
.prof-post,
.stat-box,
.composer,
.locked-card {
  box-shadow: var(--lift-1);
  transition:
    box-shadow .26s var(--ease-out),
    transform .26s var(--ease-out),
    border-color .26s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .post:hover,
  .member-card:hover,
  .prof-post:hover,
  .stat-box:hover {
    transform: translateY(-3px);
    box-shadow: var(--lift-2);
    border-color: rgba(216, 30, 18, .22);
  }
}

/* メンバーの札は自己紹介の長さで背が変わり、ボタンの高さがばらついていた。
   札を縦の箱にして、ボタンだけ下端にそろえる。 */
.member-card { display: flex; flex-direction: column; }
.member-actions { margin-top: auto; padding-top: 14px; }

/* 入力中の枠は火花色で囲って、いまどこに書いているかを分かりやすくする */
.composer:focus-within,
.todo-form:focus-within {
  border-color: rgba(216, 30, 18, .34);
  box-shadow: 0 0 0 4px rgba(216, 30, 18, .07), var(--lift-1);
}

/* ============================================================
 * 4. 登場アニメーション
 * 中身はJSであとから描かれるので、差し込まれた瞬間に下から浮き上がる。
 * 並び順に少しずつ遅らせて、一覧が「積み上がる」ように見せる。
 *
 * fill-mode は backwards。both にすると終了後も transform が残り、
 * ホバーの拡大（.cal-cell など）が効かなくなる。
 * ========================================================== */
@keyframes appRise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes appPop {
  from { opacity: 0; transform: scale(.7); }
  to   { opacity: 1; transform: none; }
}

.post,
.member-card,
.card,
.todo-item,
.conv-item,
.prof-post,
.entry-item,
.stat-box,
.progress-card,
.cal-card,
.post-rate,
.fl-row,
.picker-row {
  animation: appRise .52s var(--ease-out) backwards;
}

/* 並びの順に遅らせる。12番目より後ろは同じ遅さで打ち止め（待たせすぎない） */
.post:nth-child(1), .member-card:nth-child(1), .card:nth-child(1), .todo-item:nth-child(1), .conv-item:nth-child(1), .prof-post:nth-child(1), .entry-item:nth-child(1), .fl-row:nth-child(1), .picker-row:nth-child(1) { animation-delay: .02s; }
.post:nth-child(2), .member-card:nth-child(2), .card:nth-child(2), .todo-item:nth-child(2), .conv-item:nth-child(2), .prof-post:nth-child(2), .entry-item:nth-child(2), .fl-row:nth-child(2), .picker-row:nth-child(2) { animation-delay: .06s; }
.post:nth-child(3), .member-card:nth-child(3), .card:nth-child(3), .todo-item:nth-child(3), .conv-item:nth-child(3), .prof-post:nth-child(3), .entry-item:nth-child(3), .fl-row:nth-child(3), .picker-row:nth-child(3) { animation-delay: .10s; }
.post:nth-child(4), .member-card:nth-child(4), .card:nth-child(4), .todo-item:nth-child(4), .conv-item:nth-child(4), .prof-post:nth-child(4), .entry-item:nth-child(4), .fl-row:nth-child(4), .picker-row:nth-child(4) { animation-delay: .14s; }
.post:nth-child(5), .member-card:nth-child(5), .card:nth-child(5), .todo-item:nth-child(5), .conv-item:nth-child(5), .prof-post:nth-child(5), .entry-item:nth-child(5), .fl-row:nth-child(5), .picker-row:nth-child(5) { animation-delay: .18s; }
.post:nth-child(6), .member-card:nth-child(6), .card:nth-child(6), .todo-item:nth-child(6), .conv-item:nth-child(6), .prof-post:nth-child(6), .entry-item:nth-child(6), .fl-row:nth-child(6), .picker-row:nth-child(6) { animation-delay: .22s; }
.post:nth-child(7), .member-card:nth-child(7), .card:nth-child(7), .todo-item:nth-child(7), .conv-item:nth-child(7), .prof-post:nth-child(7), .entry-item:nth-child(7), .fl-row:nth-child(7), .picker-row:nth-child(7) { animation-delay: .26s; }
.post:nth-child(n+8), .member-card:nth-child(n+8), .card:nth-child(n+8), .todo-item:nth-child(n+8), .conv-item:nth-child(n+8), .prof-post:nth-child(n+8), .entry-item:nth-child(n+8), .fl-row:nth-child(n+8), .picker-row:nth-child(n+8) { animation-delay: .30s; }

/* チャットは新しい発言だけが増えるので、届いた1件がふわっと入る */
.msg { animation: appRise .34s var(--ease-out) backwards; }

/* ============================================================
 * 5. ボタンの手応え
 * ========================================================== */
.btn,
.prof-btn,
.fl-btn,
.member-dm-btn,
.post-rate,
.view-others-btn,
.day-today,
.cal-today,
.todo-add,
.btn-post,
.thread-send,
.members-fab,
.todo-link,
.day-arrow,
.cal-arrow {
  transition:
    transform .16s var(--ease-out),
    box-shadow .2s var(--ease-out),
    background .2s var(--ease-out),
    border-color .2s var(--ease-out),
    opacity .2s var(--ease-out);
}
.btn:active:not(:disabled),
.prof-btn:active:not(:disabled),
.fl-btn:active:not(:disabled),
.member-dm-btn:active,
.post-rate:active:not(:disabled),
.view-others-btn:active,
.day-today:active,
.cal-today:active,
.todo-add:active:not(:disabled),
.btn-post:active:not(:disabled),
.thread-send:active:not(:disabled),
.members-fab:active,
.day-arrow:active:not(:disabled),
.cal-arrow:active:not(:disabled) {
  transform: scale(.955);
}

/* 主役のボタンは火花のグラデーションにして、押す先を1つに絞る */
.btn-post:not(:disabled),
.todo-add:not(:disabled),
.thread-send:not(:disabled),
.prof-btn.primary:not(:disabled),
.fl-btn.primary:not(:disabled),
.btn-feed {
  background: var(--ember);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 2px 10px -2px rgba(216, 30, 18, .40);
}
@media (hover: hover) and (pointer: fine) {
  .btn-post:not(:disabled):hover,
  .todo-add:not(:disabled):hover,
  .thread-send:not(:disabled):hover,
  .prof-btn.primary:not(:disabled):hover,
  .fl-btn.primary:not(:disabled):hover,
  .btn-feed:hover {
    box-shadow: 0 5px 18px -3px rgba(216, 30, 18, .50);
    transform: translateY(-1px);
  }
}

/* ============================================================
 * 6. ToDo
 * ========================================================== */

/* できた瞬間にチェックが跳ねる */
.todo-check.done { animation: checkPop .42s var(--ease-pop); }
@keyframes checkPop {
  0%   { transform: scale(1); }
  38%  { transform: scale(1.32); }
  70%  { transform: scale(.94); }
  100% { transform: scale(1); }
}

.todo-item { transition: background .2s var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .todo-item:hover { background: rgba(255, 157, 0, .045); } }

/* 達成率。数字を数え上げるのは app-ui.js */
.progress-card { position: relative; overflow: hidden; }
/* 全部できた日は、カードの奥がほんのり燃える */
.progress-card.is-full {
  border-color: rgba(26, 143, 76, .30);
  background:
    radial-gradient(120% 140% at 12% 50%, rgba(26, 143, 76, .10), rgba(26, 143, 76, 0) 60%),
    var(--card);
}

/* ============================================================
 * 7. 習慣カレンダー
 * 記録した日をべた塗りの赤から火花のグラデーションに変える。
 * 件数が多い日ほど濃く（heat-1 → heat-3）して、勢いが目で分かるようにする。
 * 段階は app-ui.js が「N件」を読んで付ける。
 * ========================================================== */
.cal-cell {
  transition:
    transform .18s var(--ease-pop),
    box-shadow .18s var(--ease-out),
    border-color .18s var(--ease-out);
}
.cal-cell.has {
  background: linear-gradient(155deg, #f4694f 0%, #dd2a17 100%);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 3px 10px -4px rgba(216, 30, 18, .55);
}
.cal-cell.has.heat-2 {
  background: linear-gradient(155deg, #f4783c 0%, #d81e12 100%);
  box-shadow: 0 4px 12px -4px rgba(216, 30, 18, .62);
}
.cal-cell.has.heat-3 {
  background: linear-gradient(155deg, #ff9d00 0%, #f5580a 45%, #cb1409 100%);
  box-shadow: 0 5px 16px -4px rgba(245, 88, 10, .70);
}
@media (hover: hover) and (pointer: fine) {
  .cal-cell.has:hover:not(:disabled) {
    transform: scale(1.1);
    box-shadow: 0 7px 18px -4px rgba(216, 30, 18, .62);
  }
}
/* 記録がある日はマスが順番に灯る */
.cal-cell.has {
  animation: appPop .42s var(--ease-pop) calc(var(--i, 0) * 14ms) backwards;
}

/* 今日の印。黒枠だと暖色の並びから浮くので、火花色の輪に替える。
   開いた直後に3回だけ広がって、あとは静かにする（ずっと動くと目障り）。 */
.cal-cell.today {
  border-color: rgba(216, 30, 18, .55);
  color: var(--red-dark);
  /* 塗ってある日でも輪郭が消えないよう、枠の外側にもう一本引く */
  outline: 2px solid rgba(216, 30, 18, .45);
  outline-offset: 1px;
  animation: todayHalo 2.4s ease-out .5s 3 backwards;
}
.cal-cell.has.today {
  border-color: rgba(255, 255, 255, .92);
  color: #fff; /* 塗ってある日は白のまま。上の red-dark を打ち消す */
  animation:
    appPop .42s var(--ease-pop) calc(var(--i, 0) * 14ms) backwards,
    todayHaloHas 2.4s ease-out .8s 3 backwards;
}
@keyframes todayHalo {
  from { box-shadow: 0 0 0 0 rgba(216, 30, 18, .38); }
  to   { box-shadow: 0 0 0 7px rgba(216, 30, 18, 0); }
}
@keyframes todayHaloHas {
  from { box-shadow: 0 0 0 0 rgba(216, 30, 18, .50), 0 3px 10px -4px rgba(216, 30, 18, .55); }
  to   { box-shadow: 0 0 0 8px rgba(216, 30, 18, 0), 0 3px 10px -4px rgba(216, 30, 18, .55); }
}

/* 連続記録の数字は火花色でひとまわり大きく */
.stat-streak b {
  background: var(--ember);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ============================================================
 * 7.5 プロフィール
 * ========================================================== */

/* 大きなアイコンのうしろに火花の輪を置いて、顔まわりに視線が止まるようにする */
.prof-av-wrap::before {
  content: '';
  position: absolute;
  inset: -7px;
  border-radius: 50%;
  background: conic-gradient(from 210deg, #ff9d00, #f5580a, #d81e12, #ff9d00);
  opacity: .22;
  filter: blur(7px);
  z-index: -1;
  animation: avatarSpin 18s linear infinite;
}
.prof-av-wrap { z-index: 0; }
@keyframes avatarSpin {
  to { transform: rotate(1turn); }
}

/* プロフィールの31日ぶんのマス目。
   7列を 1fr で割っていたため、幅の広い画面ではマスが80px近くまで
   膨らんで日付の帯に見えなかった。上限を付けて小さく畳み、中央に置く。 */
.prof-cal-grid {
  grid-template-columns: repeat(7, minmax(0, 34px));
  justify-content: center;
  gap: 7px;
}
.prof-cal-cell { transition: transform .16s var(--ease-pop); }
.prof-cal-cell.on {
  background: var(--ember);
  box-shadow: 0 2px 7px -3px rgba(216, 30, 18, .55);
}
@media (hover: hover) and (pointer: fine) { .prof-cal-cell.on:hover { transform: scale(1.22); } }

/* ============================================================
 * 8. チャット（フリートーク・DM）
 * ========================================================== */
.msg-bubble {
  box-shadow: 0 1px 2px rgba(40, 18, 14, .05);
  transition: box-shadow .2s var(--ease-out);
}
.msg.mine .msg-bubble {
  background: var(--ember);
  box-shadow: 0 2px 10px -3px rgba(216, 30, 18, .42);
}
.conv-item { transition: background .18s var(--ease-out), border-color .18s var(--ease-out); }
.conv-badge { animation: appPop .4s var(--ease-pop) both; }

/* ============================================================
 * 9. 何も無いときの表示
 * 文字だけだと素っ気ないので、消えかけの火花を上に置く。
 * ========================================================== */
.empty-box,
.todo-empty,
.entry-empty,
.dm-placeholder,
.fl-empty,
.dm-list-empty {
  position: relative;
  padding-top: 18px;
}
/* DMの右側は中央ぞろえの横並び。そのままだと火花が文の左隣に出るので縦に積む */
.dm-placeholder { flex-direction: column; }

.empty-box::before,
.todo-empty::before,
.entry-empty::before,
.dm-placeholder::before,
.fl-empty::before,
.dm-list-empty::before {
  content: '';
  display: block;
  width: 46px; height: 46px;
  margin: 0 auto 14px;
  border-radius: 50%;
  border: 1.5px dashed rgba(216, 30, 18, .28);
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 157, 0, .22), rgba(255, 157, 0, 0) 62%);
  animation: emptyBreath 3.4s ease-in-out infinite;
}
@keyframes emptyBreath {
  0%, 100% { transform: scale(1); opacity: .85; }
  50%      { transform: scale(1.07); opacity: 1; }
}

/* ============================================================
 * 10. 読み込み中
 * 「読み込み中...」の一行だけだと、待っているのか壊れたのか分からない。
 * 中身の形をした灰色の板を光らせて、これから何が来るかを示す。
 * ========================================================== */
.loading {
  position: relative;
  min-height: 146px;
  padding: 22px 20px !important;
  color: transparent !important;
  user-select: none;
  overflow: hidden;
  border-radius: 18px;
  background: #fbfaf9;
  border: 1px solid var(--border);
}
.loading::before {
  content: '';
  position: absolute;
  inset: 22px 20px;
  background:
    linear-gradient(#eeecea, #eeecea) 0 2px / 38% 16px no-repeat,
    linear-gradient(#f4f2f1, #f4f2f1) 0 38px / 100% 13px no-repeat,
    linear-gradient(#f4f2f1, #f4f2f1) 0 62px / 84% 13px no-repeat,
    linear-gradient(#f4f2f1, #f4f2f1) 0 86px / 56% 13px no-repeat;
}
.loading::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 157, 0, .13) 50%, transparent 80%);
  transform: translateX(-100%);
  animation: shimmer 1.35s linear infinite;
}
@keyframes shimmer {
  to { transform: translateX(100%); }
}

/* チャットの読み込みは一行で十分なので、点滅だけにする */
.thread-loading { animation: dim 1.2s ease-in-out infinite; }
@keyframes dim {
  0%, 100% { opacity: 1; }
  50%      { opacity: .45; }
}

/* ============================================================
 * 11. 火花のはじけ
 * 「できた」「応援した」の瞬間だけ、押した場所から粒が散る。
 * 粒を作って消すのは app-ui.js。
 * ========================================================== */
.spark-burst {
  position: fixed;
  z-index: 300;
  pointer-events: none;
  width: 0; height: 0;
}
.spark-burst i {
  position: absolute;
  left: 0; top: 0;
  width: 5px; height: 5px;
  margin: -2.5px 0 0 -2.5px;
  border-radius: 50%;
  background: var(--spark-hot);
  animation: sparkFly .62s var(--ease-out) forwards;
}
.spark-burst i:nth-child(even) { background: var(--spark-deep); width: 4px; height: 4px; }
@keyframes sparkFly {
  0%   { opacity: 1; transform: translate(0, 0) scale(1); }
  70%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(.3); }
}

/* リアクションを付けた瞬間、その絵文字がひとつ跳ねる */
.rx.mine .rx-emoji { animation: heartPop .46s var(--ease-pop); }
@keyframes heartPop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.42); }
  60%  { transform: scale(.9); }
  100% { transform: scale(1); }
}

/* ============================================================
 * 12. 知らせ（トースト）
 * ========================================================== */
.toast {
  box-shadow: 0 8px 28px -8px rgba(40, 18, 14, .38);
}
.toast.show { animation: toastIn .38s var(--ease-pop); }
@keyframes toastIn {
  from { opacity: 0; transform: translate(-50%, 14px) scale(.94); }
}

/* ============================================================
 * 13. 動きを減らす設定の人へ
 * 装飾は消し、位置と色だけを残す。
 * ========================================================== */
@media (prefers-reduced-motion: reduce) {
  .app-amb i,
  .prof-av-wrap::before,
  .cal-cell.today, .cal-cell.has.today,
  .empty-box::before, .todo-empty::before, .entry-empty::before,
  .dm-placeholder::before, .fl-empty::before, .dm-list-empty::before,
  .loading::after,
  .thread-loading,
  .spark-burst {
    animation: none !important;
  }
  .post, .member-card, .card, .todo-item, .conv-item, .prof-post,
  .entry-item, .stat-box, .progress-card, .cal-card, .cal-cell.has,
  .msg, .conv-badge, .toast.show, .todo-check.done, .rx.mine .rx-emoji,
  .page-title::after, .page-head h1::after,
  .dm-head h1::after, .todo-item.done .todo-body {
    animation: none !important;
  }
  @media (hover: hover) and (pointer: fine) {
    .post:hover, .member-card:hover, .prof-post:hover, .stat-box:hover,
    .cal-cell.has:hover:not(:disabled) {
      transform: none;
    }
  }
}

/* ===== スマホ：入力欄に触れても画面が拡大しないようにする =====
 * iOS は、文字が16pxより小さい入力欄に触れると画面を勝手に拡大する。
 * コマにひとことを添えるときなど、拡大されて枠が画面からはみ出し読みにくかった。
 * 見た目の大きさは少し変わるが、拡大されないほうが使いやすい。 */
@media (max-width: 860px) {
  input:not([type='checkbox']):not([type='radio']):not([type='range']),
  textarea,
  select { font-size: 16px; }
}
