@charset "utf-8";

/* =========================================================
   ローディング／イントロ
   1. 読み込み中   点線リング＋進捗アーク＋ロゴ＋LOADING／%
   2. 読み込み完了 アークがワイヤーフレーム地球儀に変わり SCROLL ↓
   3. ズーム       一度きっかけがあれば、あとは時間で地球儀が拡大
   4. 通り抜け     星空を抜けてローダーが消え、FV が現れる

   html に付く状態クラス（JS が操作）:
     .is-intro   イントロ実行中（ページのスクロールを止める）
     .is-lit     初期表示が済んだ（リングとロゴをフェードイン）
     .is-ready   読み込み完了（地球儀と SCROLL を表示）
     .is-zooming ズーム中（--l-travel に直結。transition は使わない）
     .is-outro   退場中

   寸法はすべて --l-size（点線リングの直径）からの比率で決める。
   Figma 実測：リング直径 527px ／ 地球儀・アーク直径 332px ／ ロゴ幅 109px
   ========================================================= */

:root {
  /* 画面に対するローダーの基準サイズ（＝点線リングの直径） */
  --l-size:        min(52.7vh, 86vw);

  /* --l-size に対する各パーツの比率（Figma 実測値） */
  --l-globe-ratio: .63;   /* 332 / 527 */
  --l-logo-ratio:  .207;  /* 109 / 527 */

  /* ズーム */
  --l-zoom-max:    18;    /* 最終倍率（球を通り抜ける） */

  /* 状態変数（JS が毎フレーム書き換える） */
  --l-progress:    0;     /* 読み込み進捗 0〜1 */
  --l-travel:      0;     /* ズーム進捗   0〜1 */
  --l-line-scale:  1;     /* 線幅の補正（拡大時に線が太りすぎないように） */

  /* 動きの時間・イージング */
  --l-fast:  200ms;
  --l-base:  600ms;
  --l-slow:  900ms;
  --l-ease:  cubic-bezier(.16, 1, .3, 1);

  /* ローディング画面の背景（中心 → 四隅） */
  --l-space: radial-gradient(circle at 50% 50%,
               #00153a 0%,
               #001232 19%,
               #000f2a 33%,
               #000c22 46%,
               #010816 100%);
}

/* イントロ中はページを動かさない ---------------------------------------- */
/* スクロールは止めるが、スクロールバーの幅は残す。
   幅が変わるとヘッダーがブレークポイントをまたいで一瞬サイズが変わるため。
   html は高さを画面ぴったりにして中身を body 側で切るので、
   overflow-y:scroll でも実際には動かない（溝だけが残る） */
html.is-intro { overflow-y: scroll; height: 100%; }
html.is-intro body { overflow: hidden; height: 100%; }

/* 幕の裏でページ側のアニメーションを進めない（FV の入場を取っておく）
   ローダーは .page の外に置くので、ローダー自身には効かない */
html.is-intro .page * { animation-play-state: paused !important; }


/* =========================================================
   外枠
   ========================================================= */
.l-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--l-space);
}

/* 再訪や「動きを減らす」設定では、JS が消すまでの一瞬も見せない */
html:not(.is-intro):not(.is-outro):not(.is-zooming) .l-loader { display: none; }

.l-loader__sky {
  position: absolute;
  inset: 0;
  opacity: 0;
  will-change: opacity;
}

.l-loader__sky img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* =========================================================
   ステージ（リング・アーク・地球儀・ロゴがまとめて拡大する）
   ========================================================= */
.l-loader__stage {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--l-size);
  aspect-ratio: 1;
  will-change: scale;
}

.l-loader__stage > * { grid-area: 1 / 1; }


/* 点線リング ---------------------------------------------------------------
   回転は常時。フェードインは transition で行う（animation を二重掛けすると
   ズーム開始時に animation-name が切り替わって回転が巻き戻るため）。 */
.l-loader__ring {
  width: 100%;
  height: 100%;
  color: var(--gold);
  opacity: 0;
  transition: opacity var(--l-slow) var(--l-ease) .1s;
  animation: l-ring-spin 90s linear infinite;
}

html.is-lit .l-loader__ring { opacity: 1; }

/* 実測：点は約 149 個、周期 11.1px、線幅 5px（直径 527px のとき）
   → viewBox 200 単位では 周期 4.21 / 線幅 1.9 */
.l-loader__ring circle {
  fill: none;
  stroke: currentColor;
  stroke-width: calc(1.9 * var(--l-line-scale));
  stroke-opacity: .55;
  stroke-dasharray: 1.1 3.11;
  stroke-linecap: butt;
}

@keyframes l-ring-spin { to { rotate: 360deg; } }


/* 進捗アーク ---------------------------------------------------------------
   --l-progress は JS 側で補間済みなので、ここでは transition を掛けない
   （掛けると二重に遅れて、数字と線がずれて見える）。 */
.l-loader__arc {
  width: calc(100% * var(--l-globe-ratio));
  height: calc(100% * var(--l-globe-ratio));
  rotate: -90deg;               /* 12 時の位置から時計回り */
  transition: opacity var(--l-base) var(--l-ease);
}

.l-loader__arc circle {
  fill: none;
  stroke: var(--gold);
  stroke-width: .55;            /* 実測 約 1.5px（直径 332px のとき） */
  stroke-opacity: .9;
  stroke-linecap: round;
  stroke-dasharray: 314.16;     /* 2πr（r = 50） */
  stroke-dashoffset: calc(314.16 * (1 - var(--l-progress)));
}

html.is-ready .l-loader__arc { opacity: 0; }


/* ワイヤーフレーム地球儀 ----------------------------------------------------
   緯線・経線は正射影の楕円そのもの（折れ線ではない）ため要素数 24 で描ける。
   線幅は --l-line-scale（JS がズーム量から算出）で補正し、
   拡大しても線だけが太くなりすぎないようにする。 */
.l-loader__globe {
  width: calc(100% * var(--l-globe-ratio));
  height: calc(100% * var(--l-globe-ratio));
  opacity: 0;
  scale: .86;
  /* アークが消えるのを待ってから現れる（1 → 2 の受け渡しを段差にする） */
  transition: opacity var(--l-slow) var(--l-ease) .18s,
              scale   var(--l-slow) var(--l-ease) .18s;
}

html.is-ready .l-loader__globe { opacity: 1; scale: 1; }

.l-globe__grid ellipse {
  fill: none;
  stroke: var(--gold);
  stroke-width: calc(.5 * var(--l-line-scale));
  stroke-opacity: .55;
}

.l-globe__rim {
  fill: none;
  stroke: var(--gold);
  stroke-width: calc(.9 * var(--l-line-scale));
  stroke-opacity: .9;
}


/* 中央（ロゴ＋テキスト） ---------------------------------------------------- */
.l-loader__center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--l-size) * .036);
}

/* 登場は入れ子の wrapper 側で行う。
   img 本体の opacity を空けておかないと、ズーム中の指定と衝突するため。 */
.l-loader__logo-in {
  display: block;
  opacity: 0;
  translate: 0 6px;
  transition: opacity var(--l-slow) var(--l-ease) .2s,
              translate var(--l-slow) var(--l-ease) .2s;
}

html.is-lit .l-loader__logo-in { opacity: 1; translate: 0 0; }

.l-loader__logo {
  width: calc(var(--l-size) * var(--l-logo-ratio));
  height: auto;
}

/* テキストブロック（LOADING/% と SCROLL を同じ位置で入れ替える） */
.l-loader__status {
  position: relative;
  display: grid;
  place-items: center;
  min-height: calc(var(--l-size) * .09);
  margin: 0;
}

.l-loader__status > * { grid-area: 1 / 1; }

.l-loader__loading,
.l-loader__scroll {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--l-size) * .022);
  color: #fff;
  font-family: var(--f-en);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: .125em;
  white-space: nowrap;
}

/* LOADING ／ %
   SCROLL とは同じ位置で入れ替わるため、時間を重ねない。
   先に LOADING が消えきり（280ms）、そのあとに SCROLL が出る。 */
.l-loader__loading { transition: opacity 280ms var(--l-ease); }
html.is-ready .l-loader__loading { opacity: 0; }

.l-loader__pct {
  font-size: 16px;
  letter-spacing: .04em;
  /* 数字の幅を固定して、カウント中に文字が揺れないようにする */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

.l-loader__pct i {
  font-size: 14px;
  font-style: normal;
}

/* SCROLL ↓ —— LOADING が消えきる 280ms より後から出す（重ならないように） */
.l-loader__scroll {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--l-base) var(--l-ease) 320ms;
}

html.is-ready .l-loader__scroll { opacity: 1; pointer-events: auto; }

.l-loader__scroll svg {
  width: 10px;
  height: 22px;
  color: #fff;
  animation: l-nudge 1.8s var(--l-ease) infinite;
}

@keyframes l-nudge {
  0%, 100% { translate: 0 0;   opacity: 1; }
  50%      { translate: 0 5px; opacity: .45; }
}


/* =========================================================
   スキップ
   ========================================================= */
.l-loader__skip {
  position: absolute;
  right: clamp(16px, 3vw, 40px);
  bottom: clamp(16px, 3vw, 40px);
  padding: 8px 16px;
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: 999px;
  color: #fff;
  font-family: var(--f-en);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .125em;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--l-base) var(--l-ease) .35s,
              border-color var(--l-fast) var(--l-ease);
}

html.is-ready .l-loader__skip { opacity: .7; pointer-events: auto; }
.l-loader__skip:hover { opacity: 1; border-color: var(--gold-light); }


/* =========================================================
   ズーム中 —— すべて --l-travel に直結させる（transition は掛けない）
   JS が毎フレーム補間した値を渡しているので、ここで遅延を足すと
   二重に遅れてスクロールから乖離する。
   ========================================================= */
html.is-zooming .l-loader,
html.is-zooming .l-loader__ring,
html.is-zooming .l-loader__globe,
html.is-zooming .l-loader__logo,
html.is-zooming .l-loader__loading,
html.is-zooming .l-loader__scroll,
html.is-zooming .l-loader__skip {
  transition: none;
}

/* 星空はフェードのみ。拡大はしない。
   1920px の画像を毎フレーム拡大すると、そのたびに描き直しが走ってフレームを
   落とす。奥行きは地球儀とリングが目の前を通り過ぎることで十分に出るため、
   ここは不透明度だけ動かす（合成だけで済むので負荷がない）。 */
html.is-zooming .l-loader__sky {
  opacity: 1;
  transition: opacity calc(var(--l-fly-duration, 2000ms) * .45) ease-out;
}

/* 通り過ぎて見えなくなったものは描画対象から外す。
   ズーム終盤はステージが 18 倍＝約 9500px になり、そこで巨大な SVG を
   描き続けるのが最も重い。消えた時点で display:none にする。 */
html.is-past-ring  .l-loader__ring  { display: none; }
html.is-past-globe .l-loader__globe { display: none; }

/* LOADING はこの時点で既に消えている。
   ズーム用の式に巻き込むと動き出した瞬間に表示が戻って SCROLL と重なるので、
   明示的に 0 のままにする。 */
html.is-zooming .l-loader__loading { opacity: 0; }

/* SCROLL と SKIP は動き始めてすぐ消える */
html.is-zooming .l-loader__scroll,
html.is-zooming .l-loader__skip {
  opacity: clamp(0, calc((.12 - var(--l-travel)) * 8), 1);
  pointer-events: none;
}

/* ロゴは球面に溶け込み、通り抜けるにつれて消える */
html.is-zooming .l-loader__logo {
  opacity: clamp(0, calc((.8 - var(--l-travel)) * .5), .2);
}

html.is-zooming .l-loader__globe {
  opacity: clamp(0, calc((.95 - var(--l-travel)) * 2), 1);
}

html.is-zooming .l-loader__ring {
  opacity: clamp(0, calc((.7 - var(--l-travel)) * 2), 1);
}

/* 通り抜けた先でローダーごと透ける */
html.is-zooming .l-loader {
  opacity: clamp(0, calc((1.04 - var(--l-travel)) * 5), 1);
}


/* =========================================================
   退場
   ========================================================= */
html.is-outro .l-loader {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--l-base) var(--l-ease),
              visibility var(--l-base) var(--l-ease);
}


/* =========================================================
   レスポンシブ
   ========================================================= */
@media (max-width: 640px) {
  :root { --l-size: min(46vh, 82vw); }
}


/* =========================================================
   動きを減らす設定では演出を行わない（JS 側でもスキップする）
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  .l-loader,
  .l-loader *,
  .l-loader__ring,
  .l-loader__scroll svg {
    animation: none !important;
    transition: none !important;
  }

  html.is-intro .page * { animation-play-state: running !important; }
}
