diff --git a/CLAUDE.md b/CLAUDE.md
index 7501ed9d6dc..152b6ce14f9 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -766,6 +766,25 @@ bootstrap-subset → theme-styles.styl の順で `/css/site.css` に連結する
**767px 以下のコードと note**(`margin-inline: calc(50% - 50vw)` で画面端まで。
`.article-entry` 直下のものだけ #2568)。記事末の帯(#2874)は全幅だが、
中の `.container` が他ページと同じ左右を持つ
+ - **読み下す文章の1行は 45 字まで**(#3228。`article-measure` = `text-body × measure-chars`、
+ `_variables.styl` が持つ)。本文列は 1200px 以上で 52.5字(819px)・61.2字(954px)になり、
+ 和文の読み下しの帯(35〜45字)を超える。**列は動かさない**——`.container` と `col-md-9` は
+ 他ページと同じ枠(#3222)なので、**`.article-entry` の直下の文章の箱**(`p` / `ul` / `ol` /
+ `dl` / `blockquote` / `h1`〜`h6` / `hr` / `details` / `.note-container`)に `max-width` を置く。
+ 入れ子(`li` の中の `p`、note の中のコード)は箱に従う。右に残る空きはサイドバーとの
+ 間隔に足され、本文の左端は動かない
+ - **コード・表・図・埋め込みは上限の外。列の幅を使う。** 読み下す対象ではなく、狭めると
+ 横スクロールと縮小が増えるだけ。全 7,898 のコードブロックで、横スクロールの要る割合は
+ 954px で 8.6%・819px で 14.6% だが、702px に狭めると 24.1% になる。画像は 6,065 枚の
+ 76% が実寸 702px 超。上の「はみ出してよいもの」は**列に対する**話で、こちらは
+ **列の中の文章の幅**なので別の規則
+ - **`text-body` を幅で可変にする案は採らない。** 954px を 45 字に収めるには 21px が要り、
+ 段の台帳(#2971)と「1つの要素のサイズは1箇所」に触るうえ、見出しの em の梯子・
+ コード 13px との比・行間がすべて動く。読み下しの帯は字数の話なので、幅の側で解く
+ - 全 47,499 段落で、段落あたりの行数は 954px の 1.78 行から 45 字で 2.22 行になる
+ (1行で終わる段落 49.0% → 35.2%)。768〜1199px の読者が既に見ている行数(2.24〜2.27)と同じ
+ - 比較: Zenn 708px / 16px(44.3字)・Qiita 708px / 17px(41.6字)・はてなブログ 836px /
+ 17px(49.2字)。いずれも幅 1280〜1920px で本文の幅を変えない(2026-09 実測)
- **時間の段は2つ+例外1つ**(#3222)。`_variables.styl` が持つ。**役で選ぶ**
| 段 | 値 | 使うところ |
diff --git a/source/specials/styleguide/index.md b/source/specials/styleguide/index.md
index fd85063a1bf..983fd22f7f0 100644
--- a/source/specials/styleguide/index.md
+++ b/source/specials/styleguide/index.md
@@ -311,15 +311,24 @@ editable: true
左右の空きは全幅で 12px です。間隔の刻み(4px)の3つぶんで、幅の側だけ別の単位を持ちません。列の溝は 24px、本文とサイドバーの間は 44px(本文側 24px とサイドバー側 20px)で、どちらも同じ刻みに乗っています。
-| 画面幅 | ページの最大幅 | 本文列の内寸 | サイドバー |
-| --- | --- | --- | --- |
-| 〜575px | 画面いっぱい | 画面幅 − 24px | 本文の下 |
-| 576〜767px | 540px | 516px | 本文の下 |
-| 768〜991px | 720px | 696px | 本文の下 |
-| 992〜1024px | 960px | 936px | 本文の下 |
-| 1025〜1199px | 960px | 684px | 208px |
-| 1200〜1399px | 1140px | 819px | 253px |
-| 1400px〜 | 1320px | 954px | 298px |
+| 画面幅 | ページの最大幅 | 本文列の内寸 | 文章の1行 | サイドバー |
+| --- | --- | --- | --- | --- |
+| 〜575px | 画面いっぱい | 画面幅 − 24px | 22.5字(375px) | 本文の下 |
+| 576〜767px | 540px | 516px | 33.1字 | 本文の下 |
+| 768〜991px | 720px | 696px | 44.6字 | 本文の下 |
+| 992〜1024px | 960px | 936px | 45字(上限) | 本文の下 |
+| 1025〜1199px | 960px | 684px | 43.8字 | 208px |
+| 1200〜1399px | 1140px | 819px | 45字(上限) | 253px |
+| 1400px〜 | 1320px | 954px | 45字(上限) | 298px |
+
+**読み下す文章の1行は 45 字までです。** 和文は1行が 35〜45 字を超えると、行末から次の行頭へ目が戻れなくなります。本文列は広い画面ほど広がるので、列の幅ではなく文章の箱の幅で止めます。上限は本文の文字の大きさに字数を掛けた値で、文字の大きさを変えれば追従します。
+
+
+
+上限を持つのは段落・箇条書き・引用・見出し・note・折りたたみだけです。**コード・表・図・埋め込みは列の幅を使います。** これらは行として読み下す対象ではなく、狭めると横スクロールと縮小が増えるだけです。1400px 以上の画面ではコードの1行に 116 字入りますが、文章と同じ幅に合わせると 83 字まで落ち、横スクロールの要るブロックが 8.6% から 24.1% に増えます。右に残る空きはサイドバーとの間隔に足され、本文の左端は動きません。
**幅で切り替わる点は4つだけです。** どれも「その列に何が入るか」で決めていて、端末の呼び名では決めていません。
@@ -334,7 +343,7 @@ editable: true
はみ出してよいものは3つあります。**記事の中の画像**は列いっぱいを上限に、縮めたいときは 520px と 360px の2段階から選びます(3段階目は置きません。狙った大きさがどちらとも違うなら、画像そのものを加工します)。**横に溢れる表**は受け皿の中で横スクロールし、ページ全体は横に動きません。**コードと note は、狭い画面でだけ画面の端まで伸びます。** 幅375pxでコードの1行に入る字数が 39.9 字から 45.0 字になり、横スクロールの要るブロックが 71.8% から 64.0% に下がります。文字の位置は段落の左端に揃うので、読者から見ると背景の帯だけが端まで伸びた形になります。本文末の帯(関連記事・We're hiring)も全幅ですが、中の左右は本文と同じ位置に揃えます。
-**幅の決まりは単位ではなく構造です。** 12px・24px・44px は間隔のスケールから借りているだけで、幅そのものが持つ決まりは「ページの種類で最大幅を変えない」「切り替わる点は4つ」「はみ出すのは画像・表・コードと note だけ」の3つです。値を覚える必要はなく、どの構造に当てはまるかだけを選びます。
+**幅の決まりは単位ではなく構造です。** 12px・24px・44px は間隔のスケールから借りているだけで、幅そのものが持つ決まりは「ページの種類で最大幅を変えない」「切り替わる点は4つ」「はみ出すのは画像・表・コードと note だけ」「読み下す文章の1行は 45 字まで」の4つです。値を覚える必要はなく、どの構造に当てはまるかだけを選びます。
## 形と反応
diff --git a/themes/future/css-src/_variables.styl b/themes/future/css-src/_variables.styl
index dc5f1dd7c8b..f27b15714c0 100644
--- a/themes/future/css-src/_variables.styl
+++ b/themes/future/css-src/_variables.styl
@@ -146,6 +146,13 @@ text-lead = 18px // サイト名・サイドバーの見出し
text-title = 20px // 見出し・ロゴ・一覧カードの記事名
text-display = 24px // 大見出し(クラス無しの h2)
+// 読み下す文章の1行の上限 (#3228)。和文は 35〜45字/行を超えると目が行頭に戻れない。
+// 本文列は 1200px 以上で 52.5字(819px)・61.2字(954px)に広がるので、
+// 読み下す段の値に字数を掛けて上限を置く。px を直接書かない——段を動かしたら
+// 上限も同じ字数のまま追従する。対象は文章の箱だけで、コード・表・図は列の幅を使う
+measure-chars = 45
+article-measure = text-body * measure-chars
+
// 間隔は4の倍数だけを使う。段を数え上げずに刻みだけを置くのは、
// 使う値が gap だけでも 2〜48px の13通りあり、上限を決める理由が無いため。
// 4px 刻みなら「隣の段」が必ず 4px 差になり、5px と 6px のような
diff --git a/themes/future/css-src/theme-styles.styl b/themes/future/css-src/theme-styles.styl
index 2606bbe556c..5ce804ba9bf 100644
--- a/themes/future/css-src/theme-styles.styl
+++ b/themes/future/css-src/theme-styles.styl
@@ -1514,6 +1514,29 @@ p {
font-size: text-body;
color: var(--ink-strong);
}
+/* 読み下す文章だけが1行の上限を持つ (#3228)。列(col-md-9)は他のページと同じ枠を
+ 共有するので動かさず(#3222)、本文の器の中で文章の箱の幅だけを止める。
+ 右に残る空きはサイドバーとの間隔に足される。
+ 当てるのは .article-entry の直下の箱で、中身(入れ子の li・note の中の p)は箱に従う。
+ コード・表・図・埋め込み(figure.highlight / .scroll / img / figure / iframe /
+ .mermaid-svg)は読み下す対象ではなく、狭めると横スクロールと縮小が増えるだけなので
+ 列の幅のまま。見出しと hr を入れるのは、罫線を文章の右端でそろえるため */
+.article-entry > p,
+.article-entry > ul,
+.article-entry > ol,
+.article-entry > dl,
+.article-entry > blockquote,
+.article-entry > h1,
+.article-entry > h2,
+.article-entry > h3,
+.article-entry > h4,
+.article-entry > h5,
+.article-entry > h6,
+.article-entry > hr,
+.article-entry > details,
+.article-entry > .note-container {
+ max-width: article-measure;
+}
/* details の summary は p / li と違って本文サイズの指定対象から漏れており、
body の 13px を継承して周囲(1.2em = 15.6px)より小さく表示されていた */
.article-entry summary {
@@ -6606,6 +6629,28 @@ for n in sg-space-steps
font-size: text-meta;
}
+/* 文章の1行の上限の見本 (#3228)。帯の長さも値も article-measure から出す。
+ このページの段落自身が本物のルールで上限を受けているので、帯は段落の右端と揃う */
+.sg-measure {
+ margin: 0 0 24px;
+}
+.sg-measure-bar {
+ background: var(--brand-navy);
+ border-radius: radius-small;
+ height: 16px;
+ max-width: 100%;
+ width: article-measure;
+}
+.sg-measure-value {
+ color: var(--ink-mute);
+ font-family: font-mono;
+ font-size: text-meta;
+ margin-top: 4px;
+}
+.sg-measure-value::after {
+ content: unquote('"' + article-measure + ' = ' + text-body + ' × ' + measure-chars + '字"')
+}
+
/* 下線の位置の見本。値は _variables.styl から借りる。ここに px を書くと
決める場所が2つになる(文字の大きさの見本と同じ流儀)*/
.sg-underline-offset::after {