/* ==========================================================================
   眺める - 能動的スクリーンセーバー
   写真素材は一切使わず、CSSグラデーションとcanvasだけで
   「時刻に連動する空」「ゆっくり流れる地平線」「静かに現れては消える言葉」を表現する。
   ========================================================================== */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;
}

body {
  position: fixed;
  inset: 0;
  user-select: none;
  -webkit-user-select: none;
  cursor: default;
  font-family: "Yu Mincho", "Hiragino Mincho ProN", serif;
}

/* CSS変数の初期値（起動直後、JSが計算するまでの保険） */
:root {
  --sky-top: #050818;
  --sky-mid: #0b1230;
  --sky-bottom: #171334;
  --sil-tint: #0d0f1e;
  --sil-tint-far: #1a2032;
  --msg-color: rgba(255, 250, 240, 0.85);
  --msg-shadow-dark: 0.35;
  --msg-shadow-light: 0;
  --cloud-brightness: 0.6;
  --window-glow: 0;
  --liftoff: 5s;
}

/* 1. 空 ------------------------------------------------------------- */
#sky {
  position: fixed;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to bottom, var(--sky-top), var(--sky-mid) 55%, var(--sky-bottom));
}

/* 2. 星と月 ---------------------------------------------------------- */
#stars {
  position: fixed;
  inset: 0;
  z-index: 2;
  display: block;
  pointer-events: none;
}

/* 3. 雲 ------------------------------------------------------------- */
#clouds {
  position: fixed;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
}
.cloud {
  position: absolute;
  left: 0;
  width: 180px;
  height: 60px;
  opacity: 0;
  border-radius: 50%;
  background: radial-gradient(ellipse at 35% 35%, rgba(255,255,255,.88), rgba(255,255,255,.4) 62%, transparent 82%);
  box-shadow:
    55px 6px 0 -14px rgba(255,255,255,.55),
    -40px 10px 0 -12px rgba(255,255,255,.5),
    90px -8px 0 -20px rgba(255,255,255,.42);
  filter: blur(3px) brightness(var(--cloud-brightness, 1));
  transition: opacity 1.5s ease;
  animation-name: cloud-drift;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform, opacity;
  pointer-events: none;
}
@keyframes cloud-drift {
  from { transform: translateX(-30vw); }
  to   { transform: translateX(130vw); }
}

/* 4. 地平線シルエット（視差2層） ------------------------------------ */
#world {
  position: fixed;
  inset: 0;
  z-index: 4;
  transform: scale(1.6) translateY(30vh);
  transform-origin: 50% 100%;
  transition: transform var(--liftoff, 5s) cubic-bezier(0.45, 0, 0.15, 1);
  pointer-events: none;
}
#world.lifted {
  transform: scale(1) translateY(0);
}
.world-layer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  overflow: hidden;
}
/* パンはマスク位置ではなく子要素の transform で行う（コンポジタに乗せて省電力にするため）。
   幅の 2048px は JS の STRIP_WIDTH と一致させること。 */
.world-strip {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(100% + 2048px);
  mask-repeat: repeat-x;
  -webkit-mask-repeat: repeat-x;
  mask-position: 0 bottom;
  -webkit-mask-position: 0 bottom;
  will-change: transform;
}
#world-far {
  height: 40vh;
  opacity: .55;
}
#world-far .world-strip { background-color: var(--sil-tint-far); }
#world-near {
  height: 30vh;
  opacity: .95;
}
#world-near .world-strip { background-color: var(--sil-tint); }
/* 近景の建物に灯る窓明かり。world-strip の子要素にして、親のtranslateXパンとCSSマスクを
   そのまま受け継ぐ（マスクは要素配下ごと切り抜くため、追加の毎フレーム処理が不要になる） */
.window-lights {
  position: absolute;
  inset: 0;
  background-repeat: repeat-x;
  background-position: 0 bottom;
  background-size: 2048px 100%;   /* マスクと同じ引き伸ばし方にして位置を揃える */
  opacity: var(--window-glow, 0);
  transition: opacity 3s ease;
}
#world-near.shake {
  /* 嵐でも世界の遅さを崩さない、ゆったりした揺れ */
  animation: sil-shake 2.8s ease-in-out infinite;
}
@keyframes sil-shake {
  0%, 100% { transform: rotate(0deg); }
  25%      { transform: rotate(.15deg); }
  75%      { transform: rotate(-.15deg); }
}

/* 5. 雨・嵐の粒子 ----------------------------------------------------- */
#particles {
  position: fixed;
  inset: 0;
  z-index: 5;
  display: block;
  pointer-events: none;
}

/* 6. 天候による減光レイヤー ------------------------------------------- */
#weather-overlay {
  position: fixed;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  background-color: #4a5568;
  transition: background-color 2s ease, opacity 2s ease;
}

/* 6b. 雷（嵐のときだけ、まれに画面全体が白く光る。opacityはJSが直接いじる） --------- */
#lightning {
  position: fixed;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  background: #dce8ff;
}

/* 7. 導入演出用の地面 -------------------------------------------------- */
#ground {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 42vh;
  z-index: 7;
  transform: translateY(0) scale(1);
  transition: transform var(--liftoff, 5s) cubic-bezier(0.45, 0, 0.15, 1);
  background:
    radial-gradient(ellipse 60% 40% at 20% 30%, rgba(70,52,34,.45), transparent 65%),
    radial-gradient(ellipse 50% 45% at 75% 55%, rgba(45,33,22,.55), transparent 60%),
    radial-gradient(ellipse 70% 50% at 45% 85%, rgba(18,13,9,.7), transparent 55%),
    linear-gradient(to bottom, #241b12, #0c0805);
}
#ground.lift {
  transform: translateY(120vh) scale(1.12);
}

/* 8. 視野の狭まり（ビネット） ------------------------------------------ */
#vignette-narrow, #vignette-wide {
  position: fixed;
  inset: 0;
  z-index: 8;
  pointer-events: none;
  transition: opacity var(--liftoff, 5s) cubic-bezier(0.45, 0, 0.15, 1);
}
#vignette-narrow {
  opacity: 1;
  background: radial-gradient(ellipse at 50% 68%, transparent 6%, rgba(0,0,0,.8) 32%, rgba(0,0,0,.99) 58%);
}
#vignette-narrow.open { opacity: 0; }
#vignette-wide {
  opacity: 0;
  /* 境界の楕円が「輪」として見えないよう、開始位置を外側に寄せて薄めにする */
  background: radial-gradient(ellipse at center, transparent 58%, rgba(0,0,0,.38) 100%);
}
#vignette-wide.open { opacity: 1; }

/* 9. 流れるメッセージ --------------------------------------------------- */
#messages {
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
}
.message {
  position: fixed;
  opacity: 0;
  max-width: min(70vw, 560px);
  color: var(--msg-color);
  font-family: "Yu Mincho", "Hiragino Mincho ProN", serif;
  font-size: clamp(16px, 2.2vw, 26px);
  letter-spacing: 0.12em;
  line-height: 1.7;
  white-space: pre-line; /* 将来の長文で改行(\n)を入れたときに反映されるように */
  /* 影は「暗い影」と「白いハロ」の2層。文字色が空の明暗で切り替わる遷移中も輪郭を保つ */
  text-shadow:
    0 1px 6px rgba(0,0,0,var(--msg-shadow-dark, .35)),
    0 0 14px rgba(255,255,255,var(--msg-shadow-light, 0));
  pointer-events: none;
  transition: opacity 4s ease, color 2.5s linear;
  will-change: opacity;
}
.message.show {
  opacity: 1;
  transition: opacity 3s ease, color 2.5s linear;
}

/* 10. UI（もどる／天気） ------------------------------------------------ */
#ui {
  position: fixed;
  inset: 0;
  z-index: 10;
  opacity: 0;
  pointer-events: none;
  transition: opacity .6s ease;
}
#ui.visible { opacity: .85; }
/* 不可視のあいだは反応もさせない（見えないボタンの誤タップ・誤クリック防止） */
#ui:not(.visible) #back-link,
#ui:not(.visible) #weather-ui { pointer-events: none; }
#back-link {
  position: absolute;
  top: 20px;
  left: 20px;
  pointer-events: auto;
  color: var(--msg-color);
  text-decoration: none;
  font-size: 14px;
  letter-spacing: .05em;
  text-shadow: 0 1px 3px rgba(0,0,0,.4);
}
#back-link:hover { text-decoration: underline; }
#weather-ui {
  position: absolute;
  bottom: 20px;
  right: 20px;
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: auto;
}
/* 下端のUIは常に暗いシルエットの上に乗るため、文字色は時間帯連動させず明るい色で固定する
   （昼は --msg-color が濃紺になり、暗色×暗色で見えなくなるため） */
/* 「天気」の見出しラベル。何のボタン群かひと目で分かるように */
.ui-label {
  color: rgba(255, 248, 235, .9);
  font-size: 12px;
  letter-spacing: .15em;
  opacity: .8;
  margin-right: 2px;
  text-shadow: 0 1px 3px rgba(0,0,0,.4);
}
/* ボタンはピル型にして「押せるもの」だと分かるようにする。選択中は薄く塗りつぶす */
#weather-ui button {
  background: none;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 5px 14px;
  margin: 0;
  color: rgba(255, 248, 235, .9);
  font-family: inherit;
  font-size: 14px;
  letter-spacing: .1em;
  opacity: .65;
  cursor: pointer;
  text-shadow: 0 1px 3px rgba(0,0,0,.4);
  transition: opacity .3s ease, background-color .3s ease;
}
#weather-ui button:hover { opacity: 1; }
#weather-ui button.active {
  opacity: 1;
  background-color: rgba(255, 255, 255, .32);
}
/* 天気グループと音トグルの区切り線 */
.ui-divider {
  width: 1px;
  height: 18px;
  margin: 0 4px;
  background-color: rgba(255, 248, 235, .9);
  opacity: .4;
}

/* 11. 「夜へ」（左下にひっそり置く入力欄。書いた文字は紙飛行機に託して夜空へ放つ。保存はしない） -------- */
#yoru {
  position: fixed;
  left: 20px;
  bottom: 20px;
  z-index: 10;
  text-align: left;
  pointer-events: none;
}
#yoru.visible {
  pointer-events: auto;
}
/* stage: 入力欄の行を置くための土台 */
#yoru-stage {
  position: relative;
}
/* 誘い文句が先にフェードインし、入力欄の行は約0.4秒遅れて現れる（transition-delayで実現）。
   消えるときは #yoru.visible が外れて delay 付きのセレクタごと効かなくなるので、
   遅延なしで両方いっしょに消える。
   下端UI（天気・音）と同じ固定の明色。時刻連動の --msg-color にすると、
   昼にシルエットと同化して読めなくなるため、ここだけは時刻に関わらず明るく固定する */
#yoru-hint {
  font-size: 12px;
  opacity: 0;
  margin-bottom: 6px;
  color: rgba(255, 248, 235, .9);
  transition: opacity .6s ease;
}
#yoru.visible #yoru-hint {
  opacity: .45;
}
#yoru-row {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  opacity: 0;
  transition: opacity .6s ease;
}
#yoru.visible #yoru-row {
  opacity: .9;
  transition-delay: .4s;
}
/* 枠は下線1本だけ */
#yoru-input {
  background: none;
  border: none;
  border-bottom: 1px solid rgba(255, 248, 235, .35);
  color: rgba(255, 248, 235, .9);
  font-family: "Yu Mincho", "Hiragino Mincho ProN", serif;
  font-size: 14px;
  letter-spacing: .08em;
  width: min(50vw, 260px);
  text-align: left;
  padding: 4px 2px;
  outline: none;
  transition: border-color .3s ease;
}
#yoru-input:focus { border-bottom-color: rgba(255, 248, 235, .8); }
#yoru-input::placeholder { color: rgba(255, 248, 235, .9); opacity: .5; }
/* 「夜へ」ボタンは天気ボタンと同じピル型・同じ配色（下端UIと同様、時刻連動させず固定色） */
#yoru-send {
  background: none;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 5px 14px;
  margin: 0;
  color: rgba(255, 248, 235, .9);
  font-family: inherit;
  font-size: 14px;
  letter-spacing: .1em;
  opacity: .65;
  cursor: pointer;
  text-shadow: 0 1px 3px rgba(0,0,0,.4);
  transition: opacity .3s ease, background-color .3s ease;
}
#yoru-send:hover { opacity: 1; }
#yoru-send:disabled { opacity: .3; cursor: default; }

/* 12. 「夜へ」の送信演出（入力欄の文字→紙飛行機→光のバースト） --------------------- */
/* 送信直後、入力欄があった位置に文字を一瞬見せる土台。
   通常演出は0.25秒で縮んで消え（紙飛行機に折りたたまれる見立て）、
   reduced-motionのときはこちらを使わず0.5秒でただフェードするだけにする */
.yoru-reveal {
  position: fixed;
  z-index: 9;
  display: flex;
  align-items: center;
  color: rgba(255, 248, 235, .9);
  font-family: "Yu Mincho", "Hiragino Mincho ProN", serif;
  font-size: 14px;
  letter-spacing: .08em;
  white-space: nowrap;
  pointer-events: none;
  opacity: 1;
  transform: scale(1);
  transform-origin: left center;
}
.yoru-reveal-fold { transition: opacity .25s ease, transform .25s ease; }
.yoru-reveal-fold.go { opacity: 0; transform: scale(.6); }
.yoru-reveal-fade { transition: opacity .5s ease; }
.yoru-reveal-fade.go { opacity: 0; }

/* 紙飛行機本体。外側(outer)がXを一定ペースで、内側(inner)がYをease-outで動かす
   入れ子構造にすることで、直線ではなく「すっと昇って滑空する」弧を描く。
   --plane-duration はJSが毎回の飛行時間(1.3〜1.6秒)を書き込むカスタムプロパティで、
   outerに設定すれば子孫のinner/rotateにも継承される */
.yoru-plane-outer {
  position: fixed;
  z-index: 9;
  width: 0;
  height: 0;
  pointer-events: none;
  transition: transform var(--plane-duration, 1.4s) linear, opacity .2s ease;
}
.yoru-plane-outer.landing { opacity: 0; } /* 着地と同時にフェードアウト（バーストと入れ替わる） */
.yoru-plane-inner {
  position: absolute;
  left: 0;
  top: 0;
  transition: transform var(--plane-duration, 1.4s) ease-out;
}
.yoru-plane-rotate {
  position: absolute;
  left: -11px;
  top: -11px;
  width: 22px;
  height: 22px;
  filter: drop-shadow(0 2px 5px rgba(0,0,0,.35));
  transition: transform var(--plane-duration, 1.4s) ease;
}
.yoru-plane-rotate svg { display: block; width: 100%; height: 100%; }

/* 着地点で放つ光。「コアの閃光」「広がる輪」「画面全体の一瞬の明滅」の三段構成。
   いずれもscaleとopacityだけの短い演出で、終わったらJSがDOMから外す */
.yoru-burst-core {
  position: fixed;
  z-index: 9;
  left: 0;
  top: 0;
  width: 60px;
  height: 60px;
  margin-left: -30px;
  margin-top: -30px;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle, rgba(255, 250, 230, 1), transparent 60%);
  opacity: 1;
  transform: scale(.2);
  transition: opacity .7s ease-out, transform .7s ease-out;
}
.yoru-burst-core.burst { opacity: 0; transform: scale(2.6); }

.yoru-burst-ring {
  position: fixed;
  z-index: 9;
  left: 0;
  top: 0;
  width: 60px;
  height: 60px;
  margin-left: -30px;
  margin-top: -30px;
  border-radius: 50%;
  border: 1px solid rgba(255, 250, 230, .7);
  pointer-events: none;
  opacity: 1;
  transform: scale(.3);
  transition: opacity .6s ease-out, transform .6s ease-out;
}
.yoru-burst-ring.burst { opacity: 0; transform: scale(3); }

/* 空の一瞬の明滅。#lightning（雷）とは別の専用要素。JSが生成→@keyframes一回だけ光って自動でDOMから外す */
@keyframes yoru-sky-flash-kf {
  0%   { opacity: 0; }
  35%  { opacity: .11; }
  100% { opacity: 0; }
}
.yoru-sky-flash {
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  background: rgba(255, 250, 235, 1);
  opacity: 0;
  animation: yoru-sky-flash-kf .12s ease-out;
}

/* prefers-reduced-motion: 雲や星の瞬きは残し、パン・粒子・長い浮上時間だけ抑える。
   実際の停止処理はJS側（速度0・粒子目標0・liftoff短縮）で行う。ここでは念のため
   ユーザーの意図を尊重し、雲の移動もやや控えめにしておく。 */
@media (prefers-reduced-motion: reduce) {
  .cloud { animation-duration: 400s !important; }
}
