コンテンツにスキップ

内部通報制度をめぐる裁判記録

「ENEOSの内部通報制度をめぐる訴訟について」は、裁判文書(準備書面・判決文・証拠のPDF)と、株主総会での質疑応答を公開しているサイトです。静的サイトジェネレーターの Zensical(Material for MkDocs の後継)で作り、GitHub Pages で公開しています。サーバーもデータベースもありません。

このページは、Zensical の標準機能ではない部分、独自に工夫した部分の解説です。デザインの考え方と4サイト共通の仕組みは、ウェブサイトデザインにまとめています。末尾の「デザインシステム」の節は、このサイトの部品と値の詳細です。

全体の構成

docs/
  index.md, agm/, trial2021/, trial2024/, pdf/, about/, styleguide/   ページ(フォルダ/index.md 形式)
  trial2024/md/*.md.txt        書面の本文(1書面1ファイル)
  trial2024/.parts/*.md.txt    取り込み専用の部品(公開しない)
  pdf/                         裁判文書のPDF(ファイル名に区分・日付・書面名)
  css/                         01-color … 14-doc-accordion(番号順)
  js/                          custom.js・doc-accordion.js・lightbox.js・qa-carousel.js
  vendor/glightbox/            画像拡大(同梱)
overrides/
  main.html                    <title>・OGP・転送ページの出し分け
  partials/                    tabs-item・header・toc・copyright(テーマの部品の上書き)
scripts/
  add_pdf.py, pdf_tools.py     PDFの命名・軽量化・OCR文字層
  pdf_index.py                 PDF一覧ページの自動生成
  wait_deploy.ps1, indexnow_ping.ps1
deploy.bat                     ビルド確認 → push → 公開の完了待ち → 検索エンジンへ通知
.github/workflows/pages.yml    GitHub Actions でビルドして Pages へ公開

ページは Markdown ですが、裁判文書のページはHTMLを多く直接書いています。段落ごとの字下げ・ぶら下げ・サイドノートといった、裁判文書の体裁が Markdown では表せないためです。

Zensical だけでは足りなかったところ

Zensical は MkDocs/Material と互換を目指していますが、2026年9月時点(0.0.63)では、MkDocs のプラグインも Python フックも読みません。そのため、「プラグインやフックでやる」ことを最初から捨て、ソースへの焼き込みと、ページ内のJS/CSS で置き換えました。結果として、同じソースを Zensical でも MkDocs(予備)でもビルドでき、記事本文は全要素が一致することを確かめています。

やりたいこと 当初の手段 今の手段
裁判文書ページだけ体裁を変える フックで body.trial-doc を付ける 各ページ先頭の目印 <div class="trial-doc-marker" hidden> + CSSの body:has(.trial-doc-marker)
字下げのマーカー(:2h#id: など) フックで変換 本文ファイルに <p class="pad2 hg-idt"> として焼き込み済み
本文の取り込み(:include:) フック 標準拡張 pymdownx.snippets の --8<-- "パス"
画像クリックで拡大 mkdocs-glightbox GLightbox を docs/vendor/ に同梱し、lightbox.js が <img> を <a class="glightbox"> で包む
カルーセル用の Swiper フックが特定ページに注入 そのページの md に <link>・<script> を直接書く

:has() を使うのは、「このページだけ」をCSSで見分ける手段が他になかったためです。ブラウザの対応は広く、使えない場合は裁判文書の体裁が当たらないだけで、本文は読めます。

1. 提訴年ごとのタブのドロップダウン

Zensical の既定のタブ部品は、子ページが複数あっても最初の1件だけをリンクにして、残りをタブバーから消します。「裁判文書公開」の下に「2024年提訴」「2021年提訴」を並べたかったので、overrides/partials/tabs-item.html を上書きし、子が2件以上のときだけドロップダウンを描く分岐を足しました。

開閉は、独自のJSではなく、HTML標準の <details>/<summary> にしています。最初は独自のクリック処理で作りましたが、開発機のブラウザでは動いても、利用者の実機の Chrome では反応しないことがあり、原因を特定できませんでした。ブラウザが開閉を担う標準の部品に切り替えると、JSが効かなくても「開く」「ページに移動する」という核心の動作は保たれます。custom.js が補うのは、他のドロップダウンを閉じる、外側のクリックで閉じる、の2点だけです。

学んだこと:スマホ(タップ)では :hover が使えず、overflow-x: auto と overflow-y: visible は仕様上共存できません。ホバーやスクロールコンテナの中に出すメニューは、標準の開閉部品に任せる方が確実でした。

2. 目次・検索・ハンバーガーを出さない

  • 目次:partials/toc.html を空にしました。右のサイドバーとスマホのメニューの両方がこの部品を使うので、1か所で両方から消えます。右の余白は、サイドノートに使うためです
  • 検索:MkDocs は plugins を書かないと検索が自動で有効になるので、plugins: [] と明示しています(Zensical はプラグインを無視します)。ヘッダーの部品も上書きしました
  • ハンバーガー:全ページが hide: navigation なので、押しても何も開きません。ボタンごと削除し、タブを実質のナビゲーションにしました

3. 書面のアコーディオン(doc-accordion.js)

書面は、1行1書面の <details class="doc-acc"> に置きます。本文はビルド時にHTMLへ入るので、検索エンジン・ページ内検索・Xのカードにそのまま出ます(JSで後から読み込む方式にしていません)。JSが足すのは、行のボタンと動きです。

<details class="doc-acc" id="kouso" data-md="md/kouso.md.txt"
         data-pdf="../pdf/…pdf" data-summary="…" markdown>
<summary>控訴理由書</summary>
<div class="doc-body" markdown>


</div>
</details>
  • .pdf ボタン:data-pdf があれば有効、無ければグレー
  • .md ボタン(コピー/ダウンロード):data-md の生ファイルを fetch します。.md.txt という拡張子なのは、ビルダーが独立したページにしてしまわないためで、そのまま静的ファイルとして公開されます。旧形式の本文(:N X#id: マーカー、またはそれを焼き込んだ <p class="padN">)は、平文の Markdown に戻して渡します。タグを外す正規表現は、属性値の中の > で途切れないよう、引用符の中を丸ごと読む形にしています
  • 要約ボタン:data-summary があれば <dialog> で表示します。AIの要約には、data-summary-model と日付で出所を表示します
  • アンカー:#書面のid、または書面の中の <a name> で開いたとき、閉じている書面を開いてその位置へ移動します。Web フォントの読み込み後に高さが変わって固定ヘッダーの下へずれる問題があるため、読み込み完了後にもう一度だけ位置を取り直します(読み手がスクロールし始めていたら取り直しません)
  • サイドノート:段落の直後に置いた <aside> を、対応する注番号 <sup>N</sup> の直後へ移します。float: right の注は「置かれた位置の高さ」で右の余白に出るので、段落の後ろに置いたままだと次の段落の高さに出てしまうためです

4. サイドノート(相手方の書面での認否)

本文の横に、相手方の書面での認否を並べます。本文の列(32〜40rem)の外側、目次を出さないことで空いた右の余白に、float: right と負のマージン(Tufte CSSの手法)で追い出して置きます。スマホなどの狭い画面(76.1875em 以下)では出しません。本文の外に置く構成のため、狭い画面では置き場がないからです。

本文は、別のツール(サイドノート作成)で作り、「ウェブ用」の書き出し(段落の直後の <aside class="sn-note">)をそのまま貼ります。

5. PDFの命名と一覧ページの自動生成

PDFは scripts/add_pdf.py で docs/pdf/ に入れます。

  • ファイル名とPDFのタイトルを同じにする:ENEOS(エネオス)の内部通報制度をめぐる訴訟について――ENEOS側_2024年04月15日_答弁書.pdf(区分・日付または証拠番号・書面名)。検索結果に出るタイトルはPDFのメタデータが使われるので、ファイル名と同じ値を入れています
  • --shrink:画像だけの白黒PDFを A4・200dpi・1bit に作り直します。38MB の判決文が 1.4MB になります。色付きのページは、画質を落とさないよう断ります
  • --ocr:文字情報の無いPDFに、透明な文字層を重ねます(スキャン墨消しのOCRを呼び出し)。画像には触らないので、見た目は変わらず、検索とコピーができるようになります
  • 一覧ページ:scripts/pdf_index.py が、ファイル名から区分・日付・書面名を読み取り、ページ数とサイズを調べて、docs/pdf/index.md を静的なリンクの一覧として作ります。JSを使わずHTMLにリンクが入るので、検索エンジンがPDFを見つけやすくなります。書面の行(data-pdf)があるPDFには「本文」のリンクも付きます

6. 公開しないファイルの置き場所

書面の取り込み用の部品は、docs/trial2024/.parts/ に置いています。docs/ の中の普通のフォルダだと、静的ファイルとして site/ にそのままコピーされ、生の部品が誰でもダウンロードできてしまうためです。exclude_docs は Zensical が読まないので、フォルダ名を「.」始まりにすることで、Zensical と MkDocs のどちらでもコピーされないようにしました。--8<-- の取り込みはファイルを直接読むので、「.」始まりでも動きます。

7. 転送ページとSEO

  • <title> と見出しを分ける:front matter の seo_title がそのまま <title> になります(検索語を先頭に置く)。title はヘッダーの表示と og:title 用です(overrides/main.html)
  • 転送ページ:GitHub Pages ではサーバー側の301が使えないので、front matter の redirect_to から、meta refresh とJSで転送します。JS側は location.hash を引き継ぐので、旧URLのアンカー付きの共有リンクも、正しい書面が開いた状態の新URLに着地します。転送ページには noindex を付けます
  • robots: noindex, nofollow:見本帳などを検索結果に出さないための指定です
  • Googlebot はHTMLの先頭 2MB まで読むので、裁判文書ページの大きさ(約860KB)を記録し、2MB に近づいたらページを分けるルールにしています

8. 公開の自動化

deploy.bat は、①ビルドして失敗なら止める、②コミットして push(失敗したら最大3回、2回目からは HTTP/1.1)、③GitHub Actions の完了を待つ、④検索エンジンへ通知(IndexNow)の順です。

  • wait_deploy.ps1:GitHub Pages は、最後のステップで止まることがあります。240秒たっても終わらなければ、実行を取り消して1回だけ自動で再実行します。その間、サイトは前の版のまま公開されています。終了コードは、成功が0、失敗が1、再実行しても終わらないが2、確認できなかった(gh 未導入・未ログインなど)が3です。確認できなかったときは、IndexNow を送りません
  • IndexNow:ビルドで作ったサイトマップの全URLを、Bing などへ1回のリクエストで通知します。キーのファイルは /hotline/ の下にあるので、keyLocation の指定が要ります
  • Actions の環境は固定:Python のパッケージは全部バージョンを固定(pip freeze)し、ubuntu-latest の代わりに ubuntu-24.04 を指定しています。手元で確かめたビルドと、公開のビルドを同じにするためです

見つかった課題

  • docs/trial2024/index.md は、書面を増やすとHTMLが大きくなります。2MB に近づいたらページを分ける必要があります
  • 非公開にした提訴年のページは docs/.trial2026/ にあります。公開に戻すときは docs/trial2026/ へ戻します。戻し忘れると、PDF一覧の「本文」リンクだけが黙って抜けます
  • Zensical は新しく、仕様が変わる可能性があります。そのため requirements-mkdocs.txt に、MkDocs + Material でビルドする予備の手順を残しています。ただし Material for MkDocs は2026年11月に保守が終わります
  • **強調** が全角の句読点・括弧に隣接すると、Zensical では強調にならないことがあります。そういう箇所は <strong> と書いています

デザインシステム

サイトの見た目は、docs/css/ の番号つきのCSS(01-color → 14-doc-accordion)に分けて置いています。部品の一覧と使い方は、リポジトリの DESIGN_SYSTEM.md を正本とし、全部品を実物と同じマークアップで並べた見本帳(styleguide/)で、変更後に見た目を一画面で確認します。

方針

  • 罫線より、余白・背景色の差・影で区切る
  • 見出しは太字でなく、サイズや色のバーで立てる。太さは常に300〜400
  • 装飾は無彩色寄り。青(メイン)と、赤(警告)以外の色はほとんど使わない。ENEOSのブランド色の橙は、ロゴ文字だけに使う特別色
  • ライト/ダークの両方で読めることを、色を決める条件にする

色(01-color.css)

実際に使う色だけを定義します。使っていない色は削除しました(値のメモは別に退避)。ライトとダークで、同じ名前のトークンに別の値を入れます。

トークン 役割
--md-link-color メインの青。リンク・強調・「裁判所の判断」のラベル。ダークは明るい青(#4D8BCC)
--md-warn-red 警告の赤。告発性の核心事実・警告ラベル
--red-color-3 サイドノートの強調の赤。ダークでは --md-warn-red と同じ値に寄せる(旧値は暗い背景でコントラストが約2.9:1と不足したため)
--surface-gray 面の背景(タイトル帯・アコーディオン・カード共通)。ヘッダーより一段薄い、青みのあるグレー
--md-card-border / -soft 罫線が要る場面だけの、無彩色の線
--orange-color-1 ENEOSのブランド色の橙(ロゴ文字だけ)

色つきの強調は、色をクラス(.text-warn・.text-main)、太さをタグ(<b>)に分けて持たせます。style="color: …" を本文に書きません。

文字

  • 本文16px。見出しは h1 2.4rem、h2 と .larger が 1.6rem、.large が 1.28rem
  • 裁判文書の体裁(.doc 系)は、明朝体・行間2.4・16px固定。字下げの .idt、ぶら下げの .hg-idt(2・3 で深くなる)、左余白だけの .pad1〜.pad9
  • 本文の幅は、.width-40(max-width: 32rem、約40字)

余白

余白は、倍々のスケール(1 → 2 → 4 → 8rem、その間に6rem)から選びます。新しい値(3.3rem など)は足しません。

値 使いどころ
1rem 段落内の細かい区切り
2rem 標準的な段落間
4rem セクション内の区切り(番号つき項目の並びなど)
6rem セクション間(.gap-6)
8rem 本文 h2 の上など、ページ内で最大の区切り

スマホ(767px以下)では、6remと8remを3remに圧縮します。機械的に半分にするのではなく、部品ごとに実測して決めました。フォントサイズが変わる入れ子(アコーディオンの中)は em、ページの骨格は rem と使い分けます。

縦余白の単一所有の原則

縦の余白は、「下の要素」が margin-top だけで持つ。margin-bottom は使わない。

かつては、flex の gap とマージンが足し算になり、「目標の余白 − 直前の margin-bottom − gap」という calc の補正が連鎖していました。サイトで最も壊れやすい箇所でした。余白の持ち主を1つに決めることで、補正の calc と、モバイル専用の例外を全部なくしました。枠の中に段落を足すときは、.margin02・.margin04 を付けるだけで、前後の組み合わせを確認しなくて済みます。リファクタの前後で、PC・スマホの全セクションの間隔をブラウザで実測し、ピクセル単位で同じであることを確かめました。

部品

部品 役割
.bar-title 行頭の青いバーで立てる見出し(罫線を使わない見出しの標準形)
.sec-title / .issue-point 中央寄せの節見出し/小見出し
.hero-band ページ冒頭の帯。3つの裁判文書ページで文言をそろえている
.doc-acc 書面1行のアコーディオン。FAQ型(細い罫線・右端に開閉マーク)
.dbtn .pdf / .md / 要約のボタン。角丸のピル。無いものはグレー
.sn-note / .sidenote 右の余白のサイドノート。.strong-rd で赤の強調、.sn-badge でバッジ
.card-blue・.toc-card 面の背景(--surface-gray)のカード。ホバーは線でなく影で浮かせる
.x-share Xでシェア。リンクと同じ「アクションの色」の青
.qa-carousel 質問パネルのカルーセル(Swiper)。幅は56remまで

守っている約束

  • 「本文より広い」部品を足すときは、既存の部品が自己センタリングしているか確認する。.width-40 は max-width だけで、中央寄せを「親がたまたま32remだった」ことに頼っていました。幅の広いカルーセルを同じ親に置いたら、親が広がり、本文だけが左に取り残されました。margin-inline: auto を足して直しています。カルーセルは、本文の無名ラッパー(中身の最大幅で決まる)の外に置く必要がありました
  • Material の既定の見た目を打ち消すときは、詳細度に注意する。details.doc-acc の border: none が、最後の行の閉じの罫線に勝ってしまうため、詳細度を上げて出しています。summary の overflow: hidden も、.md のメニューを行の高さで切ってしまうので、visible に戻しています
  • 見本帳は検索結果に出さない(robots: noindex, nofollow)。専用のスタイルはページ内に閉じ込め、共通CSSに足しません
  • 一覧にある部品の一部は、今は公開していないページにだけあった記録として、DESIGN_SYSTEM.md に履歴として残しています。現在のページに当てはまる記述だけが有効です