/* KANKYO DOT — Resonant Fields
   組版は Figma を正とする。配色は2色のみで、濃淡は color-mix で2色から派生させる（CLAUDE.md §5）。 */

/* ---------------------------------------------------------------- フォント
   woff2 は同梱して self-host する。外部リクエストを1本も発生させない（CLAUDE.md §5・§7）。
   欧文は Google Fonts の unicode-range 分割をそのまま使い、和文は本文から
   使用文字だけを抜いたサブセット（再生成は ./build-jp-subset.sh）。 */

@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/instrument-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/instrument-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-serif-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-serif-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Noto Sans JP";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/noto-sans-jp-subset.woff2") format("woff2");
}

/* ---------------------------------------------------------------- トークン */

:root {
  --bg: #000000;
  --fg: #D2FF8C;

  /* 3色目を足さず、罫線は2色から派生させる。transparent ではなく --bg と混ぜて
     不透明にする。半透明だと背後の canvas が透け、ローブに重なる区間で線が消える */
  --rule: color-mix(in srgb, var(--fg) 50%, var(--bg));

  --font-sans: "Instrument Sans", "Noto Sans JP", system-ui, sans-serif;
  --font-serif: "Instrument Serif", "Noto Sans JP", serif;

  --pad: 8px;
  --gap: 16px;
  --gap-section: 96px;
}

@media (min-width: 768px) {
  :root { --pad: 16px; }
}

/* ---------------------------------------------------------------- 基礎 */

*, *::before, *::after { box-sizing: border-box; }

/* 導入中は overflow:hidden にするので、溝を常に確保して幅が変わらないようにする */
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }

body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  /* Instrument Sans は可変フォント。デザインは wdth 100（既定幅）で組まれている */
  font-variation-settings: "wdth" 100;
}

img { display: block; max-width: 100%; }

/* 本文中のテキストリンク。下線つきで、hover のときだけ外す（CLAUDE.md §5）。
   出てくる場所ごとに書くと振る舞いがずれるので、ここに1つ持つ */
.venue__inner a,
.profile__links a {
  color: inherit;
  text-decoration: underline;
  text-underline-position: from-font;
}

/* hover を持つ環境だけに当てる。タッチ端末で hover が居座るのを避ける */
@media (hover: hover) {
  .venue__inner a:hover,
  .profile__links a:hover { text-decoration: none; }
}

/* 地は写真。canvas と同じくビューポートに固定し、スクロールしても動かさない。
   body に background-attachment: fixed を置く手もあるが、iOS Safari が
   意図どおりに扱わないので、固定した擬似要素に貼っている。
   狭い画面には縦位置、広い画面には横位置の写真を当てる。当たらないほうは
   ブラウザが読みに行かないので、転送されるのは常に1枚だけ。
   body の --bg は残す。読み込み前の地であり、罫線の color-mix と
   ライムのバッジに乗る文字もこの色から作っている（CLAUDE.md §5）。 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: url("../img/bg-portrait.webp") center / cover no-repeat;
}

@media (min-width: 768px) {
  body::before { background-image: url("../img/bg-landscape.webp"); }
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 背景の場。装飾なので支援技術からは隠す（CLAUDE.md §6） */
#field {
  position: fixed;
  inset: 0;
  z-index: 0;
  display: block;
  pointer-events: none;
}

.page {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--gap-section);
  padding-inline: var(--pad);
  padding-block-end: var(--pad);
}

/* 初回の導入。ローブが浮上しきるまで本文を伏せ、スクロールも止める（CLAUDE.md §6）。
   data-intro は <head> の同期スクリプトが付け、field.js が導入の終わりに外す。
   属性が付くのは JS が動いたときだけなので、JS 無効・JS エラーでは本文が最初から見える。
   opacity ではなく visibility にしているのは、伏せているあいだタブ移動の対象からも
   外すため。トランジションは持たせず、属性が外れた瞬間に出す。 */
:root[data-intro] { overflow: hidden; }
:root[data-intro] .page { visibility: hidden; }

/* ---------------------------------------------------------------- 配信状態 */

.status {
  position: sticky;
  inset-block-start: 0;
  z-index: 2;
  display: flex;
  gap: var(--gap);
  align-items: center;
  padding-block-start: var(--pad);
}

.status__badge,
.status__text { margin: 0; }

/* 3状態すべてを出力しておき、data-state で出し分ける（CLAUDE.md §4）。
   data-state は stream.js が書く。まだ無いあいだ（JS 実行前・JS 無効時）は
   before の見た目にしておく */
.status__badge,
.status__text { display: none; }

body:not([data-state]) .status__badge--before,
[data-state="before"] .status__badge--before,
[data-state="live"] .status__badge--live,
[data-state="archive"] .status__badge--archive { display: inline-flex; }

/* 配信後は導線を持たないので、リンクごと消す。中の .visually-hidden が
   読み上げに残らないよう、バッジではなく <a> を隠す */
[data-state="archive"] .status__link { display: none; }

body:not([data-state]) .status__text--before,
[data-state="before"] .status__text--before,
[data-state="live"] .status__text--live { display: block; }

/* 3状態のバッジをまとめて包むリンク。href を1箇所に閉じるための入れ物なので、
   見た目は持たせず、バッジ自身の意匠をそのまま通す */
.status__link {
  display: inline-flex;
  color: inherit;
  text-decoration: none;
}

.status__badge {
  gap: 8px;
  align-items: center;
  justify-content: center;
  padding: 4px;
  /* 地は塗らない。地が写真になったので、グレーで塗ると箱として浮く。
     後ろを通るドットは透けるが、枠線と文字はライムなので読み取りには影響しない */
  border: 1px solid var(--fg);
  line-height: 1;
  white-space: nowrap;
}

/* 配信中だけ塗りにして強調する */
.status__badge--live {
  background: var(--fg);
  color: var(--bg);
}

/* mask で描くのは、バッジの文字色（currentColor）に追従させるため。
   配信前は --fg、配信中はライムの地に乗るので --bg になる */
.status__icon {
  width: 16px;
  height: 16px;
  background: currentColor;
  mask: url("../img/icon-onair.svg") center / contain no-repeat;
}

/* 配信中は文字とアイコンを1秒周期で点滅させる。
   アイコンは background: currentColor なので、バッジの color を動かせば
   文字と一緒に消える。地のライムと枠線は残したいので opacity は使わない。
   step-end で中間値を作らず、はっきり明滅させる。 */
@keyframes status-blink {
  0% { color: var(--bg); }
  50% { color: transparent; }
}

[data-state="live"] .status__badge--live {
  animation: status-blink 1s step-end infinite;
}

/* 明滅は運動を嫌う設定では止める（CLAUDE.md §6 のアクセシビリティ方針に合わせる） */
@media (prefers-reduced-motion: reduce) {
  [data-state="live"] .status__badge--live { animation: none; }
}

.status__text {
  line-height: 1.25;
  white-space: nowrap;
}

/* ---------------------------------------------------------------- タイトル */

.titles {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

.titles__art { margin: 0; }

.titles__art img { width: 100%; height: auto; }

.titles__meta {
  display: flex;
  justify-content: space-between;
  margin: var(--gap) 0 0;
  font-size: 18px;
  line-height: normal;
  white-space: nowrap;
}

@media (min-width: 768px) {
  .titles {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
  }
  /* デザイン注記「高さを合わせた上でなるべくフル幅に」の解。
     幅の広い Resonant Fields を列いっぱいに伸ばし、KANKYO DOT は
     アスペクト比の差（595/677 = 87.888%）だけ幅を詰める。これで高さが一致する。

     幅を img ではなくブロックに持たせているのは、直下の Forest / 2026 も
     同じ幅に揃えるため。こうすると 2026 の右端が DOT の T の右端と揃う。 */
  .titles__item--name { inline-size: 87.888%; }
}

/* ---------------------------------------------------------------- 会場・会期 */

.venue {
  display: flex;
  justify-content: flex-end;
}

.venue__inner {
  display: flex;
  flex-direction: column;
  gap: 32px;
  inline-size: 100%;
}

.venue__inner p { margin: 0; }

@media (min-width: 768px) {
  /* 2カラムの右列に揃える */
  .venue__inner { inline-size: calc((100% - var(--gap)) / 2); }
}

/* ---------------------------------------------------------------- クレジット */

.credits {
  display: grid;
  grid-template-columns: 1fr;
  column-gap: var(--gap);
  row-gap: 32px;
  align-items: start;
}

.credits__label {
  margin: 0;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.25;
}

.credits__value {
  margin: 8px 0 0;
  font-family: var(--font-serif);
  font-size: 40px;
  font-weight: 400;
  line-height: 1;
}

.credits__value--music {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}

.credits__pair {
  display: inline-flex;
  gap: 8px;
  align-items: flex-end;
}

/* ✕ は 40px の欧文セリフに添うので、寸法を em で持たせて追従させる */
.credits__cross {
  inline-size: 0.9em;
  block-size: 0.846em;
}

@media (min-width: 768px) {
  .credits { grid-template-columns: 1fr 1fr; }

  /* Figma は Mobile が 40px、Desktop が 48px */
  .credits__value { font-size: 48px; }
}

@media (min-width: 1200px) {
  .credits__value--music {
    flex-direction: row;
    gap: 8px;
    align-items: center;
  }
}

/* ---------------------------------------------------------------- コンセプト */

.concept {
  display: grid;
  grid-template-columns: 1fr;
  gap: 64px;
}

.concept__body p { margin: 0; }

/* デザインでは段落間に1行の空きが入っている */
.concept__body p + p { margin-block-start: 1.5em; }

@media (min-width: 768px) {
  .concept {
    grid-template-columns: 1fr 1fr;
    gap: var(--gap);
  }
}

/* ---------------------------------------------------------------- タイムテーブル */

.timetable {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.timetable__table {
  inline-size: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  border-block-end: 1px solid var(--rule);
}

/* 他のセクションはすべて 16px ガターの2カラムで、右列が 50% + 8px から始まる。
   表も同じ位置で割るため、列は 50% のままにしてガターの半分ずつを
   両セルのパディングで持たせる。これで本文の開始が 50% + 8px に揃う
   （table-layout: fixed では列幅の calc が効かないので、この持たせ方にしている）。 */
.timetable__table :is(th, td) {
  inline-size: 50%;
  padding-block: var(--gap);
  border-block-start: 1px solid var(--rule);
  font-weight: 400;
  line-height: 1.25;
  text-align: start;
  vertical-align: top;
}

.timetable__table th { padding-inline-end: calc(var(--gap) / 2); }

.timetable__table td { padding-inline-start: calc(var(--gap) / 2); }

/* 狭い幅では章番号と章名を積み、章名の頭を8行で揃える */
.timetable__chapter,
.timetable__name { display: block; }

.timetable__name { margin-block-start: var(--gap); }

@media (min-width: 768px) {
  /* 章番号と章名を別の段に分ける。24カラムでは章番号が 13–18、章名が 19–24 で、
     td の内容幅からガターを引いて半々に割ればちょうどその位置になる。
     td 自体を flex や grid にすると table-cell でなくなり、支援技術が
     セルとして読まなくなるため、セルの中身を浮かせて2段に割っている */
  .timetable__chapter {
    float: inline-start;
    inline-size: calc(50% - var(--gap) / 2);
    margin-inline-end: var(--gap);
  }

  /* 回り込ませず隣に置く。BFC を作れば残りの幅にそのまま収まる */
  .timetable__name {
    display: flow-root;
    margin-block-start: 0;
  }
}

.timetable__note {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  max-inline-size: 480px;
  font-size: 12px;
}

@media (min-width: 768px) {
  /* プロフィールの写真と同じ 6/24。24カラム・ガター 16px のグリッドに乗せる。
     .profile は実際のグリッドで組めるが、ここは単独のブロックなので幅を直接計算する */
  .timetable__note {
    inline-size: calc((100% - 23 * var(--gap)) / 24 * 6 + 5 * var(--gap));
    max-inline-size: none;
  }
}

/* 箱組み。段が狭く欧文は単語間が開きすぎるので分綴を許す。和文には hyphens が効かない */
.timetable__note p {
  margin: 0;
  text-align: justify;
  hyphens: auto;
  /* 語頭・語末に2文字しか残さない分綴を避ける。慣行どおり最短6文字・前後3文字 */
  hyphenate-limit-chars: 6 3 3;
}

/* ---------------------------------------------------------------- プロフィール */

.profile {
  display: flex;
  flex-direction: column;
  gap: 64px;
}

.profile__figure img {
  inline-size: 100%;
  block-size: auto;
}

.profile__bodies {
  display: flex;
  flex-direction: column;
  gap: 48px;
}

.profile__artist {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.profile__bio {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.profile__name {
  display: flex;
  gap: var(--gap);
  margin: 0;
  font-size: 18px;
  font-weight: 400;
  line-height: 1.25;
}

.profile__artist p {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  /* 箱組み。1440px 以上では 340px の段に割れるため分綴が要る */
  text-align: justify;
  hyphens: auto;
  /* 語頭・語末に2文字しか残さない分綴を避ける。慣行どおり最短6文字・前後3文字 */
  hyphenate-limit-chars: 6 3 3;
}

.profile__links {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

@media (min-width: 768px) {
  /* 24カラム・ガター 16px のグリッド。写真は 6/24、本文は右半分の 12/24 に置く。
     この規則は 1440px で 340px、1920px で 460px となり、どちらの Figma フレームとも一致する。 */
  .profile {
    display: grid;
    grid-template-columns: repeat(24, minmax(0, 1fr));
    gap: var(--gap);
    align-items: start;
  }
  .profile__figure { grid-column: 1 / span 6; }
  .profile__bodies { grid-column: 13 / span 12; min-inline-size: 0; }
}

/* 1440px 以上では各アーティストの日本語と英語を左右に割る */
@media (min-width: 1440px) {
  .profile__bio {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--gap);
  }
}

/* ---------------------------------------------------------------- フッター */

.footer {
  display: flex;
  gap: 32px;
  align-items: center;
}

.footer__mark { inline-size: 136px; }

.footer__produce { display: block; }

.footer__produce img { inline-size: 115px; }
