PageSourceSearch

https://b2-4ac.info/list/m3_56_list.html

html b2-4ac.info collected 2026-10-07 13:46:16 UTC 75,830 bytes, 1,495 lines download raw bytes

1<!doctype html>
2<html lang="ja">
3<head>
4  <meta charset="utf-8">
5  <title>kaiの判別式 的 2025秋M3 チェックリスト</title>
6  <meta name="description" content="同人音楽イベントM3向けサークルリスト。サークル情報のチェックにどうぞ。">
7  <link rel="icon" href="/favicon.ico">
8<style>
9
10/* ===== フィルタUI(シンプルなリンク帯) ===== */
11#svFilter{
12  text-align:center; margin:8px 0 6px; font-size:12px;
13}
14#svFilter a{
15  display:inline-block; padding:.42rem .75rem; margin:0 2px;
16  border:1px solid rgba(255,255,255,.16); border-radius:999px;
17  background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.03));
18}
19#svFilter a.is-active{
20  background: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.07));
21  box-shadow:0 6px 18px rgba(0,0,0,.35), inset 0 .5px 0 rgba(255,255,255,.16);
22  text-decoration:none;
23}
24
25.bn{
26float: right;
27}
28
29/* 新規追加、情報更新された作品のサークル名と作品名セルの背景色を変更する */
30#infoadd{
31background-color:#5E5150;
32}
33
34/* ポスト用 20250421 */
35.tweet-container {
36      width: 40px;
37/*    margin: 20px auto; */
38/*    text-align: center; */
39/*    border: 1px solid #ccc; */
40/*    padding: 10px; */
41/*    border-radius: 10px; */
42}
43.button-img {
44      width: 20px;
45      height: 20px;
46      cursor: pointer;
47}
48
49.text-with-button {
50/*      font-size: 16px;	*/
51/*      line-height: 1.6;	*/
52}
53.inline-button {
54      vertical-align: middle;
55      cursor: pointer;
56}
57.embed-area {
58      margin-top: 10px;
59      display: none;
60}
61
62.close-button {
63      margin-top: 8px; /* 10px */
64      padding: 4px 10px; /* 5px 10px; */
65      font-size: 14px;
66      background-color: #e0245e;
67      color: white;
68      border: none;
69      border-radius: 5px;
70      cursor: pointer;
71}
72
73/* ************************************************************************ */
74/* リスト部 */ 
75/* ************************************************************************ */
76#circle_list{
77  table-layout: fixed;
78  width: 945px;
79  border-collapse: collapse;
80}
81
82#circle_list th, #circle_list td{
83  overflow: hidden;
84  vertical-align: top;
85}
86#circle_list thead th         { white-space: nowrap; text-align: left; }
87#circle_list thead th.th-price{ font-size:16px; }
88
89/* 列ごとの表示ルール */
90#circle_list td.space { white-space: nowrap;}
91#circle_list td.circle{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
92/* #circle_list td.price { text-align: center; white-space: nowrap; font-variant-numeric: tabular-nums; } */
93
94#circle_list tbody tr.is-hidden { display:none !important; }
95
96/* 非表示用(順序は維持) */
97tr.is-hidden{ display:none !important; }
98
99/* ************************************************************************ */
100/* その他タグ別 */ 
101/* ************************************************************************ */
102
103/* タイトル行(上部の h1 とそのリンク) */
104h1{
105  margin:0;
106  padding-top:10px;   /* 旧外部CSSの値を踏襲 */
107  padding-bottom:10px;
108  font-weight:bolder;
109  font-size:24px;
110  text-decoration:none;
111}
112h1 a{
113  color:#FFF;
114  font-family: Verdana;
115  text-decoration:none;
116  font-weight:bolder;
117}
118
119/* 上部の説明テキスト(.description) */
120.description{
121  color:#F0F0F0;
122  font-size:12px;
123  font-family: Verdana;
124  font-weight:bold;
125  line-height:140%;
126  padding:0 10px 0 0;
127}
128
129/* ************************************************************************************************* */
130/* 整頓                                                                                              */
131/* ************************************************************************************************* */
132
133/* 共通の横幅センター寄せ(元955px)。必要な要素に class="wrap" を付ける */
134.wrap { max-width: 955px; margin: 0 auto; }
135
136/* プレイリスト埋め込みを中央に。レスポンシブも少しだけ */
137.media-center{ text-align: center; margin-bottom: 12px; }
138.media-center .yt-embed{
139  width: min(100%, 640px);
140  aspect-ratio: 16 / 9;
141  height: auto;
142  border: 0;
143}
144
145/* フッター */
146#footer{ clear:left; width:100%; }
147
148/* (1)header 見出し帯 */
149.page-header{
150  font-family: Verdana;
151  background-color: #1E2127;
152  padding: 10px 10px 0 25px;
153  text-align: left;
154}
155
156/* (2)ページ全体の土台 */
157body{
158  font-family: Verdana, ui-sans-serif, system-ui, "Noto Sans JP", sans-serif;
159  background-color:#272A31;
160  color:#A2A0A0;
161  margin:0;
162  padding:0;
163  /* text-align:left; */
164}
165a{ color:#C8C8A0; text-decoration:none; }
166a:hover{ color:#E9C971; text-decoration:underline; }
167
168/* (3)件数バッジ */
169#svFilter a[data-count]::after { content:" (" attr(data-count) ")"; opacity:.8; }
170
171/* (4)ボックス周り */
172.list{
173  text-align: left;
174  background-color:#2E3138;
175  margin-bottom: 15px;     
176  line-height: 120%;
177  color:#A2A0A0;
178}
179
180.list{
181 padding: 0 10px 15px 25px; /* 横は 25 / 10 に統一 */
182}
183
184/* (5)テーブル文字色 */
185.list th, .list td{
186  color:#A2A0A0;
187  line-height:150%;
188  padding-left:15px;
189  border:1px solid;
190}
191.list table{
192  font-size:14pt;
193  border-collapse: collapse;
194  border:1px solid #C0C0C0;
195}
196
197/* 7)トグルボタン */
198.global-toggle { display: inline-block; margin: 6px 4px; }
199
200/* 8) 合成音声チップ:ID→class移行(後述のHTML置換後にこちらを使う) */
201.chip--sv, .chip--svpart{
202  display:inline-flex; align-items:center; gap:.4em;
203  padding:.22rem .22rem; height:1.8em; border-radius:9999px;
204  font: 600 12px/1.1 Verdana, ui-sans-serif, system-ui, "Noto Sans JP", sans-serif;
205  letter-spacing:.02em; white-space:nowrap; vertical-align:middle;
206  background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.03));
207  border:1px solid rgba(255,255,255,.16);
208  box-shadow: inset 0 .5px 0 rgba(255,255,255,.1), 0 4px 14px rgba(0,0,0,.25);
209}
210.chip--sv{ color:#ff7a8a; border-color:rgba(255,122,138,.45); }
211.chip--svpart{ color:#f6c25b; border-color:rgba(246,194,91,.45); }
212
213/* 9) ランク色:ID→class */
214td.rank-A, td.rank-B, td.rank-C{
215  color:#000000;
216  border-color:#C0C0C0;
217  font-weight:bold; 
218  padding:0 3px;
219  text-align:center;
220}
221td.rank-A{ background:#EE0000; }
222td.rank-B{ background:#FFCC66; }
223td.rank-C{ background:#99FF99; }
224
225/* 再生中の行は、フィルタで隠されていても表示 */
226#circle_list tbody tr.force-show{ display: table-row !important; }
227
228/* バッジを付ける1列目セルをアンカーにする */
229#circle_list tbody tr.is-nowplaying{
230  position: relative;  
231}
232
233/* ← 既存の overflow:hidden を上書きするため “状態クラス” で限定 */
234#circle_list tbody tr.is-nowplaying{
235  position: relative;
236  overflow: visible; /* これで疑似要素が外側に出せる */
237}
238
239/* 再生中デバッグ用の小さなオーバーレイ */
240#np-debug-box{
241  position: fixed;
242  right: 10px;
243  bottom: 10px;
244  background: rgba(0,0,0,.7);
245  color: #fff;
246  font: 12px/1.4 Verdana, ui-sans-serif, system-ui, "Noto Sans JP", sans-serif;
247  padding: 8px 10px;
248  border-radius: 6px;
249  z-index: 99999;
250  pointer-events: none;
251  white-space: nowrap;
252}
253
254/* 1) 行の縦位置は常に中央 */
255#circle_list th, #circle_list td{
256  vertical-align: middle;
257}
258
259/* 2) 行の高さをチップ(1.8em ≒ 33.6px)に合わせて統一 */
260.list td, .list th{
261  line-height: 34px;  /* 33.6px でも可 */
262}
263
264/* 念のため:セル内のオーバーフローは今まで通り隠す */
265#circle_list th, #circle_list td{ overflow: hidden; } /* vertical-align 指定は上のルールで上書き */
266
267#circle_list td.price{
268  text-align: right;
269  font-variant-numeric: tabular-nums;
270}
271
272/* トグルの右に小さくヒント表示 */
273.embed-controls{
274  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
275  margin: 4px 0 6px;
276}
277.kbd-hint{
278  font-size:11px; opacity:.8; color:#A2A0A0; white-space:nowrap;
279}
280.kbd-hint kbd{
281  display:inline-block; padding:2px 6px; margin:0 2px;
282  border:1px solid rgba(255,255,255,.25);
283  border-radius:4px; background:#1E2127;
284  font: 600 11px/1 Verdana, ui-sans-serif, system-ui, "Noto Sans JP", sans-serif;
285  letter-spacing:.02em;
286}
287
288/* 再生アイコン用の小さな未視聴バッジ */
289.playwrap{ display:inline-block; position:relative; line-height:0; }
290.playwrap .unwatched-badge{
291  position:absolute; top:-2px; right:-2px;
292  width:7px; height:7px; border-radius:50%;
293  background:#FFD54A; border:1px solid #fff; box-shadow:0 0 2px rgba(0,0,0,.5);
294  pointer-events:none;
295}
296.playwrap.is-watched .unwatched-badge{ display:none; }
297
298/* 印刷では非表示 */
299@media print{ .unwatched-badge{ display:none !important; } }
300
301/* お知らせ行用 */
302.watch-hint{ font-size:11px; color:#A2A0A0; opacity:.9; }
303.watch-hint a{ color:#C8C8A0; text-decoration:underline; }
304
305/* 再生案内ブロック(center 代替) */
306.notice{
307  text-align:center;
308  margin: 6px 0 8px;
309}
310.notice p{ margin:0; }
311.notice p + p{ margin-top:4px; }  /* 2行目の余白だけ付ける */
312.notice .icon-yt,
313.notice .icon-x{
314  vertical-align: middle;   /* テキストと高さを揃える */
315  margin: 0 2px;
316}
317
318/* 中央寄せはそのまま活かす */
319.media-center { text-align: center; margin-bottom: 12px; }
320
321/* プレイヤーを中央基準にするための内側ラッパ */
322.player-wrap {
323  display: inline-block;        /* ← これで「塊として中央」になる */
324  position: relative;           /* ← 子の np-card をこの箱基準で絶対配置 */
325}
326
327/* IFrame Player API が挿入するiframeの寸法(425×240固定) */
328.player-wrap iframe {
329  display: block;
330  width: 425px;
331  height: 240px;
332  border: 0;
333}
334
335/* 黒い吹き出し(コメントだけ) */
336.np-bubble{
337  position: absolute;
338  left: calc(100% + 10px);   /* 右に10px空けて添える */
339  bottom: 0;                  /* 下端揃え */
340  width: 240px;               /* お好みで 260〜360px */
341  background: rgba(0,0,0,.88);
342  color: #EDEDED;
343  border: 0;                  /* 枠線なし */
344  border-radius: 10px;
345  padding: 10px 12px;
346  box-shadow: 0 8px 22px rgba(0,0,0,.45);
347  font: 12px/1.55 Verdana, "Noto Sans JP", ui-sans-serif;
348  text-align: left;
349  white-space: pre-wrap;      /* 改行をそのまま表示 */
350  word-break: break-word;
351  z-index: 2;                 /* 念のため */
352}
353
354/* プレイヤー側へ向ける小さな三角(しっぽ) */
355.np-bubble::before{
356  content:"";
357  position:absolute;
358  right:100%;
359  bottom: 12px;               /* しっぽの高さ */
360  border:6px solid transparent;
361  border-right-color: rgba(0,0,0,.88);
362}
363
364/* 画面が狭い時はプレイヤーの上に右下重ね(はみ出し防止) */
365@media (max-width: 860px){
366  .np-bubble{
367    left: auto;
368    right: 8px;
369    bottom: 8px;
370    width: min(70vw, 300px);
371  }
372  .np-bubble::before{ display:none; }
373}
374
375.np-bubble{
376  opacity: 0; transform: translateY(2px);
377  transition: opacity .18s ease, transform .18s ease;
378  pointer-events: none;        /* スマホでプレイヤー操作の邪魔をしない */
379}
380.np-bubble.is-visible{
381  opacity: 1; transform: none;
382}
383
384.np-bubble a{
385  color:#9ad1ff; text-decoration:underline;
386}
387.np-bubble a:visited{ color:#c7b6ff; }
388
389/* リンクをクリック&文字選択できるようにする */
390.np-bubble{
391  pointer-events: auto;        /* ← これに変更 */
392  user-select: text;
393  -webkit-user-select: text;   /* iOS/Safari */
394  z-index: 10;                 /* 念のため */
395}
396
397/* モバイルの自動拡大を抑止(Chrome/Safari/Firefox) */
398html{ -webkit-text-size-adjust:100%; text-size-adjust:100%; }
399
400/* ── 全ての埋込試聴ボタン(今風ピル) ─────────────────── */
401.global-toggle{
402  appearance:none;
403  display:inline-flex; align-items:center; gap:.45em;
404  padding:.48rem .9rem;
405  border-radius:9999px;
406  border:1px solid rgba(255,255,255,.16);
407  background:linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.04));
408  color:#EDECEC;
409  font:600 12px/1 ui-sans-serif,system-ui,Verdana,"Noto Sans JP",sans-serif;
410  letter-spacing:.02em;
411  cursor:pointer;
412  box-shadow:inset 0 .5px 0 rgba(255,255,255,.12), 0 6px 18px rgba(0,0,0,.35);
413  transition:background .2s ease, box-shadow .2s ease, transform .04s ease;
414}
415.global-toggle:hover{
416  background:linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.07));
417}
418.global-toggle:active{ transform:translateY(1px); }
419.global-toggle:focus-visible{
420  outline:none;
421  box-shadow:0 0 0 3px rgba(255,255,255,.18), 0 0 0 6px rgba(66,153,225,.25);
422}
423/* 「閉じる」状態など注意色を使いたい場合は is-danger を付ける */
424.global-toggle.is-danger{
425  color:#fff;
426  border-color:rgba(255,92,92,.45);
427  background:linear-gradient(180deg, rgba(255,82,82,.22), rgba(255,82,82,.16));
428}
429/* 無効時 */
430.global-toggle[disabled], .global-toggle.is-busy{
431  opacity:.6; cursor:default; pointer-events:none;
432}
433
434/* スマホで少しコンパクトに */
435@media (max-width:600px){
436  .global-toggle{ padding:.44rem .8rem; font-size:12px; }
437}
438
439/* 余白(任意:行揃え用) */
440.global-toggle{ margin:6px 4px; }
441
442/* 画面ではチェック列/印刷タイトルは隠す */
443.print-col, .print-col , .print-title { display: none; }
444
445/* 1列目(チェック列/配置列)はみ出し許可+基準化 */
446#circle_list td.print-col,
447#circle_list td.rank-A,
448#circle_list td.rank-B,
449#circle_list td.rank-C { overflow:visible; position:relative; z-index:1; }
450
451/* 念のため:行は位置基準のまま */
452#circle_list tbody tr { position: relative; }
453
454/* ▼を重ねる土台:先頭の可視セル(= print-col の次のセル)を相対配置に */
455#circle_list tbody tr > td.print-col + td{ position:relative; }
456
457/* ── 縁取り(白) */
458#circle_list tbody tr.is-playing > td.print-col + td::before,
459#circle_list tbody tr.is-nowplaying > td.print-col + td::before{
460  content:"";
461  position:absolute;
462  top:50%;
463  transform:translateY(-50%);
464  left:-5px;                /* 左外に出すのでレイアウトに干渉しない */
465  width:0; height:0;
466  border-top:10px solid transparent;
467  border-bottom:10px solid transparent;
468  border-left:13px solid #fff;   /* 白い縁取り */
469  pointer-events:none;
470  z-index:2;
471}
472
473/* ── 本体(赤) */
474#circle_list tbody tr.is-playing > td.print-col + td::after,
475#circle_list tbody tr.is-nowplaying > td.print-col + td::after{
476  content:"";
477  position:absolute;
478  top:50%; transform:translateY(-50%);
479  left:-4px;                /* 白より1px内側に */
480  width:0; height:0;
481  border-top:7px solid transparent;
482  border-bottom:7px solid transparent;
483  border-left:10px solid #ff5b5b; /* 赤い三角 */
484  pointer-events:none;
485  z-index:3;
486}
487
488/* 念のため:行に付けていた擬似要素は無効化 */
489#circle_list tbody tr.is-playing::before,
490#circle_list tbody tr.is-playing::after,
491#circle_list tbody tr.is-nowplaying::before,
492#circle_list tbody tr.is-nowplaying::after{
493  display:none !important;
494}
495
496/* 行の埋め込みの下に出すコメント吹き出し */
497.np-bubble-row{
498  display:inline-block;
499  margin:6px 0 0;
500  padding:6px 8px;
501  border-radius:8px;
502  background:rgba(0,0,0,.78);
503  color:#fff;
504  font:12px/1.5 Verdana, ui-sans-serif, "Noto Sans JP", sans-serif;
505  max-width:560px;        /* ほどよく折返す */
506  pointer-events:auto;    /* リンクを押せる */
507  user-select:text;       /* 選択できる */
508}
509.np-bubble-row a{ color:#ffe777; text-decoration:underline; }
510
511@media print{
512  .np-bubble-row{ display:none !important; }
513}
514
515/* ───────── 印刷専用 ───────── */
516@media print{
517  /* タイトルを紙の先頭に表示 */
518  .print-title{
519    display:block;
520    font: 700 16pt/1.3 ui-sans-serif,system-ui,Verdana,"Noto Sans JP",sans-serif;
521    margin: 0 0 10pt;
522    color:#000;
523  }
524
525  /* ===== 余計なパーツを隠す(説明文・ショートカット・ボタン類・center行なã
525©ï¼‰ ===== */
526  header, .page-header, .media-center, footer, #footer,
527  #svFilter, .global-toggle, .watch-hint, .kbd-hint, .notice-line,
528  .np-bubble-wrap, .np-bubble,
529  center { display:none !important; }
530  
531  #circle_list tbody tr.is-playing  > td.print-col + td::before,
532  #circle_list tbody tr.is-playing  > td.print-col + td::after,
533  #circle_list tbody tr.is-nowplaying > td.print-col + td::before,
534  #circle_list tbody tr.is-nowplaying > td.print-col + td::after{
535    display:none !important;  
536  }
537  
538  /* ===== ページ全体を“白地に黒”へ ===== */
539  html, body { background:#fff !important; color:#000 !important; }
540  a, a:visited { color:#000 !important; text-decoration:none !important; }
541
542  /* 全体の文字サイズを小さく(標準は9pt) */
543  html, body{ font-size:9pt !important; line-height:1.25 !important; }
544  #circle_list{ font-size:inherit !important; }
545
546  /* 罫線と余白をコンパクトに */
547  #circle_list{ border-collapse:separate !important; border-spacing:0 !important; }
548  #circle_list th, #circle_list td{
549    border:0.6pt solid #000 !important;
550    padding:1pt 3pt !important;   /* 1pt 3pt */
551    white-space:normal !important;
552    background:#fff !important; color:#000 !important;
553  }
554
555  /* list周りのグレー背景・余白を消す */
556  .wrap { max-width:100% !important; margin:0 !important; }
557  #container { width:auto !important; }
558  .list { background:none !important; padding:0 !important; box-shadow:none !important; }
559
560  /* ===== テーブルだけをシンプルに出力 ===== */
561  #circle_list{
562    width:100% !important;
563    table-layout:auto !important;
564    border-collapse: separate !important;
565    border-spacing: 0 !important;    
566    border:1pt solid #000 !important;
567    background:#fff !important;
568    color:#000 !important;
569  }
570  #circle_list th, #circle_list td{
571    border:1pt solid #000 !important;
572    padding:4pt 6pt !important;
573    background:#fff !important;
574    color:#000 !important;
575    white-space:normal !important;
576    overflow:visible !important;  /* 印刷時の枠欠け回避 */
577    box-shadow:none !important;
578  }
579
580  /* ランク色などの色面を無効化 */
581  .rank-A, .rank-B, .rank-C,
582  #rank_A, #rank_B, #rank_C{ background:none !important; color:#000 !important; }
583
584  /* ===== 右端「タグ」列を印刷では非表示に(チェック列は残す) ===== */
585  #circle_list th:last-child,
586  #circle_list td:last-child { display:none !important; }
587
588  /* 既に入れてあるチェック列はそのまま表示(念のため) */
589  .print-col{ display:table-cell !important; width:14pt; padding:0 4pt !important; }
590  .print-check{ transform:scale(1.2); margin:0 2pt; }
591
592  /* 背景装飾の一掃 */
593  *{ background-image:none !important; text-shadow:none !important; }
594
595  /* ページ分割の質を少し改善(効くブラウザのみ) */
596  #circle_list { break-inside:auto; }
597  #circle_list tr { break-inside:avoid; break-after:auto; }
598  
599  /* ① 再生アイコン系は印刷しない(PNGでもSVGでも) */
600  #circle_list .inline-button,                 /* 既存の再生ボタン(img/svg) */
601  #circle_list .text-with-button svg,          /* 念押し:埋め込み内のSVG */
602  #circle_list .watch-badge,                   /* 未視聴バッジ */
603  #circle_list .np-pin {                       /* 再生中の赤い▼ */
604    display:none !important;
605  }
606
607  /* ② 列幅の最適化:配置(1列目)を細く、価格も適度に */
608  #circle_list{ table-layout:fixed !important; width:100% !important; }
609
610  /* colgroup の幅を無効化してこちらの指定を優先 */
611  #circle_list col{ width:auto !important; }
612
613  /* チェック列 */
614  #circle_list th:nth-child(1),
615  #circle_list td:nth-child(1){ width:16pt !important; }
616  
617  /* 配置 */  
618  #circle_list th:nth-child(2),
619  #circle_list td:nth-child(2){ width:40pt !important; }
620
621  /* サークル */
622  #circle_list th:nth-child(3),
623  #circle_list td:nth-child(3){ width:100pt !important; }
624
625  /* 作品名 */
626  #circle_list th:nth-child(4),
627  #circle_list td:nth-child(4){ width:auto !important; }
628  
629  /* 価格 */
630  #circle_list th:nth-child(5),
631  #circle_list td:nth-child(5){ width:38pt !important; }
632  
633  /* 価格列のサイズを画面用からリセット */
634  #circle_list th.th-price,
635  #circle_list td.price{
636    font-size: inherit !important;   /* ← これで統一 */
637    font-weight: normal !important;
638    text-align: right !important;
639  }
640  
641  /* 行を詰める:余白&行間を小さめに統一 */
642  #circle_list th,
643  #circle_list td{
644    padding: 1.5pt 3.5pt !important;   
645    line-height: 1.15 !important;      /* 1.10〜1.05 */
646    vertical-align: middle !important;
647  }
648  
649  /* セル内の要素が余計な margin / line-height を持っているのを潰す */
650  #circle_list td *{
651    margin: 0 !important;
652    line-height: 1.15 !important;
653  }  
654  
655  /* 行の展開領域そのものを消す */
656  #circle_list .embed-area{ display:none !important; }  
657  
658  /* 罫線を“細く&薄く” */
659  #circle_list{
660    border: 0.5pt solid #777 !important;   /* 外枠 */
661  }
662  #circle_list th,
663  #circle_list td{
664    border: 0.5pt solid #999 !important;   /* 内側の罫線 */
665  }
666
667  /* ヘッダ行だけ少しだけ強めたい場合(任意) */
668  #circle_list thead th{
669    border-bottom: 0.75pt solid #777 !important;
670  }  
671  
672}
673
674#plPlayer{
675  width:425px;
676  min-height:240px; /* iframe消えても高さ維持 */
677  background:#000;
678}
679
680</style>
681
682</head>
683
684<body data-page-updated="2025-10-25T18:02:28+09:00">
685
686<header class="page-header wrap">
687			<h1><a href="https://ka1.seesaa.net/" accesskey="1">kaiの判別式 的 2025秋M3 チェックリスト (2025/10/25 18:02更新)</a></h1>
688			<span class="description">
689						2025秋M3の個人的購入予定&注目作リストです。委託先複数でも一部のみ掲載、頒布物複数でも個人的注目作のみ掲載の場合あり。<br />
690						※頒布価格はイベントでの価格です。通販価格は各ページを確認してください。<br />
691						※個人的注目度で色分け。(<span style="color:#FF0000;">赤</span>><span style="color:#FFCC66;">黄</span>><span style="color:#99FF99;">緑</span>)<br />
692						※youtube試聴動画はサークルリスト順。<br />
693						※作品名の隣の<img src="./yt_play.svg" width="20" height="20">や<img src="./x_play.svg" width="20" height="20">を押すと埋込み試聴動画を再生できます。<br />
694						<!-- ※<a href="https://online.m3net.jp/">M3オンライン</a><br> -->
695						※参考:<a href="https://www.m3net.jp/attendance/circle2025f.php" target="_blank">M3公式 サークルリスト</a> /<a href="https://www.m3net.jp/friend/index.php" target="_blank">M3公式 友の会ニュース</a> /<a href="https://www.dojin-music.info/event/31/audition" target="_blank">同人音楽.info M3-2025秋 新譜試聴一覧</a><br>
696						※参考:<a href="https://catalog.m3net.jp/2025f/" target="_blank">M3デジタルカタログ 2025秋</a>(試聴機能あり)<br> -->
697						※作成者:kai (<a href="https://x.com/ka1">X</a> / <a href="https://b2-4ac.info">b2-4ac.info</a> )
698						<br>	
699						<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-show-count="false">Post</a>
699<script async src="https://platform.x.com/widgets.js" charset="utf-8"></script>
699<br>
700			</span>
701</header>
702
703<div id="printTitle" class="print-title" aria-hidden="true"></div>
704
705<div class="media-center wrap">
706  <div class="player-wrap">
707    <div id="plPlayer"></div>
708    <div id="npVideoComment" class="np-bubble" aria-live="polite"></div>
709  </div>
710</div>
711  <!-- IFrame Player API を読み込み(1回だけ) -->
712  
712<script src="https://www.youtube.com/iframe_api"></script>
712
713
714<div class="list wrap">
715
716<div class="notice">
717  <p class="notice-line">
718    ※作品名の隣の
719    <img src="./yt_play.svg" width="20" height="20" alt="YouTube再生" class="icon-yt">
720    や
721    <img src="./x_play.svg" width="20" height="20" alt="X再生" class="icon-x">
722    を押すと埋込み試聴動画を再生できます。
723  </p>
724  <p class="watch-hint">
725    未視聴にはバッジ。表示または再生で消えます。(この端末のみ/送信・集計なし)
726    [ <a href="#" id="markAllWatched">全既読</a> / <a href="#" id="resetWatch">リセット</a> ]
727  </p>
728</div>
729
730<div id="svFilter">
731  <a href="#" data-filter="all"    class="is-active">すべて</a>
732  <a href="#" data-filter="latest">最新</a>
733  <a href="#" data-filter="nosv">合成音声なし</a>
734  <a href="#" data-filter="sv">合成音声・一部合成音声</a>
735</div>
736
737<!-- 全体トグル+ヒント -->
738<div class="embed-controls">
739  <button id="closeAllEmbeds" class="global-toggle">全ての埋込試聴を閉じる</button>
740  <span class="kbd-hint" aria-hidden="true">
741    ショートカット:<kbd>1</kbd>すべて <kbd>2</kbd>最新 <kbd>3</kbd>合成音声以外 <kbd>4</kbd>合成音声のみ / <kbd>Esc</kbd>全閉じ
742  </span>
743</div>
744
745<table id="circle_list" width="100%" border="1" cellspacing="0">
746  <colgroup>
747    <col style="width: 100px">   <!-- 配置 -->
748    <col style="width: 220px">  <!-- サークル -->
749    <col style="width: 435px">  <!-- 作品(広め) -->
750    <col style="width: 90px">   <!-- 価格 -->
751    <col style="width: 100px">  <!-- タグ -->
752  </colgroup>
753<!-- ここに コピペ -->
754<thead>
755<tr><th>配置</th><th>サークル</th><th>作品</th><th class="th-price">頒布価格</th><th>タグ</th></tr>
756</thead>
757<tbody>
758<tr data-updated="2025-10-16" data-ytid="6Wt7sdZoaVQ" data-comment="qurosawa氏作曲の2曲目、5曲目が好み。"><td class="rank-C">A-09a</td><td class="circle"><a href="https://x.com/Amarcord1218" target="_blank">アマルコルド</a></td><td><div class="text-with-button" data-type="youtube" data-id="6Wt7sdZoaVQ"><a href="https://x.com/Amarcord1218/status/1975154275039973424" target="_blank">アマルコルド SCENE 1</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"></td></tr>
759<tr data-updated="2025-10-17" data-ytid="tnzI147fGQQ"><td class="rank-C">B-03b</td><td class="circle"><a href="https://x.com/group_gray_gumi" target="_blank">guregumi </a></td><td><div class="text-with-button" data-type="youtube" data-id="tnzI147fGQQ"><a href="https://x.com/group_gray_gumi/status/1978822943917367310" target="_blank">ichi nen guregumi</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">800</td><td class="tags"></td></tr>
760<tr data-updated="2025-10-17" data-ytid="sxCPKaZmMwk"><td class="rank-C">B-03b</td><td class="circle"><a href="https://x.com/group_gray_gumi" target="_blank">guregumi </a></td><td><div class="text-with-button" data-type="youtube" data-id="sxCPKaZmMwk"><a href="https://x.com/group_gray_gumi/status/1978824138706878536" target="_blank">おばけとダンス</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">300</td><td class="tags"></td></tr>
761<tr data-updated="2025-10-16" data-ytid="3B8kKeljMhI" data-comment="独特でいいね。全然知らなかったので過去作もあれば買うかも。"><td class="rank-C">B-09b</td><td class="circle"><a href="https://x.com/vec_jigoku" target="_blank">地獄のべくちゃん</a></td><td><div class="text-with-button" data-type="youtube" data-id="3B8kKeljMhI"><a href="https://x.com/vec_jigoku/status/1977362556101513382" target="_blank">地獄篇</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
762<tr data-updated="2025-10-22" data-ytid="nRNqOwzXqsg"><td class="rank-C">B-22a</td><td class="circle"><a href="https://x.com/mirinn_vi" target="_blank">MIRINN</a></td><td><div class="text-with-button" data-type="youtube" data-id="nRNqOwzXqsg"><a href="https://x.com/mirinn_vi/status/1980611325014483359" target="_blank">akroma</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">500</td><td class="tags"></td></tr>
763<tr data-updated="2025-10-22" data-ytid="fwiPjet0WNk"><td class="rank-C">C-11a</td><td class="circle"><a href="https://x.com/utumiyqcom" target="_blank">うかどっとこむ</a></td><td><div class="text-with-button" data-type="youtube" data-id="fwiPjet0WNk"><a href="https://x.com/utumiyqcom/status/1979125243823202623" target="_blank">escape to the green</a> (utumiyqcom ukaihi) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"><span class="chip--svpart">一部合成音声</span></td></tr>
764<tr data-updated="2025-10-22" data-ytid="kBhPJodBP5I" data-comment="限定Remix集が附属。"><td class="rank-C">C-11a</td><td class="circle"><a href="https://x.com/ukaihi" target="_blank">うかどっとこむ</a></td><td><div class="text-with-button" data-type="youtube" data-id="kBhPJodBP5I"><a href="https://x.com/ukaihi/status/1979125234008555718" target="_blank">いきものとして</a> (ukaihi) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2500</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
765<tr data-updated="2025-10-16" data-ytid="3ZRs4qjONDo" data-comment="宮舞モカ。"><td class="rank-C">E-21b</td><td class="circle"><a href="https://x.com/kis_pulmo" target="_blank">きすみー!るみなりうむ</a></td><td><div class="text-with-button" data-type="youtube" data-id="3ZRs4qjONDo"><a href="https://x.com/kis_pulmo/status/1977689521287307352" target="_blank">深海世界のプリンセス</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
766<tr data-updated="2025-10-25" data-ytid="ZBwQhbcPpiE"><td class="rank-C">F-10a</td><td class="circle"><a href="http://shinsheena.blogspot.com/" target="_blank">Shiellinas</a></td><td><div class="text-with-button" data-type="youtube" data-id="ZBwQhbcPpiE"><a href="https://x.com/shiellinas_info/status/1981723264217997517" target="_blank">Melancholy Irises</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
767<tr data-updated="2025-10-22" data-ytid="Wd-pdegEzN0" data-comment="チエさん。注目のTalich Helfen氏が参加。"><td class="rank-B">F-15b</td><td class="circle"><a href="https://x.com/chi_e" target="_blank">kidlit</a></td><td><div class="text-with-button" data-type="youtube" data-id="Wd-pdegEzN0"><a href="https://www.kidlit.today/klcl001" target="_blank">Revoicing</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"></td></tr>
768<tr data-updated="2025-10-15"><td class="rank-C">F-21a</td><td class="circle"><a href="https://x.com/tonoasami" target="_blank">Tonometer</a></td><td><div class="text-with-button" data-type="twitter" data-id="1978042762537631983"><a href="https://x.com/tonoasami/status/1978042762537631983" target="_blank">Words+Pieces</a> <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
769<tr data-updated="2025-10-24" data-comment="「ラブリズム・エトワール」良すぎる。こういうクラップの入る曲好き。"><td class="rank-C">H-05a</td><td class="circle"><a href="https://x.com/Hylen_JP" target="_blank">Hylen Lab</a></td><td><div class="text-with-button" data-type="twitter" data-id="1981315661126304212"><a href="https://x.com/Hylen_JP/status/1981315661126304212" target="_blank">F-LEX! EP</a> <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
770<tr data-updated="2025-10-08" data-ytid="-sYotUmUNQk" data-comment="6曲目が好み。500円は買っちゃうでしょ。"><td class="rank-C">I-17b</td><td class="circle"><a href="https://x.com/chamolome" target="_blank">ちゃもろめ</a></td><td><div class="text-with-button" data-type="youtube" data-id="-sYotUmUNQk"><a href="https://x.com/chamolome/status/1975516462963171415" target="_blank">未確軌道</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">500</td><td class="tags"><span class="chip--svpart">一部合成音声</span></td></tr>
771<tr data-updated="2025-10-01" data-ytid="BoBTZqdp00g" data-comment="2曲目が好み。&lt;a href=&quot;https://www.youtube.com/watch?v=kCaCg672hSE&quot;&gt;ココ&lt;/a&gt;でフル視聴可能。&#10;合成音声は3曲目のみ。裏命。"><td class="rank-C">I-22b</td><td class="circle"><a href="https://x.com/arcairis" target="_blank">ArcaIris</a></td><td><div class="text-with-button" data-type="youtube" data-id="BoBTZqdp00g"><a href="https://x.com/ArcaIris_/status/1973327548257018342" target="_blank">Florilège</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1500</td><td class="tags"><span class="chip--svpart">一部合成音声</span></td></tr>
772<tr data-updated="2025-10-22" data-ytid="nWeCVpjTvKc" data-comment="3曲目はボカコレ2025夏ルーキーで私もおすすめの曲。"><td class="rank-C">J-08a</td><td class="circle"><a href="https://x.com/saaa_otoge" target="_blank">ウオウオ</a></td><td><div class="text-with-button" data-type="youtube" data-id="nWeCVpjTvKc"><a href="https://uouo-0005-ap.netlify.app/" target="_blank">Another Place</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
773<tr data-updated="2025-10-22" data-ytid="DHkv8_U-xU0" data-comment="いい声だ"><td class="rank-B">L-05b</td><td class="circle"><a href="https://youtube.com/@kopfstimme-tomebathy" target="_blank">Kopf stimme</a></td><td><div class="text-with-button" data-type="youtube" data-id="DHkv8_U-xU0"><a href="https://x.com/toumeinokuni/status/1979896203321205023" target="_blank">透きとおる記憶</a> (とうめいのくに) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"></td></tr>
774<tr data-updated="2025-10-23" data-ytid="WDMTY0HyiQ0"><td class="rank-C">L-05b</td><td class="circle"><a href="https://youtube.com/@kopfstimme-tomebathy" target="_blank">Kopf stimme</a></td><td><div class="text-with-button" data-type="youtube" data-id="WDMTY0HyiQ0"><a href="https://x.com/toumeinokuni/status/1980975048459759785" target="_blank">Parallel 1</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
775<tr data-updated="2025-10-16" data-ytid="O7GK1Vqwz4s" data-comment="那由歌は大分nayutaっぽさ出てていいね。"><td class="rank-C">N-16b</td><td class="circle"><a href="https://x.com/sakran_ms" target="_blank">La+Line</a></td><td><div class="text-with-button" data-type="youtube" data-id="O7GK1Vqwz4s"><a href="https://x.com/sakran_ms/status/1978099742086197590" target="_blank">去りゆく季節と日記帳 feat.那由歌</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
776<tr data-updated="2025-10-22" data-ytid="MPlVSHBpb-0"><td class="rank-C">O-18b</td><td class="circle"><a href="https://n0.com/a/szucg9ntbgwe" target="_blank">Nemurimachi </a></td><td><div class="text-with-button" data-type="youtube" data-id="MPlVSHBpb-0"><a href="https://x.com/Nemurimachi_3/status/1978843940968161549" target="_blank">YORU no POP</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
777<tr data-updated="2025-10-22" data-ytid="9fHDtomQuKM" data-comment="XFD早く聴きたかったんよこれ。気持ち良い。ヤバすぎ。"><td class="rank-A">O-19b</td><td class="circle"><a href="https://x.com/exsy_ugoemo" target="_blank">うごくエモ調</a></td><td><div class="text-with-button" data-type="youtube" data-id="9fHDtomQuKM"><a href="https://x.com/exsy_ugoemo/status/1980952282671071285" target="_blank">リドロワーズ</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1500</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
778<tr data-updated="2025-10-22" data-ytid="8JUF13pqkcQ"><td class="rank-C">R-04a</td><td class="circle"><a href="https://www.youtube.com/@sumeshiiia.k.a.virtualosushi" target="_blank">sumeshiiiと鹿あるく</a></td><td><div class="text-with-button" data-type="youtube" data-id="8JUF13pqkcQ"><a href="https://x.com/sikawalk_c/status/1979746644330762256" target="_blank">生活のシュプール</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
779<tr data-updated="2025-10-01"><td class="rank-C">R-07a</td><td class="circle"><a href="https://x.com/haru_vrchat" target="_blank">Takanashi Haruka</a></td><td><div class="text-with-button" data-type="twitter" data-id="1974399100083937452"><a href="https://x.com/haru_vrchat/status/1974399100083937452" target="_blank">Afterglow</a> <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">500</td><td class="tags"></td></tr>
780<tr data-updated="2025-10-22"><td class="rank-C">S-01ab</td><td class="circle"><a href="https://www.v-comm.jp/campaigns/508" target="_blank">アラズヨ</a></td><td><div class="text-with-button" data-type="twitter" data-id="1979870896908304398"><a href="https://x.com/utugi_xox/status/1979870896908304398" target="_blank">Draw Edge</a> (ぼくたちはいずれ。) <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1200</td><td class="tags"></td></tr>
781<tr data-updated="2025-10-22" data-ytid="eEV4lpBQo3c"><td class="rank-C">S-09ab</td><td class="circle"><a href="https://x.com/ubique_city" target="_blank">ubique</a></td><td><div class="text-with-button" data-type="youtube" data-id="eEV4lpBQo3c"><a href="https://x.com/ubique_city/status/1979850259661541785" target="_blank">solitude</a> (瀬名航×鎖那) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"></td></tr>
782<tr data-updated="2025-10-23"><td class="rank-C">U-07b</td><td class="circle"><a href="https://x.com/wagataki_v" target="_blank">wagataki</a></td><td><div class="text-with-button" data-type="twitter" data-id="1981299567099597194"><a href="https://x.com/vi_2anite/status/1981332355223781442" target="_blank">心の標本</a> (Viviα) <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
783<tr data-updated="2025-10-22" data-comment="タイトル通りの心地よいアンビエント。6曲目のみ合成音声Feng Yiのボーカル曲。"><td class="rank-C">
783い-17a</td><td class="circle"><a href="https://x.com/RistNS" target="_blank">Off-Tone </a></td><td><div class="text-with-button" data-type="twitter" data-id="1979502731237958020"><a href="https://x.com/RistNS/status/1979502731237958020" target="_blank">Gentle Slumber</a> <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
784<tr data-updated="2025-10-11" data-ytid="8Fja3VmbCQ0" data-comment="ウィスパーな2曲目がまさに私好み。"><td class="rank-C">う-05a</td><td class="circle"><a href="https://x.com/Yutogi_kataru" target="_blank">Lunaphia</a></td><td><div class="text-with-button" data-type="youtube" data-id="8Fja3VmbCQ0"><a href="https://yutogiseto.fanbox.cc/posts/10710420" target="_blank">黎明より遠く</a> (瀬戸ユトギ) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1500</td><td class="tags"></td></tr>
785<tr data-updated="2025-10-22" data-comment="曲も声も好み。無料配布!"><td class="rank-C">う-12b</td><td class="circle"><a href="https://x.com/harmoniart_P" target="_blank">harmoniart</a></td><td><div class="text-with-button" data-type="twitter" data-id="1981314663179493837"><a href="https://x.com/hidetonekorock/status/1977683232490418305" target="_blank">Zeta/Emotion File</a> <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">0</td><td class="tags"></td></tr>
786<tr data-updated="2025-10-22"><td class="rank-C">う-16b</td><td class="circle"><a href="https://x.com/phrilli" target="_blank">phrilli</a></td><td><div class="text-with-button" data-type="twitter" data-id="1979865301052432521"><a href="https://x.com/phrilli/status/1979865301052432521" target="_blank">サイノシュア</a> <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">500</td><td class="tags"></td></tr>
787<tr data-updated="2025-10-16" data-ytid="G56C-9gjG0s" data-comment="1曲目の作曲がTalich Helfen氏ã€
787‚"><td class="rank-C">う-28a</td><td class="circle"><a href="https://x.com/muse_energy" target="_blank">ENA Studio</a></td><td><div class="text-with-button" data-type="youtube" data-id="G56C-9gjG0s"><a href="https://x.com/knt_sml/status/1978414565118341294" target="_blank">Far Out / Raining on the Moon</a> (Somel) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">500</td><td class="tags"></td></tr>
788<tr data-updated="2025-10-22" data-ytid="-xpDmC_Xcl4" data-comment="2曲目がカッコ良すぎる。無料配布!"><td class="rank-B">お-17b</td><td class="circle"><a href="https://tudtmworkshop.wixsite.com/home/music" target="_blank">東北大学DTM同好会</a></td><td><div class="text-with-button" data-type="youtube" data-id="-xpDmC_Xcl4"><a href="https://x.com/ionazun_music/status/1979861141590536350" target="_blank">息の輪郭</a> (vionan feat. 雪歌ユフ) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">0</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
789<tr data-updated="2025-10-15"><td class="rank-C">か-08a</td><td class="circle"><a href="https://x.com/Lart_lier" target="_blank">L'art lier</a></td><td><div class="text-with-button" data-type="twitter" data-id="1976213018213278121"><a href="https://x.com/Lart_lier/status/1976213018213278121" target="_blank">はじまりの讃歌</a> <img src="x_play.svg" alt="X再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
790<tr data-updated="2025-10-23" data-ytid="EJelswp-hLA" data-comment="インスト。"><td class="rank-C">か-18a</td><td class="circle"><a href="https://x.com/Zuatya" target="_blank">白と黒の狭間</a></td><td><div class="text-with-button" data-type="youtube" data-id="EJelswp-hLA"><a href="https://x.com/Zuatya/status/1980212406086181372" target="_blank">夢境 〜Dream State〜</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">500</td><td class="tags"></td></tr>
791<tr data-updated="2025-10-11" data-ytid="2C3lFH1f054" data-comment="4曲目が好み。"><td class="rank-C">か-39a</td><td class="circle"><a href="https://x.com/Hiasane_" target="_blank">日あさ寝</a></td><td><div class="text-with-button" data-type="youtube" data-id="2C3lFH1f054"><a href="https://x.com/Hiasane_/status/1976603617281867937" target="_blank">光としるべ</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"></td></tr>
792<tr data-updated="2025-10-16" data-ytid="xU-buSPLSZk" data-comment="花隈千冬。8年ぶりの参加らしい。11年前のDreamin*Dreamin、持ってますよ!"><td class="rank-C">ク-03y</td><td class="circle"><a href="http://www.glass-moon.com/" target="_blank">glassmoon</a></td><td><div class="text-with-button" data-type="youtube" data-id="xU-buSPLSZk"><a href="https://x.com/miu_gm0729/status/1977153399767679475" target="_blank">薄明-twilight-</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
793<tr data-updated="2025-10-08" data-ytid="rwY689szwAs" data-comment="4曲目が好み。花隈千冬。小春六花。Gumi。"><td class="rank-C">ク-34y</td><td class="circle"><a href="https://x.com/katedama" target="_blank">katedama</a></td><td><div class="text-with-button" data-type="youtube" data-id="rwY689szwAs"><a href="https://x.com/katedama/status/1972279914599764254" target="_blank">Epilogue</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--sv">合成音声</span></td></tr>
794<tr data-updated="2025-10-22" data-ytid="ee0BIIyGnU4" data-comment="メドレー形式の物語音楽。"><td class="rank-C">コ-10b</td><td class="circle"><a href="https://x.com/i9_starbirds" target="_blank">i9の購買部!出張所</a></td><td><div class="text-with-button" data-type="youtube" data-id="ee0BIIyGnU4"><a href="https://x.com/i9_starbirds/status/1979855106914071012" target="_blank">往く</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"><span class="chip--svpart">一部合成音声</span></td></tr>
795<tr data-updated="2025-10-22" data-ytid="POgvQ-9Xm04"><td class="rank-C">コ-16b</td><td class="circle"><a href="https://x.com/yonishi_424" target="_blank">yonishi</a></td><td><div class="text-with-button" data-type="youtube" data-id="POgvQ-9Xm04"><a href="https://x.com/yonishi_424/status/1980220659205820518" target="_blank">Phase 2</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"></td></tr>
796<tr data-updated="2025-10-24" data-ytid="WwCrIl89COI"><td class="rank-C">
796サ-21a</td><td class="circle"><a href="https://x.com/sumi_yamaka" target="_blank">YAMAKA</a></td><td><div class="text-with-button" data-type="youtube" data-id="WwCrIl89COI"><a href="https://x.com/sumi_yamaka/status/1979518199432691998" target="_blank">わだつみを泳ぐ</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1000</td><td class="tags"></td></tr>
797<tr data-updated="2025-10-13" data-ytid="G0nn-3tRBWc" data-comment="声の出し方がいいよね。真っすぐ、よく通る声で聴いてて気持ち良い。"><td class="rank-C">サ-23a</td><td class="circle"><a href="https://x.com/tuggt_" target="_blank">ぐつぐつ王国</a></td><td><div class="text-with-button" data-type="youtube" data-id="G0nn-3tRBWc"><b>[委託]</b><a href="https://thephantomthief-lutzel.netlify.app/" target="_blank">怪盗ルツェルの華麗なる予告状</a> (るる) <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">2000</td><td class="tags"></td></tr>
798<tr data-updated="2025-10-05" data-ytid="NxFgT87wnjk" data-comment="&lt;a href=&quot;https://counterspelljp.bandcamp.com/album/--2&quot;&gt;bandcamp&lt;/a&gt;で既に配信中。"><td class="rank-C">シ-11b</td><td class="circle"><a href="https://x.com/mimir0102" target="_blank">Counterspell</a></td><td><div class="text-with-button" data-type="youtube" data-id="NxFgT87wnjk"><a href="https://counterspelljp.bandcamp.com/album/--2" target="_blank">こと座α星</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">500</td><td class="tags"></td></tr>
799<tr data-updated="2025-10-12" data-ytid="J1KFLqKByVA" data-comment="5曲目が好み。花隈千冬。"><td class="rank-B">シ-18a</td><td class="circle"><a href="https://x.com/afst335" target="_blank">アフリカンサマータイム</a></td><td><div class="text-with-button" data-type="youtube" data-id="J1KFLqKByVA"><a href="https://x.com/afst335/status/1977343515131846738" target="_blank">UTSUROI</a> <img src="yt_play.svg" alt="y再生" class="inline-button toggle-button" width="20" height="20"><div class="embed-area"></div></div></td><td class="price">1500</td><td class="tags"><span class="chip--svpart">一部合成音声</span></td></tr>
800</tbody>
801</table>
802</div>
803
804<footer id="footer" class="wrap"></footer>
805
806<script>
807
808// ===== YTプレイヤー生成の堅牢ブート(最小パッチ) =====
809window.plPlayer = window.plPlayer || null;
810
811let _plRetry = 0;
812let _plTimer = null;
813
814// APIスクリプトを確実に読み込む
815function ensureYTScript(){
816  if (window.YT && YT.Player) return true;
817  if (!document.getElementById('yt-iframe-api')) {
818    const s = document.createElement('script');
819    s.src = 'https://www.youtube.com/iframe_api';
820    s.id  = 'yt-iframe-api';
821    document.head.appendChild(s);
822  }
823  return false;
824}
825
826// ② プレイヤー生成関数
827function createPlPlayer(){
828  const host = document.getElementById('plPlayer');
829  if (!host) return false;
830
831  // 既に作成済みなら何もしない
832  if (window.plPlayer && typeof plPlayer.getIframe === 'function') return true;
833
834  // APIがまだなら作れない
835  if (!(window.YT && YT.Player)) return false;
836
837  window.plPlayer = new YT.Player('plPlayer', {
838    width: 425,
839    height: 240,
840    playerVars: {
841      listType: 'playlist',
842      list: 'PLBl9lbnm9dYoHzoHlzsAS-pogXTmpe7GJ',
843      rel: 0,
844      modestbranding: 1
845    },
846    events: { onReady: onPLReady, onStateChange: onPLStateChange }
847  });
848  return true;
849}
850
851// ③ API準備時の公式コールバック → ただちに生成を試みる
852window.onYouTubeIframeAPIReady = function(){
853  createPlPlayer();
854};
855
856// ④ 初期化を“少しだけ”リトライ(ChromeのF5でAPIだけ抜ける対策)
857function bootPlayerWithRetry(){
858  clearInterval(_plTimer);
859  _plRetry = 0;
860  _plTimer = setInterval(()=>{
861    const apiReady = ensureYTScript();     // 無ければ挿す
862    const made = createPlPlayer();         // 作れるなら作る
863    if (apiReady && made){
864      clearInterval(_plTimer);
865    }else if (++_plRetry > 20){            // 最大 ~10秒(500ms × 20)
866      clearInterval(_plTimer);
867    }
868  }, 500);
869}
870
871// DOM描画直後 & BFCache復帰時にも再試行
872document.addEventListener('DOMContentLoaded', bootPlayerWithRetry);
873window.addEventListener('pageshow', bootPlayerWithRetry);
874
875(function () {
876  // 印刷用タイトルに <title> を入れる
877  const pt = document.getElementById('printTitle');
878  if (pt) pt.textContent = document.title || '';
879
880  // テーブル先頭に“チェック列”を追加(画面では非表示、印刷時だけ表示)
881  const table = document.getElementById('circle_list');
882  if (!table || !table.tHead || !table.tBodies[0]) return;
883
884  // ヘッダ
885  const hrow = table.tHead.rows[0];
886  const th = document.createElement('th');
887  th.className = 'print-col';
888  th.textContent = '☑';           // 見出し(印字時の目印)
889  hrow.insertBefore(th, hrow.cells[0]);
890
891  // 各行
892  Array.from(table.tBodies[0].rows).forEach(tr => {
893    const td = document.createElement('td');
894    td.className = 'print-col';
895    const cb = document.createElement('input');
896    cb.type = 'checkbox';
897    cb.className = 'print-check';
898    td.appendChild(cb);
899    tr.insertBefore(td, tr.cells[0]);
900  });
901})();
902
903// === 既読管理(localStorage) ===
904const LS_WATCHED_KEY = 'm3list:watched';
905const loadWatched = () => { try { return JSON.parse(localStorage.getItem(LS_WATCHED_KEY)) || {}; } catch { return {}; } };
906const saveWatched = (map) => localStorage.setItem(LS_WATCHED_KEY, JSON.stringify(map));
907
908const normalizeId = (type, raw) => {
909  let s = (raw || '').trim();
910  if (type === 'youtube') s = s.split('?')[0];         // ?start= など除去
911  if (type === 'twitter') s = s.replace(/\D+/g,'');    // 数字だけ
912  return s;
913};
914const mediaKey = (type, raw) => (type === 'youtube' ? 'yt:' : 'x:') + normalizeId(type, raw);
915
916// スクリプトの先頭で
917var plPlayer = null;     // ← var で“先に”用意(let/constは使わない)
918
919function setWatchedByKey(key, on=true){
920  const map = loadWatched();
921  if (on) map[key] = 1; else delete map[key];
922  saveWatched(map);
923  document.querySelectorAll(`.playwrap[data-media-key="${key}"]`)
924    .forEach(w => w.classList.toggle('is-watched', !!on));
925}
926
927function initWatchBadge(block){
928  const type = block.getAttribute('data-type');
929  const rawId = block.getAttribute('data-id') || '';
930  const key   = mediaKey(type, rawId);
931  const btn   = block.querySelector('.toggle-button');
932  if (!btn) return;
933
934  // アイコンをラップしてバッジを置けるように
935  let wrap = btn.parentElement;
936  if (!wrap || !wrap.classList.contains('playwrap')){
937    wrap = document.createElement('span');
938    wrap.className = 'playwrap';
939    btn.replaceWith(wrap);
940    wrap.appendChild(btn);
941  }
942  wrap.dataset.mediaKey = key;
943  if (!wrap.querySelector('.unwatched-badge')){
944    const dot = document.createElement('span');
945    dot.className = 'unwatched-badge';
946    dot.title = '未視聴';
947    wrap.appendChild(dot);
948  }
949
950  // 既読状態の反映
951  if (loadWatched()[key]) wrap.classList.add('is-watched'); else wrap.classList.remove('is-watched');
952
953  return { key, wrap };
954}
955
956// ヘルパ
957function escapeHTML(s){
958  return s.replace(/&/g,'&amp;').replace(/</g,'&lt;')
959          .replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;');
960}
961
962// <a href="...">text</a> だけ許可(http/https)。他は全部エスケープ。
963function sanitizeCommentHTML(raw){
964  // まず全エスケープ
965  let html = escapeHTML(raw);
966
967  // エスケープ済みの <a> パターンだけ“解凍”
968  // href="..." または href='...' に対応。URLは http/https 限定。
969  html = html.replace(
970    /&lt;a\s+href=(?:&quot;([^&]*)&quot;|&#39;([^&]*)&#39;)\s*&gt;([\s\S]*?)&lt;\/a&gt;/gi,
971    (_, d1, d2, text) => {
972      const url = (d1 || d2 || '').trim();
973      if(!/^https?:\/\//i.test(url)) return _; // http/https 以外は却下
974      return `<a href="${url}" target="_blank" rel="noopener noreferrer">${text}</a>`;
975    }
976  );
977
978  // 改行は <br> に
979  html = html.replace(/\r?\n/g, '<br>');
980  return html;
981}
982
983
984  const blocks = document.querySelectorAll('.text-with-button');
985
986  // 個別トグル機能
987  blocks.forEach(block => {
988    const type = block.getAttribute('data-type');
989    const id = block.getAttribute('data-id');
990    const embedArea = block.querySelector('.embed-area');
991    const button = block.querySelector('.toggle-button');
992
993 // ★追加:バッジ初期化
994  const { key } = initWatchBadge(block) || {};
995
996    button.addEventListener('click', () => {
997      toggleEmbed(block, type, id, embedArea);
998		// ★追加:個別クリック時は既読化
999    	if (key) setWatchedByKey(key, true);      
1000    });
1001  });
1002
1003  // 共通処理:開閉切り替え
1004  function toggleEmbed(block, type, id, embedArea) {
1005    const isVisible = embedArea.style.display === 'block';
1006
1007    if (isVisible) {
1008      embedArea.innerHTML = '';
1009      embedArea.style.display = 'none';
1010      hideRowCommentFor(block);
1011    } else {
1012      if (type === 'twitter') {
1013        embedArea.innerHTML = `
1014          <blockquote class="twitter-tweet" data-media-max-width="300">
1015            <a href="https://twitter.com/i/status/${id}"></a>
1016          </blockquote>
1017        `;
1018        embedArea.style.display = 'block';
1019        twttr.widgets.load(embedArea);
1020      } else if (type === 'youtube') {
1021        embedArea.innerHTML = `
1022          <iframe loading="lazy" src="https://www.youtube.com/embed/${id}" 
1023                  title="YouTube video player" 
1024                  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" 
1025                  allowfullscreen>
1026          </iframe>
1027        `;
1028        embedArea.style.display = 'block';
1029      }
1030      showRowCommentFor(block);
1031    }
1032  }
1033
1034const closeAllBtn = document.getElementById('closeAllEmbeds');
1035
1036function closeAllEmbeds(){
1037  blocks.forEach(block => {
1038    const embedArea = block.querySelector('.embed-area');
1039    if (!embedArea) return;
1040    embedArea.innerHTML = '';
1041    embedArea.style.display = 'none';
1042    hideRowCommentFor(block);   // ★追加    
1043  });
1044}
1045
1046closeAllBtn?.addEventListener('click', (e) => {
1047  e.preventDefault();
1048  closeAllEmbeds();
1049});
1050
1051// Esc で全閉じ
1052document.addEventListener('keydown', (e) => {
1053  if (e.key === 'Escape') closeAllEmbeds();
1054});
1055
1056// キーボード操作
1057document.addEventListener('keydown', (e) => {
1058  if (e.target && /input|textarea|select/i.test(e.target.tagName)) return; // フォーム中は無効
1059  const a = (id) => document.getElementById(id)?.click();
1060  switch(e.key){
1061    case '1': window.svFilterApply?.('all'); break;
1062    case '2': window.svFilterApply?.('latest'); break;
1063    case '3': window.svFilterApply?.('nosv'); break;
1064    case '4': window.svFilterApply?.('sv'); break;
1065    case 'g': a('globalToggle'); break;
1066    case 'x': a('twitterToggle'); break;
1067  }
1068});
1069
1070(function(){
1071  // ===== 設定 =====
1072  // ページ公開日(Excel/VBAで body に data-page-updated を吐くのが理想)
1073  var pageUpdated = document.body.getAttribute('data-page-updated') || new Date().toISOString();
1074  var pageDate = pageUpdated.slice(0,10); // "YYYY-MM-DD"
1075
1076  const table = document.getElementById('circle_list');
1077  const rows  = table ? Array.from(table.tBodies[0].rows) : [];
1078
1079  // 合成音声検出(ID運用と将来のclass運用に両対応)
1080  var svSelector = '#synthesized-voice, #synthesized-voice-include, .chip--sv, .chip--svpart';
1081
1082  function hasSV(tr){ return !!tr.querySelector(svSelector); }
1083
1084  // “最新”の定義:行の data-updated がページ公開日と一致
1085  function isLatest(tr){
1086    var d = tr.getAttribute('data-updated'); // "YYYY-MM-DD"
1087    return d && d === pageDate;
1088  }
1089  
1090  function updateCounts(){
1091    const counts = {
1092      all: rows.length,
1093      latest: rows.filter(isLatest).length,
1094      nosv: rows.filter(tr => !hasSV(tr)).length,
1095      sv: rows.filter(hasSV).length
1096    };
1097
1098    // svFilter(簡易リンク帯)を使っている場合
1099    document.querySelectorAll('#svFilter a[data-filter]').forEach(a => {
1100      const key = a.dataset.filter;
1101      if (counts[key] != null) a.dataset.count = counts[key];
1102  });
1103
1104  // viewTabs([role="tab"])を使っている場合
1105  document.querySelectorAll('#viewTabs [role="tab"]').forEach(b => {
1106    const key = b.dataset.tab;
1107    if (counts[key] != null) b.dataset.count = counts[key];
1108  });
1109
1110}
1111
1112// 初回実行 & 既存の applyFilter / applyTab の最後でも呼ぶと常に最新
1113updateCounts();
1114 
1115
1116  // “何日前”か(行の data-updated と pageDate の日数差)
1117  function daysAgo(tr){
1118    var d = tr.getAttribute('data-updated'); if(!d) return 999;
1119    try{
1120      var t1 = new Date(d + 'T00:00:00+09:00'); // JST基準
1121      var t0 = new Date(pageDate + 'T00:00:00+09:00');
1122      return Math.round((t0 - t1) / 86400000);
1123    }catch(e){ return 999; }
1124  }
1125
1126  // ----- 更新ハイライト(1列目以外に段階的に)
1127  rows.forEach(function(tr){
1128    var k = daysAgo(tr);
1129    tr.classList.remove('recency-0','recency-1','recency-2','recency-3');
1130    if      (k === 0) tr.classList.add('recency-0'); // 今日
1131    else if (k === 1) tr.classList.add('recency-1'); // 昨日
1132    else if (k === 2) tr.classList.add('recency-2'); // 一昨日
1133    else if (k <= 4)  tr.classList.add('recency-3'); // ?4日前
1134    // それ以外は無印(背景強調なし)
1135  });
1136
1137  // ----- 合成音声/最新フィルタ(非表示切替のみ)
1138  function applyFilter(kind){
1139    rows.forEach(function(tr){ tr.classList.remove('is-hidden'); });
1140
1141  if (kind === 'latest'){
1142    rows.forEach(tr => {
1143      if (!isLatest(tr) && !tr.classList.contains('force-show')){
1144        tr.classList.add('is-hidden');
1145      }
1146    });
1147  } else if (kind === 'nosv'){
1148    rows.forEach(tr => {
1149      if (hasSV(tr) && !tr.classList.contains('force-show')){
1150        tr.classList.add('is-hidden');
1151      }
1152    });
1153  } else if (kind === 'sv'){
1154    rows.forEach(tr => {
1155      if (!hasSV(tr) && !tr.classList.contains('force-show')){
1156        tr.classList.add('is-hidden');
1157      }
1158    });
1159  }
1160
1161    // 既存の IIFE の中(applyFilter 定義の後ならどこでもOK)
1162    window.svFilterApply = applyFilter;   // ← 外に公開
1163
1164    // UI
1165    var f = document.querySelectorAll('#svFilter a[data-filter]');
1166    Array.prototype.forEach.call(f, function(a){
1167      a.classList.toggle('is-active', a.getAttribute('data-filter')===kind);
1168    });
1169    // 記憶&共有(任意)
1170    try{ localStorage.setItem('m3list:svfilter', kind); }catch(e){}
1171    location.hash = 'tab=' + kind;
1172  }
1173
1174  // 起動時:ハッシュ or 記憶 or 既定=すべて
1175  var init = (function(){
1176    var h = new URLSearchParams(location.hash.slice(1)).get('tab');
1177    return h || (localStorage.getItem('m3list:svfilter') || 'all');
1178  })();
1179  applyFilter(init);
1180
1181  // クリック
1182  var svf = document.getElementById('svFilter');
1183  if (svf) svf.addEventListener('click', function(e){
1184    var a = e.target.closest('a[data-filter]'); if(!a) return;
1185    e.preventDefault(); applyFilter(a.getAttribute('data-filter'));
1186  });
1187
1188  // ===== (任意)個別YouTubeプレイヤーの“遅延挿入”補助 =====
1189  // 「ボタン(.yt-toggle)」に data-yt-id="XXXXXXXXXXX" を付けておくと、
1190  // 押したときに同じセル内の .yt-embed に iframe を挿入/トグル
1191  document.addEventListener('click', function(e){
1192    var btn = e.target.closest('.yt-toggle[data-yt-id]'); if(!btn) return;
1193    e.preventDefault();
1194    var id = btn.getAttribute('data-yt-id');
1195    var cell = btn.closest('td') || btn.parentNode;
1196    var box = cell.querySelector('.yt-embed') || (function(){
1197      var d = document.createElement('div'); d.className='yt-embed';
1198      d.style.marginTop = '6px'; cell.appendChild(d); return d;
1199    })();
1200    if (box.firstChild){ // 既にある→トグル
1201      box.style.display = (box.style.display==='none' ? '' : 'none');
1202      return;
1203    }
1204    var ifr = document.createElement('iframe');
1205    ifr.width = '480'; ifr.height = '270';
1206    ifr.src = 'https://www.youtube-nocookie.com/embed/' + id + '?rel=0';
1207    ifr.title = 'YouTube video player';
1208    ifr.frameBorder = '0';
1209    ifr.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share';
1210    ifr.allowFullscreen = true;
1211    box.appendChild(ifr);
1212  });
1213
1214})();
1215
1216/* ここから */
1217
1218// === YouTube動画IDの正規化(URLでもIDでもOKにする) ===
1219function normalizeYtId(raw){
1220  if(!raw) return "";
1221  if (/^[a-zA-Z0-9_-]{6,}$/.test(raw) && !/^(https?:)?\/\//.test(raw)) {
1222    return raw.split('?')[0];
1223  }
1224  try{
1225    const u = new URL(raw, location.href);
1226    const v = u.searchParams.get('v');
1227    if (v) return v.split('&')[0];
1228    const m = u.pathname.match(/\/(embed|shorts)\/([^/?#]+)/);
1229    if (m && m[2]) return m[2];
1230    if (u.hostname === "youtu.be"){
1231      const m2 = u.pathname.match(/^\/([^/?#]+)/);
1232      if (m2 && m2[1]) return m2[1];
1233    }
1234  }catch(e){}
1235  return raw.split('?')[0];
1236}
1237
1238
1239// === 各<tr>に data-ytid を埋め込む(行内の data-id から抽出) ===
1240(function initYtIdDataset(){
1241  document.querySelectorAll('#circle_list tbody tr').forEach(tr=>{
1242    // すでに Excel/VBA で data-ytid を出力できるならそれを優先
1243    if (tr.dataset.ytid && tr.dataset.ytid.length){
1244      tr.dataset.ytid = normalizeYtId(tr.dataset.ytid);
1245      return;
1246    }
1247    // 行内の YouTube トグルから拾う(.text-with-button[data-type="youtube"])
1248    const y = tr.querySelector('.text-with-button[data-type="youtube"]');
1249    if (y){
1250      const id = normalizeYtId(y.getAttribute('data-id'));
1251      if (id) tr.dataset.ytid = id;
1252    }
1253  });
1254})();
1255
1256// === 再生中表示の付与/解除 ===
1257function clearNowPlaying(reapply = true){
1258  document.querySelectorAll('#circle_list tbody tr.is-nowplaying')
1259    .forEach(tr => tr.classList.remove('is-nowplaying'));    
1260  document.querySelectorAll('#circle_list tbody tr.force-show')
1261    .forEach(tr => tr.classList.remove('force-show'));
1262
1263  // applyFilter が IIFE の外から呼べるようになったのでココで再適用
1264  if (reapply && typeof window.svFilterApply === 'function'){
1265    window.svFilterApply(getActiveFilterKey());
1266  }
1267}
1268
1269// 現在のフィルタを取得するヘルパ
1270function getActiveFilterKey(){
1271  const a = document.querySelector('#svFilter a.is-active[data-filter]');
1272  return a ? a.dataset.filter : 'all';
1273}
1274
1275function setNowPlayingByVideoId(videoId){
1276  const vid = normalizeYtId(videoId);
1277  if (!vid) return;
1278
1279  // まず前の強制表示を解除+現行フィルタを再適用
1280  clearNowPlaying(true);
1281
1282  // 新しいヒットを探す
1283  const hits = Array.from(document.querySelectorAll('#circle_list tbody tr'))
1284    .filter(tr => (tr.dataset.ytid||"") === vid);
1285
1286  if (!hits.length) return;
1287
1288  // ヒット行を強制表示&バッジ
1289  hits.forEach(tr=>{
1290    tr.classList.add('force-show');          // フィルタに隠されない
1291    tr.classList.remove('is-hidden');        // 念のため即表示
1292    tr.classList.add('is-nowplaying');
1293  });
1294
1295  // (任意)画面外のときだけスクロール
1296  if (typeof ensureInView === 'function') ensureInView(hits[0]);
1297}
1298
1299function ensureInView(el, margin = 24){
1300  const r = el.getBoundingClientRect();
1301  const vh = window.innerHeight || document.documentElement.clientHeight;
1302  if (r.top < margin || r.bottom > vh - margin){
1303    el.scrollIntoView({ behavior:'smooth', block:'nearest' });
1304  }
1305}
1306
1307// === IFrame Player API: 固定プレイリストの現在曲 → バッジ同期 ===
1308
1309function onYouTubeIframeAPIReady(){
1310  plPlayer = new YT.Player('plPlayer', {
1311    width: 425,
1312    height: 240,
1313    playerVars: {
1314      listType: 'playlist',
1315      list: 'PLBl9lbnm9dYoHzoHlzsAS-pogXTmpe7GJ',
1316      rel: 0,
1317      modestbranding: 1
1318    },
1319    events: { onReady: onPLReady, onStateChange: onPLStateChange }
1320  });
1321}
1322
1323function onPLReady(){
1324  // 初期同期(インデックス取得が安定するまで少し待つ)
1325//  setTimeout(updateNowPlayingFromPlayer, 300);
1326}
1327
1328function onPLStateChange(e){
1329  if (e.data === YT.PlayerState.PLAYING) {
1330    updateNowPlayingFromPlayer();
1331  }
1332}
1333
1334// ==== プレイヤー同期(一本化)====
1335let _np_lastVid = null;
1336
1337function updateNowPlayingFromPlayer(){
1338  const p = window.plPlayer;
1339  if (!p || typeof p.getVideoData !== 'function') return;
1340  try{
1341    const vd = p.getVideoData(); // { video_id, title, ... }
1342    if (!vd || !vd.video_id) return;
1343    if (vd.video_id === _np_lastVid) return;
1344    _np_lastVid = vd.video_id;
1345
1346    // 辞書がまだ無ければここで生成(タイミング対策)
1347    if (!window.videoComments) buildVideoCommentMap();
1348
1349    // 右側カード:タイトル+コメント
1350    const tEl = document.getElementById('npVideoTitle');
1351    if (tEl) tEl.textContent = vd.title || '—';
1352
1353    // 再生時にコメントを反映
1354    const bubble = document.getElementById('npVideoComment');
1355    if (bubble){
1356      const cm = (window.videoComments && window.videoComments[vd.video_id]) || "";
1357//    bubble.textContent = cm || "";
1358      bubble.innerHTML = sanitizeCommentHTML(cm);
1359      bubble.classList.toggle('is-visible', !!cm);
1360    }
1361
1362    // 既読化&行ハイライト(既存ロジック)
1363    setWatchedByKey('yt:' + vd.video_id, true);
1364    setNowPlayingByVideoId(vd.video_id);
1365  }catch(e){}
1366}
1367
1368// === YouTube動画IDの正規化(URLでもIDでもOKにする) ===
1369function normalizeVideoId(id){
1370  if(!id) return "";
1371  const m = String(id).match(/[A-Za-z0-9_-]{11}/);
1372  return m ? m[0] : "";
1373}
1374
1375function buildVideoCommentMap(){
1376  const map = {};
1377  document.querySelectorAll('#circle_list tbody tr').forEach(tr=>{
1378    const comment = tr.getAttribute('data-comment');
1379    if(!comment) return;
1380
1381    // ① tr の data-ytid を最優先
1382    let vid = normalizeVideoId(tr.getAttribute('data-ytid'));
1383
1384    // ② 無ければ .text-with-button の data-id から推測
1385    if(!vid){
1386      const blk = tr.querySelector('.text-with-button[data-id]');
1387      if(blk) vid = normalizeVideoId(blk.dataset.id);
1388    }
1389
1390    if(vid && !map[vid]){
1391      // VBAで &#10; にしている場合の改行戻し
1392      map[vid] = comment.replace(/&#10;/g, '\n');
1393    }
1394  });
1395  window.videoComments = map;
1396}
1397
1398document.getElementById('markAllWatched')?.addEventListener('click', (e)=>{
1399  e.preventDefault();
1400  if (!confirm('ページ内にある全ての試聴を既読にします。よろしいですか?')) return;
1401  const map = loadWatched();
1402  document.querySelectorAll('.playwrap[data-media-key]').forEach(w => {
1403    map[w.dataset.mediaKey] = 1; w.classList.add('is-watched');
1404  });
1405  saveWatched(map);
1406});
1407
1408document.getElementById('resetWatch')?.addEventListener('click', (e)=>{
1409  e.preventDefault();
1410  if (!confirm('この端末の視聴履歴をリセットしますか?')) return;
1411  localStorage.removeItem(LS_WATCHED_KEY);
1412  document.querySelectorAll('.playwrap').forEach(w => w.classList.remove('is-watched'));
1413});
1414
1415// --- ① 画面読み込み時にコメント辞書を構築 ---
1416function normalizeVideoId(id){
1417  if(!id) return "";
1418  const m = String(id).match(/[A-Za-z0-9_-]{11}/);
1419  return m ? m[0] : String(id).split('?')[0];
1420}
1421const videoComments = {};
1422document.querySelectorAll('#circle_list tbody tr').forEach(tr=>{
1423  const c = tr.getAttribute('data-comment');
1424  if(!c) return;
1425  const block = tr.querySelector('.text-with-button[data-id]');
1426  if(!block) return;
1427  const vid = normalizeVideoId(block.dataset.id);
1428  if(vid){
1429    // &#10; を実際の改行に戻す(VBA側で置いた場合の保険)
1430    videoComments[vid] = c.replace(/&#10;/g, '\n');
1431  }
1432});
1433
1434// 最低限のサニタイズ:<a ...> だけ許可、それ以外はテキスト化
1435function sanitizeAllowAnchor(html){
1436  // [BR] を <br> に
1437  html = String(html || '').replace(/\[BR\]/g, '<br>');
1438  // いったん div に入れて、a 以外のタグは除去
1439  const div = document.createElement('div');
1440  div.innerHTML = html;
1441  [...div.querySelectorAll('*')].forEach(el=>{
1442    if (el.tagName.toLowerCase() !== 'a'){
1443      const txt = document.createTextNode(el.textContent);
1444      el.replaceWith(txt);
1445    }else{
1446      // href だけ残して他属性は落とす
1447      const href = el.getAttribute('href') || '#';
1448      el.replaceWith(Object.assign(document.createElement('a'), {href, textContent: el.textContent, target: '_blank', rel: 'noopener'}));
1449    }
1450  });
1451  return div.innerHTML;
1452}
1453
1454// 行の埋め込み直下にコメントを出す
1455function showRowCommentFor(block){
1456  const tr = block.closest('tr');
1457  if (!tr) return;
1458  const txt = tr.dataset.comment || '';
1459  // 何もなければ何もしない(既存あれば消す)
1460  if (!txt.trim()){
1461    hideRowCommentFor(block);
1462    return;
1463  }
1464  const area = block.querySelector('.embed-area');  // 既存の埋め込み箱
1465  if (!area) return;
1466
1467  // 既に出ていれば更新だけ
1468  let bub = area.nextElementSibling;
1469  const needNew = !(bub && bub.classList.contains('np-bubble-row'));
1470  if (needNew){
1471    bub = document.createElement('div');
1472    bub.className = 'np-bubble-row';
1473    area.insertAdjacentElement('afterend', bub);
1474  }
1475  bub.innerHTML = sanitizeAllowAnchor(txt);
1476}
1477
1478// 行のコメントを消す
1479function hideRowCommentFor(block){
1480  const area = block.querySelector('.embed-area');
1481  if (!area) return;
1482  const bub = area.nextElementSibling;
1483  if (bub && bub.classList.contains('np-bubble-row')){
1484    bub.remove();
1485  }
1486}
1487
1488</script>
1488
1489
1490<br>
1491<br>
1492<br>
1493<br>
1494</body>
1495</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.