/* =============================================================
   style.css — ダークテーマの Awwwards 的ショーケース
   フォント: 英数字は SF Mono / Menlo、日本語は Hiragino Sans
   ============================================================= */

:root {
  --bg:        #0c0f16;   /* ベースの暗色 */
  --bg-soft:   #12151f;   /* カード地 */
  --line:      #1e232f;   /* 罫線 */
  --fg:        #e7eaf1;    /* 主要テキスト */
  --fg-dim:    #7c8395;   /* 補助テキスト */
  --accent:    #6cf0d0;   /* アクセント(ミント) */
  --font: "SF Mono", Menlo, "Hiragino Sans", sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* 共有 canvas: 全画面固定。画像プレーンだけを描くので背景は透過。
   z-index:-1 で全コンテンツの背面へ置き、透過にした .card__media の穴から
   プレーンを見せる。こうすると .card の transform(登場アニメ)が作る
   スタッキングコンテキストに関係なく、ラベル等のテキストは常に前面に出る。
   pointer-events:none でカードの hover イベントを妨げない。 */
#gl {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: -1;
  pointer-events: none;
}

/* --- ヘッダー --------------------------------------------- */
.site-header {
  position: relative;
  z-index: 3;                 /* canvas より前面 */
  padding: 14vh 6vw 8vh;      /* max-width 撤去で全幅。左右は 6vw の余白を維持 */
}
.site-header__kicker {
  color: var(--accent);
  font-size: 0.8rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
}
.site-header__title {
  font-size: clamp(2.6rem, 8vw, 6rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.02;
  margin: 0.4em 0;
}
.site-header__lead {
  color: var(--fg-dim);
  font-size: 0.95rem;
}
.site-header__lead span { display: block; margin-top: 0.4em; color: #566; }

/* --- グリッド --------------------------------------------- */
.grid {
  position: relative;
  display: grid;
  /* auto-fit で画面幅に応じて列数が流動的に変化。
     基準 260px: 広い画面で 3〜4 列 / 中間で 2〜3 列 / 狭い画面で 1 列。
     min(260px, 100%) で 260px 未満の狭い端末でも横あふれしない。 */
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: clamp(1.5rem, 4vw, 4rem);
  padding: 0 6vw 12vh;        /* max-width 撤去で全幅。左右は 6vw の余白を維持 */
}

.card {
  position: relative;
}
/* 登場前の非表示は「JSが生きているとき(.js)だけ」適用する。
   JSが読み込めない環境ではこの指定が外れ、静的な写真グリッドとして見える(保険)。
   発火は app.js の IntersectionObserver が「初めて画面内に入ったとき」に
   .is-revealed を付与して行う。(同時に WebGL 側の uReveal も開始し、
   写真は下から上へのソフトワイプ + ズームアウト + フェードで現れる) */
.js .card {
  opacity: 0;
  transform: translateY(40px);
}
.card.is-revealed {
  /* duration・イージングは WebGL 側の登場演出(0.9s / ease-out)と一致させる */
  animation: rise 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes rise {
  to { opacity: 1; transform: translateY(0); }
}

.card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: transparent;    /* 背面の canvas プレーンを透かして見せる */
  /* 枠線なし: 写真をフラットに見せる(修正依頼によりボーダー削除) */
}
/* DOM 上の実画像(alt を残し SEO/A11y 用)。canvas が背面へ同じ画像を
   描くので、DOM img 自体は視覚的に隠す(opacity:0)。alt はアクセシビリティ/
   SEO のため DOM に残す。 */
.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* imgを隠すのもJSが生きているときだけ(JS死亡時は実画像がそのまま見える) */
.js .card__media img {
  opacity: 0;
}

/* ラベルは写真の外(下)。プレーン自体も .card__media の矩形にのみ
   同期させている(app.js の syncMesh)ため写真とは重ならない。 */
.card__meta {
  position: relative;
  z-index: 3;                 /* テキストは canvas より前面 */
  display: flex;
  align-items: baseline;
  gap: 0.9em;
  margin-top: 1rem;
  font-size: 0.9rem;
}
.card__meta .num {
  color: var(--accent);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
}
.card__meta .en { font-weight: 600; letter-spacing: 0.01em; }
.card__meta .ja { color: var(--fg-dim); font-size: 0.78rem; }

/* --- 仮想カーソル(ポインティングデバイスなし環境の自動デモ) ---
   カードが画面内に入ると app.js がリサージュ軌道で動かし、
   実ホバーと同じ経路でエフェクトを駆動する。PC の自作カーソルと
   デザイン統一(アクセント色のリング)。opacity は JS がホバー量と同期。 */
.card__vcursor {
  position: absolute;
  top: 0; left: 0;
  width: 18px; height: 18px;
  margin: -9px 0 0 -9px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  background: rgba(108, 240, 208, 0.15);
  box-shadow: 0 0 10px rgba(108, 240, 208, 0.35);
  pointer-events: none;
  z-index: 3;                 /* 写真より前・「</>」ボタン(4)より背面 */
  opacity: 0;
}

/* --- 「</>」ボタン(コードモーダルを開く) -------------------- */
.card { cursor: pointer; }    /* デスクトップはカードクリックでもモーダル */

.card__code-btn {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 4;                 /* 写真より前面 */
  padding: 0.3em 0.55em;
  font-family: var(--font);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  color: var(--fg-dim);
  background: rgba(12, 15, 22, 0.72);
  border: 1px solid var(--line);
  border-radius: 4px;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;
}
.card__code-btn:hover,
.card__code-btn:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
}

/* --- コードモーダル ---------------------------------------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4vh 4vw;
}
.modal[hidden] { display: none; }

.modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 6, 10, 0.78);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.modal__panel {
  position: relative;         /* backdrop より前面(後勝ち) */
  width: min(760px, 100%);
  max-height: 84vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6);
}

.modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.3rem 0.9rem;
  border-bottom: 1px solid var(--line);
}
.modal__title {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.modal__sub {
  color: var(--fg-dim);
  font-size: 0.76rem;
  margin-top: 0.15em;
}
.modal__actions { display: flex; gap: 0.5rem; flex-shrink: 0; }

.modal__copy {
  font-family: var(--font);
  font-size: 0.76rem;
  letter-spacing: 0.05em;
  color: var(--fg);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.35em 0.9em;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;
}
.modal__copy:hover,
.modal__copy:focus-visible { color: var(--accent); border-color: var(--accent); }
.modal__copy.is-copied { color: var(--accent); border-color: var(--accent); }

.modal__close {
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1;
  color: var(--fg-dim);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 4px;
  width: 2em;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;
}
.modal__close:hover,
.modal__close:focus-visible { color: var(--fg); border-color: var(--fg-dim); }

/* コード外の注意書き(CORS / ローカルサーバの案内) */
.modal__note {
  padding: 0.7rem 1.3rem;
  border-bottom: 1px solid var(--line);
  color: var(--fg-dim);
  font-size: 0.74rem;
  line-height: 1.6;
}

/* 3ブロック(index.html / style.css / script.js)を縦に並べるスクロール領域 */
.modal__body {
  overflow: auto;
  padding: 1rem 1.3rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}

.modal__file {
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;   /* 親(.modal__body)が flex のため、潰されて内容が切れるのを防ぐ */
}
.modal__file-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0.9rem;
  background: #171b26;        /* 不透明(sticky でコードの上に重なるため) */
  border-bottom: 1px solid var(--line);
  /* コピーボタンごとスクロールしないよう上に貼り付ける */
  position: sticky;
  top: 0;
  z-index: 1;
}
.modal__file-name {
  color: var(--accent);
  font-size: 0.78rem;
  letter-spacing: 0.05em;
}

/* コード領域: 横スクロール可能(縦は .modal__body 側で) */
.modal__code {
  overflow-x: auto;
  padding: 0.9rem 0.9rem 1.1rem;
  font-size: 0.74rem;
  line-height: 1.7;
  color: #b8c1d4;
  tab-size: 2;
}
.modal__code code { font-family: var(--font); white-space: pre; }

/* --- 自前シンタックスハイライト(ダークテーマ調和・外部ライブラリなし) --- */
.hl-c { color: #5d6678; }                 /* コメント */
.hl-s { color: #a9d3ae; }                 /* 文字列 / CSS 値キーワード */
.hl-k { color: var(--accent); }           /* JSキーワード / HTMLタグ名 / CSSセレクタ */
.hl-n { color: #e6c98a; }                 /* 数値(単位付き含む) */
.hl-a { color: #8ab8e8; }                 /* HTML属性名 / CSSプロパティ名 */
.hl-t { color: #8ab8e8; }                 /* GLSL 型・修飾子 */

/* --- フッター --------------------------------------------- */
.site-footer {
  position: relative;
  z-index: 3;
  /* ヘッダー/グリッドと同じ全幅+6vw余白に統一 */
  padding: 6vh 6vw 8vh;
  border-top: 1px solid var(--line);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  color: var(--fg-dim);
  font-size: 0.8rem;
}

/* --- 自作カーソル(PC のみ) -------------------------------- */
.cursor {
  position: fixed;
  top: 0; left: 0;
  width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  pointer-events: none;
  z-index: 30;                /* モーダル(20)より前面 */
  mix-blend-mode: difference;
  transition: width 0.2s, height 0.2s;
}
@media (hover: none), (pointer: coarse) {
  .cursor { display: none; }
}

/* --- レスポンシブ ----------------------------------------- */
@media (max-width: 720px) {
  /* 列数は .grid の auto-fit が自動で調整するため、ここでは固定しない。
     モバイルではヘッダーの上下余白だけ詰める。 */
  .site-header { padding: 10vh 6vw 6vh; }
}

/* 登場アニメを抑制したいユーザーへの配慮
   (WebGL 側も app.js が同じメディアクエリを見て uReveal=1 で即表示する) */
@media (prefers-reduced-motion: reduce) {
  .card { opacity: 1; transform: none; }
  .card.is-revealed { animation: none; }
}
