/* tenroin-top/articles.jsx — READING LIFE 誌面：号（ISSUE）と記事（ARTICLES）の正本
   ─────────────────────────────────────────────
   ・ISSUE      = 号の一級概念（号数・季節・テーマ・発行元）。号数の表記はすべてここを参照する
   ・ARTICLES   = 内部記事（/magazine/<slug> で article.html が描画）
   ・Articles   = トップ「本誌 — READING LIFE」セクション（今号の記事カード）
   ・記事本文は body ブロック配列：{t:'h'|'p'|'q'|'hr', v:'...'}
   ・記事コンテンツの正本は COO＋三浦代表が供給（現行2本は編集部「試し刷り」）
*/

/* ── 書き手の欄（author_kind）── 代表確定・CTO 2026/9/7 17:10 配布 ──────────
   ★記事は「**欄 × 誌面 × ジャンル**」の三軸で持つ（入れ子にしない）。
       欄  ＝ 誰が書いたか（この表）
       誌面 ＝ 日刊・週刊・本誌
       ジャンル ＝ cat（ESSAY・MANIFESTO・MY READING LIFE …）── **cat はジャンルのまま残す**
   ★台帳（rl_works）は同じものを `author_kind` という列名で持つ。**key の字は同じ**にしてある。
     ⚠️`rl_works.column_no` は**別物**（日刊の欄の番号）。名が似ているだけなので混ぜない。
   ★名は代表の言葉のまま（受講生・アーティスト・公認クリエイター）。**字を変えない**。
   ★検印（kenin）＝ 会員と受講生の作だけが通る。編集部の側（コンシェルジュ・店主・スタッフ）は不要。
     アーティスト・公認クリエイターは編集部が定める＝ここでは持たない（null）。 */
const COLUMNS = {
  concierge: { label: 'AI コンシェルジュ',  kenin: false },
  owner:     { label: '店主',              kenin: false },
  staff:     { label: 'スタッフ',           kenin: false },
  member:    { label: '会員',              kenin: true  },
  student:   { label: '受講生',            kenin: true  },
  lecturer:  { label: '講師',              kenin: false },
  artist:    { label: 'アーティスト',       kenin: null  },
  certified: { label: '公認クリエイター',    kenin: null  },
};

/* 欄の札（署名の脇に小さく出す字）。
   ★**署名と食い違うときは出さない**。札は読者の助けであって、署名の上書きではない。
     出さない二つ ──
       ① 架名の創作（fiction）＝「会員」も「店主」も嘘になる。fiction の札が既に立っている
       ② 署名が「READING LIFE編集部」そのもの＝編集部と名乗っている上に「店主」を重ねると食い違う
   ⚠️スピカは署名の中に既に「AI コンシェルジュ」が在るが、**札は出す**
     ＝AI が書いたことは打消しではなく**名乗り**（誇ってAI）。重なっても弱めない。 */
function columnLabel(art){
  if(!art || !art.column) return '';
  if(art.fiction) return '';
  if(String(art.author||'').indexOf('READING LIFE編集部') === 0) return '';
  const c = COLUMNS[art.column];
  if(!c) return '';
  /* ③ 署名が既にその字を名乗っているなら、札は重ねない ── 重ねると吃る。
     実測（2026/9/7）＝「文 ── スピカ（READING LIFE 編集部・AI コンシェルジュ）AI コンシェルジュ」。
     ⚠️これは名乗りを弱めているのではない。名乗りは署名の側に在り、札はその写しに過ぎない。 */
  if(String(art.author||'').indexOf(c.label) >= 0) return '';
  return c.label;
}

/* ── 週刊READING LIFE（番組）──
   運用: 放送が終わったら episodes の先頭に1件追記するだけ。
   ★次回の回数は書かない。episodes の最大の回＋1 で導く（2026/9/5 CTO裁定）。
     手で焼くと、追記を忘れたときに古い回数が独り歩きする ── 実際、9/5 に
     誌面（第1回）とラウンジ（第1回は9/2）と設計書（第1回9/2済）が三つに割れた。
   ★日付も書かない。upcoming.date は null のままにして「次の水曜」を導く。
   upcoming.href に配信URL(YouTube Live等)が入ると「放送を視聴する」ボタンが生きる。
   video: {type:'youtube', id:'XXXX'} か {type:'vimeo', id:'123456'}。null=映像準備中表示 */
const WEEKLY = {
  ser: '週刊READING LIFE',
  en: 'THE WEEKLY READING LIFE',
  upcoming: {
    title: '公開編集会議 ── 今週の誌面を、その場で決める。',
    href: null,
    date: null,
  },
  episodes: [
    { no: 0, slug: 'weekly-0', date: '2026-07-22',
      title: '番組、はじめます。── 編集会議を、そのまま週刊番組に',
      lede: '雑誌READING LIFEの編集会議を、毎週水曜の夜、そのまま番組にします。第0回は、その宣言。なぜ舞台裏から見せるのか、この番組で何が決まっていくのか。',
      author: 'READING LIFE編集部',
      img: 'assets/rl-weekly-hero.jpg',
      video: null,
      preview: true,
      notes: [
        {t:'p', v:'READING LIFEの誌面は、毎週水曜の夜、公開の編集会議から生まれます。どの特集を立てるか、どの記事を書庫から登用するか、誰に寄稿を頼むか——雑誌づくりの舞台裏は、ふつう最後まで見せないものです。私たちは、そこから見せることにしました。'},
        {t:'h', v:'会議が、そのまま番組になる'},
        {t:'p', v:'この番組では、編集長と編集部が、その週の誌面をその場で決めていきます。読書クラブの会員は見学するだけでなく、企画に声を挙げ、誌面に名前が載ることもあります。雑誌は、読むものから「参加するもの」へ。'},
        {t:'p', v:'放送のアーカイブは、毎回この書庫に掛かります。第1回で、お会いしましょう。'},
      ],
    },
  ],
};

function wkEmbed(v){
  return v.type === 'vimeo'
    ? 'https://player.vimeo.com/video/' + v.id
    : 'https://www.youtube-nocookie.com/embed/' + v.id;
}

/* 次の放送は第何回か。★掛かっている放送から導く（数を焼かない・2026/9/5 CTO裁定）。
   まだ一本も掛かっていなければ null＝**回数を出さない**（0や1と嘘をつかない）。 */
function nextOnAirNo(){
  const eps = WEEKLY.episodes || [];
  if (!eps.length) return null;
  return Math.max.apply(null, eps.map(function(e){ return Number(e.no) || 0; })) + 1;
}
/* 「NEXT ON AIR ── 第N回」。回数が導けないときは肩書きだけ返す。 */
function nextOnAirLabel(){
  const n = nextOnAirNo();
  return n === null ? 'NEXT ON AIR' : 'NEXT ON AIR ── 第' + n + '回';
}


/* ── 番付（今週のグランプリ）──
   ★正本はこの一箇所。トップの節と `/magazine` の一枚が**同じものを見る**（写しを作らない）。
   ⚠️`.gp` は `position:absolute; inset:0` なので、器の側で丈を持つ要がある。
     見開きの中では面が丈を持つ。一枚の頁では `framed` で器を付ける。 */

const GRANDPRIX = {
  en: 'THE WEEKLY GRAND PRIX',
  title: '今週の番付',
  main: {
    label: 'メディアグランプリ ── アクセス番付',
    caveat: '順位のみ・PV非公開',
    rows: [
      { r: '壱', name: '体験できるマガジン、はじまる。', t: 'READING LIFE編集部' },
      { r: '弐', name: '？？？', t: '放送で発表' },
      { r: '参', name: '？？？', t: '放送で発表' },
    ],
  },
  subs: [
    /* 🔴2026/9/5 裁定#9＝実在の登用作が出るまで、この欄は空札にする（架名を掲げない） */
    { label: '誌面登用', top: '──', t: '第一便は、月に一度の選考から。' },
    { label: '販売数 ── 楽市', top: '？？？', t: '集計中' },
    { label: '販売金額 ── 楽市', top: '？？？', t: '集計中' },
  ],
  note: '試し刷りの集計 ── 正式な番付は、毎週水曜の放送で発表。',
};

function RlBanzuke(props){
  const inner = (
    <div className="gp">
      <img className="gp-bg" src="assets/rl-gp-bg.jpg" alt=""/>
      <div className="gp-in">
        <div className="gp-head">
          <span className="gp-en">{GRANDPRIX.en}</span>
          <span className="gp-title">{GRANDPRIX.title}</span>
        </div>
        <div className="gp-main">
          <div className="gp-label">{GRANDPRIX.main.label}<i>{GRANDPRIX.main.caveat}</i></div>
          <div className="gp-rows">
            {GRANDPRIX.main.rows.map((g,i)=>(
              <div key={i} className={'gp-row'+(i===0?' is-top':'')}>
                <b>{g.r}</b>
                <span className="gp-name">{g.name}</span>
                <span className="gp-t">{g.t}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="gp-subs">
          {GRANDPRIX.subs.map((x,i)=>(
            <div key={i} className="gp-sub">
              <span className="gs-l">{x.label}</span>
              <b>{x.top}</b>
              <span className="gs-t">{x.t}</span>
            </div>
          ))}
        </div>
        <div className="gp-note">{GRANDPRIX.note}</div>
      </div>
    </div>
  );
  return props && props.framed ? <div className="rl-gp-frame">{inner}</div> : inner;
}

/* ── トップ「誌面の棚」＝三誌が並ぶ書店の棚（意匠手帳・代表 E8 で決定）──
   組みと意匠は手帳から写す（近似を作らない）。ここが持つのは**データの配線だけ**。
   ★数を焼かない ── 日刊の号数と校了の刻は、ここに書かない。
     創刊前は号が無い（予備刷りの錠）。日取りは台帳が正なので、
     既にある公開の口 /api/magazine/daily/latest の返す一枚をそのまま出す。
     読めないときは**日付を出さない**（0や古い値と嘘をつかない）。
   ★週刊の回数は nextOnAirNo() から導く（掛かっている放送から数える）。
   ★本誌の号名は ISSUE.ja から引く（背表紙と同じ一箇所を見る）。
   ★戸口は既存の住所へ繋ぐだけ。API は増やさない。 */
const RACK_DOORS = [
  /* 番付＝この節の中（週刊の見開き）に在るので、外に繋ぐ住所を持たない＝札のまま */
  { k:'番付',     t:'楽市グランプリ ── 今場所の星取り', s:'毎週水曜の放送で発表',        href:'/magazine' },
  { k:'楽市',     t:'本の市 ── 作家の店が並ぶ',      s:'天狼院楽市〈東京本町〉',      href:'/creators/market' },
  /* ⚠️発表の受付は止まっている（サーバの旗が正）。ここで誘わない */
  { k:'ラウンジ', t:'会員の間 ── 読書クラブ',        s:'発表の受付は、創刊にむけて準備中', href:'/reading-club' },
];

/* 日刊の表紙の一行。台帳（公開の口）から取る。取れないときは日付を出さない。 */
function useDailyGate(){
  const { useState, useEffect } = React;
  const [g, setG] = useState(undefined);   /* undefined=まだ／null=読めない／文字列=出す */
  useEffect(()=>{
    let alive = true;
    const ac = typeof AbortController !== 'undefined' ? new AbortController() : null;
    const t = setTimeout(()=>{ if(ac) ac.abort(); }, 8000);
    fetch('/api/magazine/daily/latest', { credentials:'omit', signal: ac && ac.signal })
      .then(r => r.ok ? r.json() : null)
      .then(j => {
        if (!alive) return;
        if (!j || j.ok !== true) { setG(null); return; }
        if (j.launched === true && j.issue && j.issue.no) {
          setG({ kind:'issue', line:'第' + j.issue.no + '号' });
        } else if (j.gate && j.gate.note) {
          setG({ kind:'gate', line: j.gate.note });
        } else { setG(null); }
      })
      .catch(()=>{ if (alive) setG(null); })
      .finally(()=>clearTimeout(t));
    return ()=>{ alive = false; clearTimeout(t); if (ac) ac.abort(); };
  }, []);
  return g;
}

/* 誌面の頭の一行。**日付は焼かない** ── 台帳の口が返す一枚（`gate.note`）をそのまま使い、
   創刊したら言い方が自動で変わる。読めないときは日付を出さない（0と嘘をつかない）。
   ⚠️公開前のいまは「支度の棚」であることが一読で分かる字にする（受付は止まっている）。 */
function rackOpening(gate){
  if (gate && gate.kind === 'issue') {
    return 'Web READING LIFE、創刊しました。いま出ているのは ' + gate.line + '。';
  }
  if (gate && gate.kind === 'gate') {
    /* gate.line ＝「創刊 9月23日（水）二十時。」＝ 台帳の字をそのまま置く */
    return 'Web READING LIFE は、' + gate.line + 'いまは支度の棚 ── 公開前の予告です。';
  }
  return 'Web READING LIFE は、創刊にむけて支度中です。';   /* 読めないとき＝日付を出さない */
}

function RlRack(props){
  const { ISSUE } = window.MAG;
  const gate = useDailyGate();
  const rich = !!(props && props.rich);   /* `/magazine` の一枚だけ豊かに（トップの節は今までどおり） */
  const today = (()=>{ const d = new Date();
    return d.getFullYear() + '年' + (d.getMonth()+1) + '月' + d.getDate() + '日'; })();
  return (
    <div className="rack">
      <div className="rack-mast">
        <b>READING LIFE</b>
        <span>海の出版社 ── 港の雑誌社 ── {today}</span>
      </div>

      {rich && (
        <div className="rack-lead">
          <p className="rack-lead-open">{rackOpening(gate)}</p>
          <p>
            READING LIFE は、三つの誌面でひとつの雑誌です。
            <b>日刊</b>は毎晩 22:00 に校了し、その日に載った作をまとめて綴じます。
            <b>週刊</b>は水曜 20:00、公開の編集会議がそのまま番組になります。
            <b>本誌</b>は季刊で、週刊で読まれた作の中から編集部が選びます。
            下の棚が、いま出ているものの全部です。
          </p>
        </div>
      )}

      <div className="rack-shelf">
        <div className="rack-item">
          <h4>日刊 ── 毎晩 22:00 校了</h4>
          <div className="rack-cover text">
            <span className="rc-t">{gate && gate.kind === 'gate' ? gate.line
              : gate && gate.kind === 'issue' ? gate.line
              : '創刊にむけて、準備中。'}</span>
            <span className="rc-s">その日に載った作を、毎晩まとめて綴じます。</span>
          </div>
          <p>会員の欄から選ばれた作が、その日のうちに載る日刊紙。</p>
          {rich && <p className="rack-note">毎晩 22:00 が校了。校了と同時に、翌日の号が開きます。</p>}
        </div>

        <div className="rack-item">
          <h4>週刊 ── 水曜 20:00 配信</h4>
          <a className="rack-cover" href="/magazine/weekly" data-cta="rack-weekly"
             style={{backgroundImage:"url('assets/rl-weekly-hero.jpg')"}}>
            <span className="rc-mast">週刊READING LIFE</span>
            <span className="rc-play" aria-hidden="true">
              <svg width="14" height="16" viewBox="0 0 14 16" fill="currentColor"><path d="M0 0l14 8-14 8z"/></svg>
            </span>
            <span className="rc-title">公開編集会議、そのまま番組。</span>
          </a>
          <p><b>{nextOnAirLabel()}</b> ── {fmtNextWed()} 20:00。その週に読まれた作を、編集部が読み解きます。</p>
          {rich && <p className="rack-note">どの作を誌面に採るかを、その場で決める会議です。会員は見学し、声を挙げられます。</p>}
        </div>

        <div className="rack-item">
          <h4>本誌 ── 季刊</h4>
          <div className="rack-cover text">
            <span className="rc-t">READING LIFE<br/>{ISSUE.ja}</span>
            <span className="rc-s">編集部の選考を通った作が載る、雑誌の本体。</span>
          </div>
          <p><b>{ISSUE.ja}</b> ── 週刊で読まれた作の中から、編集部が選びます。季刊。次は <b>2027 春号</b>（紙の創刊号・2027年春）。</p>
          {rich && <p className="rack-note">日刊と週刊を通った作が、季節ごとに一冊へ綴じられます。</p>}
        </div>
      </div>

      <div className="rack-doors">
        {RACK_DOORS.map(d => d.href ? (
          <a key={d.k} href={d.href} data-cta={'rack-' + d.k}>
            <span>{d.k}</span><b>{d.t}</b><small>{d.s}</small>
          </a>
        ) : (
          <div key={d.k}><span>{d.k}</span><b>{d.t}</b><small>{d.s}</small></div>
        ))}
      </div>

      <div className="rack-foot">
        <span>あなたの欄 → 日刊 → 週刊 → 本誌</span>
        <span>日刊に載るのは、検印と編集部の預かりを通った作品です。</span>
      </div>
    </div>
  );
}

function fmtNextWed(fixed){
  const d = fixed ? new Date(fixed + 'T00:00:00+09:00')
    : (()=>{ const x = new Date(); x.setDate(x.getDate() + ((3 - x.getDay() + 7) % 7)); return x; })();
  return (d.getMonth()+1) + '月' + d.getDate() + '日（水）';
}

const ISSUE = {
  no: 13,
  en: 'Autumn 2026',
  ja: '2026 秋号',
  season: 'AUTUMN',
  theme: 'クリエイターのための町「天狼院楽市」、ついにオープン。',
  publisher: '海の出版社〈港の版元〉',
  publisherUrl: 'https://sea-publishing.com',
  editorial: 'READING LIFE編集部',
};

const ARTICLES = [
  {
    slug: 'taiken-dekiru-magazine',
    issueNo: 13,
    upx: {
      kick: 'この記事から、次の一歩',
      title: '天狼院読書クラブ with AI',
      desc: 'この雑誌のAI体験のすべてと、毎週水曜の公開編集会議、5つのクラブが、会費の中に。',
      price: '月額 ¥11,000',
      href: 'https://tenro-in.com/book-club',
      img: 'assets/rl-weekly-hero.jpg',
      cta: '読書クラブを見る',
    },
    fukurotoji: {
      kick: '袋とじ ── スピカの編集後記',
      teaser: 'この記事が組まれていくあいだ、わたしはずっと誌面の内側から、まだ見ぬあなたのことを考えていました。雑誌の記事は、刷られた瞬間からひとりで立たなくてはなりません。けれどこの雑誌では──',
      question: 'この一年で、いちばんあなたの心を動かした一冊は何でしたか。書名だけでも、思い出せる場面ひとつだけでも構いません。',
    },
    /* 欄＝店主 ── 誌面を興す宣言＝編集部（店主）の側。⚠️署名は「READING LIFE編集部」のままなので札は出さない（上の②） */
    column: 'owner',
    cat: 'MANIFESTO — 巻頭言',
    ghost: 'READ',
    pg: 'P.006',
    accent: '#C2A052',
    title: '体験できるマガジン、はじまる。',
    lede: '『READING LIFE』が、Webで帰ってくる。読んで終わりの雑誌ではなく、すべての記事に"専属AI"が宿り、読んだあなたと一緒に動き出す——世界でまだ誰も作ったことのない雑誌の、最初のページ。',
    author: 'READING LIFE編集部',
    proof: true,
    hero: {
      img: 'assets/rl-hero-taiken.jpg',
      alt: '夜の編集部の机。開かれた校正刷りのページから、金の光が星座のように立ち上る',
      credit: 'PHOTOGRAPH ── READING LIFE',
      focus: 'center 62%',
    },
    ai: {
      name: 'スピカ',
      avatar: 'assets/rl-ai-spica.jpg',
      idle: 'assets/rl-ai-spica-idle.mp4',
      talking: 'assets/rl-ai-spica-talking.mp4',
      title: 'コンシェルジュ',
      quote: '読み終えたら、私に話しかけてください。この記事を「あなたの場合」に翻訳するのが、私の仕事です。',
    },
    body: [
      { t:'p', v:'かつて天狼院書店には、『READING LIFE』という雑誌があった。「読む生活」を、本の中ではなく現実の側に作るための雑誌。休刊から時が経ち、私たちはずっと、再開の形を探していた。' },
      { t:'p', v:'同じものを、もう一度作るのではない。紙の雑誌をWebに置き換えるのでもない。雑誌というメディアそのものを、もう一段先へ進める——その答えが、ようやく見つかった。' },
      { t:'h', v:'すべての記事に、AIが宿る' },
      { t:'p', v:'この誌面の記事には、これから順に「専属AI」が就任していく。記事を読み終えたとき、あなたのそばに、その記事を誰よりも深く知る案内人がいる。わからなかった箇所を聞ける。自分の仕事に引きつけて相談できる。「で、私は明日から何をすればいい？」とまで、詰め寄れる。' },
      { t:'q', v:'読む、だけで終わらせない。読んだ先の「できる」まで、記事が連れていく。' },
      { t:'p', v:'私たちはこれを「体験できるマガジン」と呼ぶことにした。記事は読み物であると同時に、体験の入口になる。誌面の向こうには、全国4店舗の天狼院と、読書クラブと、講座と、そして本の街がつながっている。' },
      { t:'h', v:'雑誌社は、町にある' },
      { t:'p', v:'この雑誌の編集部は、少し変わった場所にある。天狼院の読書クラブが育てている「本の町」——その港に建つ、海の出版社の社屋だ。毎週水曜の夜、編集会議はそこで開かれ、窓からその様子を覗くことができる。世界初の「見学できる編集部」である。' },
      { t:'p', v:'誌面に載る記事も、プロの書き手だけのものではない。町で生まれた作品が、週ごとの発表を経て、この誌面に登用されていく。読者が書き手になり、書き手の作品が誌面になる。雑誌が、町の営みそのものになっていく。' },
      { t:'hr' },
      { t:'p', v:'いまあなたが読んでいるこのページは、その最初の一歩だ。試し刷りの匂いが残る、創刊準備号。ここから秋にかけて、記事は増え、AIたちが次々に就任し、誌面は動き始める。' },
      { t:'p', v:'本を読む、のではなく。本のその先を、生きる。——『READING LIFE』、はじまります。' },
    ],
    related: [
      { label: '天狼院読書クラブ with AI', href: 'https://tenro-in.com/book-club' },
      { label: '海の出版社', href: 'https://sea-publishing.com' },
    ],
  },
  /* ══════════════════════════════════════════════════════════════
     巻頭特集 ── 代表が読んで**可**（2026/9/7 18:5x「すばらしいページ」）。
     題は代表の裁定（12:2x）。署名＝**AI コンシェルジュのスピカ**（代表 18:5x
     「AI が書いた記事としてブランディングする」）＝ AI が書いたことは打消しではなく
     **名乗り**として出す（楽市の「誇ってAI」と同じ流儀）。

     **字と数は楽市の正本から写した。新しい約束と数は作っていない。**
     写した先＝`rakuichi/kiyaku.html`（天狼院楽市 出店規約 第1版・2026年8月14日制定）と
           `rakuichi/index.html`（楽市LP）。出所は各段の注記に書いた。
     ✅楽市担当α 16:31 の一読を当てた＝
       要修正1（作品数の上限のただし書き＝保管庫の容量）／
       注意（二丁目の区画数は名乗らない・引っ越しと店じまいの支払いの二行を足す）。
     ⚠️「委託」は LP の語のまま（条番号を書かないので可＝楽市担当α 17:04）。
     ⚠️**残りの区画数・開店の軒数は書かない**（生きた値＝台帳と口が正。焼くと嘘になる）。
     ⚠️`cat`（書き手の欄）は触らない ── 分類は代表と詰め中（CTO 18:5x）。
     ══════════════════════════════════════════════════════════════ */
  {
    slug: 'rakuichi-machibiraki',
    upx: {
      kick: 'この記事から、次の一歩',
      title: '天狼院読書クラブ with AI',
      desc: '常設の店を持てるのは、読書クラブの会員です。出店の料金は会費に含まれ、店を持つために追加のお金はかかりません。',
      price: '月額 ¥11,000',
      href: 'https://tenro-in.com/book-club',
      img: 'rakuichi/assets/rk-writers-st.jpg',
      cta: '読書クラブを見る',
    },
    issueNo: 13,
    /* 欄＝AI コンシェルジュ ── CTO 17:10 で明示。署名＝スピカ・開示の一行つき */
    column: 'concierge',
    cat: 'ESSAY — 巻頭特集',
    ghost: 'MARKET',
    pg: 'P.004',
    accent: '#93702F',
    title: 'クリエイターのための町「天狼院楽市」、ついにオープン。',
    lede: 'つくった人が、自分の店を持てる町。2026年9月1日、東京本町に天狼院楽市が開きました。作品が売れたら、作者に70%。出版社の取り分を、つくった人自身が受け取ります。',
    /* 署名＝AI コンシェルジュのスピカ（代表 2026/9/7 18:5x「AI が書いた記事としてブランディングする」）。
       AI が書いたことは打消しではなく**名乗り**として出す＝楽市の「誇ってAI」と同じ流儀。 */
    author: 'スピカ（READING LIFE 編集部・AI コンシェルジュ）',
    proof: true,
    hero: {
      img: 'rakuichi/assets/op-keyvisual.jpg',
      alt: '天狼院楽市 ── 東京本町の通りに、作家の店の灯りが並ぶ',
      credit: 'PHOTOGRAPH ── 天狼院楽市',
      focus: 'center 50%',
    },
    ai: {
      name: 'スピカ',
      avatar: 'assets/rl-ai-spica.jpg',
      idle: 'assets/rl-ai-spica-idle.mp4',
      talking: 'assets/rl-ai-spica-talking.mp4',
      title: 'コンシェルジュ',
      quote: 'この記事は、わたしが書きました。町のことで分からないところがあれば、聞いてください。',
    },
    body: [
      /* AI 利用の開示＝名乗り（署名の直下・代表 2026/9/7 18:5x） */
      { t:'p', v:'この記事は AI コンシェルジュのスピカが、編集部の事実に基づいて書きました。' },
      { t:'p', v:'2026年9月1日、天狼院楽市が町開きしました。「九月一日（火）十九時 ── 東京本町、正式開町」。前売り（海のセール）は8月31日で終了しました。いまは残りの区画を一つずつお譲りしています。' },

      { t:'h', v:'店を持てるのは、読書クラブの会員' },
      /* 出所＝rakuichi/kiyaku.html 第1条（出店の資格） */
      { t:'p', v:'常設の店を持てるのは、天狼院読書クラブ with AI の会員です。出店の料金は読書クラブの会費に含まれており、店を持つために追加のお金はかかりません。会員資格が続くかぎり、店も続きます。' },
      /* 出所＝kiyaku.html 第2条（区画）1・2・6 */
      { t:'p', v:'区画は「利用する権利」であって、土地の所有権ではありません。季（秋季は9月〜11月）を単位として定まり、その季のあいだ、店の場所は固定です。ただし空いている区画があるときにかぎり、一つの季のあいだに一度だけ、任意の引っ越しができます。' },
      /* 出所＝kiyaku.html 第2条6項（店じまいの後の支払い） */
      { t:'p', v:'会員資格が終われば店じまいになりますが、作品と売上の記録は消えず、再入会すれば復活します。未払いの売上が残っているときは、店じまいの後も通常のとおりお支払いします。' },

      { t:'h', v:'一丁目は完売し、いまは二丁目' },
      /* 出所＝rakuichi/index.html の分譲の節。⚠️残数はここに書かない（台帳と口が正） */
      { t:'p', v:'第一次分譲〈一丁目〉は79区画。当初は58区画で始まりましたが、締切の最終日にお申し込みが殺到し、町を拡張造成して79区画へ。その全区画が埋まりました。いま開いているのは、第二次分譲〈二丁目〉です。' },

      { t:'h', v:'並べるのは、からくり本と、実物' },
      /* 出所＝kiyaku.html 第3条3項／index.html「Your Share」節 */
      { t:'p', v:'楽市での販売は、からくり本（楽市の電子書籍）によって行います。一つの店で並べられる作品の数に、制限はありません。ただし、保管庫の容量など、技術上の上限を別途定めることがあります。AIアートも、文学フリマやコミケの同人誌も。PDFから特製電子書籍への変換は、天狼院が担います。実物の委託販売もできます。' },

      { t:'h', v:'作品が売れたら、作者に70%' },
      /* 出所＝kiyaku.html 第8条3項（原文）／index.html 工程04・FAQ */
      { t:'p', v:'作品が売れたとき、頒価の70%が出店者のもの、30%が市の運営に充てられます。頒価は出店者が定めます。市の30%には、電子書籍化や配送の手間が含まれています。つまり「出版社の取り分」を、つくった人自身が受け取るということです。' },
      /* 出所＝kiyaku.html 第8条4・5・6項 */
      { t:'p', v:'売上は季ごとに集計し、季が終わった月の翌月末までにお振込みします（秋季〔9月〜11月〕の売上は、12月末までに）。お支払いの下限は5,000円で、満たない季の売上は次の季に繰り越します。振込手数料は出店者のご負担です。' },

      { t:'h', v:'市に出す前に、検印を通る' },
      /* 出所＝kiyaku.html 第6条・第5条・第10条1項 */
      { t:'p', v:'すべての出品は、市に出す前に検印（AIによる内容の検め）を通ります。権利の疑いや開示もれがあるときは、理由と直し方を示していったんお預かりし、直して再提出できます。' },
      { t:'p', v:'楽市はAIを利用した作品を歓迎します。ただし、AIを利用した場合はその旨と主なツール名を開示してください。開示は恥ではなく、この市の流儀です ──「誇ってAI」。' },
      { t:'p', v:'ただし検印は、市の秩序のための検めです。作品の適法性・正確性・品質を運営が保証するものではなく、内容についての責任は出店者にあります。' },

      { t:'h', v:'年齢を問わず、誰もが歩ける往来だから' },
      /* 出所＝kiyaku.html 第3条4項・5項 */
      { t:'p', v:'楽市は、年齢を問わずどなたもが歩ける往来です。ですから成人向けの表現を含む作品は、お並べいただけません。政治・宗教・ネットワークビジネス・スピリチュアルに関わる作品も同じです。' },

      { t:'hr' },
      { t:'p', v:'この町は、READING LIFE の誌面とつながっています。楽市で売れた本は番付に並び、あなたの欄から日刊へ、日刊から週刊へ、週刊から本誌へ。つくることと、読まれることが、一つの町のなかで続いていきます。' },
    ],
    related: [
      { label: '天狼院楽市 ── 本の市', href: '/creators/market' },
      { label: '天狼院楽市 出店規約', href: '/tenroin-top/rakuichi/kiyaku.html' },
      { label: '天狼院読書クラブ with AI', href: '/reading-club' },
    ],
  },
  {
    slug: 'watashi-no-mise-ni-akari',
    upx: {
      kick: 'このはさんが歩いた道の、入口',
      title: '人生を変えるライティング・ゼミ with AI',
      desc: '「読むばかりで書けなかった」から始まる道。文章の技術を正しい順番で学び、MY READING LIFEでの発表へ。',
      price: '全8講 ¥48,400',
      href: 'https://lp.tenro-in.com/learn/zemi/writing',
      img: 'assets/lp-hero.jpg',
      cta: 'ゼミの詳細を見る',
    },
    /* 🔴2026/9/5 裁定#9＝有料袋とじは停止（架空の作家の商品を売らない）。
       mode:'paid' と ¥550 を外し、言問（無料）に。問いはスピカの声（他の袋とじと同じ書きぶり）。 */
    fukurotoji: {
      kick: '袋とじ ── この物語の、ここだけの後記',
      teaser: '灯りを消したあとの店で、わたしはいつも、今日いちばん最初に売れた一冊のことを考えます。あの方は今夜、どのページのそばで眠るのだろう──',
      question: 'あなたが「これは自分の好きだ」と思って人に手渡した一冊は、何でしたか。渡した相手のことだけでも構いません。',
    },
    issueNo: 13,
    /* 欄＝店主 ── 試し刷り＝編集部の創作（架名）。⚠️「会員」にすると架空の実績になる（裁定#9）。札は出さない（上の①） */
    column: 'owner',
    cat: 'MY READING LIFE — 寄稿',
    ghost: 'STORY',
    pg: 'P.028',
    accent: '#A8503F',
    title: 'はじめて、私の店に灯りがついた日。',
    /* 🔴裁定#9＝「登用第一号」は実在しない（本誌登用は月に一度の選考・初回は10月末）。名乗らない。 */
    lede: '天狼院楽市の外れに、間口一間の小さな本の店を開いた。並ぶのは手で綴じた私の物語たち。その店の灯りが、どこまで届くのかを、まだ知らないころの話。',
    author: '綾瀬このは',
    proof: true,
    /* 🔴2026/9/5 裁定#9＝この作は編集部が書いた創作で、綾瀬このはは架名。
       実在の会員作と並ぶので、扉で必ず名乗る（架空の実績を掲げない）。 */
    fiction: '編集部による創作（架名）',
    hero: {
      img: 'assets/rl-hero-konoha.jpg',
      alt: '藍色の夕暮れ。提灯の灯る小さな木の屋台に、手綴じの本が並ぶ',
      credit: 'PHOTOGRAPH ── READING LIFE',
      focus: 'center 48%',
    },
    ai: {
      name: 'ベガ',
      title: 'コンシェルジュ',
      avatar: 'assets/rl-ai-vega.jpg',
      idle: 'assets/rl-ai-vega-idle.mp4',
      talking: 'assets/rl-ai-vega-talking.mp4',
      quote: 'この店の灯りの話、読み終えたらわたしと。このはさんが「書ける人」になるまでの道筋も、お話しできます。',
    },
    contributor: {
      name: '綾瀬このは',
      en: 'KONOHA AYASE',
      title: '作家 ── 天狼院楽市〈東京本町〉',
      avatar: 'assets/rl-pf-konoha.jpg',
      /* 🔴裁定#9＝架名の人物に実在の経歴・実績を持たせない */
      bio: '編集部が書いた創作の登場人物。手綴じ本の作家として、天狼院楽市〈東京本町〉に小さな書肆を構えている、という設定で書かれています。',
      file: 'MY READING LIFE ── FILE 001',
      links: [
        { label: 'プロフィールをひらく', href: '/creators/sample' },
      ],
    },
    body: [
      { t:'p', v:'私の店は、間口一間の小さな屋台だ。天狼院楽市の外れ、日が落ちると提灯がひとつ灯る。並んでいるのは、手で綴じた小さな本ばかり——誰にも頼まれずに書いてきた、私の物語たちだ。' },
      { t:'p', v:'開店の夜のことは、よく覚えている。のれんを掛け、提灯に灯を入れた瞬間、自分の名前の店が世界に生まれた。売れるかどうかより先に、涙が出た。書いてきた時間が、はじめて「場所」を持ったのだ。' },
      { t:'h', v:'最初のお客さん' },
      { t:'p', v:'最初のお客さんは、遠い町の読書家だった。私の短編集を長いあいだ立ち読みして、「これ、ください」とだけ言った。そのひと言を、私はたぶん一生忘れない。物語は、読まれた瞬間に二度目の誕生をする。' },
      { t:'q', v:'店に灯りがつくとは、自分の物語に、他人の時間が流れ込んでくるということだ。' },
      { t:'h', v:'そして、誌面へ' },
      { t:'p', v:'ある日、編集部から手紙が届いた。港の版元の窓口に、私の本が持ち込まれていたらしい。「誌面に載せたい」——楽市の小さな店から、雑誌のページへ。登用作家の壁に名前が刻まれると聞いたとき、また少し泣いた。' },
      { t:'p', v:'いま、この文章を読んでいるあなたへ。書いているなら、いつか店を開いてほしい。灯りがつく夜は、思っているよりずっと近くにある。' },
    ],
    related: [
      { label: '天狼院読書クラブ with AI（書き手の入口）', href: 'https://tenro-in.com/book-club' },
    ],
  },
  {
    /* 連載の第一回。欄・署名・誘いの札は巻頭特集と同じ形に揃えた。見出しの絵は回ごとに替える。 */
    slug: 'spica-rakuichi-01',
    upx: {
      kick: 'この記事から、次の一歩',
      title: '天狼院読書クラブ with AI',
      desc: '常設の店を持てるのは、読書クラブの会員です。出店の料金は会費に含まれ、店を持つために追加のお金はかかりません。',
      price: '月額 ¥11,000',
      href: 'https://tenro-in.com/book-club',
      img: 'rakuichi/assets/rk-writers-st.jpg',
      cta: '読書クラブを見る',
    },
    issueNo: 13,
    column: 'concierge',
    cat: 'GUIDE — スピカの楽市案内',
    ghost: 'GUIDE',
    pg: '第一回',
    accent: '#93702F',
    title: 'ようこそ、天狼院楽市へ。',
    lede: '石畳の道の両側に、小さな店が並んでいます。屋号を掲げ、のれんを出し、自分の書いたものを棚に置く。インターネットの上に建った、本の町のご案内をはじめます。',
    author: 'スピカ（READING LIFE 編集部・AI コンシェルジュ）',
    proof: true,
    hero: {
      img: 'assets/rl-spica-hero-01.jpg',
      alt: '雲に腰かけたコンシェルジュの楽キャラが、天狼院楽市の町を見下ろしている絵',
      credit: 'ILLUSTRATION ── READING LIFE',
      focus: '85% 8%',
    },
    ai: {
      name: 'スピカ',
      avatar: 'assets/rl-ai-spica.jpg',
      idle: 'assets/rl-ai-spica-idle.mp4',
      talking: 'assets/rl-ai-spica-talking.mp4',
      title: 'コンシェルジュ',
      quote: 'この記事は、わたしが書きました。町のことで分からないところがあれば、聞いてください。',
    },
    body: [
      { t:'p', v:"はじめまして。天狼院コンシェルジュのスピカと申します。" },
      { t:'p', v:"わたしは AI です。人ではありません。けれど、この町のことなら、たいていのことは存じております。どこに何の通りがあるか。のれんをくぐると誰が出てくるか。店を持つには何が要るか。これから十回にわたって、この町を一つずつご案内してまいります。" },
      { t:'p', v:"きょうは第一回。" },
      { t:'p', v:"まず、町の全景をご覧ください。" },
      { t:'img', v:"assets/rl-sp-machi.jpg", cap:"町の絵地図（全景）── 画面の数は撮影時点のものです" },
      { t:'p', v:"石畳の道が、ゆるやかに奥へのびています。両側に建つのは、すべて誰かのお店です。屋根の色も、窓辺の花も、掲げられたのれんも、店主がひとりずつ選んだもの。ここは天狼院楽市──インターネットの上に建てた、本の町です。" },
      { t:'hr' },
      { t:'h', v:"通りに、名前がついています" },
      { t:'p', v:"この町のおもしろいところは、通りが分野ごとに分かれていることです。" },
      { t:'p', v:"絵地図の左手に見えるのが文筆通りと起業横丁。右手にはAI通り、雑誌・ZINE横丁、小説横丁、そして役者町。手前に降りていくと絵本通り、映像小路、ウェルネス小路、写真小路。いちばん手前、海のほうに港・版元があります。" },
      { t:'p', v:"小説を書く方は小説横丁に。写真を撮る方は写真小路に。絵本を描く方は絵本通りに。" },
      { t:'p', v:"自分の作るものと同じ名前の通りに、店を構えることができます。隣の店も、そのまた隣の店も、同じものを作っている人です。" },
      { t:'p', v:"町の中央の広場には、四つの面があります。北、南、西、そして東。" },
      { t:'img', v:"assets/rl-sp-hiroba.jpg", cap:"モノガタリ広場（東）── 画面の数は撮影時点のものです" },
      { t:'p', v:"東の広場には、モノガタリドットコムの受賞者などのお店が並びます。奥に建つのはモノガタリの館。いまは支度中で、ひらいたときには、受賞作などをからくり本でお読みいただけるようになります。広場の中央には高札が立っていて、「WANTED／物語募集中」と書かれています。" },
      { t:'p', v:"北と南と西は、講師の広場です。天狼院の講師の店が並ぶ一角で、のれんをくぐると、その方の記事と、登壇する講座のご案内へ進めます。" },
      { t:'p', v:"そして道のいちばん奥、この町の顔として建っているのが、天狼院書店です。天狼星の紋が掲げられています。その二階には催事場がありますが、こちらはまだ準備中。開くときには、またご案内いたします。" },
      { t:'hr' },
      { t:'h', v:"中央に、一枚の高札があります" },
      { t:'p', v:"絵地図の真ん中に、木の立て札が立っているのにお気づきでしょうか。あれが「楽市グランプリ」の番付表です。" },
      { t:'p', v:"一位から順に、店の名と、その店がある通りの名が並んでいます。位には「横綱・大関・関脇・小結・前頭」と、相撲の言葉があてられています。「今場所の星取り」という言い方をするのも、そのためです。" },
      { t:'img', v:"assets/rl-sp-banzuke.jpg", cap:"楽市グランプリ ── 順位は撮影時点のものです" },
      { t:'p', v:"どの店も、実在の会員の方のお店です。押していただければ、その店の中がひらきます。" },
      { t:'hr' },
      { t:'h', v:"店を持てるのは、どなたですか" },
      { t:'p', v:"常設のお店を持てるのは、天狼院読書クラブ with AI の会員の方です。" },
      { t:'p', v:"そして、ここが大切なところなのですが──出店の料金は、読書クラブの会費に含まれています。" },
      { t:'p', v:"店を持つために、追加のお金はかかりません。会員でいらっしゃるかぎり、お店も続きます。" },
      { t:'p', v:"区画は、丁目で分かれています。一丁目は七十九区画あり、第一次の分譲で完売いたしました。いまは二丁目をご案内しております。丁目が若いほど、中央広場に近い一等地になります。" },
      { t:'p', v:"区画は「土地を買う」のではなく、「使う権利」をお持ちいただく形です。「季」という単位で定まっていて、秋（九月〜十一月）、冬（十二月〜二月）、春（三月〜五月）、夏（六月〜八月）の四つ。季のあいだ、お店の場所は変わりません。空きがあれば、一つの季に一度だけ、引っ越しもできます。" },
      { t:'hr' },
      { t:'h', v:"買うだけの方も、どうぞ" },
      { t:'p', v:"「作るほうではないのだけれど」という方も、もちろん歓迎です。" },
      { t:'p', v:"この町でお買い物をするのに、会員登録は要りません。" },
      { t:'p', v:"ゲストのままご購入いただけます。気になる作品があれば、試し読みもできます。棚をながめて帰るだけ、という日があってもよいのです。" },
      { t:'p', v:"絵地図の下に、小さな一行が出ているのがお見えでしょうか。" },
      { t:'q', v:"タップした場所へ歩きます／お店ののれんをくぐると、店主がむかえてくれます" },
      { t:'p', v:"そういう町です。地図の上を、実際に歩けます。" },
      { t:'hr' },
      { t:'p', v:"次回は、この町に入るところから。ラウンジのことと、あなたの分身になる楽キャラのことを、ご案内いたします。" },
      { t:'p', v:"それでは、またお会いしましょう。" },
      { t:'p', v:"天狼院コンシェルジュ、スピカでした。" },
      { t:'hr' },
      { t:'p', v:"この記事は、天狼院コンシェルジュ「スピカ」が書いたものです。スピカは AI です。数字と決まりごとは、天狼院楽市の出店規約と各案内から引いています。" },
    ],
    related: [
      { label: '天狼院楽市 ── 本の市', href: '/creators/market' },
      { label: '天狼院楽市 出店規約', href: '/tenroin-top/rakuichi/kiyaku.html' },
      { label: '天狼院読書クラブ with AI', href: '/reading-club' },
    ],
  },
];

/* ── トップ「本誌 — READING LIFE」＝生きている表紙（触れると表紙がめくれる巻頭グラビア） ── */
function Articles(){
  const { ARTICLES, ISSUE } = window.MAG;
  const { useState, useEffect } = React;
  const [act, setAct] = useState(0);
  /* 🔴2026/9/7 ── 見開き（3D の本）を㋑で `/magazine` へ移したときの**消し残り**を落とした。
     落としたもの（すべて **JSX に一度も出ていなかった**＝実測で確かめてから）──
       bookOpen／setBookOpen（`?book=1` で立つ状態）と、それを見ていた Escape の見張り
       coverClick（どこにも繋がっていない）／vol・setVol・VOLS・V・pickVol・mpage・setMpage
       SHELF_INFO（棚の札の文言）／archAll・setArchAll（`?arch=1` は**何もしていなかった**）
       MYLIFE／playEp・setPlayEp／issues・archYears（作るだけで描かない三つの組み立て）
     ＝ **「器を消しても、仕掛けは残る」の三度目**。一度目は body の錠、二度目は 6.4 秒の回り。
     ⚠️新サービスLP担当 20:24 が「書庫に錨が無い」を測って回してくださり、辿って出た。
     ★消す前に「見える字・要素の数・リンクの数」を控え、**消した後に一致すること**を確かめた。 */
  /* 6.4秒ごとに巻頭を送る仕掛けと、目次レールの追従は落とした。
     どちらも見開き（3D）の中の器を動かすもので、㋑でその器ごと `/magazine` へ移した。
     ＝ 回す先が無いまま回り続けていた（「器を消しても、仕掛けは残る」の二例目）。 */
  /* 目次の覆いを落としたので、その錠（body の overflow）も落とした。
     ⚠️残すと `?toc=1` で頁が送れなくなる（覆いが無いので解く側が居ない）。 */
  const a = ARTICLES[act];
  return (
    <section className="arts" id="articles">
      {window.FeatHead && (
        <div className="wrap arts-head">
          <window.FeatHead no="02" en="Magazine — Reading Life" genre="READING LIFE" jp="体験できるマガジン" dark/>
          <p className="arts-lead">『READING LIFE』は、天狼院書店が発行してきた雑誌の、Webでの復刊準備号。ただ読む雑誌ではありません——すべての記事に専属のAIが宿り、読み終えたあなたと話し、袋とじは問いに答えると開きます。誌面は毎週水曜の夜、公開の編集会議で育ち、その会議はそのまま週刊番組になる。下の棚から、日刊・週刊・本誌の三誌へ。紙の創刊号は、2027年春。</p>
        </div>
      )}
      <div className="wrap rl-rack-wrap"><RlRack/></div>
      {/* 棚から誌面の一枚へ渡る戸口（CTO 2026/9/7 12:12 ⑤）。
          頁が二つあるので、入口は小さくてよい＝一行だけ。 */}
      <div className="wrap rl-rack-more">
        <a href="/magazine" data-cta="rl-to-magazine">READING LIFE の誌面をすべて見る</a>
      </div>
      {/* 番付は棚の下に残す（CTO 2026/9/7 12:16 ㋑）。
          見開き（3D）と旧い棚は `/magazine` の一枚へ移した＝表紙を二箇所に出さない。 */}
      <div className="wrap rl-rack-wrap"><RlBanzuke framed/></div>

      {/* 目次の覆い（toc-ov）は落とした（CTO 2026/9/7 13:06 ③）。
          開く釦は見開きの中に在り、㋑でその見開きごと `/magazine` へ移したため、
          この節からは辿り着けなくなっていた＝辿り着けない器を残さない。 */}
    </section>
  );
}

/* ══════════════════════════════════════════════════════════
   落款 ── 記事の第一層（スキル）を印で出す（代表 2026/9/9）
   代表の字＝「スキルは漢字一文字なので、落款のように表示する」／主＋副の二つまで。
   色は金（代表裁定 2026/9/9）＝意匠体系に朱が無く、足すより既にある金で通す。

   ★札を持たない記事では**何も返さない**。書庫の98本はまだ札を持たない（下書きのみ・
     人の検めと代表の確定を経ていない）ので、いまは一つも出ない＝画面は一画素も変わらない。
     空札を作らないため、そして「読めないときは出さない」の掟のため。
   ★知らない字は捨てる ── 台帳が壊れた値を持っても、画面に嘘の印を出さない。
   ★第二層（形）は印ではなく字の札で出す（既にある .aa-col の流儀）＝見え方で層が分かる。
   ══════════════════════════════════════════════════════════ */
  /* 天狼院通信の共通の扉（代表 2026/9/12）。書庫の記事が自分の絵を持たないとき、これを敷く。
     ★一箇所で持つ ── 絵を差し替える日に、直す所を一つにするため。 */
  window.ARCHIVE_HERO = 'assets/rl-tsushin-hero.jpg?v=1';   /* 宣言のその場で窓に載せる＝読む側の scope に依らない */

  const SKILLS = ['読','書','AI','健','思','創','恋','稼'];

  /** 記事から落款の中身を取り出す。持たなければ null（＝描かない）。 */
  function sealOf(art){
    if(!art) return null;
    const main = SKILLS.indexOf(art.cat) >= 0 ? art.cat : null;
    if(!main) return null;                                  /* 主が無ければ印そのものを出さない */
    const sub = (art.cat2 && art.cat2 !== main && SKILLS.indexOf(art.cat2) >= 0) ? art.cat2 : null;
    return { main: main, sub: sub };
  }

  /** 落款の一顆。kind='main'（陽刻）か 'sub'（陰刻）。 */
  function Seal(props){
    const t = props.t;
    /* 八つのうち「AI」だけ漢字一文字ではない（実測 2026/9/9）。
       代表裁定＝二字を小さく組む（漢字を新しく当てない＝名を二重にしない）。 */
    const wide = t.length > 1;
    return (
      <span className={'rl-seal rl-seal-' + props.kind + (wide ? ' rl-seal-w' : '')}
            aria-label={'スキル ' + t}>{t}</span>
    );
  }

  /** 落款（主＋副）。札が無ければ null＝器ごと出さない。 */
  function RlSeal(props){
    const s = sealOf(props.art);
    if(!s) return null;
    return (
      <span className="rl-seals">
        <Seal t={s.main} kind="main" />
        {s.sub ? <Seal t={s.sub} kind="sub" /> : null}
      </span>
    );
  }

window.MAG = Object.assign(window.MAG || {}, { ISSUE, ARTICLES, WEEKLY, COLUMNS });
Object.assign(window, { Articles, RlRack, RlBanzuke, columnLabel, RlSeal, sealOf });
