/* VPN LIFE — 公開サイト
 *
 * 参照した実測値
 *   北欧、暮らしの道具店 — 測度518px / 本文16px・行間1.75 / 本文色#444 / 段落間32px
 *   ASCII.jp            — 測度592px / 本文16px → 全角37字/行
 *   サイボウズ式         — 測度455px / 本文14px → 全角32.5字/行
 *   （2026-08-26 / 08-27 に実サイトから採寸）
 *
 * ── コンテンツ幅は1本だけ（2026-08-27 改訂）────────────────
 *   従来は 本文620px / 図版・表・チャート860px の2本立てだった。
 *   スクロールすると右端が 792px と 1032px を行き来して落ち着かない。
 *   本文・図版・表・チャートをすべて --measure に揃え、
 *   .wrap 自体を「--measure + 左右パディング」に縮めて中央に置く。
 *   結果、ページ上のすべての要素が同じ左端・同じ右端に並ぶ。
 *
 *   720px にした根拠（2026-08-27 palt を外して測り直し）
 *     - 日本語PC本文の推奨行長は全角35〜45字（アクセシビリティ指針は40字以内）
 *     - 本文17px + letter-spacing .02em → 1字あたり実測17.26px
 *       720 / 17.26 = 全角41.7字。実ページの1行目の実測は40〜45字
 *       （palt を使っていた時は1字15.73pxで45.8字。8%だけ「詰めて」多く入れていた）
 *     - 日本語の長文を読ませるサイト13本の実測のうち、本文幅を
 *       指定している11本（青空文庫64.4字・はてなブログ77.2字は幅未指定なので除外）は
 *       PC 34.6〜49.7字・中央値39.5字。41.7字は中央値のすぐ上で範囲内
 *       （palt を使っていた45.8字は上から3番目に長かった）
 *     - SPは同じ11本で 18.5〜23.8字・中央値21.5字。うちは20.0字で範囲内
 *     - render.py が出力する表の min-width は最大720px。
 *       720px にすると、PCでは全部の表が横スクロールなしで収まる。
 *       この制約があるので --measure は下げない
 *
 * ── そのほか決めたこと ──
 *   - 本文は真っ黒にしない。長時間読むと黒はコントラストが強すぎて疲れる
 *   - 階層は「文字サイズ」ではなく「余白」で作る。見出しを大きくしすぎない
 *   - 囲みは減らす。連続させない。強調が続くと、どれも強調でなくなる
 *   - 罫線は2段階持つ。構造を示す線(--rule)と、行を分けるだけの線(--rule-soft)
 */

:root{
  /* 地は純白にしない。わずかに温度を持たせて長時間読める明度にする */
  --paper:#FCFBF9;
  --card:#FFFFFF;
  --sunk:#F5F4F1;
  /* ── 面を3段にする（2026-08-28 新設）──────────────────────
     旧: ヘッダ・本文・フッタが3つとも --paper で、境目は1pxの線だけだった。
     実測でも header の background と body の background が同一値で、
     影も透過ぼかしも無い。ページが「3つの面」ではなく「1枚の紙」に見える。
     器（chrome）と中身（content）を背景で分ける。
       ライト --shell #FFFFFF（上）／--paper #FCFBF9（中）／--footer-bg #F4F2EE（下）
       ダーク --shell #1E2122（上）／--paper #17191A（中）／--footer-bg #121415（下）
     境界線は既存の --rule のまま。本文の地は1文字も変えない。 */
  /* 2026-08-28 夜 改訂: --shell は #FFFFFF だった。
     地 #FCFBF9 との比が 1.03:1 しかなく、実質フラットで、
     1pxの線と極薄い影だけで面を持たせていた（ダークは 1.09:1 で解けていた）。
     #F2F0EB にして 1.09:1 まで離す。 */
  --shell:#F2F0EB;
  /* 2026-08-28 夜 再改訂: フッタは --shell と同じ面にする。
     「ヘッダとフッタ＝器の面／本文＝紙の面」で上下が対になる。
     旧 #F4F2EE は body 比 1.08:1 で、器としても紙としても中途半端だった。 */
  --footer-bg:#F2F0EB;
  --foot-ink:#575D5F;     /* フッタの文字。対 --footer-bg 約6.1:1 */
  --shell-line:#E6E5E1;
  --shell-shadow:0 6px 16px -14px rgba(0,0,0,.18);
  /* アクセントの面に乗せる文字。ここをトークンにしないと
     ライトで #08211D が出てしまう（この CSS の
     `:root:not([data-theme="light"])` はメディアクエリの外にあるので
     ライトでも当たる）。ライト 白 対 #136F63 6.03:1／
     ダーク #08211D 対 #6BBFB0 7.79:1。 */
  --on-accent:#FFFFFF;
  --ink:#373C3E;          /* 本文。真っ黒(#000)は日本語長文だと目が疲れる */
  --ink-strong:#1E2224;   /* 見出しと強調 */
  /* 補助テキストは薄くしすぎない。
     旧 --faint(#9AA0A2) は地に対して 2.5:1 しかなく、
     出典・キャプション・パンくずが読めていなかった。3.9:1 まで上げる。
     （柔らかさは色を薄くして作らない。余白と行間で作る） */
  --muted:#62696B;        /* 対 paper 5.4:1 */
  /* --faint は 2026-08-27（見出し改訂）で #797F81 → #6E7476。
     旧値は対 paper 3.93:1 で、WCAG AA の小文字基準4.5:1に届いていなかった。
     この色は figcaption・.tblnote・.src・.crumbs・.stamp・.na に使われていて、
     全部12〜12.5pxの小さい文字なので、いちばん基準を満たすべき場所だった。
     新値は 4.59:1（ダークは #7E8587 で 4.70:1）。
     .mk-2 の輪郭・.mk-eq の塗りにも使っているが、こちらは上げる分には安全側。 */
  --faint:#6E7476;        /* 対 paper 4.6:1 */
  --rule:#E6E5E1;         /* 構造の線。外枠・セクション区切り */
  --rule-soft:#EFEEEA;    /* 行を分けるだけの線。表の行間など */
  --rule-strong:#CBCCC7;

  --accent:#136F63;       /* 深緑。計測・確認済みを表す */
  --accent-soft:#EBF3F0;
  --accent-ink:#0B4A42;

  /* ── 塗りの2段（2026-08-27 新設 / 08-27 夜 改訂）──────────
     ページの中で「面」を持てるのは h2 と表ヘッダの2つだけ。
     実測（下の「見出しの階層」参照）で、競合4本ともこの2つを塗っている。
     地に対する強さを band > thead の順で固定する。
       ライト --band 対 paper 9.80:1（ΔL* 70.9）／ --thead 5.83:1（ΔL* 56.8）
       ダーク --band 対 paper 5.80:1（ΔL* 52.7）／ --thead 3.03:1（ΔL* 34.2）
     ダーク側は下の @media を参照。旧値は 2.42 / 1.91 で、
     ライトの4分の1しか離れていなかった（オーナー指摘「見にくい」の正体）。 */
  --band:#0B4A42;      --band-ink:#FFFFFF;    /* 白抜き 10.1:1 */
  --thead:#136F63;     --thead-ink:#FFFFFF;   /* 白抜き  6.0:1 */

  /* 見出しの装飾だけを本文の左端より外へ出す量。
     帯・縦線はここぶんだけ外に張り出し、見出しの「文字」は
     本文とまったく同じ左端に残る（.wrap の padding は最小20pxなので溢れない）。 */
  --hb:16px;
  --alert:#A4362C;        /* 不可・警告 */
  --alert-soft:#FBEFED;
  --alert-ink:#7A251D;
  --note:#8A6410;
  --note-soft:#FBF4E4;
  --note-ink:#6E4E0B;      /* 対 paper 6.8:1。「計測中」など、注意色の“文字”用 */

  /* サイト全体でただ1つのコンテンツ幅。ここを変えると全要素が一緒に動く */
  --measure:720px;
  --pad:clamp(20px,5vw,32px);

  --radius:10px;          /* 角は少し丸く。硬さを抜く */
  --radius-sm:6px;
}

/* ── ダークの面（2026-08-27 夜 改訂）──────────────────────
   旧値は「地より少し明るい緑の面 ＋ 白抜き」だった。実測すると

                   ライト        ダーク（旧）
     h2 の帯 対 地   9.80:1        2.42:1     ← ライトの4分の1
     表ヘッダ 対 地   5.83:1        1.91:1     ← ライトの3分の1

   ライトで作った序列が、ダークではほぼ平らになっていた。
   オーナーが「まだ見にくい」と言って送ってきたのはダークの画面だった。

   なぜこうなったのか（原因）
     ライトの地は #FCFBF9（L* 98.6）で、明度スケールのいちばん端にある。
     だから「濃い面」は地からも白い文字からも同時に遠ざかれる。
       面 #0B4A42 は L* 27.7。地との差 ΔL* 70.9、白文字との差 ΔL* 71。両方大きい。
     ダークの地は #17191A（L* 8.6）で、これも端にある。
     ここで面を「地より少し明るい緑」にすると、面は地に近いまま
     白い文字だけが遠くにある、という片側だけの設計になる。
       旧 #256054 は L* 36.7。地との差 ΔL* 28.2 しかない（ライトの40%）。

   決めたこと: **ダークでは面と文字の役割を入れ替える。**
     h2 の帯 = 地より明るい緑の面 ＋ **濃い文字**（白抜きをやめる）
     ライトが「濃い面＋白い字」なら、ダークは「明るい面＋濃い字」。
     こうすると面は地から離れられて、文字も面から離れられる。

     --band  #43A394  L* 61.2  地との差 ΔL* 52.7（ライトの74%）対 地 5.80:1
       文字 #08211D（ライトの帯の色と同系のいちばん濃い緑）で 5.54:1
     --thead #2C7064  L* 42.8  地との差 ΔL* 34.2（ライトの60%）対 地 3.03:1
       ここは白抜きのまま。文字 #F2F5F4 で 5.30:1
       表ヘッダまで明るい面にすると h2 と見分けが付かなくなるので、
       「明るい面＋濃い字（h2）」と「中くらいの面＋白い字（表ヘッダ）」で
       塗り方の種類ごと分ける。ライトの 9.80 : 5.83 と同じ順序が
       ダークでも 5.80 : 3.03 で保たれる（比は 1.68倍 対 1.91倍）。
     どちらも「面 対 地 3:1」（非テキストの最低基準）を初めて満たす。
     旧値は 2.42 / 1.91 で、2つとも満たしていなかった。 */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --paper:#17191A; --card:#1D2123; --sunk:#222628;
    /* 旧 --shell #1E2122 は 対 地 1.09:1。#232729 で 1.17:1。
       フッタは #121415 → #0E1011 と暗くする案だったが、
       #17191A の下には余地がなく 1.08:1 までしか離れなかった。
       方向を変えて --shell と同じ面まで **上げる**（1.17:1）。
       地が明るくなるぶん、文字も #9AA1A3 → #A8AFB1 に上げる。 */
    --shell:#232729; --footer-bg:#232729; --shell-line:#33393B;
    --shell-shadow:0 6px 16px -12px rgba(0,0,0,.55);
    --on-accent:#08211D; --foot-ink:#A8AFB1;
    --ink:#CFD4D5; --ink-strong:#EDEFEF; --muted:#9AA1A3; --faint:#7E8587;
    --rule:#2F3436; --rule-soft:#272B2D; --rule-strong:#3D4346;
    /* accent-soft は h3 の面をやめたので、残る用途（.callout.info・.b-ok・
       .site-link:hover）だけを見て決め直した。1.25 → 1.55（対 地）。
       .b-ok の文字(--accent-ink #9FD8CC)は 8.82 → 7.12 に下がるが基準内。 */
    --accent:#6BBFB0; --accent-soft:#1E403A; --accent-ink:#9FD8CC;
    --alert:#E39289; --alert-soft:#332019; --alert-ink:#F0B5AC;
    --note:#D6B36B; --note-soft:#2C2517; --note-ink:#E2C689;
    --band:#43A394; --band-ink:#08211D;    /* 面の文字 5.5:1 ／ 面 対 地 5.80:1 */
    --thead:#2C7064; --thead-ink:#F2F5F4;  /* 面の文字 5.3:1 ／ 面 対 地 3.03:1 */
  }
}
:root[data-theme="dark"]{
  --paper:#17191A; --card:#1D2123; --sunk:#222628;
  --shell:#232729; --footer-bg:#232729; --shell-line:#33393B;
  --shell-shadow:0 6px 16px -12px rgba(0,0,0,.55);
  --on-accent:#08211D; --foot-ink:#A8AFB1;
  --ink:#CFD4D5; --ink-strong:#EDEFEF; --muted:#9AA1A3; --faint:#7E8587;
  --rule:#2F3436; --rule-soft:#272B2D; --rule-strong:#3D4346;
  --accent:#6BBFB0; --accent-soft:#1E403A; --accent-ink:#9FD8CC;
  --alert:#E39289; --alert-soft:#332019; --alert-ink:#F0B5AC;
  --note:#D6B36B; --note-soft:#2C2517; --note-ink:#E2C689;
  --band:#43A394; --band-ink:#08211D;
  --thead:#2C7064; --thead-ink:#F2F5F4;
}

*{box-sizing:border-box;margin:0;}
/* ── アンカーの着地位置（2026-08-28 改訂）──────────────────
   旧: html{scroll-padding-top:72px} だけで、見出し側の scroll-margin-top は 0。
   実測すると 72px は効いていて、55pxのヘッダの下には潜っていなかった
   （目次から飛んだ直後の h2 の top は 3本とも 72px）。
   ただしヘッダを 64px に上げるので 72px では余裕が8pxしか残らない。
   ここで h2[id] に scroll-margin-top を足すと 72 + 76 = 148px と二重に効いてしまう。
   （scroll-padding は器側、scroll-margin は着地側で、両方が加算される）
   なので **効かせる場所を1つに寄せる**。html 側を 0 にして、
   ページ内リンクの行き先である見出しにだけ scroll-margin-top を持たせる。
   build/site のページ内リンクは #top（body）と h2[id] の2種類しかないので
   （実測: href="#..." の全件が h2 の id か #top）、取りこぼしは無い。 */
html{scroll-behavior:smooth;scroll-padding-top:0;-webkit-text-size-adjust:100%;}
h2[id],h3[id],h4[id]{scroll-margin-top:80px;}   /* ヘッダ65px + 余白15px */
/* 641〜699px はナビが2段に折り返してヘッダが 65px → 91px になる。
   80px のままだと 11px 潜るので、この幅だけ 91+15=106px にする。
   （実測: 641px 91px ／ 660px 91px ／ 690px 91px ／ 700px 65px） */
@media (min-width:641px) and (max-width:699px){
  h2[id],h3[id],h4[id]{scroll-margin-top:106px;}
}
body{
  background:var(--paper);
  color:var(--ink);
  font-family:"Noto Sans JP",-apple-system,BlinkMacSystemFont,"Hiragino Kaku Gothic ProN",
              "Yu Gothic Medium","游ゴシック Medium",sans-serif;
  font-size:17px;
  /* 行間は触らない。下に挙げた13本の実測で line-height は
     1.50〜2.00・中央値1.75（PC）。1.95 より上は note.com の 2.00 だけで、
     13本中12本より広い。段落の間も margin-bottom 30px ÷ 行送り33.15px＝0.90行分で、
     計測できた7本（0.33 / 0.57 / 0.67 / 0.83 / 1.00 / 1.25 / 1.29）の中央値0.83を上回る。
     「詰まって見える」の原因は縦ではなく横だったので、縦は動かさない。
     両方いじると、どちらが効いたのか次に分からなくなる。 */
  line-height:1.95;
  /* ── 本文から palt を外す（2026-08-27 改訂）────────────────
     旧: font-feature-settings:"palt" 1 + letter-spacing:.015em
     旧コメントは「palt で約物を詰め、その分を letter-spacing で全体に返す」
     と書いていたが、返せていなかった。実測（本文17px / Noto Sans JP）:

       palt が詰めるもの      palt なし → palt あり
         。 、 「 」          17.00px(1.000em) → 8.50px(0.500em)  ちょうど半分
         あ                   17.00px          → 16.51px(0.971em)
         を                   17.00px          → 15.69px(0.923em)
         漢字                 17.00px          → 17.00px          変わらない
       43字の文の全体幅       727.6px          → 665.3px          −62.3px(−8.56%)
       letter-spacing:.015em が返していた分    +11.0px（62.3px の17.6%）

     残り8割は返っていない。全部返すには .085em 必要で、
     それは漢字まで離れて分かち書きに見える（実測サイト最大値は .063em）。
     そもそも letter-spacing は「すべての字の後ろ」に同じ量を足すので、
     句点だけが失った 0.5em は、いくら足しても比率としては戻らない。
     オーナー指摘「。の間がなさすぎる」は、この0.5emそのものだった。

     日本語の長文を読ませるサイト13本の実測（2026-08-27。
     新聞・出版社系・note・はてなブログ・青空文庫・官公庁・企業メディア）:
       本文に palt を使っている … 13本中 2本（ダイヤモンド・オンライン / WIRED.jp）
       使っていない             … 13本中11本
       PC 1280 / SP 375 のどちらで数え直しても同じ2本だった。
       非 palt の11本は 。が例外なく 1.000em、palt の2本は 0.500em。
     letter-spacing は 9本が 0、4本が .020〜.063em（中央値0）。
       .02em はダイヤモンド・オンラインの実測値。
       1行あたり0.3字しか払わずに、字間にわずかな息を入れられる。

     「palt を外すと『。」』が2emになって間延びする」は Chromium では起きない。
     text-spacing-trim の初期値 normal が連続約物を自動で詰める。
     実測: あ→。→」→あ と並べた4字は、
     text-spacing-trim:space-all だと 68px、既定（normal）だと 59.5px。
     ただし text-spacing-trim は Chrome/Edge 123+ だけ
     （caniuse 70.88% / Safari 27・Firefox 157 とも未対応）。
     Safari・Firefox では約物が連続したときだけ間延びが残るが、
     上の11本はいずれもその状態で運用している。 */
  font-feature-settings:normal;
  letter-spacing:.02em;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;      /* ページ本体は絶対に横に動かさない */
}

/* ── palt を残す場所 ──────────────────────────
   外したのは「読ませる文」からだけ。
   ここに挙げたのは全部ラベルで、文ではない（＝句点が出てこない）。
   ラベルは狭い枠に収めるほうが仕事をするので、詰めてよい。
   実測でも palt を使う2本（ダイヤモンド / WIRED）は
   ラベルと本文を区別せず全面に掛けており、ラベル側は問題になっていない。
   ここを本文と一緒に外すと、表ヘッダ・バッジ・グラフのラベルが
   約8%広がる。前回そろえた .vs2 の3列（SP 375）と
   .bars のラベル省略なしは、この詰めの上に成立している。

   td はここに入れない。値のセルにも文が入るからで、
   実際 137セル中8セルに句点がある。外した代償は実測で
   SP 375 の .vs2 7本のうち3本が +18 / +18 / +22px 伸びるだけ
   （横スクロールは7本とも0のまま）。この程度なら文のほうを取る。 */
h1,h2,h3,h4,
thead th,.badge,.na,
.site .brand,.site nav,.crumbs,.stamp,
.ax,.bars .br-l,.bars .br-v,
.figs .k,.figs .v,
.toc li,.answer .lbl,.pending .lbl,.sum .lbl,.sum .who,.site-link,.ent{
  font-feature-settings:"palt" 1;
}

/* 見出しは大きさより「余白」と「太さ」で立てる */
h1,h2,h3,h4{
  color:var(--ink-strong);
  font-weight:700;
  line-height:1.5;
  letter-spacing:.01em;
  /* 日本語を文節で折る。対応ブラウザではタイトルの不自然な改行が消える。
     ただし auto-phrase は文節の切れ目しか見ず行長を均さないので、
     見出し・短ラベルでは balance を必ず併記する。
     auto-phrase は Chromium系だけ（Safari・Firefox 合わせて約27%は無視）で、
     効かない環境ではこの balance だけが仕事をする。 */
  word-break:auto-phrase;
  text-wrap:balance;
  /* anywhere から break-word へ。anywhere は「語の途中でも折ってよい」に加えて
     min-content 幅まで1文字に縮めるので、表・グリッドの中で幅計算まで変わる。
     長すぎて入らない語だけを救う目的には break-word で足りる（下の実測を参照）。 */
  overflow-wrap:break-word;
  line-break:strict;
}
@supports not (word-break:auto-phrase){
  h1,h2,h3{word-break:normal;overflow-wrap:break-word;}
}

a{color:var(--accent-ink);text-decoration:underline;
  text-decoration-color:color-mix(in srgb,var(--accent) 28%,transparent);
  text-underline-offset:4px;text-decoration-thickness:1px;}
a:hover{text-decoration-color:var(--accent);}
a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px;}
:root[data-theme="dark"] a,:root:not([data-theme="light"]) a{color:var(--accent);}
/* ★ オーナー指示（docs/REWRITE-RULES.md 4-1）: 太字は <b> で書く。
   既存の <strong> と見え方を同じにしておく。移行中は両方が混ざる。 */
strong,b{font-weight:700;color:var(--ink-strong);}
.mono{font-family:ui-monospace,"SFMono-Regular",Menlo,monospace;
  font-variant-numeric:tabular-nums;font-size:.92em;letter-spacing:0;}

/* ── 骨格 ─────────────────────────────────
   .wrap の内寸がそのまま --measure。ヘッダもフッタも本文も同じ列に乗る。
   max-width を持つ子要素は全部 --measure なので、右端は1本に揃う。 */
.wrap{max-width:calc(var(--measure) + var(--pad) * 2);margin:0 auto;padding:0 var(--pad);}
.measure{max-width:var(--measure);}

/* ── ヘッダ（2026-08-28 作り直し）─────────────────────────
   直した中身と、その根拠になった実測値（375px・ダーク）

     ヘッダ背景 rgb(23,25,26) ＝ body と同一値・影なし・下線1pxだけ
       → sticky なのに「面」に見えず、本文が線の下に吸い込まれるだけだった。
         背景を --shell に分け、下線と弱い影を足して面にする。
     ブランド 15px（本文17pxより小さい）／マーク・図形ゼロ／色はナビと同じ緑
       → 7つ目のメニューに見えていた。20px/800 にし、
         左に CSS だけで描く角丸のマークを置く（画像は使わない）。
         文字色は --ink-strong にして、緑は LIFE の3文字とマークだけに残す。
     ナビ 13px／リンクの実寸 27×25px／gap 19px
       → タップの推奨44×44pxに対して高さ57%・幅61%。
         15px・min-height:44px・padding 0 11px にする。
     375px で nav.scrollWidth 385 / clientWidth 228 ＝ 157px が画面外
       → 「実測データ」「検証方法」の2本が1文字も見えず、
         はみ出していることを示す表示も無かった。
         SPでは nav を折り返して2段にし、はみ出しを 0 にする（下の @media）。
     6項目とも色・太さ・線が同値で、現在地が分からない
       → aria-current="page" に太字と下線2pxを付ける。 */
.site{border-bottom:1px solid var(--shell-line);background:var(--shell);
  box-shadow:var(--shell-shadow);
  position:sticky;top:0;z-index:40;}
.site .bar{display:flex;align-items:center;gap:20px;min-height:64px;}
/* ★★★ 2026-09-01: セレクタを .site の中に絞った。
   各社のキーカラーのボタン（a.cta.brand）も .brand を持っていて、
   ここの指定と、下の SP の position:fixed をまとめて拾っていた。
   その結果、ボタンが画面の上端に貼り付いたまま動かなくなっていた。 */
.site .brand,.site .brand:link,.site .brand:visited{
  display:inline-flex;align-items:center;gap:10px;
  font-weight:800;font-size:20px;letter-spacing:.04em;color:var(--ink-strong);
  text-decoration:none;white-space:nowrap;line-height:1;flex:0 0 auto;}
/* 詳細度のメモ: ダークの `:root:not([data-theme="light"]) a`（0,2,1）に勝つには
   クラス3つ必要（0,3,0）。`.brand:link`（0,2,0）では負けて全部が緑に戻る。 */
.site .bar .brand{color:var(--ink-strong);}
.site .bar .brand em{font-style:normal;color:var(--accent);}
/* マークは画像を使わない。角丸の色面＋文字1字（render.py が出す .brand-mark）。
   面 対 ヘッダ地はライト 5.83:1／ダーク 8.4:1 で、
   非テキストの最低基準3:1を両方で超える。 */
.brand-mark{display:inline-grid;place-items:center;
  width:26px;height:26px;border-radius:7px;
  font-size:15px;font-weight:800;letter-spacing:0;line-height:1;
  background:var(--accent);color:var(--on-accent);flex:0 0 auto;}

.site nav{display:flex;flex-wrap:wrap;gap:2px;font-size:15px;
  margin-left:auto;justify-content:flex-end;}
/* :link を1つ足して詳細度を上げている。これが無いと
   ダークの `:root:not([data-theme="light"]) a{color:var(--accent)}`（0,2,1）に
   `.site nav a`（0,1,2）が負けて、ナビ6本が全部アクセントの緑に戻る。 */
.site nav a,.site nav a:link,.site nav a:visited{
  display:inline-flex;align-items:center;min-height:44px;padding:0 11px;
  color:var(--ink);text-decoration:none;white-space:nowrap;line-height:1;
  border-radius:var(--radius-sm);}
/* hover の地は --sunk をやめる。ライトの --sunk(#F5F4F1) は
   新しい --shell(#F2F0EB) とほぼ同値で、押せる場所だと分からなくなる */
.site nav a:hover{color:var(--accent);background:var(--accent-soft);}
.site nav a[aria-current="page"]{color:var(--ink-strong);font-weight:700;
  box-shadow:inset 0 -2px 0 var(--accent);}

/* ── 記事の入口 ──
   .crumbs と .stamp は「どこの階層か」「いつの数字か」を担保する情報なのに、
   ページの中でいちばん弱い文字（12.5px・--faint 4.59:1）だった。
   13px・--muted（ライト 5.4:1／ダーク 6.7:1）に上げる。
   --faint 自体は figcaption・.tblnote・.src・チャートの目盛りでも使っていて
   そちらはオーナー確認済みなので、トークンは動かさずここだけ差し替える。 */
.crumbs{font-size:13px;color:var(--muted);padding:26px 0 0;letter-spacing:.02em;}
.crumbs a,.crumbs a:link,.crumbs a:visited{color:var(--muted);text-decoration:none;}
.crumbs a:hover{color:var(--accent-ink);text-decoration:underline;}

.head{padding:22px 0 0;}
/* ★★★ 2026-09-01 オーナー指摘「タイトル、右寄せ、改行すんな」。
   h1 は h2〜h4 と同じ text-wrap:balance を継いでいて、2行になると
   行の長さをそろえるために右へ寄って見えていた。h1 だけ pretty に戻す。 */
.head h1{font-size:clamp(26px,3.6vw,36px);line-height:1.48;letter-spacing:0;
  max-width:var(--measure);text-wrap:pretty;text-align:left;}
.head .lede{margin-top:24px;font-size:17px;line-height:2;color:var(--ink);
  max-width:var(--measure);}
.stamp{margin-top:26px;padding-top:18px;border-top:1px solid var(--rule);
  display:flex;flex-wrap:wrap;gap:6px 26px;font-size:13px;color:var(--muted);
  max-width:var(--measure);letter-spacing:.02em;}
.stamp b{color:var(--ink);font-weight:500;}
/* 「最終更新 2026年08月27日」は1つの塊。ここが折れると、ラベルと値が
   別の行に離れて、行頭に値だけが残る。実測でいちばん長いのは151px
   （SPの内寸335pxの45%）なので、まとめて折らないほうが安全。 */
.stamp>span{white-space:nowrap;}

/* ── 結論。囲みはこの1つだけに絞る ── */
.answer{max-width:var(--measure);margin:40px 0;padding:8px 0 8px 28px;
  border-left:3px solid var(--accent);}
/* ラベルは本文17pxの88%（契約 §3-2）。12px では「読む価値がある囲み」だと
   分からず飛ばされる（Miller & Davis 1993）。競合4本の帯も 85〜100%。 */
.answer .lbl{font-size:15px;letter-spacing:.16em;color:var(--accent-ink);
  font-weight:700;margin-bottom:16px;}
.answer ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:16px;}
.answer li{font-size:16.5px;line-height:1.9;padding-left:20px;position:relative;}
.answer li::before{content:"";position:absolute;left:0;top:.78em;width:7px;height:1.5px;
  background:var(--accent);}

/* ── 目次。囲まず、罫線だけで ── */
.toc{max-width:var(--measure);margin:40px 0 52px;padding:24px 0;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);}
.toc h2,.toc .toc-h{font-size:12px;letter-spacing:.16em;color:var(--faint);font-weight:700;
  margin-bottom:16px;}
.toc ol{margin:0;padding:0;list-style:none;counter-reset:t;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:11px 28px;}
/* 番号は本文の外に出す。いまは全項目1行に収まっているが、見出しが長くなった
   ときに2行目が番号の下（＝本文より左）へ戻ると、目次の中に左端が2つできる。
   grid にして番号を別の列に出し、折り返した行を1行目の見出しに揃える。
   li の中身は <a> 1個だけなので、grid の匿名アイテム分割の心配がない。
   列幅は 2桁+ピリオドぶんの 2.6ch。数字は tabular-nums なので全項目で揃う。 */
.toc li{counter-increment:t;font-size:14.5px;line-height:1.7;
  display:grid;grid-template-columns:2.6ch 1fr;column-gap:8px;align-items:baseline;}
.toc li::before{content:counter(t) ".";color:var(--faint);
  font-variant-numeric:tabular-nums;}
.toc a{color:var(--ink);text-decoration:none;}
.toc a:hover{color:var(--accent-ink);text-decoration:underline;}

/* ── 本文 ── */
article{padding-bottom:88px;}

/* ── 見出しの階層（2026-08-27 全面改訂）─────────────────
   これまでは「余白と太さだけ」で階層を作っていた。実測すると

     h2 24px / h3 17.5px / 本文 17px

   で、h3 は本文の1.03倍。装飾も色差も無い。
   だから節の切れ目が「少し広い余白」でしか示されず、
   スクロールすると全部が同じ濃さの文字の列に見えていた。
   （オーナー指摘「メリハリがない」「論文みたいで面白くない」の正体）

   参照した実測（2026-08-27 に Chromium 148 / PC1280・SP375 で採寸）

     dzk.jp（VPN UNIVERSITY・移行元）
       本文 15px/27px #333（対地 12.6:1）
       h2 22px #000 ＋ 下 3px の黒罫 ＋ その下に 1px #ccc（二重罫）／ 上下 margin 20px・padding 20px 10px
       h3 20px #000 ＋ 左 5px の黒い縦線（::before・高さ100%）／ margin 35px 0・padding 15px 20px
       h4 16px **白抜き ＋ 黒ベタの帯**（#000）／ margin 20px 0・padding 10px 15px 10px 20px
       表: thead を持たず、**1列目のセルだけ #F2F2F2**。ヘッダ行を塗る形は使っていない
       ＝「面ベタ・白抜き」を1階層だけに使い、それが最強の合図になっている
          （ただし dzk は h4 に置いているので、h2 より h4 のほうが強く見える。逆転している）

     tsuzukiblog.org（VPNフリーク・競合。/vpn/nordvpn-fee/ と /vpn/game/ の2本）
       本文 17px/30.6px #434347（対地 9.6:1）・段落下 37.4px
       h2 23.8px ＋ 左 8px の濃紺 #213555 ＋ 面 rgba(33,53,85,.03)／ margin-top 95.2px・下 47.6px
          左右 margin -16px で本文より外に張り出し、**文字の左端は本文と揃う**
       h3 22.1px ＋ 下 2px の濃紺の全幅罫（::before）／ margin-top 66.3px・下 44.2px
       h4 20.4px ＋ 左 5px #517D99（濃紺を薄めた中間色）・面なし／ margin-top 61.2px・下 30.6px
       表: thead th が **#3D79D5 ベタ・白抜き・13px・700**、行見出し th は rgba(78,110,151,.05) の薄面
       SP375 では h2 18px / h3 16.5px / h4 15.75px。本文15pxに対して 1.20 / 1.10 / 1.05倍
       ＝**大きさはほとんど変えず、装飾の「量」だけを単調に減らして階層を作っている**

     docs/research/jp-table-conventions.md A-4「列ヘッダをブランド色で塗る 5/13」
       モバレコ #00BCD1／オリコン #0078D7／VPNフリーク #3D79D5 ほか。全部が白抜き。

   ここから決めたこと。

   1. 階層は「装飾の量」を単調に減らして作る。種類も毎回変える。
        h2 = 面ベタ（濃緑）＋ 反転文字        いちばん強い。ページ内で塗る見出しはこれだけ
        h3 = 左 5px ＋ 下 2px の線（accent）  面は持たない。線を2本
        h4 = 左 3px の縦線のみ（--faint）     線1本
      「面ベタ → 線2本 → 線1本」で、色を見分けられなくても順序が付く。

      ── h3 から「薄い面」を外した理由（2026-08-27 夜 実測）──────
      初版の h3 は --accent-soft の薄い面を敷いていた。実測すると

        h3 の面 対 地   ライト 1.09:1（ΔL* 3.5）／ ダーク 1.25:1（ΔL* 9.2）

      非テキストの最低基準は 3:1。両テーマとも大きく下回っていて、
      **面積だけ大きくて、目には何も届いていない装飾**だった。
      いま h3 を支えていたのは左4pxの線（ライト5.83:1 / ダーク8.15:1）だけで、
      中間の階層として機能していない、というPMの指摘はそのとおりだった。

      では薄い面を「見える濃さ」まで上げればよいかというと、上げられない。
      3:1 を満たす面はもう中間色で、それは表ヘッダ（ライト5.83 / ダーク3.03）と
      同じ帯域に入る。**面という手段は h2 と表ヘッダの2枠で使い切っている。**
      3段目を面で作ろうとすると、必ずどちらかと衝突する。

      そこで3段目は「線」に振り替えた。線は面と違って、
      地が白でも黒でも同じ濃さの色を置ける（accent の対 地は
      ライト5.83 / ダーク8.15 で、ダークのほうがむしろ強い）。
      テーマを反転しても序列が崩れないのは、この性質のおかげ。

      装飾の量（塗られる面積・PC1280 実測）でも単調に減る:
        h2      752 × 50px ＝ 約37,600px²（面）
        表ヘッダ 720 × 41px ＝ 約29,520px²（面）
        h3      左5px×42 ＋ 下2px×736 ＝ 約1,682px²（線2本）
        h4      左3px×33          ＝ 約99px²（線1本）
      旧 h3 の面は 30,240px² あったが、上のとおり 1.09:1 なので
      「面積は最大級なのに見えない」という一番たちの悪い状態だった。

      下線の型は tsuzukiblog の h3（下2pxの濃紺の全幅罫）と同じ。
      表の直上に置いたときは、この下線が「ここから下がこの表」の
      区切りになる（旧版で薄い面に期待していた役割を、線が引き取る）。

   2. 大きさは競合と同じく“ほとんど変えない”。
      h2 24 / h3 19 / h4 17.5 / 本文 17（PC）＝ 1.41 / 1.12 / 1.03倍。
      tsuzukiblog の 1.40 / 1.30 / 1.20 より小さい。
      向こうの h3 は下2pxの罫だけ、こちらは下2px＋左5pxの2本なので、
      足りない分は大きさではなく線の本数で払っている。
      h3 が本文の1.03倍で装飾も無かった以前より確実に分かれる。

   3. 装飾だけを本文の左端より外へ出す（--hb）。
      帯も縦線も --hb ぶん外に張り出すが、**見出しの文字は本文と同じ左端に残る**。
      「ページ上のすべての要素が同じ左端に並ぶ」という
      このファイルの一番の決めごとを崩さずに、面と線を足せる。
      tsuzukiblog が h2 だけでやっている手法を、h2・h3・h4 の3つとも揃えた。

   4. 番号・アイコン・グラデーションは付けない。
      情報が増えないし、h2 の面ベタという一番強い合図が薄まる。 */
article h2,.prose h2{
  font-size:clamp(20px,2.4vw,24px);
  max-width:calc(var(--measure) + var(--hb) * 2);
  margin:76px calc(var(--hb) * -1) 24px;
  padding:13px var(--hb);
  background:var(--band);color:var(--band-ink);
  border-radius:var(--radius-sm);
  letter-spacing:.02em;   /* 白抜きは字面が太って見えるので、わずかに開ける */
}
article h2:first-child{margin-top:0;}

article h3,.prose h3{
  font-size:19px;
  max-width:calc(var(--measure) + var(--hb) * 2);
  margin:50px calc(var(--hb) * -1) 18px;
  padding:2px var(--hb) 9px calc(var(--hb) - 5px);
  border-left:5px solid var(--accent);
  border-bottom:2px solid var(--accent);
}

article h4,.prose h4{
  font-size:17.5px;
  max-width:calc(var(--measure) + var(--hb) * 2);
  margin:34px calc(var(--hb) * -1) 12px;
  padding:1px 0 1px calc(var(--hb) - 3px);
  border-left:3px solid var(--faint);
}

/* 囲みの中の見出しは、囲みそのものが階層を示している。
   ここに帯や縦線を重ねると、囲みが二重になって
   「どれが本当に強いのか」が読めなくなる（このファイルの原則）。 */
.callout h3,.callout h4,
.steps li h3,.steps li h4,
.answer h3,.answer h4{
  margin:0 0 10px;padding:0;background:none;border:none;border-radius:0;
  color:var(--ink-strong);max-width:none;font-size:16px;letter-spacing:.01em;}
.callout.crit h3{color:var(--alert-ink);}
/* ── 改行（2026-08-27 再改訂。今度は実測で決めた）──────────────
   オーナー指摘の2例を、実際のフォント（Noto Sans JP）・実際の字送り
   （letter-spacing .02em）・実際の幅（SP 335px / PC 720px）で
   8通りの設定に流し込んで、1文字ずつ Range で行を復元して比べた。

     例1「…同じ土俵に載りません。並べて比べられるものと、片方にしか…」
     例2「…日本（NordVPN2都市／Surfshark1都市）・ベトナム（…）・インド（…）…」

   分かったこと（SP 335px / PC 720px とも同じ結論）:

     overflow-wrap:  anywhere / normal / break-word の3つは
                     4種の文字列すべてで出力が1文字も変わらなかった。
                     つまり anywhere は今回の折れ方の原因ではない。
                     日本語は既定で「どの文字の間でも折れる」ので、
                     並べて比／べられる も NordVPN2都／市 も、
                     anywhere を外しただけでは そのまま残る。
                     （anywhere を外す理由は別にある。上の h1..h4 のコメント参照）

     line-break:strict は 例1・例2 では差が出なかったが、
                     別に用意した「ショッピング・チャット・キーワード」を
                     幅200〜340pxの8通りで流すと 2通りで差が出た。
                       normal: 「…とショ／ッピングとチャ／ットに…」
                       strict: 「…と／ショッピングとチャットに…」
                     小書き仮名を行頭に落とさない。入れる価値がある。

     word-break:auto-phrase が、2例を直した唯一の設定だった。
                     例1 「並べて比べられる」が1つの塊のまま残る
                     例2 「都市」「インド」が割れなくなり、
                          （NordVPN2都市／Surfshark1都市）が丸ごと次行へ落ちる

   前回 auto-phrase を段落から外した理由は
   「台数を気にしなくて／よい のような2文字の孤立行を作る」だったが、
   その文字列を SP 335px で流し直すと
       いまの設定（normal）: 「…台数を気にしなく／てよい」（3文字）
       auto-phrase        : 「…台数を／気にしなくてよい」（8文字）
   で、auto-phrase のほうが孤立が浅い。text-wrap:pretty と併用すれば
   最終行の孤立はさらに抑えられる。前回の判断は取り消す。

   代償: auto-phrase は行長を均さないので、行末が今より不揃いになる。
   「語の途中で折れない」ほうを取る（オーナーの指摘はそこだった）。
   auto-phrase は Chromium系だけ。Safari・Firefox では宣言ごと無視され、
   下の @supports が normal + break-word に戻す（＝いまと同じ折れ方に留まる）。 */
/* .box は render.py が1つも出力していない未定義のセレクタだった（本体の定義もない）。
   囲みの体系はこれから設計するので、いまは参照ごと外す。
   実体のないセレクタを残すと「もう対応済み」に見えて、設計のときに見落とす。 */
/* ── 2026-08-27 4回目の指摘で、上の結論を取り消した ───────────────
   オーナー「レイアウトがキモい。左寄りで、意味不明なところで改行される」。
   PC・SP を 375 / 1280 で、本文の全文字を Range で走査して測り直した結果、
   **行末の穴も、字間の伸びも、どちらも word-break:auto-phrase が単独の原因**
   だと分かった。auto-phrase は文節の切れ目でしか折らないので、
   次の文節が入らないと文節まるごとぶんの穴が空く。
   左揃えならその穴が右端の空きになり（SP 標準偏差 40px、最大 250px）、
   両端揃えならその穴が字間に乗る（PC 送り最大 23.45px＝素の +35%）。
   見え方が変わるだけで、穴の大きさは同じ。

   4通りを実測した（compare / review、SP375 / PC1280、ラベルは除外）:
                            行末SD                送りmax（素:SP16.84 PC17.36）
                            SP           PC       SP       PC
     1 auto-phrase + start  33.0 / 40.0  35.9/45.7  16.86   17.36
     2 auto-phrase + justify 0.3 /  0.3   0.3/ 0.3  79.55   23.45
     3 normal + start       12.7 / 14.9  11.6/ 8.4  16.86   17.36  ← 採用
     4 normal + justify      0.3 /  0.3   0.3/ 0.3  21.52   18.91

   ここまでは 3 を採った。だが「語中改行」を種類別に数え直すと 3 は不合格だった。
   4ページ(compare/review/netflix-kr/how-we-test)を SP375 / PC1280 で分類:
                          カタカナ語を割る   英数字を割る   漢字熟語の切れ目
     3 normal   SP/PC       59 / 39           21 / 3         109 / 62
     1 auto-phrase SP/PC    39 / 32           19 / 3          53 / 36
   漢字熟語の切れ目は日本語の通常の組み方（許容）。だが
   「シ／ンガポール」「ホー／チミン」「Dou／bleVPN」は、
   オーナーが名指しした「意味不明なところで改行される」そのものだった。
   → **カタカナ語と英数字を割らないことを最優先にし、auto-phrase に戻す。**
   残った割れは全部 .vs2 の表のセルだったので、下の「表のセル」の節で潰した。
   結果 SP のカタカナ割れは 59 → 1件。

   （以下は 3 を採ったときの記録。行末SDの数値だけは今も有効）
   3 は行末のばらつきと字間の伸びを同時に小さくできる唯一の組み合わせ。
   字間はまったく伸びない（送り＝素のまま）。行末の空きの中央値は
   SP 11.9〜12.7px、PC 10.7〜11.5px で、いずれも1文字の幅より小さい。
   これは日本語組版の既定でもある（JIS X 4051 は禁則以外どこでも折る）。
   禁則は line-break:strict が見る。実測でも違反0件。

   代償: 語中改行（語の途中で折れる）が増える。実測で
     SP 1→36 / 8→38件、PC 1→15 / 3→21件。
   ただし auto-phrase でも0件ではなく、オーナーが挙げた
   「速度その／ものではありません」は auto-phrase 側で出ていたもので、
   normal では出ない（文節境界が その|もの だから auto-phrase は必ずそこで折る）。
   個別に折らせたくない句は .ph（white-space:nowrap）で書き手が指定する。

   .tblnote と .src は「短いラベル」ではなく文（句点が出る）なので、
   下のラベル用の行から外し、本文と同じ扱いにした。ここが SP の
   250px / PC の 183px の穴の出どころだった。 */
article p,.prose p,.answer li,.sec-lead,.sum,.callout p,.steps li p,details p,
.tblnote,.src,article li,.prose li{
  word-break:auto-phrase;overflow-wrap:break-word;line-break:strict;text-wrap:pretty;
  text-align:start;}
@supports not (word-break:auto-phrase){
  article p,.prose p,.answer li,.sec-lead,.sum,.callout p,.steps li p,details p,
  .tblnote,.src,article li,.prose li{word-break:normal;}
}

/* ── 行末を揃える（2026-08-27 3回目の指摘を受けて実測で決めた）──────────
   オーナー「全体的に文章が左寄りになってて、変なところで改行されるのが多い」。
   3回目なので、今度は「変なところ」が何を指しているのかを数えるところから始めた。
   5ページ全部の段落を1文字ずつ Range で走査して行を復元し、
   行末と行頭に来ている文字の組を全部拾った（.tmp-research/linemeasure.js）。

   分かったこと（本文161段落／PC 318行・SP 637行）
     語中改行（カタカナ・英字の途中で折れた）   PC 0/157  SP   0/476
     数字と単位が割れた                        PC 0      SP   1→0
     接続詞が2行にまたがった                    PC 0      SP   0
     行頭禁則違反（、。」が行頭に来た）           PC 0      SP   0
     最終行が2文字以下（孤立行）                 PC 0/161  SP   0/161
   つまり前回入れた word-break:auto-phrase + line-break:strict は効いていて、
   「変なところで折れる」は **すでに1件も起きていない**。

   同じ計測を競合にかけると、うちだけが直っていることが分かる:
     dzk.jp/nordvpn-review      SP 語中改行 80/319（25.1%）禁則違反18 孤立行16/268
     dzk.jp/how-to-resolve-…    SP 語中改行 24/188（12.8%）禁則違反 4 孤立行19/219
     うち（5ページ合計）          SP 語中改行  0/476（ 0 %）禁則違反 0 孤立行 0/161
   日本語の宿命ではなく、設定で消せるものだった。うちは消せている。

   では何が残っていたのか → **行末の位置がバラバラ**だった。
     右端の空きの標準偏差（3行以上の段落・最終行を除く）
       うち PC 中央値 13.8px ／ SP 中央値 23.7px（最大 109.9px）
       dzk.jp SP 中央値 2.5〜8.3px
   auto-phrase は「文節の切れ目でしか折らない」ので、次の文節が入らないと
   行末に文節まるごとぶんの穴が空く。dzk はどこでも折るから穴が空かない
   （そのかわり語中改行が25%出る）。うちは穴のほうを選んでいた。
   オーナーが見ていた「変なところで改行される」は、この穴のことだった。

   8通りを実測して比べた（compare / review / netflix-kr の3ページ）:
                                   右端SD中央値      語中改行
                                   PC     SP        PC    SP
     A 現行 auto-phrase + pretty    13.8   23.7      0/141  0/435
     B auto-phrase + balance        19.0   20.2      0      0
     D word-break:normal + pretty    3.3    5.4      9/138 24/407
     F auto-phrase + justify         0.0    0.0      0      0   ← 両方直る
   両端揃え（justify）は、穴を「行末の空き」ではなく「字間」に配分する。
   だから語中改行を1件も増やさずに行末が揃う。日本語の組版はもともと
   これが既定（W3C 日本語組版処理の要件は行の調整処理を前提に書かれている）。

   代償も測った（全角の送りが何pxになるか。素の送りは16.8px）:
     PC 720px  中央値 18.07px(+7.5%)  p90 20.69(+23%)  p99 23.48(+40%)  最大 26.18(+56%)
     SP 335px  中央値 18.74px(+12%)   p90 24.22(+45%)  p99 31.16(+86%)  最大 45.45(+172%)
   SP の最大 45.45px は「作品には原理的に」の8文字を335pxに引き伸ばした行で、
   1文字ずつバラバラに見える。行が20字しかない列で両端揃えをやると、
   1本の穴が字間全部に乗るのでこうなる。

   決めたこと: **PC（768px以上）だけ両端揃えにする。SPは左揃えのまま。**
     PC は1行41字あるので、同じ穴でも1字あたりの負担が半分以下になる
     （p99 で +40%。SPは +86%）。行末は完全に揃う（SD 0.0px）。
     SP の右端のばらつき 23.7px は CSS では直せない。
     原因は文節が長いこと（「Surfsharkだけが」で1文節＝8字＝130px）なので、
     文のほうを短くするしかない。docs/CONTRACT-boxes.md に PM 向けに書いた。

   balance は使わない: PC では pretty(13.8) より悪く(19.0)、SP でも 3.5px しか
   縮まない。しかも Chromium の balance は6行までしか効かない（長い段落は素通り）。
   最終行の孤立を抑える pretty のほうが、実測で 0/161 を維持できている。 */
/* 両端揃えは PC からも外した。理由は上の4通りの表（送り max 23.45px）。
   行末を0pxに揃える代わりに字間が最大 +35% 伸びており、
   オーナーが「キモい」と言っていたのはこの伸びのほうだった。 */
/* 短いラベルは行長を均すのが本命。auto-phrase は効く環境での上乗せ。
   .tblnote / .src はここから外した（文であって、ラベルではない）。 */
.vnote,.sub,figcaption,.figs .n,.stamp,.head .lede{
  word-break:auto-phrase;text-wrap:balance;overflow-wrap:break-word;line-break:strict;}
/* 折らせたくない句を書き手が指定できる逃げ道。
   16本中13本が nowrap でやっているのはこれ。
   ただし列より長い句を nowrap のままにすると、その手前の行に
   句ぶんの穴が丸ごと空く。実測で SP375 の compare は
   「（NordVPN1都市／Surfshark1都市）」1本だけで
   285px（行の85%）の穴を作り、ページの行末SDを 12.7→29.2px に押し上げていた。
   一度 SP だけ white-space:normal にしたが、撤回した。
   穴の原因は .ph という仕組みではなく、26字の句を .ph で括っていたこと。
   そちらは書き手側で分割済み（.ph の最長は11字・約120pxになった）。
   SP で無効にすると、こんどは「1,715.0」と「Mbps」が上下に割れる。
   値と単位を離さないのが .ph の存在理由なので、SPでも nowrap を効かせる。 */
.ph{white-space:nowrap;}
article p{max-width:var(--measure);margin:0 0 30px;}   /* 段落間は広く取る */
article ul,article ol{max-width:var(--measure);margin:0 0 30px;padding-left:1.4em;
  display:flex;flex-direction:column;gap:13px;}
article li::marker{color:var(--faint);}

/* H2直下の要約。囲まず、太さと色だけで立てる。
   色は --muted(5.4:1) から --ink(10.8:1) へ（2026-08-27）。
   節の頭と終わりが両方グレーだと、節の中でいちばん先に読ませたい2行が
   いちばん薄い、という逆転が起きていた。差は太さ(500)と大きさ(16px)で付ける。 */
/* 本文と 1px だけ違う 16px は「別の役割」ではなく「不揃い」に見える。
   大きさは本文と同じ17pxに揃え、違いは font-weight:500 だけで付ける。 */
.sec-lead{max-width:var(--measure);font-size:17px;color:var(--ink);font-weight:500;
  margin:0 0 30px;line-height:1.9;}

/* ── 節の結論 .sum（節末のまとめ と 節末の判定 を統合。docs/CONTRACT-boxes.md §3）──
   modifier は2つだけ:
     .sum-w  「つまり」型（解説・レビューの節末）
     .sum-v  「この節の結論」型（比較ページ。勝者バッジ .who つき）

   grid の構造（列・gap・align-items・display:contents）は前セッションで
   オーナー指摘2番「ただしの切れ方が気持ち悪い」を実測で直した結果なので、
   1行も変えていない。変えたのは枠・余白・ラベルの大きさだけ。

   枠: border-top をやめて 1px の全周枠・角丸2px。塗らない・影なし。
     - 塗らない  … Foster & Coles (1977): 強すぎる書式は非強調部分の成績を下げる
     - 影を出さない … 競合4本（DZK/sni-hub/tsuzukiblog/my-best）で box-shadow 0件
     - 枠色は --faint。契約の初案は --rule-strong だったが、実測すると
       地に対して ライト 1.57:1 / ダーク 1.76:1 しかなく、受け入れ条件4
       （非文字コントラスト 3:1）を満たせない。--faint なら ライト 4.61:1 /
       ダーク 4.70:1（実測値は報告のとおり）。1px でも輪郭が読める最小の色。

   ラベル: 12/12.5px → 15px（本文17pxの88%）。オーナー指摘6番の核心。
     競合4本のラベルは本文比 85〜100% に収まっており、本文超えは0本。
     アイコンは付けない（競合4本で0件）。 */
.sum{max-width:var(--measure);
  border:1px solid var(--faint);border-radius:2px;
  background:none;box-shadow:none;
  padding:16px 18px;font-size:15px;line-height:1.9;color:var(--ink);margin:0 0 30px;
  display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:12px;align-items:baseline;}
/* grid は「連続するテキスト」しか匿名アイテムにまとめない。<span class="ph"> のような
   本文中のインライン要素はそのままだと独立したアイテムになり、本文が細切れに折れる。
   display:contents で箱を消すと、前後のテキストと1つの匿名アイテムに戻る。
   .ph の white-space:nowrap は子のテキストに継承されるので効いたまま（実測で確認）。
   ※ここに <a> を入れると箱が消えて下線が出なくなる。本文にリンクを置くときは
     .sum を使わず通常の段落に書くこと。 */
.sum>.ph,.sum>strong,.sum>em,.sum>b{display:contents;}
.sum .lbl{font-size:15px;font-weight:700;line-height:1.5;}

/* 「つまり」型。ラベルは実測 41.3px（12.5px時）と短く、15pxにしても本文の列は
   十分残るので、.sum-v と違って1行取らず同じ行に置く（統合前の「つまり」と同じ流儀）。 */
.sum-w .lbl{color:var(--accent-ink);letter-spacing:.1em;white-space:nowrap;}

/* 判定型。ラベルもバッジも横に並べず、1行ずつ取って上に積む。本文は箱の幅を
   まるごと使う（＝PC でも SP でも1列）。

   ── なぜバッジを行内に置かないか（2026-08-27 実測。3度目の同じ症状）──
   バッジ .who を本文と同じ行に置くと、本文の列がバッジぶん痩せる。そこへ
   両端揃え（@media min-width:768px の justify）が掛かると、痩せた列に
   合わせて字間が開き「た だ し 勝 っ た 数 で」のようにバラける。
   実測（/compare/nordvpn-vs-surfshark/ PC1280・.sum-v 6個）:
     バッジ行内     全角の送り 中央値 18.34px / 最大 21.38px（素の15.34pxの+39%）
     バッジ1行取り  中央値 15.34px / 最大 15.34px（素のまま。伸びなし）
   統合前は balance グループに居て justify が掛かっていなかったので出ていなかった。
   囲みに padding 18px が付いたぶん、行内に置いたときの列はさらに痩せている。
   縦が1行ぶん伸びるが、字間の破綻より詰まりのほうを取る。
   置き方は .answer .lbl / .pending .lbl と同じ流儀。色は --muted。 */
.sum-v{grid-template-columns:minmax(0,1fr);margin:0 0 34px;line-height:1.85;row-gap:8px;}
.sum-v .lbl{grid-column:1 / -1;letter-spacing:.16em;color:var(--muted);}
.sum-v .who{grid-column:1 / -1;}
.sum .who{justify-self:start;display:inline-block;
  background:var(--accent);color:#fff;font-weight:700;
  font-size:12.5px;padding:2px 11px;border-radius:var(--radius-sm);
  letter-spacing:.03em;white-space:nowrap;}
:root[data-theme="dark"] .sum .who,
:root:not([data-theme="light"]) .sum .who{color:var(--paper);}

/* ── 図版。2〜3段落に1枚入れて、文字の連続を切る ── */
/* ★★ 2026-09-01: 図の上が 0 で、直前の段落にくっついていた（オーナー指摘）。
   上を 32px 空ける。段落の下マージンと重なるので、見た目は 32〜40px になる。 */
figure{max-width:var(--measure);margin:30px 0 34px;}
figure.wide{max-width:var(--measure);}   /* 本文と同じ幅。飛び出させない */
figure img,figure svg{display:block;width:100%;height:auto;border-radius:var(--radius);
  border:1px solid var(--rule);background:var(--card);}
/* 棒だけの図は枠を外す。中身が「文字と帯」だけなので、枠は内容を1つも足していない
   （Tufte が「濃いグリッドは chartjunk」と書いた側）。
   ただし格子・軸を持つ図（coverage_grid / line_chart）の枠は残す。
   Inbar/Tractinsky/Meyer (2007, n=87) と ISCAP 2017 の追試で、
   極端なミニマリズムは beauty / clarity / simplicity すべてで低評価になり、
   縦横のグリッド線を両方剥ぐと4次元すべてで有意に低下した（p<0.05）。
   全部は剥がさない。 */
figure .bars{border:none;background:transparent;}
figure .chart svg{border:1px solid var(--rule);}   /* 現状維持（明示） */
/* ★★★ 2026-09-01 オーナー指摘:「テーブルやグラフの上には軽い見出しというか
   タイトルを書けよ。何のグラフなのか、チャートなのか分からんやろ。」 */
.figttl{margin:0 0 10px;font-size:14px;font-weight:700;color:var(--ink-strong);
  letter-spacing:.02em;line-height:1.6;display:flex;align-items:center;gap:8px;}
.figttl::before{content:"";width:3px;height:15px;border-radius:2px;
  background:var(--accent);flex:0 0 3px;}
figcaption{margin-top:8px;font-size:12.5px;color:var(--faint);line-height:1.65;}
figcaption a{color:var(--faint);}
/* 画像の出典。数値の .src と同じ役割を、図版のキャプション内で果たす */
figcaption .credit{display:inline-block;margin-left:2px;color:var(--faint);}
figcaption .credit::before{content:"／";margin-right:6px;opacity:.6;}
.shot{position:relative;}
/* SVGのままの図（coverage_grid / line_chart / series_slot）を入れる箱。
   viewBox を持つので、SPでは潰さず横スクロールさせる（@media側）。
   潰すと文字が実効5.6pxになる（2026-08-27 実測）。 */
.chart{max-width:var(--measure);}

/* ── 横棒グラフ .bars（2026-08-27 新設）──────────────────
   bar_chart() / load_chart() を SVG から HTML+CSS に移した受け皿。

   SVGをやめた理由（D-0 の実測）:
     viewBox 720 の SVG は SP 335px で 0.465倍に潰れ、
     宣言 13px の文字が実効 6.05px、宣言12.5pxが5.82pxになっていた。
     同じ画面の本文は16px、図の説明文（figcaption）は12.5px。
     つまり図の中の文字が、その説明文の半分以下という逆転が起きていた。
     前回 min-width:620px を外したのは、横スクロールを
     「文字の縮小」に置き換えただけで、問題を移しただけだった。
   HTMLなら font-size がそのまま効き、幅だけが親に追従する。
   日本語サイトで横棒グラフを持っていた3本も、3本ともSVGではなくHTMLだった。 */
.bars{max-width:var(--measure);margin:0 0 8px;}
.bars .br{margin:0 0 14px;}
/* 最後の行の下マージンは落とす。
   残すと .bars の高さが最終トラックより下に伸び（正確には親と相殺し）、
   .ax-l の参照線が最終行に届かなくなる。 */
.bars .br:last-child{margin-bottom:0;}
.bars .br-hd{display:flex;justify-content:space-between;align-items:baseline;
  gap:12px;margin:0 0 6px;}
/* ラベルは伸縮側。長い国名／都市名は省略記号で切る（折り返して行を増やさない） */
.bars .br-l{font-size:13px;color:var(--ink);min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
/* ラベルに添えるロゴ（社名の棒だけ。_htmlbar が logo(slug, label, 18) を出す）。
   ここを明示しないと figure img{display:block;width:100%} を食らって
   55px角のブロックになる（棒グラフは figure の中に描かれるため）。
   セレクタは 0,0,3,0 で figure img の 0,0,0,2 を上回るので、
   ファイル内の順序に関係なく勝つ。
   vertical-align は baseline のままだと画像の下辺が baseline に乗り、
   18px のロゴが13pxの社名に対して大きく沈む。
   社名の視覚中心はおよそ baseline+0.35em なので、
   画像の下辺をそこから半分（9px）下げた -0.34em に置く。
   background/border は .ent .lg と同じ考え方。白背景前提のロゴがあるので
   暗所では地に馴染ませず白を敷く（下の :root ルール）。 */
.bars .br-l .lg{display:inline-block;width:18px;height:18px;
  vertical-align:-.34em;margin-right:7px;
  border-radius:4px;object-fit:contain;
  background:var(--card);border:1px solid var(--rule);}
:root[data-theme="dark"] .bars .br-l .lg,
:root:not([data-theme="light"]) .bars .br-l .lg{background:#fff;}
/* 数値は固定側。桁を揃えて縦に読めるようにする */
.bars .br-v{font-size:13px;font-weight:700;color:var(--ink-strong);
  font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;}
.bars .br-tk{position:relative;height:10px;border-radius:5px;
  background:var(--sunk);overflow:hidden;}
/* 既定の棒。--rule-strong はトラック(--sunk)に対して
   ライト1.5:1 / ダーク1.4:1 しかなく（実測）、棒がほぼ消える。
   .mk のときと同じ理由で、意味を持つ面には --muted を使う
   （ライト5.1:1 / ダーク5.8:1。非テキストの最低基準3:1を満たす） */
.bars .br-tk>i{display:block;height:100%;border-radius:5px;
  background:var(--muted);}
.bars .br.is-top .br-tk>i{background:var(--accent);}
/* 負荷の3段階。色相だけに頼らず、順に「緑・黄・赤」で濃さも変える */
.bars .br.lv-ok  .br-tk>i{background:var(--accent);}
.bars .br.lv-mid .br-tk>i{background:var(--note);}
.bars .br.lv-hi  .br-tk>i{background:var(--alert);}

/* ── 合計行 .br-sum（2026-08-27 新設）──────────────────
   _sumline() が出す「その他9都市 合計130台」の行。
   render.py のコメントにあるとおり、**この行には棒を引かない**。
   合計を個別と同じ尺度に載せると、130台の棒が最上位（256台）より
   長くはならないにしても、韓国77台より長い「1つの都市」があるように見える。

   棒が無い行なので、棒の代わりに「これは合計だ」と分かる形が要る。
   新しい見た目は作らず、サイト内で既に使っている2つの語彙を重ねる:

     1. 上に1本の罫（--rule-strong）。
        .sum が「節の締め」を上罫で示していたのと同じ引き方で、
        帳簿の合計線としても日本語の表で最も一般的な形。
        罫の上下に余白を取って、個別の行の並びから物理的に切り離す。
        --rule ではなく --rule-strong を使うのは、ダークで確かめたため。
        --rule(#2F3436) は地(#17191A)に対して 1.3:1 しかなく、
        「行を分けるだけの線」としては足りても、
        意味を持つ線（ここから下は合計）としては消える。
        --rule-strong は 1.9:1。.sum の枠と同じ token に揃う。
     2. 文字を --muted に落とす。個別の行は --ink / --ink-strong なので、
        濃さが1段違う＝「同じ列の値ではない」が色を見なくても分かる。
        .na（欠測）と .b-wait が既に「--muted＝この列の実測値ではない」で
        揃っているので、その読み方をそのまま使う。

   数字は tabular-nums のまま（上の .br-v を継承）。桁は縦に揃う。
   .br:last-child{margin-bottom:0} が効くので下の余白は増えない。
   増える高さは罫1px＋padding-top 11px＋.br-hd の下マージンを
   0に落とした分（−6px）＝ 実質 +6px。 */
.bars .br-sum{border-top:1px solid var(--rule-strong);padding-top:11px;margin-top:4px;}
.bars .br-sum .br-hd{margin-bottom:0;}
.bars .br-sum .br-l,.bars .br-sum .br-v{color:var(--muted);}

/* 参照線。Heer & Bostock (CHI 2010, n=2,880) でグリッド線の追加は
   精度を有意に向上させた（F(3,2802)=31.98, p<0.001）。
   ただし「最低8px間隔」が条件なので、線は2本までに絞る。
   位置は axis に依存するので render.py が left: を計算して実要素で出す。 */
.bars-load{position:relative;}
.bars-load .ax-l{position:absolute;top:0;bottom:0;width:1px;
  background:var(--rule-strong);pointer-events:none;z-index:0;}
.bars-load .br{position:relative;z-index:1;}   /* 線より棒を上に */

/* 軸ラベル。棒の下に1行だけ置く。.bars と同じ幅なので目盛りの位置が一致する */
.ax{position:relative;height:16px;max-width:var(--measure);margin:4px 0 0;
  font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums;
  letter-spacing:.02em;}
.ax-m{position:absolute;transform:translateX(-50%);white-space:nowrap;}
.ax-e{position:absolute;right:0;white-space:nowrap;}

/* ── 欠損の3状態 ───────────────────────────
   空白と 0 で埋めない。Song & Szafir (IEEE TVCG 2019) の実験で
   空白（information removal）とゼロ埋め（zero-filling）は
   知覚品質・確信度ともに最下位群だった。
   記号（「-」）ではなく語で書く。日本語UIでは記号より情報量が多い。
   凡例は必ず表の直後の .tblnote に添える（商用12ソース中0件しかやっていない）。 */
.na{font-size:12.5px;color:var(--faint);font-style:normal;white-space:nowrap;}
.na-x{color:var(--muted);}                     /* 非公開＝その社が公表していない */
.na-n{color:var(--faint);}                     /* 拠点なし＝その国に拠点が存在しない */
.na-w{color:var(--note-ink);}                  /* 計測中＝当サイトがまだ確認していない */
.shot .tag{position:absolute;top:12px;left:12px;z-index:2;
  background:var(--ink-strong);color:var(--paper);
  font-size:11px;padding:3px 9px;border-radius:var(--radius-sm);letter-spacing:.04em;}

/* ── 注意。ページに1〜2個まで ── */
.callout{max-width:var(--measure);margin:0 0 34px;padding:22px 24px;
  border-radius:var(--radius);border:1px solid var(--rule);}
.callout.crit{background:var(--alert-soft);border-color:color-mix(in srgb,var(--alert) 26%,transparent);}
.callout.note{background:var(--note-soft);border-color:color-mix(in srgb,var(--note) 24%,transparent);}
.callout.info{background:var(--accent-soft);border-color:color-mix(in srgb,var(--accent) 20%,transparent);}
.callout h3{margin:0 0 10px;font-size:16px;}
.callout.crit h3{color:var(--alert-ink);}
.callout p{margin:0 0 12px;font-size:15px;line-height:1.9;max-width:none;}
.callout p:last-child{margin-bottom:0;}
.callout .cite{font-size:12px;color:var(--muted);margin-top:14px;}

/* ── 表 ──
   幅は本文と同じ。render.py が出す min-width は最大720pxなので、
   PCでは全部の表が横スクロールなしで収まる。 */
/* 枠線は border ではなく outline で引く。
   border だと内寸が 720-2=718px になり、min-width:720px の表が
   2px だけはみ出して横スクロールバーが出てしまう。
   outline は幅を食わないので、内寸をきっちり --measure に保てる。 */
.tblwrap{max-width:var(--measure);overflow-x:auto;margin:0 0 36px;
  outline:1px solid var(--rule);outline-offset:-1px;border-radius:var(--radius);
  -webkit-overflow-scrolling:touch;}

/* ── 2列だけの表（.tblwrap.narrow）2026-08-27 夜 新設 ──────────
   render.py が2列の表にだけ narrow を付ける（いまは compare ページの
   「国 / サーバー台数」「国 / 現在の負荷」の2本）。

   何が起きていたか（PC1280 実測）
     表の幅 720px。1列目 379px ／ 2列目 341px。
     国名は左寄せ、数値は右寄せ（.num）なので、
     「日本」の右端から「292台」の左端まで **618px** 空いていた。
     行を目で追うと、左端の国名から右端の数値まで視線が
     本文1行ぶんの距離を横断することになる。
     オーナー指摘「パーセントと国名の間が広すぎる」はこの618pxのこと。

   間隔は幅だけで決まる。実測（同じページ・同じ行「日本 / 292台」）:
     表の幅 260 → 間隔158 ／ 300 → 198 ／ 340 → 238 ／ 360 → 258
     ／ 400 → 298 ／ 460 → 358 ／ 520 → 418 ／ 720 → 618
   列の配分（1列目を狭くする等）を変えても間隔は1pxも動かない。
   国名が左端・数値が右端に固定されている以上、
   間隔 ＝ 表の幅 −（左右のpadding 32px）−（国名の幅）−（数値の幅）だから。

   360px にした理由
     1. 中身が必要とする最小幅は実測 232px
        （国の列＝最長「シンガポール」89px＋padding 32px＝121px、
          数値の列＝ヘッダ「サーバー台数」79px＋padding 32px＝111px）。
        360px はここに 128px の余裕を足した値。13行すべてで折り返しゼロ
        （行の高さは 720px のときと同じ 55/56px のまま。実測で確認）。
        300px まで詰めても折り返しはしないが、
        ヘッダ「サーバー台数」が列の幅の 78% を占めて窮屈に見える（360pxでは 65%）。
     2. --measure 720px のちょうど半分。本文幅と無関係な数字を持ち込まない。
     3. docs/research/chart-and-table-conventions.md の
        「compare ページを3ブロックに割る」提案が、この2表の min_width を
        360 と書いている。そこと同じ値にした。

   中央寄せにする（2026-08-27 夜・オーナー指示で改訂）
     前回ここは左寄せだった。理由は「ページ上のすべての要素が同じ左端に並ぶ」
     （--measure を1本にした理由そのもの）で、中央寄せにするとこの表だけ
     左端が 180px 内側にずれて縦のラインが1本増えるから。
     オーナーが中央寄せを明示的に指示したので、中央寄せに変える。

     そのままだと崩れるもの（実測して分かった2つ）と、その始末:

     (a) 表の下の <p class="tblnote"> が本文の左端に残る。
         表が中央、注記が左、で「1つの物」に見えなくなる。
         → .tblwrap.narrow の直後の .tblnote だけ、表と同じ幅・同じ中央に置く。
           文字は中央揃えにしない（2行になったとき読みにくい）。
           表と同じ 360px の箱を中央に置いて、その中で左揃え。
     (b) この表は左端の縦のラインから外れる唯一の要素になる。
         外れるなら「本文の列から降りた、独立した1枚」に見えないと中途半端になる。
         → 上下の余白を本文の段落間(30px)より広い 40px にして、
           前後の本文から切り離す。幅が狭いぶん、離すことで自立させる。

   SP（375px）では触らない
     .wrap の内寸が 335px なので、max-width:360px は効かず 335px のまま。
     中央寄せも余白 0 で効かない。
     つまり SP の見た目・横スクロール0・1列目 sticky は変更前と1pxも変わらない。 */
.tblwrap.narrow{max-width:360px;margin-left:auto;margin-right:auto;margin-top:40px;}
/* .tblnote の margin-top:-20px はそのまま効かせる（表に添わせるための値）。
   左右と下だけ上書きして、表と同じ 360px の箱を中央に置く。 */
.tblwrap.narrow + .tblnote{max-width:360px;margin-left:auto;margin-right:auto;margin-bottom:40px;}
/* 2列で折り返しが起きないので、行の高さは折り返し前提の 55px まで要らない。
   縦の空きも「広すぎる」の一部なので、上下だけ 15px → 12px（行 55px → 49px）。
   左右の 16px は動かさない（上の間隔の計算がこれを前提にしている）。 */
.tblwrap.narrow tbody th,.tblwrap.narrow tbody td{padding-top:12px;padding-bottom:12px;}
table{border-collapse:collapse;width:100%;min-width:520px;font-size:14.5px;}
/* 行を分ける線は構造線より薄くする。線が主張すると表が「硬く」見える */
th,td{text-align:left;padding:15px 16px;border-bottom:1px solid var(--rule-soft);
  vertical-align:middle;line-height:1.7;}
/* ヘッダ行は濃色に白抜き（2026-08-27）。
   旧: --sunk(#F5F4F1) の面に --muted(#62696B) の12px。
   地(#FCFBF9)と面の差が 1.06:1 しかなく、ヘッダ行が「行」に見えていなかった。
   docs/research/jp-table-conventions.md A-4 の実測「列ヘッダをブランド色で塗る 5/13」
   に合わせる。競合は全部が白抜き（モバレコ #00BCD1／オリコン #0078D7／
   VPNフリーク #3D79D5）。うちは --thead(#136F63) で、白抜き 6.0:1。
   h2 の帯(--band 9.8:1)より弱いので、ページの中の序列は
   「h2 の帯 ＞ 表のヘッダ ＞ 行見出し(--sunk)」で固定される。 */
thead th{background:var(--thead);font-size:12.5px;color:var(--thead-ink);font-weight:700;
  letter-spacing:.05em;white-space:nowrap;
  border-bottom:none;padding-top:12px;padding-bottom:12px;}
tbody tr:last-child td,tbody tr:last-child th{border-bottom:none;}
td.num,th.num{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;}
/* 出典・取得日。表の枠の外に置く。枠内だとSPの横スクロールで一緒に流れてしまう */
.tblnote{max-width:var(--measure);margin:-24px 0 14px;font-size:12.5px;
  color:var(--faint);line-height:1.8;}
.tblnote a{color:var(--faint);}

/* ── 表の中の主体（VPN・配信サービス）──
   文字だけの表は、どの行が何の話なのか目で追えない。
   ロゴを頭に置くと、行を読まずに縦方向で見つけられるようになる。 */
.ent{display:inline-flex;align-items:center;gap:9px;text-decoration:none;
  color:var(--ink-strong);font-weight:700;line-height:1.4;
  /* 「Private Internet Access」のような長い社名が1文字ずつ折れないようにする */
  word-break:keep-all;overflow-wrap:normal;}
td .ent,th .ent{min-width:0;}
/* 主体の列は最初に幅を確保する。バッジやボタンの列に押されて
   「Private Internet Access」が3行に折れるのを防ぐ */
table td:first-child:has(.ent),
table th:first-child:has(.ent){width:31%;}
a.ent:hover span{text-decoration:underline;
  text-decoration-color:color-mix(in srgb,var(--accent) 45%,transparent);
  text-underline-offset:3px;}
.ent .lg{flex:none;border-radius:5px;object-fit:contain;background:var(--card);
  border:1px solid var(--rule);}
/* 暗所ではロゴの白背景が浮くので、地に馴染ませる */
:root[data-theme="dark"] .ent .lg,
:root:not([data-theme="light"]) .ent .lg{background:#fff;}

/* ── 拠点の有無の表 .cov / .yes / .no（2026-08-27 新設）─────────
   coverage_table() が出す「14カ国 × 5社」の表。
   .cov は社の列（thead の th と tbody の td の両方）に付く。
   中身は ○ / ✕ の1文字だけで、語（拠点あり／拠点なし）は
   title 属性と .sr-only に入っている。

   (1) .cov ＝ 列そのものの整え方

   実測（PC1280・改訂前）: 表の幅 875px に対して .tblwrap の内寸は 720px。
   **155px 分が横スクロールに落ちていた。**
   原因は thead th{white-space:nowrap} で、社名が1行に伸びていたこと。
     Private Internet Access の列だけで 216.8px（他社は 123〜147px）。
   .cov の列だけ折り返しを許すと 740px まで縮む（scroll 155px → 20px）。
   740 は render.py が付ける min-width の値そのものなので、
   **CSS 側で詰められる限界まで詰め切った**ことになる。
   語の途中では割らない（下の table th の keep-all がそのまま効く）。
   text-wrap:balance で「Private Internet / Access」のように行を均す。
   代償は thead の高さ 51.3px → 76.5px（+25px）。
   155px の横スクロールと引き換えなら安い。
   .ent は縦積みにしない。縦積みは .vs2（1対1の比較表）だけの型で、
   ふつうの表のロゴは全部「ロゴ左・社名右」で揃っている。ここもそちらに残す。

   値のセルは中央揃え。1文字しか入らない列で左揃えにすると、
   列見出しの中心と ○ の位置がずれて、どの社の列か目で辿れない。

   (2) .yes / .no ＝ 色に頼らない見分け方

   このサイトの決まりで **セルは塗らない**（勝敗も有無も、
   セルの塗りではなく中身に付いた印で示す＝ .mk と同じ考え方）。
   ここも塗らず、既にある印の語彙にそのまま乗せる:

     .yes（拠点あり）… --accent。「深緑＝計測・確認済み」。
                        .mk-1（この項目で上）・.b-ok（実測で確認できた）と同じ色。
                        各社が公開しているデータに載っている＝確認済み、で意味が一致する。
     .no （拠点なし）… --faint。**.na-n（拠点なし）と同じ色**。
                        同じ「その国に拠点が存在しない」を、
                        表の中では ✕、注記の中では語で書いているだけなので、
                        色まで同じにして1つの意味に見せる。
                        --alert（不可・警告）は使わない。拠点が無いのは
                        その社の失点ではなく事実で、15セルを赤にすると
                        同じページの .b-ng（韓国版は不可）の判定が埋もれる。

   **色を抜いても3点で見分けが付く**（モノクロ印刷・色覚の両方に効く）:
     1. 字形が違う  ○（閉じた円）と ✕（交差する2本）
     2. 太さが違う  700 と 400。.b-claim が「塗らない＋太字をやめる」で
                    b-ok と切り離しているのと同じ、重さの1段差。
     3. 明度が違う  --accent は対 paper 5.2:1、--faint は 4.6:1。
                    グレースケールに落としても ○ のほうが濃い。
   ライト・ダークとも --accent / --faint は @media 側で定義済みなので、
   片方だけで成立する色にはならない。

   ○ は字面が大きく、✕ より一回り大きく見える字なので、
   line-height:1 の inline-block に入れて行の高さを 1.7 のまま動かさない。
   ラベルではなく記号なので palt は掛けない（掛けると ○ が左に寄る）。 */
thead th.cov{white-space:normal;text-align:center;}
thead th.cov .ent{text-wrap:balance;}
td.cov{text-align:center;}
.yes,.no{display:inline-block;line-height:1;font-size:15px;
  font-feature-settings:normal;letter-spacing:0;}
.yes{color:var(--accent);font-weight:700;}
.no{color:var(--faint);font-weight:400;}

.site-link{display:inline-block;font-size:12.5px;white-space:nowrap;
  padding:5px 12px;border:1px solid var(--rule-strong);border-radius:5px;
  color:var(--accent-ink);text-decoration:none;font-weight:700;}
.site-link:hover{border-color:var(--accent);background:var(--accent-soft);}

/* ── 状態表示 ── */
.badge{display:inline-block;font-size:12px;font-weight:700;padding:3px 9px;
  border-radius:var(--radius-sm);white-space:nowrap;line-height:1.6;letter-spacing:.02em;}
/* 実測で確認できたもの。塗る。このサイトでいちばん強い印 */
.b-ok{background:var(--accent-soft);color:var(--accent-ink);}
.b-ng{background:var(--alert-soft);color:var(--alert-ink);}
.b-wait{background:var(--sunk);color:var(--muted);}
.b-warn{background:var(--note-soft);color:var(--note);}
/* 使えるが、どの会社でも差が出ない。vpn-life-68 で追加。
   これまで [注意]（b-warn）を当てていたが、肯定の判定に注意の札が付いて
   「使えるのに突き放された」「判定と説明がちぐはぐ」と読者5人が書いた。
   札を外して文だけにしたら、今度は「この行だけ形が違う」と4人。
   判定の列は札でそろえたうえで、注意でも実測でもない一段を用意する。
   b-wait と同じ地味な塗りにする（当サイトの判定の強さではなく、
   どの社でも同じという意味なので、色で強弱を付けない）。 */
.b-even{background:var(--sunk);color:var(--ink);}
/* 公式がそう書いているだけで、当サイトは未検証。
   このサイトの売りは「実測しかしない」ことなので、
   伝聞が実測と同じ見た目で出ると、いちばんの強みが消える。
   b-ok と3点で切り離す:
     1. 塗らない（b-ok / b-ng / b-wait は全部塗りがある。ここだけ地のまま）
     2. 輪郭を破線にする。.pending が「まだ計測していない」を破線で示しているので、
        サイト内で破線＝未確定という読み方がすでに成立している
     3. 太字をやめる（700 → 500）。文字の重さでも一段下げる
   b-wait（計測中）は --sunk の“塗り”なので、塗りの有無で b-claim と区別が付く。
   輪郭は border ではなく outline で引く（.tblwrap と同じ理由）。
   border だと 1px 分だけ他のバッジより大きくなり、
   同じ行に並べたときに高さが揃わなくなる。outline は幅を食わない。 */
.b-claim{background:transparent;color:var(--muted);font-weight:500;
  outline:1px dashed var(--faint);outline-offset:-1px;}

/* ── 手順 ── */
.steps{max-width:var(--measure);list-style:none;counter-reset:s;padding:0;margin:0 0 36px;
  display:flex;flex-direction:column;gap:30px;}
.steps li{counter-increment:s;display:grid;grid-template-columns:30px 1fr;gap:0 18px;}
/* 本文・図版はすべて右の列に流す。
   指定しないと3つめ以降（手順中のスクリーンショット）が
   番号用の30px列に落ちて、図版だけ30px幅に潰れる。 */
.steps li>*{grid-column:2;min-width:0;}
.steps li::before{content:counter(s);grid-column:1;grid-row:span 2;
  width:29px;height:29px;border-radius:50%;
  border:1.5px solid color-mix(in srgb,var(--accent) 55%,transparent);color:var(--accent-ink);
  display:grid;place-items:center;
  font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;margin-top:3px;}
.steps li h4{font-size:16.5px;margin:0 0 8px;}
.steps li p{margin:0;font-size:15.5px;color:var(--ink);max-width:none;}
.steps li figure{margin:18px 0 0;max-width:none;}

/* ── 数値の要約 ── */
.figs{max-width:var(--measure);display:grid;
  grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:0;margin:0 0 36px;
  border:1px solid var(--rule);border-radius:var(--radius);overflow:hidden;}
.figs>div{padding:20px 22px;border-right:1px solid var(--rule-soft);}
.figs>div:last-child{border-right:none;}
/* span を並べているので、明示的にブロックにしないと値とラベルが1行に混ざる */
.figs .k,.figs .v,.figs .n{display:block;}
.figs .k{font-size:12px;color:var(--muted);line-height:1.6;letter-spacing:.04em;}
.figs .v{font-size:24px;font-weight:700;color:var(--ink-strong);margin-top:6px;
  font-variant-numeric:tabular-nums;line-height:1.3;
  word-break:auto-phrase;text-wrap:balance;letter-spacing:0;}
.figs .v.small{font-size:17px;line-height:1.6;padding:5px 0;}
.figs .n{font-size:12px;color:var(--faint);margin-top:5px;line-height:1.6;}

/* ── 計測待ち ── */
.pending{max-width:var(--measure);border:1px dashed var(--rule-strong);
  border-radius:var(--radius);padding:22px 24px;margin:0 0 34px;background:var(--sunk);}
.pending .lbl{font-size:15px;letter-spacing:.12em;color:var(--muted);font-weight:700;}
.pending p{margin:10px 0 0;font-size:15px;color:var(--ink);line-height:1.9;max-width:none;}

/* ── 出典 ── */
.src{max-width:var(--measure);font-size:12.5px;color:var(--faint);margin:-18px 0 34px;}

/* ── 1対1の比較表 .vs2 ────────────────────────
   日本語サイト16本の実測（2026-08-27）で分かったこと:
     - 9列に詰めた表は PC/SP とも1534pxで横スクロール。3列に絞った1本だけが SP 345px で収まった
     - 勝ちセルの背景塗りは13本中0本。SPカード化（display:contents）も13本中0本
   → 表は節ごとに「項目｜A社｜B社」の3列だけにし、毎回ヘッダで社名を再掲する。
     PCでもSPでも同じ3列。畳まないので「どっちがNordでどっちがSurfか」が消えない。
   勝敗は塗りではなく値の頭の印（.mk）で示す。印はセルの中身に付いているので、
   列幅や折り返しが変わっても意味が残る。 */
/* 比較項目の見出し。表の外に置くので、下の表とくっつけて「この表の名前」に見せる。
   h3 の下2px罫が「ここから下がこの表」の区切りになるので、下の間隔は詰める。
   ただし詰めすぎると h3 の下罫と表の外枠が二重線に見えるので、14px は空ける
   （10px だと二重に見えた。実測で決めた）。
   左右の張り出し(--hb)は h3 と揃えたままにする（外して表と幅が変わると揃わなくなる）。 */
article h3.vs2-h{margin:50px calc(var(--hb) * -1) 14px;}
/* 3列固定。table-layout:fixed にしないと、長い値のある列だけが太る */
.vs2 table{min-width:0;width:100%;table-layout:fixed;}
.vs2 .c-item{width:26%;}            /* SP 375px で約88px。項目名が2行に収まる下限 */
.vs2 thead th{white-space:normal;text-align:center;padding:12px 10px;vertical-align:bottom;}
.vs2 thead th.c-item{text-align:left;}
/* ロゴが上・社名が下。実測では7本中3本がこの型（残りは横並び） */
.vs2 thead .ent{display:inline-flex;flex-direction:column;align-items:center;
  gap:6px;text-align:center;font-size:13.5px;letter-spacing:.01em;
  color:var(--thead-ink);max-width:100%;}
/* ヘッダが濃色になったので、ロゴの下線も地の色ではなく面の色に合わせる */
.vs2 thead a.ent:hover span{text-decoration-color:color-mix(in srgb,var(--thead-ink) 70%,transparent);}
/* ロゴの白い台紙は濃色の上でそのまま使う。枠線だけ面に馴染ませる */
.vs2 thead .ent .lg{border-color:color-mix(in srgb,var(--thead-ink) 35%,transparent);}
.vs2 thead .ent .lg{width:clamp(28px,3.4vw,36px);height:clamp(28px,3.4vw,36px);
  margin:0;padding:2px;}
/* ロゴが取れていない社は名前だけ。中央揃えのまま崩れない */
.vs2 thead .ent span{word-break:keep-all;overflow-wrap:break-word;text-wrap:balance;}
.vs2 tbody th[scope="row"]{background:var(--sunk);font-weight:700;color:var(--ink-strong);
  font-size:13px;white-space:normal;vertical-align:top;
  word-break:auto-phrase;text-wrap:balance;}
.vs2 tbody td{vertical-align:top;}
/* 強調された値は「無制限（台数制限なし）」のような短い句。
   ここだけ文節で折って行長を均す。長い説明文にまで balance を掛けると
   行数が増えてかえって読みにくくなる（実測で確認） */
.vs2 tbody td strong{word-break:auto-phrase;text-wrap:balance;}
/* 勝ち側は塗らない。太字と印だけの控えめな強調に留める（塗るサイトは13本中0本） */
.vs2 td.w strong,.vs2 td.w b{color:var(--accent-ink);}
:root[data-theme="dark"] .vs2 td.w strong,:root[data-theme="dark"] .vs2 td.w b,
:root:not([data-theme="light"]) .vs2 td.w strong,
:root:not([data-theme="light"]) .vs2 td.w b{color:var(--accent);}
.vs2 .vnote{display:block;font-size:11.5px;color:var(--muted);font-weight:400;
  margin-top:4px;line-height:1.65;letter-spacing:.01em;}
.vs2 .sub{display:block;font-size:12px;color:var(--muted);margin-top:3px;line-height:1.6;}
.vs2 .draw{color:var(--faint);}

/* ── 勝敗の印 ──
   実測で7本が値の頭に記号や色つき丸を置いている。塗りと違い、
   セルの中身に付いているのでレイアウトが変わっても残る。
   3種を「塗り／輪郭だけ／グレーの塗り」に分け、色だけに頼らず形で見分けられるようにする。

   印の色は --rule-strong ではなく --faint を使う。
   --rule-strong は地に対して ライト1.6:1 / ダーク1.9:1 しかなく（実測）、
   罫線としてはそれでいいが、意味を持つ印としては消えてしまう。
   --faint は 3.9:1 / 4.2:1 で、非テキストの最低基準3:1を満たす。 */
.mk{display:inline-block;width:11px;height:11px;border-radius:50%;flex:none;
  margin-right:6px;vertical-align:-1px;}
.mk-1{background:var(--accent);}                                /* この項目で上 */
.mk-2{background:transparent;box-shadow:inset 0 0 0 1.5px var(--faint);}  /* 下 */
.mk-eq{background:var(--faint);}                                /* 同等・判定なし */
/* 読み上げ用。目には出さないが、印の意味は音声で必ず伝わるようにする */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}

/* 節末の判定と節末のまとめは .sum（.sum-v / .sum-w）に統合した。
   定義は上の「節の結論 .sum」を参照。
   ぶら下げの経緯: PC1280 実測で1行目の本文は左637.1px・2行目272.5px、ずれ364.6px。
   grid でバッジを別列に出し、ラベルを1行取って上に置いて 0.00px に直した。
   この構造は .sum-v にそのまま引き継いでいる（触らないこと）。 */

/* ── 比較の対 ── */
.vs{max-width:var(--measure);display:grid;grid-template-columns:1fr 130px 1fr;
  align-items:center;gap:16px;padding:18px 0;border-bottom:1px solid var(--rule-soft);}
.vs:last-of-type{border-bottom:none;}
.vs .side{font-size:15px;}
.vs .side.r{text-align:right;}
.vs .side.won{font-weight:700;color:var(--accent-ink);}
.vs .mid{font-size:12px;color:var(--faint);text-align:center;}
.vs .sub{display:block;font-size:12.5px;color:var(--muted);font-weight:400;margin-top:3px;}
/* PCは列の位置でどちらの社か分かるので社名は隠す。SPでは1列になるため出す（下の @media） */
.vs .who{display:none;}

/* ── FAQ ── */
details{max-width:var(--measure);border-bottom:1px solid var(--rule);}
details:first-of-type{border-top:1px solid var(--rule);}
summary{padding:20px 32px 20px 0;cursor:pointer;font-weight:700;font-size:15.5px;
  list-style:none;position:relative;color:var(--ink-strong);}
summary::-webkit-details-marker{display:none;}
summary::after{content:"";position:absolute;right:6px;top:50%;width:8px;height:8px;
  border-right:1.5px solid var(--muted);border-bottom:1.5px solid var(--muted);
  transform:translateY(-70%) rotate(45deg);transition:transform .2s;}
details[open] summary::after{transform:translateY(-30%) rotate(225deg);}
details p{padding:0 0 22px;margin:0;font-size:15.5px;color:var(--ink);max-width:none;}

/* ★★★ 2026-09-01 オーナー指摘「この部分は目立たすな。邪魔」。
   出典の折りたたみは根拠なので残す。ただし FAQ と同じ大きさで並ぶと
   本文より目立つので、キャプションと同じ 12.5px の薄い字に落とす。 */
details.fold{border:none;margin:-6px 0 26px;}
details.fold summary{padding:6px 22px 6px 0;font-size:12.5px;font-weight:500;
  color:var(--faint);}
details.fold summary::after{width:6px;height:6px;right:8px;
  border-right-color:var(--faint);border-bottom-color:var(--faint);}
details.fold ul{margin:0 0 16px;padding-left:18px;font-size:12.5px;
  color:var(--faint);line-height:2;}
details.fold a{color:var(--faint);}

/* ── 記事ではないページ（運営者情報・検証方法）の本文 ── */
.prose{padding-bottom:88px;}
/* 帯・縦線は上の article h2/h3/h4 と共通。ここでは間隔だけを詰める
   （記事より節が短いので、76px だと節と節が離れすぎる） */
.prose h2{margin:68px calc(var(--hb) * -1) 22px;}
.prose h2:first-child{margin-top:40px;}
.prose h3{margin:44px calc(var(--hb) * -1) 14px;}
/* 段落間は行間より広くする（2026-08-28 夜）。
   本文17px・行送り33.15px に対して margin-bottom が 28px だと
   「段落の切れ目 < 行の切れ目」になり、長文が一枚岩に見える。
   36px にして行送りを上回らせる。見出しの margin には触っていない。 */
.prose p{max-width:var(--measure);margin:0 0 36px;}
.prose ol,.prose ul{max-width:var(--measure);margin:0 0 28px;padding-left:1.4em;
  display:flex;flex-direction:column;gap:13px;}
.prose li::marker{color:var(--faint);}

/* ── フッタ（2026-08-28 作り直し）─────────────────────────
   旧: background:transparent（body と地続き）・上に1px線だけ・下に72pxの空白。
       リンクは2本、色は 4.70:1（ライト 4.59:1）でページ内でいちばん弱かった。
       18,501px の記事を読み切った読者に出せる出口が、いちばん読みにくい2本だけ。
   直したこと
     - 背景を --footer-bg に分ける（ライト #F4F2EE ／ダーク #121415）。
       これでヘッダ・本文・フッタが3つの面になる。
     - 文字を --faint から --muted に上げる。
     - 下の空白 72px → 56px。読み終わりに穴を残さない。
     - ヘッダと同じ6リンクを再掲する（.foot-nav。文章は足していない）。 */
.foot{border-top:1px solid var(--rule);background:var(--footer-bg);
  padding:48px 0 56px;font-size:13px;
  color:var(--foot-ink);line-height:1.9;}
.foot .disc{max-width:var(--measure);color:var(--foot-ink);margin-bottom:20px;}

/* フッタのナビ。ヘッダと同じ6本の再掲なので、色も同じ --ink に合わせる。
   ここも :link を足して詳細度を上げないと、ダークで緑に戻る。 */
.foot-nav{display:flex;flex-wrap:wrap;gap:2px 4px;
  margin:0 -11px 26px;padding-bottom:22px;border-bottom:1px solid var(--rule);
  font-size:15px;}
.foot-nav a,.foot-nav a:link,.foot-nav a:visited{
  display:inline-flex;align-items:center;min-height:44px;padding:0 11px;
  color:var(--ink);text-decoration:none;line-height:1;border-radius:var(--radius-sm);}
.foot-nav a:hover{color:var(--accent);background:var(--accent-soft);}

/* ── 上に戻る（2026-08-28 夜 改訂）──────────────────────
   記事の実測 18,501px に対して、戻る手段がゼロだった。
   render.py が footer の直後に <a class="totop" href="#top"> を出しているので、
   ここで丸ボタンにする。中身は文字の ↑ ひとつで、画像は使わない。

   ── なぜ position:fixed をやめたか（実測）──
   前回は幅にかかわらず fixed にしていた。375px で

     ボタン    left=315  right=359
     本文カラム left=0    right=375   → 重なり 60px

   となり、scrollY=0 の時点で本文のリンクの文字を隠していた。
   375px の本文カラムの内寸は335pxで、ボタンが要る 44+16=60px の
   逃げ場がそもそも無い。**body に padding-bottom を足しても直らない。**
   あれが効くのは「文書のいちばん下」だけで、画面に固定されたボタンは
   どの位置までスクロールしても本文の上に乗り続けるため。

   決めたこと: **逃げ場がある幅でだけ浮かせる。**
     幅1024px以上 … .wrap の外寸は784pxで固定なので、左右の余白は
                     (1024-784)/2 = 120px ある。right:24px + 幅44px = 68px なので
                     本文カラムには 52px 以上の余裕を残して届かない。
     幅1024px未満 … 浮かせず、フッタのいちばん下の余白（padding-bottom 56px、
                     文字が1文字も無い帯）に負のマージンで置く。
                     重なりは構造上ゼロになる。18,500px を読み切った読者が
                     いちばん下で必ず出会う位置なので、出口としては同じ役目を果たす。

   型セレクタの a を1つ足して詳細度を (0,2,1) にそろえている。
   `.totop:link`（0,2,0）だと `:root:not([data-theme="light"]) a`（0,2,1）に負け、
   ↑ の文字色が地の緑と同じになって矢印が消える（ライトで実測 1.00:1）。 */
a.totop,a.totop:link,a.totop:visited{
  position:relative;z-index:50;
  width:44px;height:44px;border-radius:50%;
  /* 上に -52px でフッタの下余白の中に入れ、左マージン auto で右に寄せる */
  margin:-52px 16px 8px auto;
  display:grid;place-items:center;
  font-size:18px;line-height:1;text-decoration:none;
  background:var(--accent);color:var(--on-accent);
  box-shadow:0 4px 14px rgba(0,0,0,.35);}
a.totop:hover{background:var(--accent-ink);color:var(--on-accent);}
@media (min-width:1024px){
  a.totop,a.totop:link,a.totop:visited{
    position:fixed;right:24px;bottom:24px;margin:0;}
}

/* ── スマートフォン ───────────────────────────
   原則: ページ本体は横に動かさない。動くのは表とチャートの内側だけ。 */
@media (max-width:640px){
  /* 張り出しは 16px → 12px。.wrap の左右 padding は 375px のとき 20px なので、
     帯の外側に 8px 残る。ページ本体は横に動かさない（実測で確認） */
  :root{--hb:12px;}
  body{font-size:16.5px;line-height:1.9;}

  /* ── SPのヘッダ（2026-08-28）────────────────────────────
     旧: 1段のまま overflow-x:auto。375px で scrollWidth 385 / clientWidth 228＝
         157px が画面外。「実測データ」「検証方法」は1文字も見えず、
         横に払える手掛かり（フェード・矢印・スクロールバー）も無かった。
     直しかた: 横スクロールをやめて **折り返す**。
       .wrap の内寸は375pxのとき335px。リンクは padding 0 11px 込みで
       81/51/97/51/94/82px なので、4本＋2本の2段でちょうど収まり、
       はみ出しは 0 になる（横に払う操作そのものが要らなくなる）。
     2段にするとヘッダは約150pxになり、812pxの画面の18%を占めるので、
     SPでは sticky をやめて静止させる。戻る手段は .totop（固定の丸ボタン）が担う。 */
  /* 2026-08-28 夜 再改訂: SPは position:static にしていた。
     実測すると /vpn/nordvpn/review/ は全高 20,714px あり、
     147px のヘッダが流れてしまうので **99.3% の区間で看板が見えない**。
     .totop も Y=20,663px（99.8%地点）にしか無く、戻る導線が死んでいた。
     ヘッダ147pxのうち上の -95px を画面の外に逃がして貼り付けると、
     ブランド行の 52px だけが上端に残る（812pxの6.4%）。
     ナビ2段はスクロールで流れるので、本文にはかぶらない。 */
  /* ── なぜ position:sticky;top:-95px を採らなかったか（実測）──
     指定どおり top:-95px を当てて 375px で測ると、上端に残る52pxは
     **ブランド行ではなくナビの2段目**（「実測データ 検証方法」）だった。
     sticky は箱の下端側を残すので、箱の上に組んであるブランド行から
     先に画面外へ出ていく。ブランドを残すには箱の中の並びを
     「ナビが上・ブランドが下」に反転するしかなく、看板が下に来てしまう。

     同じ結果（ブランド行52pxだけが貼り付き、ナビ2段は流れる）を
     並びを崩さずに出すため、**ブランド行だけを position:fixed にする**。
       .site  は静止のまま。上に52pxぶんの場所を空けておく
       .brand は上端に固定した52pxの帯（地と下線はヘッダと同じ）
     常時のコストは52px（812pxの6.4%）で指定どおり。ナビ2段は流れる。 */
  .site{position:static;box-shadow:none;padding-top:52px;}
  .site .bar{min-height:0;flex-wrap:wrap;align-items:center;
    gap:0;padding-top:8px;padding-bottom:8px;}
  .site .brand,.site .brand:link,.site .brand:visited{
    position:fixed;top:0;left:0;right:0;z-index:45;
    display:flex;align-items:center;gap:10px;
    height:52px;min-height:0;padding:0 var(--pad);
    font-size:18px;
    background:var(--shell);border-bottom:1px solid var(--shell-line);}
  .site nav{width:100%;margin-left:0;justify-content:flex-start;
    margin-inline:-11px;}
  .site nav a,.site nav a:link,.site nav a:visited{min-height:44px;}
  /* 上端に残るのは 52px なので、その分＋余白を逃がす */
  h2[id],h3[id],h4[id]{scroll-margin-top:60px;}
  .foot-nav{font-size:15px;}
  .head h1{font-size:25px;line-height:1.52;}
  /* 本文16.5pxに対して h2 1.21 / h3 1.09 / h4 1.03倍。
     tsuzukiblog の SP375 実測（15px に対して 1.20 / 1.10 / 1.05）とほぼ同じ比率。
     大きさでは分けない。分けているのは帯・薄面＋線・線だけ、の3段。 */
  article h2,.prose h2{font-size:20px;padding:11px var(--hb);}
  article h2{margin:56px calc(var(--hb) * -1) 20px;}
  article h3,.prose h3{font-size:18px;padding:2px var(--hb) 8px calc(var(--hb) - 5px);}
  article h3{margin:40px calc(var(--hb) * -1) 15px;}
  article h4,.prose h4{font-size:17px;padding-left:calc(var(--hb) - 3px);}
  article h4{margin:28px calc(var(--hb) * -1) 10px;}
  .prose h2{margin:52px calc(var(--hb) * -1) 16px;}
  .prose h3{margin:38px calc(var(--hb) * -1) 12px;}
  /* 囲みの中の見出しは SP でも 16px に固定する（契約 §3-2）。
     ここを書かないと .prose h3（同詳細度・後勝ち）に負けて 18px になり、
     本文17pxを唯一超えるラベルになる。競合4本に本文超えは0本だった。 */
  .callout h3,.callout h4,
  .steps li h3,.steps li h4,
  .answer h3,.answer h4{font-size:16px;padding:0;margin:0 0 10px;}
  article p{margin-bottom:28px;}
  .prose p{margin-bottom:34px;}
  .toc ol{grid-template-columns:1fr;}
  .answer{padding:6px 0 6px 20px;}

  /* 1列に潰れると「値・項目名・値」の順になって何の比較か分からなくなる。
     項目名を先頭へ送り、各値には社名を添える。 */
  .vs{grid-template-columns:1fr;gap:4px;padding:16px 0;}
  .vs .side,.vs .side.r{text-align:left;}
  .vs .mid{order:-1;text-align:left;font-weight:700;color:var(--muted);
    font-size:12px;letter-spacing:.06em;margin-bottom:4px;}
  .vs .who{display:block;font-size:11px;letter-spacing:.06em;color:var(--faint);
    font-weight:500;margin-bottom:1px;}
  .vs .side+.mid+.side{margin-top:6px;}
  /* .sum-v はPCの時点で1列（上の定義を参照）。ここでは行間だけ詰める。
     .who は grid アイテムなので、justify-self:start が無いと1fr いっぱいに
     伸びて緑の帯になる（.sum .who に指定済み）。 */
  .sum-v{row-gap:7px;}
  .sum-w{grid-template-columns:minmax(0,1fr);row-gap:4px;}
  /* 枠が付いたぶん左右を少し詰める。内寸335pxのうち本文に305px残る */
  .sum{padding:14px 15px;}

  .figs{grid-template-columns:1fr 1fr;}
  .figs>div{border-bottom:1px solid var(--rule-soft);padding:16px 18px;}
  .figs>div:nth-child(2n){border-right:none;}
  .figs .v{font-size:22px;}
  .steps li{grid-template-columns:26px 1fr;gap:14px;}
  .steps li::before{width:25px;height:25px;font-size:12px;}

  /* ── データの表（.tblwrap 単体）──────────────
     国×指標のような行列は、畳むと縦に長くなりすぎて比較にならない。
     競合実測（2026-08-27 / 390px）でも、データ表は例外なく横スクロール:
       VPNラボ 7列800px（1列目固定）／ LIH 7列1020px ／ vpn-hikaku 8列773px
     いちばん出来がよかった VPNラボ に合わせ、
     「1列目を貼り付けたまま横スクロール」にする。
     行の見出し（国名・項目名）が消えないので、何の行か分からなくならない。 */
  th,td{padding:12px 13px;font-size:13.5px;}
  .tblwrap:not(.vs2) th,.tblwrap:not(.vs2) td{position:relative;}
  /* width:9em は「行見出しの分だけ確保する」の意味。
     指定しないと min-width の余りが1列目にも配分され、
     335pxの画面で固定列だけが270pxを占めて、肝心のデータが見えなくなる。 */
  .tblwrap:not(.vs2) tr>:first-child{
    width:9em;white-space:normal;word-break:auto-phrase;
    text-wrap:balance;overflow-wrap:anywhere;}
  /* 貼り付けた1列目の地は、ヘッダ行と同じ濃色にする。
     ここだけ --sunk のままだと、横スクロールした瞬間に
     ヘッダ行の左端に色の穴が開く */
  .tblwrap:not(.vs2) thead th:first-child{
    position:sticky;left:0;z-index:3;background:var(--thead);}
  .tblwrap:not(.vs2) tbody th:first-child,
  .tblwrap:not(.vs2) tbody td:first-child{
    position:sticky;left:0;z-index:2;background:var(--paper);}
  /* 固定列の右に落ちる影。ここから先がスクロールする、という合図 */
  .tblwrap:not(.vs2) thead th:first-child::after,
  .tblwrap:not(.vs2) tbody th:first-child::after,
  .tblwrap:not(.vs2) tbody td:first-child::after{
    content:"";position:absolute;top:0;right:0;bottom:-1px;width:11px;
    transform:translateX(100%);pointer-events:none;
    background:linear-gradient(to right,rgba(0,0,0,.045),rgba(0,0,0,0));}
  :root[data-theme="dark"] .tblwrap:not(.vs2) th:first-child::after,
  :root[data-theme="dark"] .tblwrap:not(.vs2) td:first-child::after,
  :root:not([data-theme="light"]) .tblwrap:not(.vs2) th:first-child::after,
  :root:not([data-theme="light"]) .tblwrap:not(.vs2) td:first-child::after{
    background:linear-gradient(to right,rgba(0,0,0,.28),rgba(0,0,0,0));}
  /* 2列の表は SP 375 でも横スクロールしない（実測 scrollWidth − clientWidth ＝ 0）。
     影は「ここから先がスクロールする」の合図なので、出す理由がない。
     消さないと、動かない表の1列目の右に縦の帯が1本残って読みにくい。 */
  .tblwrap.narrow th:first-child::after,
  .tblwrap.narrow td:first-child::after{display:none;}

  /* ── 1対1の比較表（.vs2）──────────────────
     旧 .vs-table はSPでカード化（display:contents）して行をカードに畳んでいたが、
     これは日本語サイト13本中0本の独自手法だった。
     畳むと「どちらの列がどちらの社か」を読者が毎回組み立て直すことになる。
     3列に絞った今は 375px に素直に収まるので、畳まずそのまま出す。 */
  article h3.vs2-h{margin:40px calc(var(--hb) * -1) 12px;}
  .vs2 th,.vs2 td{padding:11px 7px;font-size:13px;}
  .vs2 thead th{padding:10px 6px;}
  .vs2 tbody th[scope="row"]{font-size:12.5px;padding-left:10px;padding-right:7px;}
  .vs2 thead .ent{font-size:12px;gap:5px;letter-spacing:0;}
  .vs2 thead .ent .lg{width:22px;height:22px;}
  .vs2 .mk{width:9px;height:9px;margin-right:5px;}
  .vs2 .vnote{font-size:11px;margin-top:3px;}

  /* ── 横棒グラフ（HTML版）──────────────────
     SPでも文字を縮めない。ここが今いちばん壊れていたところ。
     旧: viewBox 720 の SVG が 335px に潰れて実効 6.05px
     新: 12.5px のまま（figcaption と同じ大きさ）。横スクロールも出ない。 */
  .bars .br-l,.bars .br-v{font-size:12.5px;}
  .bars .br{margin-bottom:12px;}
  .bars .br-hd{gap:10px;}

  /* ── 格子・軸を持つ図だけは横スクロールに戻す ──
     潰して読めなくするよりよい。前回 min-width を外したのは、
     横スクロールを「文字の縮小」に置き換えただけだった。
     720ではなく560にするのは、必要な最小幅だけを確保するため。 */
  .chart{overflow-x:auto;-webkit-overflow-scrolling:touch;}
  .chart svg{min-width:560px;}
}
/* ── 表のセル: カタカナ語と英数字を割らせない（2026-08-27）──────────────
   本文を auto-phrase に戻したあとも SP375 でカタカナ割れが 34件残り、
   出どころは全部 .vs2 のセルだった（「シ／ンガポール」「ベト／ナム」
   「マレー／シア」「インドネ／シア」）。原因は2つ:
     (a) セルが 9em しかなく、auto-phrase でも文節が入りきらないと素の折り方に落ちる
     (b) SP の .vs2 tbody th に overflow-wrap:anywhere が入っていて、
         英数字（DoubleVPN / ThreatProtection）を任意の位置で割っていた
   セルに入るのは国名・機能名・数値で、いずれも短い語。
   語を割るくらいなら表を横に伸ばすほうがよい。表は .tblwrap の中で
   横スクロールする作りになっていて、ページ本体は overflow-x:hidden なので、
   ページ全体の横スクロールは 0 のまま（実測で確認済み）。
   ここは上の @media より後ろに置いて、SP側の anywhere も上書きする。 */
table th,table td,
.vs2 thead th,.vs2 tbody th,.vs2 tbody td,
.vs2 tbody td strong,.vs2 thead .ent span,
.tblwrap:not(.vs2) tr>:first-child,
.tblwrap:not(.vs2) thead th:first-child,
.tblwrap:not(.vs2) tbody td:first-child{
  word-break:keep-all;overflow-wrap:normal;}

/* ── 2列の表（.tblwrap.narrow）が本文幅からはみ出していた ──────────
   2026-08-28 オーナー指摘「◯◯とはの表に横スクロールが出て、
   セルの文字が『海外から日本のサー…』で切れている」。実測して原因を2つに分けた。

   (1) 横スクロール ＝ 箱と表の幅が食い違っていた
       .tblwrap.narrow{max-width:360px}（上の 921行）に対して、
       render.py が表に inline で min-width:460px を付けている。
       inline は CSS より強いので table{min-width:520px}（929行）ではなく
       460px が効き、**箱 360px に 460px の表**が入っていた。
       実測 unblock/tbs-free（PC1280）: clientWidth 360 / scrollWidth 460 → 100px はみ出し。
       SP375 では箱が 335px になるので 125px はみ出し。
       → 2列の表だけ min-width を 0 に戻す。inline に勝つため !important が要る
         （CSS で inline を上書きする唯一の手段）。table{width:100%} は既に効いているので、
         表は箱の幅（PC 360px / SP 335px）ちょうどに収まる。

   (2) 文字切れ ＝ text-overflow ではなかった
       narrow のセルの text-overflow は実測で全部 clip、overflow は visible。
       省略記号は1文字も出ていない（HTML にも「…」は0件）。
       切れて見えていたのは (1) のはみ出しそのもの。
       1列目が SP で position:sticky（1283行付近）なので、
       横スクロール前の状態では 2列目の見えている幅が 335 − 178 = 157px しかなく、
       282px あるセルの右 125px が箱の外に出て、右端でスパッと切れて見えていた。
       → (1) を直せば消えるが、幅を詰めるとセルが折り返せないと今度は表が縮まない。
         直前のブロック（1353行）が全セルに word-break:keep-all を掛けていて、
         日本語は1文字も折れない。実測の最小幅は SP13.5px で
         1列目「当サイトの視聴可否判定」175px ＋ 2列目「海外から日本のサービスを見る」215px
         ＝ 390px で、335px の箱には入らない。
       → 2列の表のセルだけ、本文と同じ word-break:auto-phrase にする。
         auto-phrase は文節の切れ目でしか折らないので
         「海外から／日本の／サービスを／見る」となり、
         1353行が守っているカタカナ語・英数字は割れない（実測で確認）。
         auto-phrase は Chromium系だけなので、下の @supports が
         非対応ブラウザを normal（日本語の既定＝どこでも折る）に戻す。
         495〜605行の本文の設定と .vs2・データ表の keep-all は一切触っていない。

   (3) narrow が付いていない2列の表が30本あった
       build/site を全部数えると 2列の表は167本、うち30本は
       .narrow が付かないまま inline min-width:460px を持っている
       （vpn/{slug}/ の「ページ / 何が書いてあるか」）。箱は SP で 335px なので
       同じ125pxのはみ出しが出る。narrow の有無ではなく **列が2つかどうか**で
       効かせたいので、:has() で「3つめのセルが無い表」を選ぶ。
       :has() 非対応のブラウザでは規則ごと落ちて、いまと同じ（＝横スクロール）に留まる。
       この形にすると render.py 側で narrow を付け足さなくても直る。

   (4) 1列目の position:sticky を2列の表では外す
       sticky は「横スクロールしても行見出しを残す」ための指定（1283行付近）。
       2列の表はもう1pxも横に動かないので仕事が無く、
       positioned な要素として .tblwrap の outline より後に描かれるぶん、
       枠の左下1辺を --paper で塗り潰していた（実測: セルの bottom と
       .tblwrap の bottom がどちらも 550.1px で完全に重なる）。
       静的に戻すと枠が1周つながる。スクロールの合図の影も同じ理由で消す。

   列数の多い表（3列以上）はここに入らない。設計どおり .tblwrap の中で
   横スクロールしたまま（実測 SP375: 6列 740px / 5列 640px / 4列 560px /
   3列 675px、いずれも変更前後で1pxも動かない）。 */
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))){min-width:0 !important;}
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) th,
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) td{
  word-break:auto-phrase;overflow-wrap:break-word;line-break:strict;}
@supports not (word-break:auto-phrase){
  .tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) th,
  .tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) td{word-break:normal;}
}
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) thead th:first-child,
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) tbody th:first-child,
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) tbody td:first-child{
  position:static;}
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) th:first-child::after,
.tblwrap:not(.vs2)>table:not(:has(tr>*:nth-child(3))) td:first-child::after{
  display:none;}

@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto;}*{transition:none !important;}}

/* ══════════════════════════════════════════════════════════════
   ★★★★ 2026-09-01 オーナー指示で新設
     「ポジティブな部分には緑のボックス、ネガティブな部分は赤のボックスで囲む」
     「向いている人・向いていない人とか、ちゃんと見せ方も変えた方がいい」
     「必要な場所には画像を差し込む」「記事につながるボタンを置く」
   ★ 色は既存のトークンを使う（--accent 緑 / --alert 赤）。
     新しい色を足すと、明暗の切り替えで片方が読めなくなる。
   ══════════════════════════════════════════════════════════════ */

/* ── メリット／デメリットの2列 ────────────────────────────
   ★★★★ 2026-09-01 オーナー指摘で作り直した:
     「グリーンっぽいのやめてくれるかな？クローンサイトに寄せてると思われる」
     「今のVPNライフのカラーに寄せてください」
     「緑、赤、緑で、緑が多すぎる」
   ★ このサイトで「面」を持てるのは h2 の帯と表の見出しの2つだけ、と決めてある
     （上の「塗りの2段」参照）。**箱を色で塗りつぶさない。**
     地はカードのままにして、色は**左の罫と見出しの文字だけ**に置く。
   ★ 「◯◯がおすすめなのは」は3つ目の箱なので、**色を使わない。**
     ここまで色を付けると緑・赤・緑になって、うるさくなる。 */
.pncols{display:grid;grid-template-columns:1fr 1fr;gap:18px;
        max-width:var(--measure);margin:0 0 30px;}
@media (max-width:700px){.pncols{grid-template-columns:1fr;gap:14px;}}

.pnbox{border:1px solid var(--rule);border-left-width:3px;border-radius:8px;
       padding:16px 18px 14px;background:transparent;}
.pnbox > .ttl{margin:0 0 10px;font-size:14px;font-weight:700;letter-spacing:.04em;}
.pnbox ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:9px;}
.pnbox li{font-size:14.5px;line-height:1.85;padding-left:18px;position:relative;
          color:var(--ink);}
.pnbox li::before{position:absolute;left:0;top:0;font-size:12.5px;font-weight:700;}

.pnbox.good{border-left-color:var(--accent);}
.pnbox.good > .ttl{color:var(--accent-ink);}
.pnbox.good li::before{content:"○";color:var(--accent);}

.pnbox.bad{border-left-color:var(--alert);}
.pnbox.bad > .ttl{color:var(--alert-ink);}
.pnbox.bad li::before{content:"×";color:var(--alert);}

/* ── 「◯◯がおすすめなのは」 ──────────────────────────────
   ★ 3つ目の箱。**色を使わない。**罫と余白だけで区切る。 */
.fitbox{max-width:var(--measure);margin:0 0 26px;padding:16px 18px 14px;
        border:1px solid var(--rule);border-radius:8px;background:var(--paper-2,transparent);}
.fitbox > .ttl{margin:0 0 10px;font-size:14px;font-weight:700;
               color:var(--ink-strong);letter-spacing:.02em;}
.fitbox ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:9px;}
.fitbox li{font-size:14.5px;line-height:1.85;padding-left:18px;position:relative;
           color:var(--ink);}
.fitbox li::before{content:"";position:absolute;left:2px;top:.82em;
                   width:8px;height:1.5px;background:var(--rule-strong);}

/* ── 記事へつなぐボタン ──────────────────────────────────
   ★★★ 2026-09-01: 文字色が背景と同じ色になっていて、
     ボタンが「緑の塗りだけ」に見えていた（オーナー指摘「ボタンもなんのこの色ないの？」）。
     原因は .prose a{color:...} に負けていたこと。**詳細度を上げる。**
     色は --on-accent（このサイトが持っているトークン）を使う。 */
/* ★★★ オーナー指摘「ボタンはセンタリングしろって、何回言ったらわかんの？」 */
.ctawrap{max-width:var(--measure);margin:0 0 34px;text-align:center;}
.ctawrap .capt{display:block;font-size:13px;color:var(--muted);margin:0 0 10px;}
/* ★★★ 詳細度のメモ（2026-09-01・ダークで実測して見つけた）:
   `article a.cta` は (0,1,2) で、ダークの
   `:root:not([data-theme="light"]) a{color:var(--accent)}`（0,2,1）に**負ける**。
   その結果、ボタンの文字色が地の色と同じ #6BBFB0 になり、
   ダークでは「緑の塊」に見えていた（ライトでは正しく出ていたので気づけなかった）。
   → :link / :visited を足して (0,2,1) にそろえる。
     同点なら後に書いたほうが勝つので、ここが勝つ。 */
.prose a.cta,article a.cta,a.cta,
.prose a.cta:link,article a.cta:link,a.cta:link,
.prose a.cta:visited,article a.cta:visited,a.cta:visited{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  margin-inline:auto;
  min-width:min(340px,100%);padding:14px 26px;border-radius:8px;
  background:var(--accent);color:var(--on-accent);
  font-weight:700;font-size:15px;line-height:1.5;
  text-decoration:none;border:1px solid var(--accent);
  transition:filter .15s ease;}
.prose a.cta::after,a.cta::after,
.prose a.cta:link::after,a.cta:link::after{content:"›";font-size:18px;font-weight:700;
                                 color:var(--on-accent);}
.prose a.cta:hover,a.cta:hover{filter:brightness(1.08);text-decoration:none;}
.prose a.cta.ghost,a.cta.ghost,
.prose a.cta.ghost:link,a.cta.ghost:link,
.prose a.cta.ghost:visited,a.cta.ghost:visited{
                               background:transparent;color:var(--ink-strong);
                               border-color:var(--rule-strong);}
.prose a.cta.ghost::after,a.cta.ghost::after{color:var(--muted);}
.prose a.cta.ghost:hover,a.cta.ghost:hover{border-color:var(--accent);filter:none;}

/* ── 「あわせて読みたい」の記事カード ─────────────────── */
a.readnext{display:flex;gap:14px;align-items:center;max-width:var(--measure);
           margin:0 0 34px;padding:14px 16px;border:1px solid var(--rule);
           border-radius:8px;text-decoration:none;}
a.readnext:hover{border-color:var(--rule-strong);}
a.readnext .lb{flex:0 0 auto;font-size:11px;letter-spacing:.1em;
               color:var(--muted);font-weight:700;}
a.readnext .tx{display:flex;flex-direction:column;gap:4px;min-width:0;}
a.readnext .tx b{font-size:15px;color:var(--ink-strong);line-height:1.6;}
a.readnext .tx span{font-size:13px;color:var(--muted);line-height:1.7;}

/* ── STEP の見出しに番号をつける ──────────────────────── */
h3.step{display:flex;align-items:baseline;gap:12px;}
h3.step .n{flex:0 0 auto;font-size:12px;font-weight:800;letter-spacing:.08em;
           color:var(--accent-ink);background:var(--accent-soft);
           border:1px solid color-mix(in srgb,var(--accent) 30%,transparent);
           border-radius:6px;padding:3px 9px;}

/* ── 2列だけの表の幅（★ 2026-09-01 に直した） ──────────────
   ★ .tblwrap.narrow は max-width:360px で、
     「日本 … 292台」のような**短い値**の2列表のために作ったもの。
     そこに長い文（「サイトは日本語あり（…）。アプリと問い合わせ窓口は未確認」）
     が入る表を流したら、360px に押し込まれて横スクロールになり、
     オーナーに「テーブルがなんでこんなに細くなってんの？」と言われた。
   ★★ 長い値が入る2列表は narrow を使わないこと。
     どうしても2列で出すなら、下の .tblwrap.spec を使う（本文幅いっぱい）。 */
.tblwrap.spec{max-width:var(--measure);margin-left:0;margin-right:0;}
.tblwrap.spec table{min-width:0;}
/* ★ table() は1列目も <td> で出す。th だけを指定しても効かない（2026-09-01 に気づいた）。 */
.tblwrap.spec tbody tr > *:first-child{width:38%;white-space:nowrap;color:var(--muted);}
.tblwrap.spec tbody tr > *:last-child{color:var(--ink-strong);font-weight:600;}
@media (max-width:600px){
  .tblwrap.spec tbody tr > *:first-child{width:46%;white-space:normal;}
}

/* ══════════════════════════════════════════════════════════════
   ★★★★ 2026-09-01（2回目）オーナー指摘で足したもの
     「タイトルが変なところで改行されてる。導入文も」
     「テーブルは全部崩れ出るんでやり直し。列の幅は全て一緒に。
       縦詰めになって縦長になるとかしないで」
     「リストだけを無造作に置くな。ボックスで囲め」
     「VPNのロゴ出すとか、キーカラーごとにグラフの色変えるとか」
     「ボタンはVPNサービスのキーカラーに」
   ══════════════════════════════════════════════════════════════ */

/* ── 日本語の折り返し ──────────────────────────────────────
   ★ 「マレーシアから日本のサービスを使うための／VPNを、」のように
     文節の途中で折れていた。auto-phrase は文節で折る（対応ブラウザのみ）。
     知らないブラウザは値を無視するので、従来どおりに折れるだけ。 */
h1,h2,h3,h4,.lede,.sec-lead,figcaption,.tblnote,.answer li,.callout p,
.pnbox li,.fitbox li,.listbox li,.sum{
  word-break:auto-phrase;line-break:strict;}

/* h1 に「｜」があるときは、そこで折る（行頭に｜が来ないように） */
.head h1 .t1,.head h1 .t2{display:block;}
.head h1 .t2{font-size:.72em;color:var(--muted);margin-top:.35em;}
.head h1 .t2::before{content:"";}

/* ── 表 ───────────────────────────────────────────────────
   ★★ 列の幅をそろえる。1列目（VPN名）だけ広く、あとは等幅。
     ExpressVPN の「大阪、渋谷、東京、横浜」が縦に4行積まれて
     行だけが縦長になっていた（オーナー指摘）。 */
.tblwrap.grid table{table-layout:fixed;width:100%;}
.tblwrap.grid th,.tblwrap.grid td{
  white-space:normal;overflow-wrap:anywhere;word-break:auto-phrase;
  vertical-align:middle;}
.tblwrap.grid tbody td{padding-top:14px;padding-bottom:14px;}
.tblwrap.grid .ent{white-space:normal;}

/* ── 裸のリストを置かないための箱 ───────────────────────── */
.listbox{max-width:var(--measure);margin:0 0 30px;padding:16px 18px 14px;
         border:1px solid var(--rule);border-left:3px solid var(--rule-strong);
         border-radius:8px;}
.listbox > .ttl{margin:0 0 10px;font-size:14px;font-weight:700;color:var(--ink-strong);}
.listbox ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:9px;}
.listbox li{font-size:14.5px;line-height:1.85;padding-left:18px;position:relative;}
.listbox li::before{content:"";position:absolute;left:2px;top:.82em;
                    width:8px;height:1.5px;background:var(--rule-strong);}

/* ── ロゴ付き・キーカラーの横棒 ──────────────────────────── */
/* 棒どうしの間隔も 14px では詰まって見えた（ロゴが 22px あるため）。 */
.vbars{max-width:var(--measure);margin:0;display:flex;flex-direction:column;gap:22px;}
.vb{display:grid;grid-template-columns:minmax(150px,1fr) auto;
    grid-template-areas:"l t" "r r";gap:6px 12px;align-items:center;}
.vb-l{grid-area:l;display:flex;align-items:center;gap:8px;min-width:0;}
.vb-l b{font-size:14px;font-weight:600;color:var(--ink);
        overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.vb-l .lg{width:22px;height:22px;flex:0 0 22px;border-radius:5px;}
.vb-l .fl{font-size:18px;line-height:1;flex:0 0 auto;}
.vb-t{grid-area:t;font-size:14px;font-weight:700;color:var(--ink-strong);
      font-variant-numeric:tabular-nums;white-space:nowrap;}
.vb-r{grid-area:r;display:block;height:9px;border-radius:99px;
      background:var(--rule-soft);overflow:hidden;}
.vb-r i{display:block;height:100%;border-radius:99px;background:var(--accent);}

/* ── ロゴと数字のカード（画面が撮れていない社の図） ───────── */
.bcard{max-width:var(--measure);border:1px solid var(--rule);border-radius:10px;
       overflow:hidden;}
.bcard .bc-h{display:flex;align-items:center;gap:12px;padding:14px 18px;
             background:color-mix(in srgb,var(--bc) 14%,transparent);
             border-bottom:3px solid var(--bc);}
.bcard .bc-h .lg{width:34px;height:34px;border-radius:7px;}
.bcard .bc-h b{font-size:17px;color:var(--ink-strong);}
/* ★★★ 2026-09-01 オーナー指摘:「1、2、3、4、5。5カラムをなんで4カラムで並べて、
   返金30日が1つだけ下に残ってんの？」
   auto-fit だと入る数だけ詰めるので、5項目のとき 4＋1 になって最後が余る。
   → 項目の数（--n・render.py が渡す）でそのまま割る。**項目は4つまでにする。** */
.bcard .bc-b{display:grid;grid-template-columns:repeat(var(--n,4),minmax(0,1fr));}
@media (max-width:700px){
  .bcard .bc-b{grid-template-columns:repeat(2,minmax(0,1fr));}
}
.bcard .bc-i{padding:14px 18px;border-right:1px solid var(--rule-soft);
             border-top:1px solid var(--rule-soft);}
.bcard .bc-i span{display:block;font-size:12px;color:var(--muted);margin-bottom:4px;}
.bcard .bc-i b{font-size:16px;color:var(--ink-strong);font-variant-numeric:tabular-nums;}

/* ── 表の中に置く、公式サイトへの小さなボタン ──────────────────
   ★ オーナー指摘「右側には公式へのボタンを置けよ」。
     比較表のいちばん右の列に、その社のキーカラーで置く。 */
/* ★ 詳細度のメモ: `:root:not([data-theme="light"]) a{color:var(--accent)}` は
   (0,2,1) で、data-theme が付いていない既定の状態でも当たる。
   `.minicta:link`(0,2,0) では負けて、文字が地の緑になる。
   `article a.minicta:link`(0,2,2) まで上げること（.cta と同じ形）。 */
.minicta,.prose a.minicta,article a.minicta,
.minicta:link,.minicta:visited,
.prose a.minicta:link,.prose a.minicta:visited,
article a.minicta:link,article a.minicta:visited{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  padding:7px 12px;border-radius:6px;white-space:nowrap;
  background:var(--bc,var(--accent));color:var(--bf,#fff);
  border:1px solid var(--bc,var(--accent));
  font-size:13px;font-weight:700;line-height:1.2;text-decoration:none;}
.minicta:hover{filter:brightness(1.08);text-decoration:none;}
.minicta .lg,.shot .minicta .lg{width:16px;height:16px;flex:0 0 16px;border-radius:4px;}

/* ── 各社のキーカラーのボタン ────────────────────────────── */
/* ★ 文字色は白の決め打ちをやめた。CyberGhost の #FCCC0C（黄）に白を載せると
   1.5:1 しか出ず、ボタンの文字が読めなかった（2026-09-01 にダークで実測）。
   render.py が --bc の明るさから --bf（読める側の色）を出して渡す。 */
.prose a.cta.brand,a.cta.brand,
.prose a.cta.brand:link,a.cta.brand:link,
.prose a.cta.brand:visited,a.cta.brand:visited{
  background:var(--bc);border-color:var(--bc);color:var(--bf,#fff);
  gap:10px;padding:14px 24px;}
.prose a.cta.brand .lg,a.cta.brand .lg{width:24px;height:24px;border-radius:6px;
                                       background:#fff;padding:2px;}
.prose a.cta.brand::after,a.cta.brand::after,
.prose a.cta.brand:link::after,a.cta.brand:link::after{color:var(--bf,#fff);}

/* ── おすすめ順の 1・2・3 ─────────────────────────────────
   ★ 2026-09-01: まとめに返金日数のグラフを置いていて
     「なんでいきなり返金保証の日数のグラフが出てくるの？」と言われた。
     **見出しの中身に合う図を置くこと。**まとめなら順位。 */
.ranks{max-width:var(--measure);display:flex;flex-direction:column;gap:12px;}
.rk{display:flex;align-items:center;gap:14px;padding:14px 18px;
    border:1px solid var(--rule);border-left:4px solid var(--bc);border-radius:8px;}
.rk-n{flex:0 0 auto;width:28px;height:28px;border-radius:50%;background:var(--bc);
      color:#fff;font-weight:800;font-size:15px;display:flex;
      align-items:center;justify-content:center;}
.rk .lg{width:32px;height:32px;border-radius:7px;flex:0 0 32px;}
.rk-t{display:flex;flex-direction:column;gap:3px;min-width:0;}
.rk-t b{font-size:16px;color:var(--ink-strong);}
.rk-t span{font-size:13px;color:var(--muted);line-height:1.7;}

/* ★★★★ 2026-09-01: 表を <figure> に入れたら、図版用の .shot img{width:100%} が
   表の中のロゴにも効いて、22pxのロゴが146pxに膨らんでいた。
   オーナー指摘「テーブルは全部崩れ出るんでやり直しです」の正体。
   ★ 図版の中に表を入れるときは、ロゴを図版の画像として扱わないこと。 */
.shot .lg{width:auto;height:auto;max-width:none;}
.shot .ent .lg,.shot td .lg,.shot th .lg{width:22px;height:22px;flex:0 0 22px;}
/* ★★★ 2026-09-01（2度目）: 上の逃がしが効きすぎて、図版の中に置いた
   棒グラフ・カード・順位・ボタンのロゴまで元の大きさ（512px）に戻っていた。
   オーナー指摘「VPNのアイコンでかすぎ」。**部品ごとに大きさを決め直す。** */
.shot .vb-l .lg{width:22px;height:22px;flex:0 0 22px;}
.shot .bcard .lg{width:34px;height:34px;flex:0 0 34px;}
.shot .rk .lg{width:32px;height:32px;flex:0 0 32px;}
.shot .cta .lg{width:24px;height:24px;flex:0 0 24px;}
.shot table{width:100%;}

/* ★★★★★ 2026-09-03 オーナー指示:
   「基本的には既存の記事と同じ見た目の方がいいですね。
     なので、全てそれで一回作り直してもらってもいいですか？」
   → 既存の WordPress 記事（AFFINGER・/best-vpns-for-uk/ ほか）の見た目に合わせる。
     ライブページから実測した値:
       h2  22px 700 白文字 / 背景 #132851 / padding 15px 20px
       h3  20px 700 #132851 / 下線 1px #132851 / padding 10px 20px
       h4  16px 700 #132851 / 左罫 5px #132851
       th  背景 #FAFAFA / padding 10px
       本文 15px・行間1.9・#333 / 地は白
   ★ 既存記事はダークモードを持たない。**当サイトの生成ページも白地に固定する。**
     地と文字が記事ごとに変わると「同じ見た目」にならない。 */
:root{
  --paper:#FFFFFF; --card:#FFFFFF; --sunk:#FAFAFA;
  --shell:#FFFFFF; --footer-bg:#F7F7F7; --shell-line:#E3E3E3;
  --ink:#333333; --ink-strong:#132851; --muted:#666666; --faint:#888888;
  --rule:#DDDDDD; --rule-soft:#EEEEEE; --rule-strong:#CCCCCC;
  --band:#132851;  --band-ink:#FFFFFF;
  --thead:#FAFAFA; --thead-ink:#333333;
  --accent:#0033CC; --accent-ink:#0033CC;
  --on-accent:#FFFFFF;
  --foot-ink:#555555;
}
/* ★ 既存記事に合わせて、ダークの切り替えを当てない。
   トークンをライトの値に固定する（消すのではなく上書きして、
   もとの定義はそのまま残す。戻すときはこのブロックを外すだけで済む）。 */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --paper:#FFFFFF; --card:#FFFFFF; --sunk:#FAFAFA;
    --shell:#FFFFFF; --footer-bg:#F7F7F7; --shell-line:#E3E3E3;
    --ink:#333333; --ink-strong:#132851; --muted:#666666; --faint:#888888;
    --rule:#DDDDDD; --rule-soft:#EEEEEE; --rule-strong:#CCCCCC;
    --band:#132851; --band-ink:#FFFFFF;
    --thead:#FAFAFA; --thead-ink:#333333;
    --accent:#0033CC; --accent-ink:#0033CC; --on-accent:#FFFFFF;
    --foot-ink:#555555;
    --shell-shadow:0 6px 16px -14px rgba(0,0,0,.18);
    --accent-soft:#EEF2FC;   /* ★ 地は紺・青の配色なので、薄緑ではなく薄青にそろえる */
    --alert:#A4362C;
    --alert-soft:#FBEFED;
    --alert-ink:#7A251D;
    --note:#8A6410;
    --note-soft:#FBF4E4;
    --note-ink:#6E4E0B;
  }
}
:root[data-theme="dark"]{
  --paper:#FFFFFF; --card:#FFFFFF; --sunk:#FAFAFA;
  --shell:#FFFFFF; --footer-bg:#F7F7F7; --shell-line:#E3E3E3;
  --ink:#333333; --ink-strong:#132851; --muted:#666666; --faint:#888888;
  --rule:#DDDDDD; --rule-soft:#EEEEEE; --rule-strong:#CCCCCC;
  --band:#132851; --band-ink:#FFFFFF;
  --thead:#FAFAFA; --thead-ink:#333333;
  --accent:#0033CC; --accent-ink:#0033CC; --on-accent:#FFFFFF;
  --foot-ink:#555555;
  /* ★★★ 2026-09-03: ここを書き漏らして、STEPの箱や注意書きの面が
     **ダークの濃い色のまま**残っていた（濃緑の箱に青文字で読めなかった）。
     オーナー指摘「色味がダークモードありきの色味のままなんで、全てそこは調整して」。
     ★ ダークで定義しているトークンは、**1つ残らず**ここで戻すこと。 */
  --shell-shadow:0 6px 16px -14px rgba(0,0,0,.18);
  --accent-soft:#EEF2FC;   /* ★ 地は紺・青の配色なので、薄緑ではなく薄青にそろえる */
  --alert:#A4362C;
  --alert-soft:#FBEFED;
  --alert-ink:#7A251D;
  --note:#8A6410;
  --note-soft:#FBF4E4;
  --note-ink:#6E4E0B;
}
/* 見出しの寸法も既存記事に合わせる */
article h2,.prose h2{font-size:22px;padding:15px 20px;border-radius:0;letter-spacing:0;}
/* ★ 既存記事の h3 は「下線だけ」。左罫は h4 の役目。両方付けると別物に見える */
article h3,.prose h3{font-size:20px;color:#132851;border-bottom:1px solid #132851;
  border-left:0;border-top:0;border-right:0;
  padding:10px 20px;background:none;border-radius:0;}
article h4,.prose h4{font-size:16px;color:#132851;border-left:5px solid #132851;
  padding:10px 15px 10px 20px;background:#fff;}
article p,.prose p{font-size:15px;line-height:1.9;}

/* ── IPアドレス確認ツール（/tools/ip/）─────────────────────
   ★ 2026-09-03: 競合の被リンクを開けたら、他社が自分の意思で貼ったリンクは4本しかなく、
     貼られていたのは「一覧」と「ツール」だった。道具は記事より貼られる。
   ★ 面を持てるのは h2 の帯と表の見出しの2つ、という決めごとを守る。
     ここは箱を塗りつぶさず、左の罫と数字の大きさだけで見せる。 */
.iptool{border:1px solid var(--rule);border-left:5px solid #132851;
  background:#fff;padding:18px 20px;}
.iptool .ipbig{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 14px;
  padding-bottom:12px;border-bottom:1px solid var(--rule-soft);}
.iptool .ipbig .v{font-size:26px;font-weight:700;color:#132851;
  font-variant-numeric:tabular-nums;word-break:break-all;line-height:1.35;}
.iptool .iprow{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 14px;
  padding:10px 0;border-bottom:1px solid var(--rule-soft);}
.iptool .iprow .v{font-size:15px;font-weight:700;color:var(--ink-strong);}
.iptool .k{flex:0 0 auto;min-width:8.5em;font-size:13px;color:var(--muted);}
.iptool .tblnote{margin:12px 0 0;}
@media (max-width:600px){
  .iptool{padding:15px 16px;}
  .iptool .ipbig .v{font-size:22px;}
  .iptool .k{min-width:100%;}
}

/* ── VPN比較ツール（/tools/compare/）───────────────────── */
.cmptool{border:1px solid var(--rule);border-left:5px solid #132851;background:#fff;padding:18px 20px;}
.cmptool .cmppick{display:flex;flex-wrap:wrap;gap:12px 20px;padding-bottom:14px;
  border-bottom:1px solid var(--rule-soft);margin-bottom:14px;}
.cmptool .cmppick label{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--muted);}
.cmptool select{font:inherit;font-size:15px;color:var(--ink-strong);padding:8px 10px;
  border:1px solid var(--rule-strong);border-radius:2px;background:#fff;max-width:15em;}
.cmptool select:focus-visible{outline:2px solid #132851;outline-offset:1px;}
.cmptbl th[scope="row"]{text-align:left;font-weight:400;color:var(--muted);width:12em;}
.cmptbl td.won{font-weight:700;color:#132851;}
@media (max-width:600px){
  .cmptool{padding:15px 16px;}
  .cmptool .cmppick label{width:100%;}
  .cmptool select{max-width:none;flex:1;}
  .cmptbl th[scope="row"]{width:auto;}
}
