---
title: "AI に読まれるサイトへ ― 研究から仕事までの道を引き直した"
slug: ai-readable-openings
date: 2026-10-28
day: 399
meta_description: "pixelstomotors.comの表示の約9割は機械で、人は1日20表示前後。人が読んでいたのは学習環境づくりと配膳ロボットの現場の話だった。相談のページ、AIに引用されやすい書き出し、公開を検索へすぐ知らせる仕組みを1晩で入れた。"
tags: [アクセス解析, Webサイト, AI検索, IndexNow, Cloudflare, ChatGPT, コンサル, 発信]
series: "ひとり研究所の裏側"
---

**pixelstomotors.com を開いている閲覧の約9割は機械で、人の閲覧は1日20表示前後でした。その少ない人が読みに来ていたのは、自分でロボットの学習環境を作る話と、配膳ロボットを現場で回す話です。** そこで、研究の記録から仕事の相談までの道を1晩で引き直しました。相談のページを作り、記事の書き出しを AI が答えに引用しやすい形に直し、公開したページを検索エンジンへすぐ知らせる仕組みを入れています。

このサイトには、ロボットの学習と配膳ロボットのシミュレーションの記録を、コードとログを省かずに400本ほど置いています。誰が、何を読みに来ているのか。それを知りたくて、自前で入れていた計測の数字を読みました。結果は思っていたのと違いました。計測の数え方では「ページが開かれた回数」が3日で867回ありましたが、そのうち751回は、検索エンジンのページの確かめや、自動で動くブラウザによるものでした。人だと分かるのは78回です。

数は少なくても、人の動きには形がありました。いちばん読まれていたのは「ロボットの AI の学習用 GPU を、買うか借りるか」の導入比較ガイドで、研究室の記録を何本も渡り歩いた人、記事の下に置いた調査メモや zip まで取りに来た人もいました。一方で、相談のフォームに入力を始めた人は0人です。**詰まっているのは入口ではなく、読んだ人が「この人に頼める」と気づく出口のほうでした。**

もう1つ分かったのは、AI の読み方です。サイトに来るクローラー（自動でページを集めに来るプログラム）を数えると、4日で4,298回。そのうち32回は、誰かが ChatGPT に質問し、その答えを作るために ChatGPT がこのサイトを読みに来た回数でした。人が検索するより AI に聞いて調べるようになると、AI に読まれて引用されることが、人に届く道そのものになります。

やったことは次のとおりです。

| やったこと | なぜ | どうなったか |
|---|---|---|
| 自前の計測の数を読む | 誰が何を読んでいるかを知るため | 人は1日20表示前後。読まれていたのは学習環境づくりと配膳ロボットの現場の話 |
| 小さな改善を4つ入れる | 数が少なくても損をしない所から直すため | ハコブくんの知らせの数を人と機械に分け、導入比較ガイドの最初に結論を出し、古い記録と記事の素材に入口を付けた |
| 改善の判断の基準を先に決める | あとで数字に合わせて基準を動かさないため | 効果・楽さ・施策の質の3つと、結論の決め方を決めた |
| MASTER を v2.1 にする | 研究の先に仕事を置くため | Mission に4行目を足し、主指標を「研究」と「仕事」の2本にした |
| 相談のページを作る | 何を頼めるかが分からなかったため | 一緒に手を動かすコンサルの案内（/consult）を公開した |
| 公開をすぐ Bing に知らせる | ChatGPT の検索は Bing を土台にしているため | 全674ページを知らせ、以後は公開のたびに自動で知らせる |
| 記事の書き出しを、問いへの答えにする | AI は答えに使える一文を探して読むため | 決まりを足し、研究の記録35本の書き出しを直した |

【図解】LOG399_research_to_work.html

効果が出たかはまだ分かりません。人の閲覧が1週分たまる11月7日ごろに、決めた基準で確かめます。この記事の「見込める効果」は、すべて見込みです。

この記事の最初の段落も、新しく決めた書き出しの決まり（最初の1〜2文で、記事が答える問いに答える）で書いています。


## 作業ログ ― アクセスの数を読んでから、相談のページと書き出しの決まりを入れるまで

### 自前の計測の表は、鍵がないと開かない作りだった

数を見る表（/api/ev-stats）を開くと、404（ページがない）が返ってきました。一緒に作業している AI（Claude）は「計測が止まっているかもしれない」と言いかけましたが、そうではありませんでした。5日前に、数の表を外から見られないよう、鍵（Cloudflare の秘密の値 STATS_KEY）を付けたときだけ開く作りにしていました。鍵がなければ、表は「ない」ふりをします。

> 鍵変えたよ。自分でやったんだから、あとのログから調べなよ

鍵の控えは、外付けの SSD（KIOXIA）に置いたファイルにあります。Claude は、そのファイルを中身を画面に出さずに読み込み、表に渡して数を取りました。鍵の場所と取り方は、検証の記録（claude/web_improvement_trial.md）に書き足しています。

### 人と機械を分けると、表示の約9割は機械だった

計測には、10月26日から「人か機械か」の印を付けていました。マウスや指の操作があった表示を「人」、自動で動くブラウザやクローラーの名乗りがある表示を「機械」、どちらでもない表示を「不明」にしています。

| 週（月曜はじまり） | 表示 | 人 | 機械 | 不明 | 印なし |
|---|---|---|---|---|---|
| 10/12〜10/18 | 22 | — | — | — | 22 |
| 10/19〜10/25 | 1,292 | 1 | 20 | 1 | 1,270 |
| 10/26〜10/28（途中） | 867 | 78 | 751 | 38 | 0 |

10月19日の週の1,270回には印がありません。表示時間の中央値が6秒なのに、75％以上読んだ割合が82％でした。一瞬で最後まで読み込む、機械に近い形です。人の数として使えるのは、10月26日からだけでした。

人の78表示の中身は次のとおりです。

| 見たもの | 数 |
|---|---|
| 表示時間の中央値 | 11秒 |
| 75％以上読んだ割合 | 24％ |
| スマホの割合 | 46％ |
| 来た所 | 直接・不明 39、サイト内 16、Google 16、Yahoo 3、LinkedIn 3、Google アプリ 1、Microsoft Teams 1 |
| よく見られたページ | 導入比較ガイド 14（75％以上読んだのは14％）、配膳ロボットのラストワンマイルの記事 6（外へのリンクを3回押した）、トップ 5、自宅の研究室づくり Log#1 4、模倣学習の先の考察記事 4 |
| 押したもの | フッターの about 3、本文の X 3、ひとり研究所の裏側 2、LOG392・LOG337 の分けたファイル（md・zip・json） |
| 迷い | リンクでない所を押した 4、連打 0 |
| フォーム | メッセージのページの表示 2、入力を始めた 0 |

外から来た訪問は約60回、1日20回前後です。見た人を見分ける番号を残さない作りなので、何人かは数えられません。

> サイトのどんなことに興味持っているようですか？

人の関心は2本に分かれていました。自分でロボットの学習環境をどう作るか（導入比較ガイド・研究室の記録・π0.5 の記録）と、配膳ロボットを現場でどう回すか（ラストワンマイル・協働ロボットの法律）です。サイトが出しているものとは噛み合っていました。ただ、導入比較ガイドは、来た人を最後まで読ませられていません。

### 少ない数でも損をしない所から、4つ直した

> まだはっきり改修がどんなことが必要かがわかるほど情報がないので、改修するとしたらどのあたりがいいですか？

数が少ないうちは、どの結果になっても損をしない所と、少ない数でも効果が見える所を選びました。

> そのくらいの変更なら今進めてください。

1つ目は計測の直しです。更新を知らせるハコブくん（新しい記録が出ると画面の下を走るキャラクター）の数には、人と機械の区別がありませんでした。さらに、自分の閲覧を外す設定（?p2m-notrack=1）にも従っていませんでした。自分の確認の閲覧が「出た」に入っていたことになります。機械の印を付け、自分の閲覧を外すようにしました。

- ねらい：ハコブくんの知らせを、人だけの数で判断できるようにする
- 変わったこと：/api/hk-stats に「機械の印なし」「機械」「印なし（10/28より前）」の表と、?who=notbot などの絞り込みが付いた
- 見込める効果：今の「出た 643・押した 5」の割合（1％未満）が、人だけで出し直せる。11月7日ごろに確かめる

2つ目は導入比較ガイドです。最初の画面の文を、やったことの説明から結論に変えました。「結論：使うのが月180時間より少ないなら、借りる方が安い。RTX 5090 の PC を4年使う場合の目安です。買うなら、GPU のメモリは24GB以上が条件です。」

- ねらい：いちばん来るページで、最初の画面だけで答えが分かるようにする
- 変わったこと：最初の画面の文が結論になった（ページの数字の出典はそのまま）
- 見込める効果：計算機（#calc）へのクリックが増える。75％以上読んだ割合は下がってもよい。結論を最初に読んで離れるのは失敗ではないため

3つ目は古い記録です。検索から来た人は、mechArm の初期の DAY の記録に着くことが多く、そこで止まっていました。公開から60日より前の記録のタイトルの下に、同じシリーズの最新（シリーズが止まっていればサイト全体の最新）への黒い帯を出しました。

4つ目は記事の素材です。素材のファイルを分けて置いている記事のタイトルの下に、「この記事の素材（コード・ログ・データ ○ファイル・まとめてダウンロードあり）」の灰色の帯を出し、ファイルの一覧へ飛べるようにしました。

- ねらい：再現したい人が、記事を下までたどらずに素材へ着けるようにする（Mission の「再現可能な形で公開する」に近い動き）
- 変わったこと：素材のある48本の記事のタイトルの下に入口が付いた
- 見込める効果：押したものに「素材」（数える場所 files）が出る。/files/ への移動が増える

帯も結論の文も、押された回数を数える印を付けています。全体で約15分（依頼から公開と本番の確認まで）、そのうち人が手を動かした時間は0分でした。

### 改善の判断の基準を、次の改善の前に決めた

この改善は、「Claude と組んで数字を読む → 直す → 公開する、を回すと、売り物になるか」を確かめる検証の1回目です。基準をあとで決めると、出た数字に合わせて動かしてしまいます。

> これを決めましょう！

| 見るもの | 基準 |
|---|---|
| 効果 | 判断できた改善のうち、半分以上が狙いどおりに動く（対象の数が30未満なら「判断できない」として数えない） |
| 楽さ | 改善1回あたり、人が手を動かした時間（判断・確認を含む）の平均が10分以内 |
| 施策の質 | Claude が出した案の3分の2以上が採用され、公開後の直し・戻しが改善1回あたり1回以下 |
| 結論の決め方 | 3つとも満たせば「売り物として成り立つ」、2つなら「条件つき」、1つ以下なら「成り立たない」 |

### AI に読まれているのは誰か、クローラーの内訳を出した

> AIがたくさん読んでいるのはなぜですか？記事ペースが多いから？

自前の計測は、ページの中の仕掛け（JavaScript）が動いたときだけ数えます。ChatGPT などが記事を集めに来るときの多くは、ページの文字を取るだけで、仕掛けを動かしません。そのため、配信のときに名乗りで見分けて数える別の表（/api/cr-stats）を、10月25日から置いていました。

| クローラー | どこの何か | 回数 | 見たページ |
|---|---|---|---|
| meta-externalagent | Meta（AI） | 1,040 | 700 |
| Googlebot | Google（検索） | 997 | 422 |
| Amazonbot | Amazon（Alexa・AI） | 686 | 534 |
| Applebot | Apple（Siri・検索・AI） | 346 | 217 |
| GoogleOther | Google（その他） | 322 | 179 |
| ClaudeBot | Anthropic（学習） | 319 | 227 |
| GPTBot | OpenAI（学習） | 228 | 225 |
| bingbot | Bing（検索。ChatGPT の検索・Copilot も使う） | 193 | 103 |
| OAI-SearchBot | OpenAI（ChatGPT の検索） | 109 | 53 |
| ChatGPT-User | ChatGPT（利用者の依頼で読む） | 32 | 17 |
| Bytespider | ByteDance（AI） | 10 | 4 |
| YandexBot | Yandex（検索） | 10 | 1 |
| Baiduspider | Baidu（検索） | 2 | 2 |
| DuckDuckBot | DuckDuckGo（検索） | 2 | 1 |
| Yeti | Naver（検索） | 1 | 1 |
| Claude-User | Claude（利用者の依頼で読む） | 1 | 1 |

4日で4,298回、今週は1日あたり約1,400回です。記事の数そのものより、10月17日に検索に出す設定へ切り替え、サイトマップと AI 向けの案内（/llms.txt）を置いたことで、一通り集めに来ている形です。GPTBot や ClaudeBot は、記事の外に分けたコード（LOG383 のスクリプトなど）まで1本ずつ読んでいました。

ChatGPT-User の32回のうち14回はトップページで、試しに URL を渡した読みが混ざっていると見ています。残りは、マイクロファクトリー、π0.5 の学習、配膳ロボットの費用と補助金、Claude Code の課金など、16本の記事に1回ずつ散らばっていました。

> これは狙い通りかな。これがもっと増えてほしいところだね

### 研究の先に仕事を置き、MASTER を v2.1 にした

Claude は最初、MASTER（判断の軸を書いた上位の文書）に沿って「AI に引用される数は副次の指標で、主指標は再現可能な環境数」と答えました。

> まぁそうだけど、人がAIを活用するので同じくらい大事だよ

> それとも仕事や相談につながる入口として、が大事だろうね。研究だけしていても意味はなく、研究の先に仕事が必ずないといけないかな

このやり取りで、話の中心が「引用の数」から「研究から仕事までの道」に移りました。MASTER を直した所は次のとおりです。

| 直した所 | 前 | 後 |
|---|---|---|
| Mission | 3行（環境を作る・再現可能な形で公開する・誰でも始められる状態を増やす） | 4行目「その研究を、Physical AI を導入する組織と一緒に手を動かす仕事につなげる。」を足した |
| 主指標 | 再現可能な環境数（唯一） | 研究＝再現可能な環境数／仕事＝仕事につながった数（相談を実際に行った件数と、有料になった件数の2段） |
| 手前の指標 | なし | AI 経由で人に届いた数（ChatGPT-User など。記事のページだけ）と、相談のページへ来た数。目標にはしない |
| 契約層の主 | 共同研究／R&D契約／Motion UX コンサル | 一緒に手を動かすコンサル（主）／共同研究／R&D契約 |
| 相談の窓口 | AI活用の記事とフォームだけ。トップ・SNS には出さない | フィジカルAI は /consult。フッターと SNS のプロフィール欄にもリンクを1つ置く。トップの画面の中と SNS の投稿には出さない |

相談の窓口を「トップと SNS に出さない」決まりを残すかでは、4つの案（残す／フッターとプロフィール欄にだけ置く／トップに出す／投稿でも呼びかける）を並べ、フッターとプロフィール欄にだけ置く案になりました。探した人だけが確実にたどり着け、「まず記録を読んでもらう」も崩さない形です。

### 一緒に手を動かすコンサルの案内を作った

> コンサルが一番ありそうかな。オンラインや定期的に時間を作って出張するくらいなら可能な気がする。でもコンサルと言っても一緒に手を動かすが前提にはなると思うけど

決まったことは、打ち合わせは週1回、訪問は月1回くらい（全国どこでも。交通費と宿泊費は別）、料金はページに出さず相談で決める、最初の相談はオンライン30分まで無料、それ以降は有料、の5つです。MASTER は新しい肩書きやキャッチコピーを作ることを禁じているので、「伴走型」のような名前は付けず、「一緒に手を動かすコンサル」と中身をそのまま書いています。

最初の画面は、主役の違う3案（一緒にやること／根拠の数字／進め方）を作り、「一緒にやること」を主役にした案Aにしました。来た人が何を頼めばいいか分からないことが問題だったので、最初の画面はその答えにしています。

【画像】LOG399_01_consult_fv_plans.png 相談のページの最初の画面の3案。上から、一緒にやることが主役の案A、根拠の数字が主役の案B、進め方が主役の案C

ページは、最初の画面（一緒にやること3つ）、根拠の数字、進め方、誰がやっているか、の順です。根拠の3つ目は、はじめ「止まった配膳ロボットを店員が直す時間（約5秒）」にしていましたが、1年の記録（/one-year）につながる「1年分の作業ログ379本」に替えました。

デザインは、導入比較ガイドに合わせて直しました。色・太い見出し・白抜きの番号の見出し・大きな数字の並べ方・白と薄い灰色と黒の帯をそろえ、写真や絵は使っていません。そのあと画面を見ながら、次の順に直しています。

| 直し | 中身 |
|---|---|
| 1 | 見出しが「フィジカルAI／の導入を、」で折れていたので小さくした |
| 2 | 最初の画面のカードの上の線を消し、上下の余白を詰めた（ページ全体の節の余白が、最初の画面にも重なっていた） |
| 3 | 最初の画面の 01〜03 のカードを押すと、各節へ移るようにした |
| 4 | 進め方のカードの上の線を消し、マウスを乗せると黒くなるようにした |
| 5 | ボタンとカードに、ガイドのボタンと同じ 4px の角丸を付けた |
| 6 | 相談のボタンを、ガイドの相談のボタンと同じオレンジ（#f2600c）にした |

【画像】LOG399_02_consult_page.png 公開した相談のページ（/consult）の全体。最初の画面、根拠の数字、進め方、誰がやっているかの順に並ぶ

- ねらい：記録を読んで興味を持った人が、何を頼めるかと、頼んだらどう進むかを1ページで分かるようにする
- 変わったこと：フッターの「相談について」、研究室と導入シミュレーションの記録の末尾、AI 向けの案内（/llms.txt）から /consult へつながった。ボタンは相談の種類「フィジカルAI」を選んだ状態でフォームを開く
- 見込める効果：相談のページへ来た数と、そこからフォームに進んだ数で確かめる。今のフォームの入力開始は0

### 公開したページを、IndexNow で Bing にすぐ知らせるようにした

ChatGPT の検索は、Bing の検索結果を土台にしています。今までは、Bing が自分で巡回して見つけるのを待っていました。IndexNow は、ページを公開したときに、こちらから検索エンジンへ「このページが変わった」と知らせる仕組みです。

main に push すると、GitHub Actions が公開を2分待ってから、増えた・変わったページだけを送ります。記録が変わったときは、トップと /llms.txt も一緒に送ります。最初の1回は、サイトマップの全674ページを送りました。

1回目は 403 で断られました。サイトマップを取りに行く Python の既定の名乗りが Cloudflare の守りに止められたのと、鍵のファイルの確認がまだ済んでいなかったためです。名乗りを付け、数分待って送り直すと、200（受け付けた）が返りました。鍵のファイル名は IndexNow の決まりで公開する文字列ですが、この記事では <INDEXNOW_KEY> に置き換えています。

- ねらい：新しい記録が ChatGPT の答えに使われるまでの時間を短くする
- 変わったこと：公開のたびに、変わったページが自動で Bing などに届く
- 見込める効果：ChatGPT-User が読みに来る回数（今は3日で32回、うち14回はトップ）で確かめる

### 記事の最初の1〜2文を、問いへの答えにする決まりを足し、35本を直した

AI は、質問への答えに使える一文を探してページを読みます。今までの書き出しの決まりは「最初の1〜2段落で、何が起きていたか・なぜ気になるかを言う」でしたが、最初の文が場面の説明だと、答えとして切り出せません。記事の書き方の決まり（article_rules.md）の冒頭の書き出しに、次を足しました。

- 書く前に、その記事が答える問いを1つ決める。問いは本文に書かない
- 最初の1〜2文で、その問いに答える。主語・対象・条件・数字を入れ、「今回」「この店」のような前後に頼る語を使わない
- 道具や機体は、最初に出る所で正式な名前にする（例: Physical Intelligence の π0.5）
- 実物の話か、シミュレーションの話かを、答えの文の中で分かるようにする
- 答えが出ていない記事は、今の時点で分かっていることを1文で書く
- メタディスクリプションの最初の文も、同じ答えにそろえる

> フィジカルAI研究所とサービスロボット導入シミュレーションの記事はこの形式に全て直してください。

公開済みの記録は直さない決まりがありますが、直すように言われたときは直します。フィジカルAI研究室の15本とサービスロボット導入シミュレーションの20本、合わせて35本の書き出しを直しました。最初の差し替えでは LOG352 の1本が漏れていて、対象の記事の数（35）と直した数（34）が合わないことを確かめの段階で見つけ、あとから足しています。多くは、今の書き出しの前に答えの段落を足しています。もともと冒頭に答えがあった7本（LOG361・370・374・382・393・397・398）は、最初の文だけを置き換えました。

| 記事 | 前の最初の文 | 後の最初の文 |
|---|---|---|
| LOG393 | 28卓の小さなファミレスに配膳ロボットを2台入れたら、… | 3Dのファミレスのシミュレーションで、28卓の小さな店に配膳ロボットを2台入れると、… |
| LOG382 | 配膳ロボットを入れたら、ホールのスタッフを1人減らせるのか。 | 配膳ロボットでホールのスタッフを1人減らせる条件は、…試算で見つかりましたが、差し引きは月約7.5万円の持ち出しでした。 |
| LOG345 | お手本を19回見せて覚えさせた AI に、机の上のロボットアームを初めて動かさせました。 | お手本19本で学習した Physical Intelligence の π0.5 で mechArm 270 を初めて動かすと、…手首が指令の角度に届かず止まりました。 |

検索結果に出る説明文（メタディスクリプション、Studio から移した記事は description）の最初の文も同じ答えにそろえ、AI が読む全文のファイル（記事の素材の中の全文）にも同じ直しを入れました。数字は、それぞれの記事の本文と説明文にあるものだけを使っています。直した35ページは、IndexNow で公開と同時に知らせています。

### 次に確かめること

| いつ | 何を |
|---|---|
| 11月7日ごろ | 改善 No.01 の結果（導入比較ガイドの計算機へのクリック、「今の続き」と「素材」の帯が押された数、ハコブくんの知らせの人だけの割合） |
| 11月7日ごろ | ChatGPT-User が読みに来た回数と、読まれた記事（IndexNow と書き出しの直しの効果） |
| 11月7日ごろ | 相談のページに来た数と、そこからフォームに進んだ数 |
| 残り | X と LinkedIn のプロフィール欄への相談のページのリンク、MASTER v2.1 の Project への貼り替え（人の手で行う） |

### 差分：p2m-site commit daae7c1（ハコブくんの数の直し・導入比較ガイドの結論・古い記録の帯・記事の素材の帯）

```diff
commit daae7c1
アクセスの数から見た小さな改善4つ（計測の直し・導入比較ガイドの結論・古い記録から今への道・記事の素材の入口）

- ハコブくんの記録も ?p2m-notrack=1 と「トラッキングしないで」に従い、機械の印（k）を付ける。/api/hk-stats に人と機械の表と ?who=notbot・bot・old
- 導入比較ガイドの最初の画面の文を、結論（月180時間より少ないなら借りる方が安い・買うならGPUメモリ24GB以上）に変える
- 公開から60日より前の記録のタイトルの下に、シリーズの最新（なければサイト全体の最新）への道を出す（数える場所 now）
- 分けたファイルのある記事のタイトルの下に、素材の枠（#files）への入口を出す（数える場所 files）
- README に、Claude の確認では ?p2m-notrack=1 を付けることと、上の決まりを書く

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXSYG9NkMRzRGxEeaqX


diff --git a/README.md b/README.md
index f85c664..1467f37 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,9 @@ Web改善の検証（Project の `claude/web_improvement_trial.md`）のため
 - エイイチや Claude の確認の閲覧を数に入れないため、どれかのページを `?p2m-notrack=1` を付けて開くと、そのブラウザでは以後送らない（`?p2m-notrack=0` で元に戻す。`?p2m-notrack=check` で、そのブラウザが今どちらの設定かが画面の上に出る）。iPhone の Safari は、サイトを7日開かないとこの設定を消すことがあるため、ときどき check で確かめる。Do Not Track・Global Privacy Control を設定したブラウザも送らない
 - 人と機械を分ける印（2026-10-25 から）：1回の表示ごとに `k`（h＝人の操作＝マウス・指・ホイール・キーがあった／b＝機械＝クローラーや自動のブラウザの名乗り・navigator.webdriver／x＝操作なし）を付ける。それより前の記録は「印なし」。週ごとの表に4つの内訳が出て、`?who=human`・`bot`・`unknown`・`old` でほかの表をその種類だけに絞れる。名乗り（ユーザーエージェント）は判定に使うだけで保存しない
 - 記録しない：入力した内容・コピーした文章・IP アドレス・ブラウザの種類・Cookie。番号はその1回の表示だけのもので、ブラウザに保存しない
+- Claude が公開後に自動のブラウザで確かめるときは、最初に開くページに `?p2m-notrack=1` を付ける（そのブラウザでは以後送らない）。付け忘れても navigator.webdriver で「機械」に入るので、人の数には混ざらない（2026-10-28）
+- ハコブくんの記録（/api/hk-event）も、`?p2m-notrack=1` の設定と「トラッキングしないで」の設定に従う。機械の印（k：b＝機械／n＝機械の印なし。2026-10-28 より前は印なし）を付け、`/api/hk-stats?who=notbot`・`bot`・`old` で絞れる（2026-10-28）
+- 記事ページの入口（2026-10-28）：公開から60日より前の記録は、タイトルの下に「今の続き」（「{シリーズ名}の最新」＝同じシリーズの60日以内の最新。なければ「いま進めている記録」＝サイト全体の最新）を出す（押すと `今の続き>now` で数える）。分けたファイルのある記事は、タイトルの下に「この記事の素材」（本文の「ファイル一式」の枠 #files へ飛ぶ。`素材>files`）を出す
 - 押したものの「ページのどの部分か」は、クラス名（.richText・.related・.consult など）で決めている。部品に `data-ev-area="名前"` を付けると、その名前で数える（名前は `worker/index.js` の `EV_AREAS` にあるものだけ受け付ける）。リンクやボタンに `data-ev="名前"` を付けると、行き先の前にその名前が付く
 
 記事・4コマの画像と動画は GitHub に入れない。ただし `public/og/` の画像は、GitHub にあるサムネイルの HTML から書き出したものなので GitHub に入れる。サイトの `/media/ファイル名` を `worker/index.js` が R2 から返す。
diff --git a/src/components/HakobuParade.astro b/src/components/HakobuParade.astro
index c9de857..af81f24 100644
--- a/src/components/HakobuParade.astro
+++ b/src/components/HakobuParade.astro
@@ -73,8 +73,21 @@
   }
 
   // 効果の記録を送る（ページを移っても届くよう sendBeacon を使う）
+  // 送らない場合（サイトの使われ方の記録と同じ決まり。2026-10-28）：?p2m-notrack=1 で記録しない設定にしたブラウザ（エイイチ・Claude の確認）、
+  // 「トラッキングしないで」の設定のブラウザ
+  // 機械の印（2026-10-28）：wd＝navigator.webdriver、hl＝名乗りに Headless・bot などが入っているかの判定結果だけ（名乗りそのものは送らない）
+  const HK_AUTO_UA = /headless|lighthouse|bot\/|bot;|\bbot\b|crawl|spider|slurp|preview|phantom|puppeteer|playwright|selenium/i;
+  function reportOff(): boolean {
+    const nav = navigator as Navigator & { globalPrivacyControl?: boolean };
+    if (nav.doNotTrack === '1' || nav.globalPrivacyControl === true) return true;
+    try { return localStorage.getItem('p2m-notrack') === '1' || new URLSearchParams(location.search).get('p2m-notrack') === '1'; } catch { return false; }
+  }
   function report(e: 'shown' | 'click' | 'later', it: { id: string; kind: string }) {
-    const body = JSON.stringify({ e, id: it.id, kind: it.kind, path: location.pathname, w: window.innerWidth < 600 ? 'sp' : 'pc' });
+    if (reportOff()) return;
+    const body = JSON.stringify({
+      e, id: it.id, kind: it.kind, path: location.pathname, w: window.innerWidth < 600 ? 'sp' : 'pc',
+      wd: navigator.webdriver ? 1 : 0, hl: HK_AUTO_UA.test(navigator.userAgent || '') ? 1 : 0,
+    });
     try {
       if (!navigator.sendBeacon || !navigator.sendBeacon('/api/hk-event', new Blob([body], { type: 'text/plain' }))) {
         fetch('/api/hk-event', { method: 'POST', body, keepalive: true }).catch(() => {});
diff --git a/src/pages/gpu-buy-or-rent.astro b/src/pages/gpu-buy-or-rent.astro
index ccb2906..c3b9fcd 100644
--- a/src/pages/gpu-buy-or-rent.astro
+++ b/src/pages/gpu-buy-or-rent.astro
@@ -43,7 +43,7 @@ const jsonLd = [
     <div class="fv-text">
       <p class="who">これからロボットAIの学習環境を用意する、<br>企業の担当者・研究者・エンジニア向け</p>
       <h1 id="fv-h">ロボット<span class="lat">AI</span>の<br>学習用<span class="lat">GPU</span>、<br>買うか借りるか</h1>
-      <p class="fv-lead">買う前に借りて、実際に学習させました。見積書と、利用明細を並べます。実費と計算機で、自分の場合どちらが合うかを決められる導入ガイドです。</p>
+      <p class="fv-lead"><b>結論：使うのが月180時間より少ないなら、借りる方が安い。</b>RTX 5090のPCを4年使う場合の目安です。買うなら、GPUのメモリは24GB以上が条件です。実際に借りて学習させた実費（7回で4,677円）と、自分の条件で確かめられる計算機を置いています。</p>
       <div class="fv-cta"><a class="btn dark" href="#calc">自分の条件で計算する<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
     </div>
     <div class="fv-docs">
@@ -724,6 +724,7 @@ const jsonLd = [
 /* 英字（Manrope の一番太い800）を、日本語の900と同じ太さに見せる */
 .gbr .fv h1 .lat,.gbr h2 .lat,.gbr .h-num{-webkit-text-stroke:.028em currentColor;paint-order:stroke fill;letter-spacing:.01em}
 .gbr .fv-lead{margin:0;font-size:1rem;line-height:1.85;color:#2a2d33;max-width:30em}
+.gbr .fv-lead b{display:block;margin-bottom:6px;font-size:1.15rem;line-height:1.6;color:var(--ink)}
 .gbr .fv-cta{display:flex;flex-wrap:wrap;gap:10px}
 .gbr .fv-docs{display:grid;grid-template-columns:minmax(0,380px) 120px minmax(0,380px);align-items:stretch}
 .gbr .doc{background:#fff;border:1px solid var(--rule);padding:20px 24px;display:flex;flex-direction:column;justify-content:space-between;gap:14px;min-height:330px;min-width:0}
diff --git a/src/pages/record/[slug].astro b/src/pages/record/[slug].astro
index d6d2e7b..10e4d95 100644
--- a/src/pages/record/[slug].astro
+++ b/src/pages/record/[slug].astro
@@ -90,6 +90,18 @@ const url = `${SITE}/record/${r.slug}`;
 // 全文（Markdown。Studio から移した記事は HTML）を head に、ファイルの一覧を構造化データ（hasPart）に出して、AI がたどれるようにする
 const filesIndexPath = `public/files/${r.day}/index.json`;
 const filesIndex = existsSync(filesIndexPath) ? JSON.parse(readFileSync(filesIndexPath, 'utf-8')) : null;
+// 記事の素材（分けたファイル）への入口（2026-10-28）。本文の「ファイル一式」の枠に id="files" を付け、タイトルの下から飛べるようにする
+if (filesIndex) body = body.replace('<div class="filebox fb-all">', '<div class="filebox fb-all" id="files">');
+const filesCount = filesIndex && body.includes('id="files"') ? filesIndex.files.length : 0;
+// 古い記録から今の話への道（2026-10-28）。検索から古い記録に着いた人が、そこで止まらないように。
+// 公開から60日より前の記録に出す。同じシリーズに60日以内の記録があればその最新へ（「{シリーズ名}の最新」）、なければサイト全体の最新の記録へ（「いま進めている記録」）
+const DAY_MS = 864e5, OLD_DAYS = 60;
+const fresh = (c) => Date.now() - new Date(c.published).getTime() < OLD_DAYS * DAY_MS;
+const isOld = !isEnglish && Date.now() - new Date(r.published).getTime() >= OLD_DAYS * DAY_MS;
+const seriesNow = isOld ? (await allCards()).find((c) => c.series === r.series && c.slug !== r.slug && !/-en$/.test(c.slug) && fresh(c)) : null;
+const siteNow = isOld && !seriesNow ? (await allCards()).find((c) => !/-en$/.test(c.slug) && c.slug !== r.slug) : null;
+const nowCard = seriesNow || siteNow;
+const ym = (iso) => { const d = new Date(new Date(iso).getTime() + 9 * 3600e3); return `${d.getUTCFullYear()}年${d.getUTCMonth() + 1}月`; };
 const codeLang = { csharp: 'C#', json: 'JSON', yaml: 'YAML', markdown: 'Markdown', python: 'Python', text: 'Text' };
 const jsonLd = [
   {
@@ -129,6 +141,15 @@ const jsonLd = [
     {r.thumb ? <div class="hero"><iframe src={r.thumb} sandbox="allow-scripts" title={r.title} scrolling="no" tabindex="-1"></iframe></div> : r.cover && <img class="hero-img" src={r.cover} alt={r.title} width="1920" height="1080" />}
     <div class="meta"><span class="day">{r.day}</span>{seriesPage ? <a class="tag" href={`/${seriesPage[0]}`}>{r.series}</a> : <span class="tag">{r.series}</span>}<span class="date">{ymd(r.published)}</span></div>
     <h1 class="title">{r.title}</h1>
+    {nowCard && (
+      <a class="now-bar" href={`/record/${nowCard.slug}`} data-ev="今の続き" data-ev-area="now">
+        <span class="nb-k">{ym(r.published)}の記録です。{seriesNow ? `${seriesName}の最新` : 'いま進めている記録'}</span>
+        <span class="nb-t">{nowCard.day}　{nowCard.title}</span><i class="ms" aria-hidden="true">arrow_forward</i>
+      </a>
+    )}
+    {filesCount > 0 && (
+      <a class="files-jump" href="#files" data-ev="素材" data-ev-area="files">この記事の素材（コード・ログ・データ {filesCount}ファイル・まとめてダウンロードあり）<i class="ms" aria-hidden="true">arrow_downward</i></a>
+    )}
     {kind === 'studio'
       ? <div class="richText" set:html={body} />
       : body ? <div class="richText" set:html={body} /> : <div class="richText"><Fragment set:html={toc} /><Content /></div>}
@@ -198,6 +219,16 @@ const jsonLd = [
   .rec .meta { display: flex; align-items: center; gap: 12px; margin-top: 16px; }
   .rec .day { font: 400 28px/28px var(--sans); }
   .rec .title { margin: 12px 0 40px; font: 600 28px/42px var(--sans); overflow-wrap: anywhere; }
+  .rec .title:has(+ .now-bar), .rec .title:has(+ .files-jump) { margin-bottom: 24px; }
+  .now-bar { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 2px 12px; margin: 0 0 24px; padding: 12px 16px; border-radius: 4px; background: var(--ink); color: #fff; text-decoration: none; }
+  .now-bar .nb-k { grid-column: 1; font: 400 13px/20px var(--sans); color: rgba(255,255,255,.72); }
+  .now-bar .nb-t { grid-column: 1; font: 600 15px/24px var(--sans); overflow-wrap: anywhere; }
+  .now-bar .ms { grid-column: 2; grid-row: 1 / span 2; font-size: 20px; transition: transform .2s ease; }
+  .now-bar:hover .ms { transform: translateX(3px); }
+  .files-jump { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 24px; padding: 12px 16px; border-radius: 4px; background: #f0f0f0; color: var(--ink); font: 600 14px/22px var(--sans); text-decoration: none; }
+  .files-jump .ms { font-size: 20px; flex: none; }
+  .files-jump:hover { background: #e6e6e6; }
+  #files { scroll-margin-top: 88px; }
 
   .richText { color: var(--ink); font-family: var(--sans); }
   .richText p { font-size: 18px; line-height: 36px; margin: 8px 0 12px; overflow-wrap: anywhere; }
diff --git a/worker/index.js b/worker/index.js
index 5f8e528..05e7f90 100644
--- a/worker/index.js
+++ b/worker/index.js
@@ -230,17 +230,29 @@ async function hkEvent(request, env) {
   const at = new Date();
   const day = new Date(at.getTime() + 9 * 3600e3).toISOString().slice(0, 10); // 日本時間の日付
   const key = `hk-events/${day}/${at.getTime()}-${crypto.randomUUID().slice(0, 8)}`;
-  await env.MESSAGES.put(key, '', { customMetadata: { e, kind, id, path, w } });
+  // k：b＝機械（クローラー・自動のブラウザの名乗り、navigator.webdriver）／n＝機械の印なし。2026-10-28 から（それより前は印なし＝o）
+  const k = evKind(request, { wd: d.wd, hl: d.hl, u: 1 }) === 'b' ? 'b' : 'n';
+  await env.MESSAGES.put(key, '', { customMetadata: { e, kind, id, path, w, k } });
   return new Response(null, { status: 204 });
 }
 
 async function hkStats(request, env, url) {
   if (request.method !== 'GET') return new Response('Method Not Allowed', { status: 405 });
+  // who=notbot で機械の印のない記録だけ、who=bot で機械だけ、who=old で印を付ける前（2026-10-28 より前）の記録だけを数える（なければ全部）
+  const WHO = { notbot: 'n', bot: 'b', old: 'o' };
+  const who = WHO[url.searchParams.get('who')] ? url.searchParams.get('who') : '';
   const rows = [];
+  const kinds = new Map();
   let cursor;
   do {
     const r = await env.MESSAGES.list({ prefix: 'hk-events/', cursor, include: ['customMetadata'], limit: 1000 });
-    for (const o of r.objects) rows.push({ day: o.key.split('/')[1], ...(o.customMetadata || {}) });
+    for (const o of r.objects) {
+      const m = o.customMetadata || {};
+      const day = o.key.split('/')[1], k = m.k || 'o';
+      const kv = kinds.get(k) || { shown: 0, click: 0, later: 0 }; kv[m.e] = (kv[m.e] || 0) + 1; kinds.set(k, kv);
+      if (who && k !== WHO[who]) continue;
+      rows.push({ day, ...m });
+    }
     cursor = r.truncated ? r.cursor : undefined;
   } while (cursor);
   const add = (map, k, ev) => { const v = map.get(k) || { shown: 0, click: 0, later: 0 }; v[ev] = (v[ev] || 0) + 1; map.set(k, v); return v; };
@@ -248,8 +260,11 @@ async function hkStats(request, env, url) {
   const weekOf = (day) => { const d = new Date(day + 'T00:00:00Z'); d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 6) % 7)); return d.toISOString().slice(0, 10); };
   const byDay = new Map(), byWeek = new Map(), byItem = new Map(), byW = new Map();
   for (const r of rows) { add(byDay, r.day, r.e); add(byWeek, weekOf(r.day), r.e); add(byItem, r.id, r.e); add(byW, r.w, r.e); }
+  const KIND_JA = { n: '機械の印なし', b: '機械', o: '印なし（10/28より前）' };
   const data = {
     total: rows.length,
+    who: who || null,
+    byKind: ['n', 'b', 'o'].filter((k) => kinds.has(k)).map((k) => ({ kind: KIND_JA[k], ...kinds.get(k) })),
     byWeek: [...byWeek].sort((a, b) => b[0].localeCompare(a[0])).map(([week, v]) => {
       const end = new Date(week + 'T00:00:00Z'); end.setUTCDate(end.getUTCDate() + 6);
       return { week: `${week} 〜 ${end.toISOString().slice(5, 10)}`, ...v };
@@ -269,6 +284,8 @@ async function hkStats(request, env, url) {
 <title>ハコブくんの知らせの記録</title><style>body{font:14px/1.7 -apple-system,'Noto Sans JP',sans-serif;margin:24px;color:#242424;background:#f7f7f7}
 h1{font-size:20px}h2{font-size:16px;margin-top:28px}table{border-collapse:collapse;background:#fff;min-width:min(100%,640px)}th,td{border:1px solid #ddd;padding:6px 10px;text-align:left}th{background:#eee}p{color:#555}</style></head><body>
 <h1>ハコブくんの知らせの記録</h1><p>サイトの更新を知らせてハコブくんが走った回数と、そのあと見た人がどう動いたか。数だけを残しており、誰かは分からない。日付は日本時間。</p>
+<p>${who ? `絞り込み：${esc(who)}（?who= を外すと全部）` : '全部の記録。?who=notbot で機械の印のない記録だけ、?who=bot で機械だけ、?who=old で印を付ける前の記録だけに絞れる'}</p>
+<h2>人と機械（絞り込みに関係なく全部。2026-10-28 から印を付けている）</h2>${table('種類', data.byKind, 'kind')}
 <h2>週ごと（月曜はじまり。週が変わると新しい行が増える）</h2>${table('週', data.byWeek, 'week')}
 <h2>日ごと</h2>${table('日付', data.byDay, 'day')}
 <h2>更新ごと</h2>${table('更新', data.byItem, 'id')}
@@ -282,7 +299,7 @@ h1{font-size:20px}h2{font-size:16px;margin-top:28px}table{border-collapse:collap
 // 1回のページ表示 = 1件。中身は持たず、付箋（customMetadata）に書く（一覧のときに中身を読まずに数えられる）。
 // 同じ表示が戻ってきて送り直したときは n が増える。数えるときは v（その表示だけの番号）ごとに n が最大の1件を使う。
 // IP アドレス・ブラウザの種類・Cookie は残さない。v はブラウザに保存されない、その表示だけの番号
-const EV_AREAS = new Set(['hakobu', 'header', 'footer', 'crumbs', 'toc', 'consult', 'pager', 'related', 'body', 'main', 'sim', 'other']);
+const EV_AREAS = new Set(['hakobu', 'header', 'footer', 'crumbs', 'toc', 'consult', 'pager', 'related', 'body', 'main', 'sim', 'now', 'files', 'other']);
 const EV_DEPTHS = new Set([0, 25, 50, 75, 100]);
 const evInt = (x, max) => { const n = Math.floor(Number(x)); return Number.isFinite(n) && n >= 0 ? Math.min(n, max) : 0; };
 // 自動で巡回するプログラムの名乗り（検索エンジン・AI のクローラー・SNS のプレビュー・自動のブラウザ）。名乗りそのものは保存しない
@@ -332,7 +349,7 @@ async function evRecord(request, env, url) {
 // 週は月曜はじまり（日本時間の日付から、その週の月曜の日付を出す）
 const evWeekOf = (day) => { const d = new Date(day + 'T00:00:00Z'); d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 6) % 7)); return d.toISOString().slice(0, 10); };
 const evMedian = (a) => { if (!a.length) return 0; const b = [...a].sort((x, y) => x - y); const m = b.length >> 1; return b.length % 2 ? b[m] : Math.round((b[m - 1] + b[m]) / 2); };
-const EV_AREA_JA = { hakobu: 'ハコブくん', header: 'ヘッダー', footer: 'フッター', crumbs: '現在地', toc: '目次', consult: '相談の案内', pager: '前後の記事', related: '関連記事', body: '本文', main: 'ページの中身', other: 'その他' };
+const EV_AREA_JA = { hakobu: 'ハコブくん', header: 'ヘッダー', footer: 'フッター', crumbs: '現在地', toc: '目次', consult: '相談の案内', pager: '前後の記事', related: '関連記事', body: '本文', main: 'ページの中身', now: '今の続き', files: '記事の素材', other: 'その他' };
 
 async function evStats(request, env, url) {
   if (request.method !== 'GET') return new Response('Method Not Allowed', { status: 405 });
```

### 差分：p2m-site commit fdae8ed（相談のページを検索に出し、フッター・研究の記録の末尾・llms.txt からつなぐ）

```diff
commit fdae8ed
相談のページ（/consult）を検索に出し、フッター・研究の記録の末尾・llms.txt からつなぐ（MASTER v2.1）

- フッターの ADAPT DESIGN の列に「相談について」
- フィジカルAI研究室と導入シミュレーションの記録の末尾に、仕事で使うときの一言と /consult へのボタン（AI活用の相談の案内が出る記事には出さない）
- /llms.txt の導入前ガイドの並びに /consult
- /consult の noindex とサイトマップからの除外を外し、構造化データ（Service）を足す
- トップの画面の中と SNS の投稿には出さない

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXSYG9NkMRzRGxEeaqX


diff --git a/README.md b/README.md
index fd1aed3..339494e 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ Web改善の検証（Project の `claude/web_improvement_trial.md`）のため
 
 ## AI活用の記事と相談の案内
 
-- 一緒に手を動かすコンサルの案内：`/consult`（`src/pages/consult.astro`。2026-10-28）。ボタンは `/message?topic=physical-ai`。MASTER の「相談の窓口」の決まりを直すまでは、noindex・サイトマップから外し（`astro.config.mjs`）、ほかのページからつながない
+- 一緒に手を動かすコンサルの案内：`/consult`（`src/pages/consult.astro`。2026-10-28）。ボタンは `/message?topic=physical-ai`。入口はフッターの「相談について」・研究の記録の末尾（フィジカルAI研究室と導入シミュレーションの記録。文は `src/pages/record/[slug].astro` の `WORK_NOTE`）・`/llms.txt`。トップの画面の中と SNS の投稿には出さない（MASTER v2.1）
 
 AI活用の記事（フィジカルAIの研究を回すために作った仕組みの記録）は、シリーズ「ひとり研究所の裏側」（`series: "ひとり研究所の裏側"`・/series4。2026-10-17 に「ロボティクスデザイン実務フロー」から名前を変えた）に置く。「フィジカルAI研究室」は学習・推論を回す回だけにする。
 AI活用の記事の末尾には、相談の案内（`/message?topic=ai` への導線）を出す。出す記事は、Markdown の記事なら先頭の項目に `ai_consult: true` を書く。Studio から移した記事は `src/data/aiConsult.json` に slug を足す。サイトのトップ・SNS・動画には AI活用の相談を出さない。
diff --git a/astro.config.mjs b/astro.config.mjs
index 8cd8f59..cb21184 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -9,8 +9,7 @@ export default defineConfig({
   build: { format: 'file' },
   // 検索エンジン向けの全ページ一覧（/sitemap-index.xml と /sitemap-0.xml を作る）。404 ページと確認用のページ（/preview/）は載せない
   integrations: [
-    // /consult は MASTER の「相談の窓口」の決まりを直すまで検索に出さない（2026-10-28）
-    sitemap({ filter: (page) => !page.endsWith('/404') && !page.endsWith('/404/') && !page.includes('/preview/') && !/\/consult\/?$/.test(page) }),
+    sitemap({ filter: (page) => !page.endsWith('/404') && !page.endsWith('/404/') && !page.includes('/preview/') }),
   ],
   markdown: {
     // コードは今のサイトと同じく色を付けずに出す
diff --git a/src/lib/nav.ts b/src/lib/nav.ts
index 2adc441..0e8091a 100644
--- a/src/lib/nav.ts
+++ b/src/lib/nav.ts
@@ -32,6 +32,7 @@ export const NAV_MEDIA: NavLink[] = [
 
 export const NAV_OFFICE: NavLink[] = [
   { href: '/#about', label: '事業所について' },
+  { href: '/consult', label: '相談について' },
   { href: '/message', label: 'メッセージ' },
   { href: '/privacypolicy', label: 'Privacy policy' },
 ];
diff --git a/src/pages/consult.astro b/src/pages/consult.astro
index 97b215a..031fd06 100644
--- a/src/pages/consult.astro
+++ b/src/pages/consult.astro
@@ -3,13 +3,19 @@
 // 決めたこと（エイイチ 2026-10-28）：打ち合わせは週1回・訪問は月1回くらい（全国どこでも。交通費・宿泊費は別）・
 // 料金はページに出さず相談で決める・最初の相談はオンライン30分まで無料、それ以降は有料
 // 最初の画面は案A（一緒にやることが主役）。新しい肩書き・キャッチコピーは付けない（MASTER の枝概念の追加禁止）
-// MASTER の「相談の窓口」の決まりを直すまでは検索に出さず（noindex・サイトマップから外す）、ほかのページからもつながない
+// 入口（MASTER v2.1・2026-10-28）：フッター（相談について）・研究の記録の末尾（フィジカルAI研究室・導入シミュレーション）・/llms.txt。
+// トップの画面の中と SNS の投稿には出さない（SNS はプロフィール欄にだけリンクを置く）
 import Base from '../layouts/Base.astro';
+import { SITE, AUTHOR } from '../lib/seo';
 const title = 'フィジカルAIの導入を、一緒に手を動かして進めます';
 const description = 'ロボット学習の環境の立ち上げ、サービスロボットの導入前の確認、現場で回る運用の決め方を、週1回の打ち合わせと月1回の訪問で一緒に進めます。最初の30分の相談は無料（オンライン）。';
 const CTA = '/message?topic=physical-ai';
+const jsonLd = [{
+  '@context': 'https://schema.org', '@type': 'Service', name: title, description, url: SITE + '/consult',
+  serviceType: 'フィジカルAI・ロボット導入のコンサルティング（一緒に手を動かす形）', provider: AUTHOR, areaServed: { '@type': 'Country', name: 'Japan' }, inLanguage: 'ja',
+}];
 ---
-<Base title={`${title} | Pixels to Motors`} description={description} path="/consult" noindex={true}>
+<Base title={`${title} | Pixels to Motors`} description={description} path="/consult" jsonLd={jsonLd}>
   <div class="cs">
     <section class="fv">
       <div class="in fv-in">
diff --git a/src/pages/llms.txt.ts b/src/pages/llms.txt.ts
index 705c5bf..f9ce6b3 100644
--- a/src/pages/llms.txt.ts
+++ b/src/pages/llms.txt.ts
@@ -38,6 +38,7 @@ export async function GET() {
     '',
     `- [配膳ロボットの導入前シミュレーション](${SITE}/serving-robot-one-less-staff): 店舗の図面と人数から、何人で回るか・どこで止まるか・月いくらかかるかを出す`,
     `- [ロボットAIの学習用GPU、買うか借りるか](${SITE}/gpu-buy-or-rent): 実費と損益分岐の計算機で決める導入ガイド`,
+    `- [フィジカルAIの導入を、一緒に手を動かして進めます](${SITE}/consult): ロボット学習の環境の立ち上げ・サービスロボットの導入前の確認・現場で回る運用の決め方を、週1回の打ち合わせと月1回の訪問で一緒に進めるコンサル。最初の30分の相談は無料（オンライン）`,
     `- [ロボットに、何を任せればいいのか](${SITE}/thinking): 考察記事から、いま考えていること`,
     `- [Pixels to Motors の1年](${SITE}/one-year): 画面の中の AI から、ロボットを動かす AI へ`,
     `- [課題地図](${SITE}/issues): フィジカルAIが社会実装される前に解くべき課題（週1回更新）`,
diff --git a/src/pages/record/[slug].astro b/src/pages/record/[slug].astro
index 10e4d95..ce6b754 100644
--- a/src/pages/record/[slug].astro
+++ b/src/pages/record/[slug].astro
@@ -86,6 +86,12 @@ const nearby = others.slice(start, start + 6);
 // Markdown の記事は先頭の項目 ai_consult: true、Studio から移した記事は src/data/aiConsult.json の slug で決める
 const showConsult = kind === 'md' ? entry.data.ai_consult === true : (aiConsult as string[]).includes(r.slug);
 const url = `${SITE}/record/${r.slug}`;
+// 研究の記録の末尾から、相談のページ（/consult）へ（MASTER v2.1・2026-10-28）。AI活用の相談の案内が出る記事には出さない
+const WORK_NOTE = {
+  'フィジカルAI研究室': 'この記録の学習環境を、自社でも立ち上げたい方へ。借りて測るところから、一緒に手を動かして進めます。',
+  '導入シミュレーション': '自店や提案先の店で、ロボットを入れる前に確かめたい方へ。店の形と人数から、一緒に手を動かして試算します。',
+};
+const workNote = !showConsult && !isEnglish ? WORK_NOTE[r.series] : null;
 // 長いコード・ログ・データを外に出した記事（LOG364 から。tools/split_files.py）は、
 // 全文（Markdown。Studio から移した記事は HTML）を head に、ファイルの一覧を構造化データ（hasPart）に出して、AI がたどれるようにする
 const filesIndexPath = `public/files/${r.day}/index.json`;
@@ -159,6 +165,12 @@ const jsonLd = [
         <a class="btn-dark" href="/message?topic=ai">メッセージで相談する<i class="ms">arrow_forward</i></a>
       </aside>
     )}
+    {workNote && (
+      <aside class="consult" aria-label="仕事でのご相談について" data-ev-area="consult">
+        <p>{workNote}</p>
+        <a class="btn-dark" href="/consult" data-ev="記録の末尾:相談について">一緒に進め方を見る<i class="ms">arrow_forward</i></a>
+      </aside>
+    )}
     {(newer || older) && (
       <nav class="pager" aria-label="同じシリーズの前後の記事">
         {older ? <a class="pg pg-prev" href={`/record/${older.slug}`}><span class="pg-k">← 前の記事　{older.day}</span><span class="pg-t">{older.title}</span></a> : <span />}
```

### 差分：相談のページのデザインの直し（commit d6e6729・d9e4104・fc74adf・f51f95c）

```diff
commit d6e6729
相談のページのデザインを導入比較ガイドにそろえ、3つ目の根拠を1年の記録へ

- 色・文字（Manrope＋Noto Sans JP の 900）・番号の見出し（白抜きの 01〜03）・数字の強調（.facts3）・白／薄い灰色／黒の帯・角のないボタンを、/gpu-buy-or-rent と同じ値にした。差し色の橙（実際に払った分専用）は使わない
- 3つ目の根拠を「店員が直す時間」から「1年分の作業ログ 379本」（/one-year へ）に替えた
- 見出しの1行目が「フィジカルAI／の導入を、」で折れないよう、大きさを下げた

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXSYG9NkMRzRGxEeaqX


diff --git a/src/pages/consult.astro b/src/pages/consult.astro
index 031fd06..07b23e1 100644
--- a/src/pages/consult.astro
+++ b/src/pages/consult.astro
@@ -3,6 +3,7 @@
 // 決めたこと（エイイチ 2026-10-28）：打ち合わせは週1回・訪問は月1回くらい（全国どこでも。交通費・宿泊費は別）・
 // 料金はページに出さず相談で決める・最初の相談はオンライン30分まで無料、それ以降は有料
 // 最初の画面は案A（一緒にやることが主役）。新しい肩書き・キャッチコピーは付けない（MASTER の枝概念の追加禁止）
+// デザインは導入比較ガイド（/gpu-buy-or-rent）にそろえる（色・文字・番号の見出し・数字の強調・帯）。写真や絵は使わない（2026-10-28）
 // 入口（MASTER v2.1・2026-10-28）：フッター（相談について）・研究の記録の末尾（フィジカルAI研究室・導入シミュレーション）・/llms.txt。
 // トップの画面の中と SNS の投稿には出さない（SNS はプロフィール欄にだけリンクを置く）
 import Base from '../layouts/Base.astro';
@@ -16,108 +17,162 @@ const jsonLd = [{
 }];
 ---
 <Base title={`${title} | Pixels to Motors`} description={description} path="/consult" jsonLd={jsonLd}>
+  <link slot="head" rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Noto+Sans+JP:wght@400;500;700;900&display=swap" />
   <div class="cs">
-    <section class="fv">
-      <div class="in fv-in">
-        <div class="txt">
-          <p class="who">フィジカルAI・ロボットの導入を進める企業の方へ</p>
-          <h1>フィジカルAIの導入を、<br>一緒に手を動かして<br>進めます</h1>
-          <p class="lead">ロボットに何を任せ、どこを人が持つか。学習環境の立ち上げから、現場で回る運用の落とし所まで、週1回の打ち合わせと月1回の訪問で一緒に進めます。</p>
-          <a class="cta" href={CTA} data-ev="無料で相談する（最初の画面）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a>
+    <section class="fv" aria-labelledby="fv-h">
+      <div class="fv-in">
+        <div class="fv-text">
+          <p class="who">フィジカル<span class="lat">AI</span>・ロボットの導入を進める、<br>企業の担当者・研究開発チーム向け</p>
+          <h1 id="fv-h">フィジカル<span class="lat">AI</span>の導入を、<br>一緒に手を動かして<br>進めます</h1>
+          <p class="fv-lead"><b>ロボットに何を任せ、どこを人が持つか。</b>学習環境の立ち上げから、現場で回る運用の落とし所まで、週1回の打ち合わせと月1回の訪問で一緒に進めます。</p>
+          <div><a class="btn dark" href={CTA} data-ev="無料で相談する（最初の画面）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
         </div>
-        <ol class="do">
-          <li><b>01</b><span><strong>ロボット学習の環境を立ち上げる</strong>借りて測り、買うかどうかを決めるところまで</span></li>
-          <li><b>02</b><span><strong>サービスロボットを入れる前に確かめる</strong>店の形・台数・回し方をシミュレーションで比べる</span></li>
-          <li><b>03</b><span><strong>現場で回る運用を決める</strong>止まり方と人の手間を実物から読み、運用で解く</span></li>
+        <ol class="do" aria-label="一緒にやること">
+          <li><span class="do-n">01</span><div><h2>ロボット学習の環境を立ち上げる</h2><p>借りて測り、買うかどうかを決めるところまで</p></div></li>
+          <li><span class="do-n">02</span><div><h2>サービスロボットを入れる前に確かめる</h2><p>店の形・台数・回し方をシミュレーションで比べる</p></div></li>
+          <li><span class="do-n">03</span><div><h2>現場で回る運用を決める</h2><p>止まり方と人の手間を実物から読み、運用で解く</p></div></li>
         </ol>
       </div>
     </section>
 
-    <section class="proof">
-      <div class="in">
-        <h2>どれも、自分で手を動かして確かめてきたことです</h2>
-        <div class="nums">
-          <a href="/gpu-buy-or-rent" data-ev="根拠：導入比較ガイド"><b>4,677<small>円</small></b><span>ロボットAIの学習を、クラウドで7回回した実費。買うか借りるかの判断まで公開しています</span><em>導入比較ガイドを見る<i class="ms" aria-hidden="true">arrow_forward</i></em></a>
-          <a href="/serving-robot-one-less-staff" data-ev="根拠：配膳ロボットの試算"><b>19<small>本</small></b><span>配膳ロボットの導入シミュレーションの記録。店の図面と人数から、何人で回るかを出します</span><em>導入前の試算を見る<i class="ms" aria-hidden="true">arrow_forward</i></em></a>
-          <a href="/record/serving-robot-video-ledger" data-ev="根拠：現場の観察"><b>5<small>秒</small></b><span>止まった配膳ロボットを店員が直す時間。長いのは、店員が来るまでのほうでした</span><em>現場の観察の記録を見る<i class="ms" aria-hidden="true">arrow_forward</i></em></a>
+    <section class="band-white" aria-labelledby="proof-h">
+      <div class="wrap">
+        <div class="sec-head"><span class="sec-no" aria-hidden="true">01</span><h2 id="proof-h">どれも、自分で手を動かして<br>確かめてきたこと</h2></div>
+        <div class="facts3">
+          <a class="fact" href="/gpu-buy-or-rent" data-ev="根拠：導入比較ガイド">
+            <b class="fact-n">4,677<small>円</small></b>
+            <h3>ロボット<span class="lat">AI</span>の学習を、<br>クラウドで7回回した実費</h3>
+            <p>借りて測り、買うか借りるかの判断まで公開しています。</p>
+            <span class="more">導入比較ガイドを見る<i class="ms" aria-hidden="true">arrow_forward</i></span>
+          </a>
+          <a class="fact" href="/serving-robot-one-less-staff" data-ev="根拠：配膳ロボットの試算">
+            <b class="fact-n">19<small>本</small></b>
+            <h3>配膳ロボットの<br>導入シミュレーションの記録</h3>
+            <p>店の図面と人数から、何人で回るか・どこで止まるかを出します。</p>
+            <span class="more">導入前の試算を見る<i class="ms" aria-hidden="true">arrow_forward</i></span>
+          </a>
+          <a class="fact" href="/one-year" data-ev="根拠：1年の記録">
+            <b class="fact-n">379<small>本</small></b>
+            <h3>コードと実行ログを省かずに残した、<br><span class="lat">1</span>年分の作業ログ</h3>
+            <p><span class="lat">AI</span> に書かせ・確かめさせ・記録させる進め方が、ロボットを動かす <span class="lat">AI</span> の土台になっています。</p>
+            <span class="more">1年の記録を見る<i class="ms" aria-hidden="true">arrow_forward</i></span>
+          </a>
         </div>
       </div>
     </section>
 
-    <section class="flow">
-      <div class="in">
-        <h2>進め方</h2>
+    <section class="band-tint" aria-labelledby="flow-h">
+      <div class="wrap">
+        <div class="sec-head"><span class="sec-no" aria-hidden="true">02</span><h2 id="flow-h">進め方</h2></div>
         <ol class="steps">
-          <li><b>まず</b><strong>オンラインで30分</strong><span>無料。今の状況と、ロボットに任せたいことを伺います</span></li>
-          <li><b>次に</b><strong>1か月、小さく試す</strong><span>ここから有料です。料金は、内容を伺ってから相談して決めます</span></li>
-          <li><b>そして</b><strong>週1回の打ち合わせと<br>月1回の訪問</strong><span>訪問は全国どこでも。交通費・宿泊費は別にいただきます</span></li>
+          <li class="first"><span class="kicker">まず</span><h3>オンラインで<span class="lat">30</span>分</h3><p>無料。今の状況と、ロボットに任せたいことを伺います。</p></li>
+          <li><span class="kicker">次に</span><h3><span class="lat">1</span>か月、小さく試す</h3><p>ここから有料です。料金は、内容を伺ってから相談して決めます。</p></li>
+          <li><span class="kicker">そして</span><h3>週<span class="lat">1</span>回の打ち合わせと<br>月<span class="lat">1</span>回の訪問</h3><p>訪問は全国どこでも。交通費・宿泊費は別にいただきます。</p></li>
         </ol>
       </div>
     </section>
 
-    <section class="who-box">
-      <div class="in">
-        <h2>誰がやっているか</h2>
-        <p>島津栄一（Pixels to Motors）。29年のデザイナー経験。秋田から、ロボットの学習と推論を自分の手で回し、その記録をすべて公開しています。ロボットやフィジカルAIが、これからどこに立つのかを見極め、いま運用に耐える落とし所へ持っていくことを仕事にしています。</p>
-        <a class="cta" href={CTA} data-ev="無料で相談する（最後）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a>
+    <section class="band-ink" aria-labelledby="who-h">
+      <div class="wrap">
+        <div class="sec-head"><span class="sec-no" aria-hidden="true">03</span><h2 id="who-h">誰がやっているか</h2></div>
+        <div class="who-row">
+          <p class="who-text">島津栄一（Pixels to Motors）。29年のデザイナー経験。秋田から、ロボットの学習と推論を自分の手で回し、その記録をすべて公開しています。ロボットやフィジカルAIが、これからどこに立つのかを見極め、いま運用に耐える落とし所へ持っていくことを仕事にしています。</p>
+          <div><a class="btn" href={CTA} data-ev="無料で相談する（最後）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
+        </div>
       </div>
     </section>
   </div>
 </Base>
 
 <style>
-  .cs { padding-top: 64px; background: var(--bg); color: var(--ink); }
-  .in { width: 1080px; max-width: calc(100% - 48px); margin: 0 auto; }
-  .cs h2 { margin: 0 0 32px; font: 700 28px/1.5 var(--sans); }
-  .cta { display: inline-flex; align-items: center; gap: 10px; padding: 14px 24px; border-radius: 4px; background: var(--dark); color: #fff; font: 600 16px/24px 'Noto Sans JP', sans-serif; text-decoration: none; }
-  .cta .ms { font-size: 20px; transition: transform .2s ease; }
-  .cta:hover .ms { transform: translateX(3px); }
+  /* 色・文字・形は導入比較ガイド（/gpu-buy-or-rent の .gbr）と同じ値。差し色（橙）は「実際に払った分」専用なので、このページでは使わない */
+  .cs {
+    --paper: #f4f5f7; --sheet: #fff; --ink: #121418; --muted: #5c616b; --rule: #e2e4e9; --tint: #e9ebef;
+    --gut: max(16px, env(safe-area-inset-left, 0px));
+    --font: "Manrope", "Noto Sans JP", "Hiragino Sans", system-ui, sans-serif;
+    background: var(--paper); color: var(--ink); font-family: var(--font); font-size: 17px; line-height: 1.75; letter-spacing: .02em;
+    padding-top: 48px; -webkit-font-smoothing: antialiased;
+  }
+  .cs *, .cs *::before, .cs *::after { box-sizing: border-box; }
+  .cs h1, .cs h2, .cs h3 { text-wrap: balance; letter-spacing: 0; margin: 0; }
+  .cs p { margin: 0; }
+  .cs .lat { -webkit-text-stroke: .028em currentColor; paint-order: stroke fill; letter-spacing: .01em; }
+  .cs section { padding-block: 80px; }
+  .cs .wrap { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding-inline: var(--gut); display: grid; gap: 40px; }
+
+  .btn { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; text-decoration: none; padding: 12px 20px; border: 1.5px solid var(--ink); color: var(--ink); background: var(--sheet); font-size: .95rem; }
+  .btn.dark { background: var(--ink); border-color: var(--ink); color: #fff; }
+  .btn .ms { font-size: 18px; transition: transform .2s; }
+  .btn:hover { transform: translateY(-1px); }
+  .btn:hover .ms { transform: translateX(3px); }
+  .btn:focus-visible { outline: none; text-decoration: underline; text-underline-offset: 4px; }
+  @media (prefers-reduced-motion: reduce) { .btn:hover { transform: none; } }
 
-  .fv { min-height: calc(100vh - 64px); display: flex; align-items: center; padding: 64px 0; box-sizing: border-box; }
-  .fv-in { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 56px; align-items: center; }
-  .who { margin: 0 0 16px; font: 500 14px/22px var(--sans); color: var(--ink-2); }
-  h1 { margin: 0 0 24px; font: 700 44px/1.35 var(--sans); letter-spacing: .01em; }
-  .lead { margin: 0 0 32px; font: 400 16px/1.9 var(--sans); max-width: 30em; }
-  .do { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
-  .do li { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 16px; align-items: start; padding: 24px; background: var(--panel); border-radius: 4px; }
-  .do b { font: 700 24px/1 var(--sans); }
-  .do strong { display: block; margin-bottom: 6px; font: 700 18px/1.5 var(--sans); }
-  .do span { font: 400 14px/1.8 var(--sans); color: var(--ink-2); }
+  /* 最初の画面 */
+  .fv { padding: 0; }
+  .fv-in { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding: 72px var(--gut) 88px; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 56px; align-items: center; }
+  .fv-text { display: grid; gap: 20px; max-width: 33rem; }
+  .who { font-size: .9rem; font-weight: 700; line-height: 1.6; }
+  .fv h1 { font-size: clamp(1.9rem, 3.9vw, 2.9rem); line-height: 1.14; font-weight: 900; letter-spacing: -.01em; }
+  .fv-lead { font-size: 1rem; line-height: 1.85; color: #2a2d33; max-width: 30em; }
+  .fv-lead b { display: block; margin-bottom: 6px; font-size: 1.15rem; line-height: 1.6; color: var(--ink); }
+  .do { list-style: none; margin: 0; padding: 0; background: var(--sheet); border-top: 2px solid var(--ink); }
+  .do li { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 8px; align-items: center; padding: 22px 24px 22px 20px; }
+  .do li + li { border-top: 1px solid var(--rule); }
+  .do-n { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 2.6rem; line-height: 1; color: var(--sheet); -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill; letter-spacing: -.02em; }
+  .do h2 { font-size: 1.1rem; line-height: 1.5; font-weight: 700; }
+  .do p { margin-top: 4px; font-size: .88rem; color: var(--muted); line-height: 1.7; }
 
-  .proof { padding: 96px 0; background: var(--dark); color: #fff; }
-  .proof h2 { color: #fff; }
-  .nums { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
-  .nums a { display: flex; flex-direction: column; padding: 8px 32px 8px 0; color: #fff; text-decoration: none; }
-  .nums a + a { padding-left: 32px; border-left: 1px solid rgba(255,255,255,.18); }
-  .nums b { font: 700 56px/1.1 var(--sans); }
-  .nums small { font-size: 20px; font-weight: 500; margin-left: 4px; }
-  .nums span { margin: 16px 0 24px; font: 400 15px/1.8 var(--sans); color: rgba(255,255,255,.8); }
-  .nums em { margin-top: auto; display: inline-flex; align-items: center; gap: 6px; font: 600 14px/22px var(--sans); font-style: normal; text-decoration: underline; text-underline-offset: 4px; }
-  .nums em .ms { font-size: 18px; transition: transform .2s ease; }
-  .nums a:hover em .ms { transform: translateX(3px); }
+  /* 番号の見出し（導入比較ガイドの .sec-head と同じ） */
+  .sec-head { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; }
+  .sec-no { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(3.2rem, 7vw, 5rem); line-height: .82; color: var(--paper); -webkit-text-stroke: 3px var(--ink); paint-order: stroke fill; letter-spacing: -.02em; }
+  .sec-head h2 { flex: 1 1 20rem; padding-bottom: 4px; font-size: clamp(1.75rem, 3.3vw, 2.55rem); line-height: 1.3; font-weight: 800; letter-spacing: -.005em; }
+  .band-white { background: #fff; }
+  .band-white .sec-no { color: #fff; }
+  .band-tint { background: var(--tint); }
+  .band-tint .sec-no { color: var(--tint); }
+  .band-ink { background: var(--ink); color: #e8eaf0; }
+  .band-ink h2 { color: #fff; }
+  .band-ink .sec-no { color: var(--ink); -webkit-text-stroke-color: #fff; }
 
-  .flow { padding: 96px 0; }
-  .steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
-  .steps li { padding: 28px 24px; background: var(--panel); border-radius: 4px; }
-  .steps b { display: block; margin-bottom: 12px; font: 600 13px/20px var(--sans); color: var(--ink-3); }
-  .steps strong { display: block; margin-bottom: 8px; font: 700 22px/1.45 var(--sans); }
-  .steps span { font: 400 14px/1.8 var(--sans); color: var(--ink-2); }
+  /* 根拠の数字（導入比較ガイドの .facts3 と同じ） */
+  .facts3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 2px solid var(--ink); }
+  .fact { padding: 24px 28px 8px 0; display: grid; gap: 10px; align-content: start; min-width: 0; color: var(--ink); text-decoration: none; }
+  .fact + .fact { padding-left: 28px; border-left: 1px solid var(--rule); }
+  .fact-n { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(2.4rem, 5vw, 3.4rem); line-height: 1; letter-spacing: -.02em; text-autospace: no-autospace; }
+  .fact-n small { font-size: .42em; font-weight: 700; margin-left: 4px; }
+  .fact-n small.pre { margin: 0 4px 0 0; }
+  .fact h3 { margin-top: 6px; font-size: 1.02rem; line-height: 1.5; }
+  .fact p { font-size: .85rem; color: var(--muted); line-height: 1.75; }
+  .more { margin-top: 8px; display: inline-flex; align-items: center; gap: 6px; font-size: .88rem; font-weight: 700; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
+  .more .ms { font-size: 18px; transition: transform .2s; }
+  .fact:hover .more { text-decoration-thickness: 2px; }
+  .fact:hover .more .ms { transform: translateX(3px); }
 
-  .who-box { padding: 0 0 120px; }
-  .who-box p { margin: 0 0 40px; max-width: 40em; font: 400 16px/2 var(--sans); }
+  /* 進め方 */
+  .steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
+  .steps li { background: var(--sheet); padding: 24px 24px 22px; display: grid; gap: 8px; align-content: start; border-top: 2px solid var(--ink); }
+  .steps li.first { background: var(--ink); color: #fff; }
+  .kicker { font-size: .8rem; font-weight: 700; letter-spacing: .12em; color: var(--muted); }
+  .steps li.first .kicker { color: #b9bec7; }
+  .steps h3 { font-size: 1.35rem; line-height: 1.45; font-weight: 800; }
+  .steps p { font-size: .88rem; line-height: 1.75; color: var(--muted); }
+  .steps li.first p { color: #cfd4de; }
 
-  @media (max-width: 767px) {
-    .in { max-width: calc(100% - 32px); }
-    .fv { min-height: auto; padding: 48px 0 64px; }
-    .fv-in { grid-template-columns: 1fr; gap: 32px; }
-    h1 { font-size: 30px; }
-    .cs h2 { font-size: 22px; margin-bottom: 24px; }
-    .proof, .flow { padding: 64px 0; }
-    .nums { grid-template-columns: 1fr; }
-    .nums a, .nums a + a { padding: 24px 0; border-left: 0; }
-    .nums a + a { border-top: 1px solid rgba(255,255,255,.18); }
-    .nums b { font-size: 44px; }
-    .steps { grid-template-columns: 1fr; }
-    .who-box { padding-bottom: 80px; }
+  /* 誰がやっているか */
+  .who-row { display: grid; grid-template-columns: minmax(0, 36em) auto; gap: 32px 56px; align-items: end; justify-content: space-between; }
+  .who-text { font-size: 1rem; line-height: 2; color: #cfd4de; }
+
+  @media (max-width: 900px) {
+    .fv-in { grid-template-columns: 1fr; gap: 36px; padding: 48px var(--gut) 64px; }
+    .facts3, .steps { grid-template-columns: 1fr; }
+    .fact, .fact + .fact { padding: 24px 0 16px; border-left: 0; }
+    .fact + .fact { border-top: 1px solid var(--rule); }
+    .who-row { grid-template-columns: 1fr; }
+    .cs section { padding-block: 64px; }
+  }
+  @media (max-width: 600px) {
+    .do li { grid-template-columns: 56px minmax(0, 1fr); padding: 18px 16px 18px 14px; }
+    .do-n { font-size: 2rem; }
   }
 </style>
commit d9e4104
相談のページ：最初の画面の3項目を各節へのリンクに、余白と線を整え、進め方のカードを押すと黒に

- 最初の画面の 01〜03 を押すと、01 根拠・02 進め方・03 誰がやっているか へ移る（マウスを乗せると黒に）
- 最初の画面の上の線を消し、上下の余白を詰めた（.cs section の 80px が最初の画面にもかかっていた）
- 進め方のカードの上の線を消し、マウスを乗せると黒になるようにした

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXSYG9NkMRzRGxEeaqX


diff --git a/src/pages/consult.astro b/src/pages/consult.astro
index 07b23e1..2160486 100644
--- a/src/pages/consult.astro
+++ b/src/pages/consult.astro
@@ -28,14 +28,14 @@ const jsonLd = [{
           <div><a class="btn dark" href={CTA} data-ev="無料で相談する（最初の画面）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
         </div>
         <ol class="do" aria-label="一緒にやること">
-          <li><span class="do-n">01</span><div><h2>ロボット学習の環境を立ち上げる</h2><p>借りて測り、買うかどうかを決めるところまで</p></div></li>
-          <li><span class="do-n">02</span><div><h2>サービスロボットを入れる前に確かめる</h2><p>店の形・台数・回し方をシミュレーションで比べる</p></div></li>
-          <li><span class="do-n">03</span><div><h2>現場で回る運用を決める</h2><p>止まり方と人の手間を実物から読み、運用で解く</p></div></li>
+          <li><a href="#proof" data-ev="最初の画面：01へ"><span class="do-n">01</span><div><h2>ロボット学習の環境を立ち上げる</h2><p>借りて測り、買うかどうかを決めるところまで</p></div><i class="ms" aria-hidden="true">arrow_downward</i></a></li>
+          <li><a href="#flow" data-ev="最初の画面：02へ"><span class="do-n">02</span><div><h2>サービスロボットを入れる前に確かめる</h2><p>店の形・台数・回し方をシミュレーションで比べる</p></div><i class="ms" aria-hidden="true">arrow_downward</i></a></li>
+          <li><a href="#who" data-ev="最初の画面：03へ"><span class="do-n">03</span><div><h2>現場で回る運用を決める</h2><p>止まり方と人の手間を実物から読み、運用で解く</p></div><i class="ms" aria-hidden="true">arrow_downward</i></a></li>
         </ol>
       </div>
     </section>
 
-    <section class="band-white" aria-labelledby="proof-h">
+    <section class="band-white" id="proof" aria-labelledby="proof-h">
       <div class="wrap">
         <div class="sec-head"><span class="sec-no" aria-hidden="true">01</span><h2 id="proof-h">どれも、自分で手を動かして<br>確かめてきたこと</h2></div>
         <div class="facts3">
@@ -61,7 +61,7 @@ const jsonLd = [{
       </div>
     </section>
 
-    <section class="band-tint" aria-labelledby="flow-h">
+    <section class="band-tint" id="flow" aria-labelledby="flow-h">
       <div class="wrap">
         <div class="sec-head"><span class="sec-no" aria-hidden="true">02</span><h2 id="flow-h">進め方</h2></div>
         <ol class="steps">
@@ -72,7 +72,7 @@ const jsonLd = [{
       </div>
     </section>
 
-    <section class="band-ink" aria-labelledby="who-h">
+    <section class="band-ink" id="who" aria-labelledby="who-h">
       <div class="wrap">
         <div class="sec-head"><span class="sec-no" aria-hidden="true">03</span><h2 id="who-h">誰がやっているか</h2></div>
         <div class="who-row">
@@ -97,7 +97,7 @@ const jsonLd = [{
   .cs h1, .cs h2, .cs h3 { text-wrap: balance; letter-spacing: 0; margin: 0; }
   .cs p { margin: 0; }
   .cs .lat { -webkit-text-stroke: .028em currentColor; paint-order: stroke fill; letter-spacing: .01em; }
-  .cs section { padding-block: 80px; }
+  .cs section { padding-block: 80px; scroll-margin-top: 48px; }
   .cs .wrap { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding-inline: var(--gut); display: grid; gap: 40px; }
 
   .btn { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; text-decoration: none; padding: 12px 20px; border: 1.5px solid var(--ink); color: var(--ink); background: var(--sheet); font-size: .95rem; }
@@ -109,15 +109,20 @@ const jsonLd = [{
   @media (prefers-reduced-motion: reduce) { .btn:hover { transform: none; } }
 
   /* 最初の画面 */
-  .fv { padding: 0; }
-  .fv-in { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding: 72px var(--gut) 88px; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 56px; align-items: center; }
+  .cs .fv { padding: 0; }
+  .fv-in { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding: 48px var(--gut) 64px; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 56px; align-items: center; }
   .fv-text { display: grid; gap: 20px; max-width: 33rem; }
   .who { font-size: .9rem; font-weight: 700; line-height: 1.6; }
   .fv h1 { font-size: clamp(1.9rem, 3.9vw, 2.9rem); line-height: 1.14; font-weight: 900; letter-spacing: -.01em; }
   .fv-lead { font-size: 1rem; line-height: 1.85; color: #2a2d33; max-width: 30em; }
   .fv-lead b { display: block; margin-bottom: 6px; font-size: 1.15rem; line-height: 1.6; color: var(--ink); }
-  .do { list-style: none; margin: 0; padding: 0; background: var(--sheet); border-top: 2px solid var(--ink); }
-  .do li { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 8px; align-items: center; padding: 22px 24px 22px 20px; }
+  .do { list-style: none; margin: 0; padding: 0; background: var(--sheet); }
+  .do a { display: grid; grid-template-columns: 72px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 22px 20px 22px 20px; color: var(--ink); text-decoration: none; transition: background .2s, color .2s; }
+  .do a > .ms { font-size: 20px; color: var(--muted); transition: transform .2s, color .2s; }
+  .do a:hover { background: var(--ink); color: #fff; }
+  .do a:hover p, .do a:hover > .ms { color: #cfd4de; }
+  .do a:hover .do-n { color: var(--ink); -webkit-text-stroke-color: #fff; }
+  .do a:hover > .ms { transform: translateY(3px); }
   .do li + li { border-top: 1px solid var(--rule); }
   .do-n { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 2.6rem; line-height: 1; color: var(--sheet); -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill; letter-spacing: -.02em; }
   .do h2 { font-size: 1.1rem; line-height: 1.5; font-weight: 700; }
@@ -151,7 +156,10 @@ const jsonLd = [{
 
   /* 進め方 */
   .steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
-  .steps li { background: var(--sheet); padding: 24px 24px 22px; display: grid; gap: 8px; align-content: start; border-top: 2px solid var(--ink); }
+  .steps li { background: var(--sheet); padding: 24px 24px 22px; display: grid; gap: 8px; align-content: start; transition: background .2s, color .2s; }
+  .steps li:hover { background: var(--ink); color: #fff; }
+  .steps li:hover .kicker { color: #b9bec7; }
+  .steps li:hover p { color: #cfd4de; }
   .steps li.first { background: var(--ink); color: #fff; }
   .kicker { font-size: .8rem; font-weight: 700; letter-spacing: .12em; color: var(--muted); }
   .steps li.first .kicker { color: #b9bec7; }
@@ -164,7 +172,7 @@ const jsonLd = [{
   .who-text { font-size: 1rem; line-height: 2; color: #cfd4de; }
 
   @media (max-width: 900px) {
-    .fv-in { grid-template-columns: 1fr; gap: 36px; padding: 48px var(--gut) 64px; }
+    .fv-in { grid-template-columns: 1fr; gap: 32px; padding: 32px var(--gut) 48px; }
     .facts3, .steps { grid-template-columns: 1fr; }
     .fact, .fact + .fact { padding: 24px 0 16px; border-left: 0; }
     .fact + .fact { border-top: 1px solid var(--rule); }
@@ -172,7 +180,7 @@ const jsonLd = [{
     .cs section { padding-block: 64px; }
   }
   @media (max-width: 600px) {
-    .do li { grid-template-columns: 56px minmax(0, 1fr); padding: 18px 16px 18px 14px; }
+    .do a { grid-template-columns: 56px minmax(0, 1fr) auto; padding: 18px 14px; }
     .do-n { font-size: 2rem; }
   }
 </style>
commit fc74adf
相談のページ：ボタンとカードに 4px の角丸（導入比較ガイドのボタンと同じ値）

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXSYG9NkMRzRGxEeaqX


diff --git a/src/pages/consult.astro b/src/pages/consult.astro
index 2160486..f29f612 100644
--- a/src/pages/consult.astro
+++ b/src/pages/consult.astro
@@ -100,7 +100,8 @@ const jsonLd = [{
   .cs section { padding-block: 80px; scroll-margin-top: 48px; }
   .cs .wrap { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding-inline: var(--gut); display: grid; gap: 40px; }
 
-  .btn { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; text-decoration: none; padding: 12px 20px; border: 1.5px solid var(--ink); color: var(--ink); background: var(--sheet); font-size: .95rem; }
+  /* 角丸は導入比較ガイドのボタンと同じ 4px。ボタンとカードにだけ付ける */
+  .btn { border-radius: 4px; display: inline-flex; align-items: center; gap: 8px; font-weight: 700; text-decoration: none; padding: 12px 20px; border: 1.5px solid var(--ink); color: var(--ink); background: var(--sheet); font-size: .95rem; }
   .btn.dark { background: var(--ink); border-color: var(--ink); color: #fff; }
   .btn .ms { font-size: 18px; transition: transform .2s; }
   .btn:hover { transform: translateY(-1px); }
@@ -116,7 +117,7 @@ const jsonLd = [{
   .fv h1 { font-size: clamp(1.9rem, 3.9vw, 2.9rem); line-height: 1.14; font-weight: 900; letter-spacing: -.01em; }
   .fv-lead { font-size: 1rem; line-height: 1.85; color: #2a2d33; max-width: 30em; }
   .fv-lead b { display: block; margin-bottom: 6px; font-size: 1.15rem; line-height: 1.6; color: var(--ink); }
-  .do { list-style: none; margin: 0; padding: 0; background: var(--sheet); }
+  .do { list-style: none; margin: 0; padding: 0; background: var(--sheet); border-radius: 4px; overflow: hidden; }
   .do a { display: grid; grid-template-columns: 72px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 22px 20px 22px 20px; color: var(--ink); text-decoration: none; transition: background .2s, color .2s; }
   .do a > .ms { font-size: 20px; color: var(--muted); transition: transform .2s, color .2s; }
   .do a:hover { background: var(--ink); color: #fff; }
@@ -156,7 +157,7 @@ const jsonLd = [{
 
   /* 進め方 */
   .steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
-  .steps li { background: var(--sheet); padding: 24px 24px 22px; display: grid; gap: 8px; align-content: start; transition: background .2s, color .2s; }
+  .steps li { border-radius: 4px; background: var(--sheet); padding: 24px 24px 22px; display: grid; gap: 8px; align-content: start; transition: background .2s, color .2s; }
   .steps li:hover { background: var(--ink); color: #fff; }
   .steps li:hover .kicker { color: #b9bec7; }
   .steps li:hover p { color: #cfd4de; }
commit f51f95c
相談のページ：相談のボタンを導入比較ガイドの相談のボタンと同じオレンジに

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXSYG9NkMRzRGxEeaqX


diff --git a/src/pages/consult.astro b/src/pages/consult.astro
index f29f612..c58a8a0 100644
--- a/src/pages/consult.astro
+++ b/src/pages/consult.astro
@@ -25,7 +25,7 @@ const jsonLd = [{
           <p class="who">フィジカル<span class="lat">AI</span>・ロボットの導入を進める、<br>企業の担当者・研究開発チーム向け</p>
           <h1 id="fv-h">フィジカル<span class="lat">AI</span>の導入を、<br>一緒に手を動かして<br>進めます</h1>
           <p class="fv-lead"><b>ロボットに何を任せ、どこを人が持つか。</b>学習環境の立ち上げから、現場で回る運用の落とし所まで、週1回の打ち合わせと月1回の訪問で一緒に進めます。</p>
-          <div><a class="btn dark" href={CTA} data-ev="無料で相談する（最初の画面）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
+          <div><a class="btn cta" href={CTA} data-ev="無料で相談する（最初の画面）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
         </div>
         <ol class="do" aria-label="一緒にやること">
           <li><a href="#proof" data-ev="最初の画面：01へ"><span class="do-n">01</span><div><h2>ロボット学習の環境を立ち上げる</h2><p>借りて測り、買うかどうかを決めるところまで</p></div><i class="ms" aria-hidden="true">arrow_downward</i></a></li>
@@ -77,7 +77,7 @@ const jsonLd = [{
         <div class="sec-head"><span class="sec-no" aria-hidden="true">03</span><h2 id="who-h">誰がやっているか</h2></div>
         <div class="who-row">
           <p class="who-text">島津栄一（Pixels to Motors）。29年のデザイナー経験。秋田から、ロボットの学習と推論を自分の手で回し、その記録をすべて公開しています。ロボットやフィジカルAIが、これからどこに立つのかを見極め、いま運用に耐える落とし所へ持っていくことを仕事にしています。</p>
-          <div><a class="btn" href={CTA} data-ev="無料で相談する（最後）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
+          <div><a class="btn cta" href={CTA} data-ev="無料で相談する（最後）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
         </div>
       </div>
     </section>
@@ -102,7 +102,10 @@ const jsonLd = [{
 
   /* 角丸は導入比較ガイドのボタンと同じ 4px。ボタンとカードにだけ付ける */
   .btn { border-radius: 4px; display: inline-flex; align-items: center; gap: 8px; font-weight: 700; text-decoration: none; padding: 12px 20px; border: 1.5px solid var(--ink); color: var(--ink); background: var(--sheet); font-size: .95rem; }
-  .btn.dark { background: var(--ink); border-color: var(--ink); color: #fff; }
+  /* 相談のボタンは導入比較ガイドの相談のボタン（.cta-x-main）と同じオレンジ。マウスを乗せると黒（黒い帯の上では白） */
+  .btn.cta { --cta: #f2600c; background: var(--cta); border-color: var(--cta); color: #fff; transition: background .15s, border-color .15s, color .15s, transform .2s; }
+  .btn.cta:hover { background: var(--ink); border-color: var(--ink); }
+  .band-ink .btn.cta:hover { background: #fff; border-color: #fff; color: var(--ink); }
   .btn .ms { font-size: 18px; transition: transform .2s; }
   .btn:hover { transform: translateY(-1px); }
   .btn:hover .ms { transform: translateX(3px); }
```

### コード：src/pages/consult.astro（公開した最後の版）

```astro
---
// 一緒に手を動かすコンサルの案内（2026-10-28）。「何を頼めるか」を書き、ほかのページの出口はここへつなぐ
// 決めたこと（エイイチ 2026-10-28）：打ち合わせは週1回・訪問は月1回くらい（全国どこでも。交通費・宿泊費は別）・
// 料金はページに出さず相談で決める・最初の相談はオンライン30分まで無料、それ以降は有料
// 最初の画面は案A（一緒にやることが主役）。新しい肩書き・キャッチコピーは付けない（MASTER の枝概念の追加禁止）
// デザインは導入比較ガイド（/gpu-buy-or-rent）にそろえる（色・文字・番号の見出し・数字の強調・帯）。写真や絵は使わない（2026-10-28）
// 入口（MASTER v2.1・2026-10-28）：フッター（相談について）・研究の記録の末尾（フィジカルAI研究室・導入シミュレーション）・/llms.txt。
// トップの画面の中と SNS の投稿には出さない（SNS はプロフィール欄にだけリンクを置く）
import Base from '../layouts/Base.astro';
import { SITE, AUTHOR } from '../lib/seo';
const title = 'フィジカルAIの導入を、一緒に手を動かして進めます';
const description = 'ロボット学習の環境の立ち上げ、サービスロボットの導入前の確認、現場で回る運用の決め方を、週1回の打ち合わせと月1回の訪問で一緒に進めます。最初の30分の相談は無料（オンライン）。';
const CTA = '/message?topic=physical-ai';
const jsonLd = [{
  '@context': 'https://schema.org', '@type': 'Service', name: title, description, url: SITE + '/consult',
  serviceType: 'フィジカルAI・ロボット導入のコンサルティング（一緒に手を動かす形）', provider: AUTHOR, areaServed: { '@type': 'Country', name: 'Japan' }, inLanguage: 'ja',
}];
---
<Base title={`${title} | Pixels to Motors`} description={description} path="/consult" jsonLd={jsonLd}>
  <link slot="head" rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Noto+Sans+JP:wght@400;500;700;900&display=swap" />
  <div class="cs">
    <section class="fv" aria-labelledby="fv-h">
      <div class="fv-in">
        <div class="fv-text">
          <p class="who">フィジカル<span class="lat">AI</span>・ロボットの導入を進める、<br>企業の担当者・研究開発チーム向け</p>
          <h1 id="fv-h">フィジカル<span class="lat">AI</span>の導入を、<br>一緒に手を動かして<br>進めます</h1>
          <p class="fv-lead"><b>ロボットに何を任せ、どこを人が持つか。</b>学習環境の立ち上げから、現場で回る運用の落とし所まで、週1回の打ち合わせと月1回の訪問で一緒に進めます。</p>
          <div><a class="btn cta" href={CTA} data-ev="無料で相談する（最初の画面）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
        </div>
        <ol class="do" aria-label="一緒にやること">
          <li><a href="#proof" data-ev="最初の画面：01へ"><span class="do-n">01</span><div><h2>ロボット学習の環境を立ち上げる</h2><p>借りて測り、買うかどうかを決めるところまで</p></div><i class="ms" aria-hidden="true">arrow_downward</i></a></li>
          <li><a href="#flow" data-ev="最初の画面：02へ"><span class="do-n">02</span><div><h2>サービスロボットを入れる前に確かめる</h2><p>店の形・台数・回し方をシミュレーションで比べる</p></div><i class="ms" aria-hidden="true">arrow_downward</i></a></li>
          <li><a href="#who" data-ev="最初の画面：03へ"><span class="do-n">03</span><div><h2>現場で回る運用を決める</h2><p>止まり方と人の手間を実物から読み、運用で解く</p></div><i class="ms" aria-hidden="true">arrow_downward</i></a></li>
        </ol>
      </div>
    </section>

    <section class="band-white" id="proof" aria-labelledby="proof-h">
      <div class="wrap">
        <div class="sec-head"><span class="sec-no" aria-hidden="true">01</span><h2 id="proof-h">どれも、自分で手を動かして<br>確かめてきたこと</h2></div>
        <div class="facts3">
          <a class="fact" href="/gpu-buy-or-rent" data-ev="根拠：導入比較ガイド">
            <b class="fact-n">4,677<small>円</small></b>
            <h3>ロボット<span class="lat">AI</span>の学習を、<br>クラウドで7回回した実費</h3>
            <p>借りて測り、買うか借りるかの判断まで公開しています。</p>
            <span class="more">導入比較ガイドを見る<i class="ms" aria-hidden="true">arrow_forward</i></span>
          </a>
          <a class="fact" href="/serving-robot-one-less-staff" data-ev="根拠：配膳ロボットの試算">
            <b class="fact-n">19<small>本</small></b>
            <h3>配膳ロボットの<br>導入シミュレーションの記録</h3>
            <p>店の図面と人数から、何人で回るか・どこで止まるかを出します。</p>
            <span class="more">導入前の試算を見る<i class="ms" aria-hidden="true">arrow_forward</i></span>
          </a>
          <a class="fact" href="/one-year" data-ev="根拠：1年の記録">
            <b class="fact-n">379<small>本</small></b>
            <h3>コードと実行ログを省かずに残した、<br><span class="lat">1</span>年分の作業ログ</h3>
            <p><span class="lat">AI</span> に書かせ・確かめさせ・記録させる進め方が、ロボットを動かす <span class="lat">AI</span> の土台になっています。</p>
            <span class="more">1年の記録を見る<i class="ms" aria-hidden="true">arrow_forward</i></span>
          </a>
        </div>
      </div>
    </section>

    <section class="band-tint" id="flow" aria-labelledby="flow-h">
      <div class="wrap">
        <div class="sec-head"><span class="sec-no" aria-hidden="true">02</span><h2 id="flow-h">進め方</h2></div>
        <ol class="steps">
          <li class="first"><span class="kicker">まず</span><h3>オンラインで<span class="lat">30</span>分</h3><p>無料。今の状況と、ロボットに任せたいことを伺います。</p></li>
          <li><span class="kicker">次に</span><h3><span class="lat">1</span>か月、小さく試す</h3><p>ここから有料です。料金は、内容を伺ってから相談して決めます。</p></li>
          <li><span class="kicker">そして</span><h3>週<span class="lat">1</span>回の打ち合わせと<br>月<span class="lat">1</span>回の訪問</h3><p>訪問は全国どこでも。交通費・宿泊費は別にいただきます。</p></li>
        </ol>
      </div>
    </section>

    <section class="band-ink" id="who" aria-labelledby="who-h">
      <div class="wrap">
        <div class="sec-head"><span class="sec-no" aria-hidden="true">03</span><h2 id="who-h">誰がやっているか</h2></div>
        <div class="who-row">
          <p class="who-text">島津栄一（Pixels to Motors）。29年のデザイナー経験。秋田から、ロボットの学習と推論を自分の手で回し、その記録をすべて公開しています。ロボットやフィジカルAIが、これからどこに立つのかを見極め、いま運用に耐える落とし所へ持っていくことを仕事にしています。</p>
          <div><a class="btn cta" href={CTA} data-ev="無料で相談する（最後）">無料で相談する（30分）<i class="ms" aria-hidden="true">arrow_forward</i></a></div>
        </div>
      </div>
    </section>
  </div>
</Base>

<style>
  /* 色・文字・形は導入比較ガイド（/gpu-buy-or-rent の .gbr）と同じ値。差し色（橙）は「実際に払った分」専用なので、このページでは使わない */
  .cs {
    --paper: #f4f5f7; --sheet: #fff; --ink: #121418; --muted: #5c616b; --rule: #e2e4e9; --tint: #e9ebef;
    --gut: max(16px, env(safe-area-inset-left, 0px));
    --font: "Manrope", "Noto Sans JP", "Hiragino Sans", system-ui, sans-serif;
    background: var(--paper); color: var(--ink); font-family: var(--font); font-size: 17px; line-height: 1.75; letter-spacing: .02em;
    padding-top: 48px; -webkit-font-smoothing: antialiased;
  }
  .cs *, .cs *::before, .cs *::after { box-sizing: border-box; }
  .cs h1, .cs h2, .cs h3 { text-wrap: balance; letter-spacing: 0; margin: 0; }
  .cs p { margin: 0; }
  .cs .lat { -webkit-text-stroke: .028em currentColor; paint-order: stroke fill; letter-spacing: .01em; }
  .cs section { padding-block: 80px; scroll-margin-top: 48px; }
  .cs .wrap { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding-inline: var(--gut); display: grid; gap: 40px; }

  /* 角丸は導入比較ガイドのボタンと同じ 4px。ボタンとカードにだけ付ける */
  .btn { border-radius: 4px; display: inline-flex; align-items: center; gap: 8px; font-weight: 700; text-decoration: none; padding: 12px 20px; border: 1.5px solid var(--ink); color: var(--ink); background: var(--sheet); font-size: .95rem; }
  /* 相談のボタンは導入比較ガイドの相談のボタン（.cta-x-main）と同じオレンジ。マウスを乗せると黒（黒い帯の上では白） */
  .btn.cta { --cta: #f2600c; background: var(--cta); border-color: var(--cta); color: #fff; transition: background .15s, border-color .15s, color .15s, transform .2s; }
  .btn.cta:hover { background: var(--ink); border-color: var(--ink); }
  .band-ink .btn.cta:hover { background: #fff; border-color: #fff; color: var(--ink); }
  .btn .ms { font-size: 18px; transition: transform .2s; }
  .btn:hover { transform: translateY(-1px); }
  .btn:hover .ms { transform: translateX(3px); }
  .btn:focus-visible { outline: none; text-decoration: underline; text-underline-offset: 4px; }
  @media (prefers-reduced-motion: reduce) { .btn:hover { transform: none; } }

  /* 最初の画面 */
  .cs .fv { padding: 0; }
  .fv-in { max-width: calc(1080px + 2 * var(--gut)); margin: 0 auto; padding: 48px var(--gut) 64px; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 56px; align-items: center; }
  .fv-text { display: grid; gap: 20px; max-width: 33rem; }
  .who { font-size: .9rem; font-weight: 700; line-height: 1.6; }
  .fv h1 { font-size: clamp(1.9rem, 3.9vw, 2.9rem); line-height: 1.14; font-weight: 900; letter-spacing: -.01em; }
  .fv-lead { font-size: 1rem; line-height: 1.85; color: #2a2d33; max-width: 30em; }
  .fv-lead b { display: block; margin-bottom: 6px; font-size: 1.15rem; line-height: 1.6; color: var(--ink); }
  .do { list-style: none; margin: 0; padding: 0; background: var(--sheet); border-radius: 4px; overflow: hidden; }
  .do a { display: grid; grid-template-columns: 72px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 22px 20px 22px 20px; color: var(--ink); text-decoration: none; transition: background .2s, color .2s; }
  .do a > .ms { font-size: 20px; color: var(--muted); transition: transform .2s, color .2s; }
  .do a:hover { background: var(--ink); color: #fff; }
  .do a:hover p, .do a:hover > .ms { color: #cfd4de; }
  .do a:hover .do-n { color: var(--ink); -webkit-text-stroke-color: #fff; }
  .do a:hover > .ms { transform: translateY(3px); }
  .do li + li { border-top: 1px solid var(--rule); }
  .do-n { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 2.6rem; line-height: 1; color: var(--sheet); -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill; letter-spacing: -.02em; }
  .do h2 { font-size: 1.1rem; line-height: 1.5; font-weight: 700; }
  .do p { margin-top: 4px; font-size: .88rem; color: var(--muted); line-height: 1.7; }

  /* 番号の見出し（導入比較ガイドの .sec-head と同じ） */
  .sec-head { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; }
  .sec-no { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(3.2rem, 7vw, 5rem); line-height: .82; color: var(--paper); -webkit-text-stroke: 3px var(--ink); paint-order: stroke fill; letter-spacing: -.02em; }
  .sec-head h2 { flex: 1 1 20rem; padding-bottom: 4px; font-size: clamp(1.75rem, 3.3vw, 2.55rem); line-height: 1.3; font-weight: 800; letter-spacing: -.005em; }
  .band-white { background: #fff; }
  .band-white .sec-no { color: #fff; }
  .band-tint { background: var(--tint); }
  .band-tint .sec-no { color: var(--tint); }
  .band-ink { background: var(--ink); color: #e8eaf0; }
  .band-ink h2 { color: #fff; }
  .band-ink .sec-no { color: var(--ink); -webkit-text-stroke-color: #fff; }

  /* 根拠の数字（導入比較ガイドの .facts3 と同じ） */
  .facts3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 2px solid var(--ink); }
  .fact { padding: 24px 28px 8px 0; display: grid; gap: 10px; align-content: start; min-width: 0; color: var(--ink); text-decoration: none; }
  .fact + .fact { padding-left: 28px; border-left: 1px solid var(--rule); }
  .fact-n { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(2.4rem, 5vw, 3.4rem); line-height: 1; letter-spacing: -.02em; text-autospace: no-autospace; }
  .fact-n small { font-size: .42em; font-weight: 700; margin-left: 4px; }
  .fact-n small.pre { margin: 0 4px 0 0; }
  .fact h3 { margin-top: 6px; font-size: 1.02rem; line-height: 1.5; }
  .fact p { font-size: .85rem; color: var(--muted); line-height: 1.75; }
  .more { margin-top: 8px; display: inline-flex; align-items: center; gap: 6px; font-size: .88rem; font-weight: 700; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
  .more .ms { font-size: 18px; transition: transform .2s; }
  .fact:hover .more { text-decoration-thickness: 2px; }
  .fact:hover .more .ms { transform: translateX(3px); }

  /* 進め方 */
  .steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
  .steps li { border-radius: 4px; background: var(--sheet); padding: 24px 24px 22px; display: grid; gap: 8px; align-content: start; transition: background .2s, color .2s; }
  .steps li:hover { background: var(--ink); color: #fff; }
  .steps li:hover .kicker { color: #b9bec7; }
  .steps li:hover p { color: #cfd4de; }
  .steps li.first { background: var(--ink); color: #fff; }
  .kicker { font-size: .8rem; font-weight: 700; letter-spacing: .12em; color: var(--muted); }
  .steps li.first .kicker { color: #b9bec7; }
  .steps h3 { font-size: 1.35rem; line-height: 1.45; font-weight: 800; }
  .steps p { font-size: .88rem; line-height: 1.75; color: var(--muted); }
  .steps li.first p { color: #cfd4de; }

  /* 誰がやっているか */
  .who-row { display: grid; grid-template-columns: minmax(0, 36em) auto; gap: 32px 56px; align-items: end; justify-content: space-between; }
  .who-text { font-size: 1rem; line-height: 2; color: #cfd4de; }

  @media (max-width: 900px) {
    .fv-in { grid-template-columns: 1fr; gap: 32px; padding: 32px var(--gut) 48px; }
    .facts3, .steps { grid-template-columns: 1fr; }
    .fact, .fact + .fact { padding: 24px 0 16px; border-left: 0; }
    .fact + .fact { border-top: 1px solid var(--rule); }
    .who-row { grid-template-columns: 1fr; }
    .cs section { padding-block: 64px; }
  }
  @media (max-width: 600px) {
    .do a { grid-template-columns: 56px minmax(0, 1fr) auto; padding: 18px 14px; }
    .do-n { font-size: 2rem; }
  }
</style>
```

### コード：tools/indexnow.py（鍵の値は <INDEXNOW_KEY> に置き換えた）

```python
#!/usr/bin/env python3
"""公開したページを、IndexNow で検索エンジン（Bing など。ChatGPT の検索は Bing を土台にしている）にすぐ知らせる（2026-10-28）。

使い方（.github/workflows/indexnow.yml が main への push のたびに動かす）
  python3 tools/indexnow.py <前の commit> <今の commit>   … その間に増えた・変わったページだけ知らせる
  python3 tools/indexnow.py --all                         … 公開中のサイトマップの全ページを知らせる（最初の1回・まとめて出し直すとき）
  どちらも --dry-run を付けると、送らずに一覧だけ出す

鍵は public/{KEY}.txt に置いた公開の文字列（IndexNow の決まりで、誰でも見られる場所に置く。秘密ではない）。
"""
import json, re, subprocess, sys, urllib.request, xml.etree.ElementTree as ET

SITE = 'https://pixelstomotors.com'
HOST = 'pixelstomotors.com'
KEY = '<INDEXNOW_KEY>'
ENDPOINT = 'https://api.indexnow.org/indexnow'
# 名乗りがないと Cloudflare の守り・IndexNow に断られる（python の既定の名乗りは 403 になった）
UA = {'User-Agent': 'p2m-indexnow/1.0 (+https://pixelstomotors.com)'}


def changed_files(a, b):
    out = subprocess.run(['git', 'diff', '--name-only', '--diff-filter=AM', a, b], capture_output=True, text=True, check=True).stdout
    return [l for l in out.splitlines() if l]


def front_slug(path):
    try:
        text = open(path, encoding='utf-8').read()
    except OSError:
        return None
    m = re.search(r'^slug:\s*"?([\w.-]+)"?\s*$', text, re.M)
    return m.group(1) if m else None


def urls_from_diff(a, b):
    urls, record_changed = set(), False
    for f in changed_files(a, b):
        if f.startswith('src/content/records/') and f.endswith('.md'):
            s = front_slug(f)
            if s: urls.add(f'{SITE}/record/{s}'); record_changed = True
        elif f.startswith('src/data/records/') and f.endswith('.json'):
            try: s = json.load(open(f, encoding='utf-8')).get('slug')
            except (OSError, ValueError): s = None
            if s: urls.add(f'{SITE}/record/{s}'); record_changed = True
        elif re.fullmatch(r'src/pages/[\w-]+\.astro', f):
            name = f.split('/')[-1][:-6]
            urls.add(SITE + ('/' if name == 'index' else f'/{name}'))
        elif f.startswith('src/data/issues/'):
            urls.add(f'{SITE}/issues')
    if record_changed:
        urls.update({SITE + '/', SITE + '/llms.txt'})
    return sorted(urls)


def urls_from_sitemap():
    with urllib.request.urlopen(urllib.request.Request(SITE + '/sitemap-0.xml', headers=UA), timeout=30) as r:
        root = ET.fromstring(r.read())
    ns = {'s': 'http://www.sitemaps.org/schemas/sitemap/0.9'}
    return [e.text.strip() for e in root.findall('.//s:loc', ns)] + [SITE + '/llms.txt']


def submit(urls):
    body = json.dumps({'host': HOST, 'key': KEY, 'keyLocation': f'{SITE}/{KEY}.txt', 'urlList': urls[:10000]}).encode()
    req = urllib.request.Request(ENDPOINT, data=body, headers={'Content-Type': 'application/json; charset=utf-8', **UA}, method='POST')
    try:
        with urllib.request.urlopen(req, timeout=30) as r:
            return r.status, ''
    except urllib.error.HTTPError as e:
        return e.code, e.read()[:300].decode('utf-8', 'replace')


def main():
    args = [a for a in sys.argv[1:] if a != '--dry-run']
    dry = '--dry-run' in sys.argv
    urls = urls_from_sitemap() if args[:1] == ['--all'] else urls_from_diff(args[0], args[1])
    print(f'{len(urls)} 件')
    for u in urls[:50]: print(' ', u)
    if not urls or dry:
        return
    status, detail = submit(urls)
    # 200＝受け付けた／202＝受け付けたが鍵の確認待ち。それ以外は失敗（最初の数回は SiteVerificationNotCompleted の 403 が返ることがある）
    print('IndexNow の返事:', status, detail)
    if status not in (200, 202):
        sys.exit(1)


if __name__ == '__main__':
    main()
```

### コード：.github/workflows/indexnow.yml

```yaml
# 公開したページを、IndexNow で検索エンジン（Bing など）にすぐ知らせる（2026-10-28）
# main に push されたら、Cloudflare の公開（約40秒）を待ってから、増えた・変わったページだけを送る
# 手で動かすとき（Actions の画面の Run workflow）は、公開中のサイトマップの全ページを送る
# 中身は tools/indexnow.py
name: 公開したページを検索エンジンに知らせる

on:
  push:
    branches: [main]
    paths: ['src/**', 'public/**']
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: indexnow
  cancel-in-progress: false

jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: 公開を待つ
        run: sleep 120
      - name: 知らせる
        env:
          BEFORE: ${{ github.event.before }}
          AFTER: ${{ github.sha }}
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            python3 tools/indexnow.py --all
          else
            if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then BEFORE="$AFTER~1"; fi
            python3 tools/indexnow.py "$BEFORE" "$AFTER"
          fi
```

### 出力：IndexNow の最初の送信（全674ページ）

```text
# 鍵のファイルが公開されたかを確かめる
$ curl -s -o /dev/null -w "key %{http_code}\n" https://pixelstomotors.com/<INDEXNOW_KEY>.txt
key 200

# 1回目：Python の既定の名乗りでサイトマップを取りに行くと、Cloudflare に止められた
urllib.error.HTTPError: HTTP Error 403: Forbidden

# 2回目：サイトマップは curl で取り、送信に名乗りを付けた。鍵の確認がまだ済んでいなかった
674 True
status 403 b'{"errorCode":"SiteVerificationNotCompleted","message":"Site Verification is not completed. Please wait for some time for the verification to complete and try again.","details":null}'

# 3回目：数分待って送り直した
674 status 200
```

### データ：書き出しの直しの中身 spec.py（35本の答えの文とメタディスクリプション）

```python
# 書き出しの直し（2026-10-28・article_rules.md「最初の1〜2文は、問いへの答えにする」）
# mode: 'pre' = 今の最初の段落の前に、答えの段落を足す / ('rep', old) = 最初の段落の頭の old を new に置き換える
# meta: メタディスクリプション（md の記事だけ。120字以内・最初の文を答えにそろえる）
SPEC = {
 'precision-is-not-learning-so101': dict(mode='pre',
  new='ロボットアームの動きを細かく合わせる表（FKテーブル）をいくら濃くしても、アームが失敗から学ぶようにはなりません。精度を上げることと失敗から学ぶことは別の仕事だと、mechArm 270 の動的追従の作業を振り返る対話で行き着き、次は失敗から学ぶアームを SO-101 で作ることにしました。'),
 'where-learning-data-lives': dict(mode='pre',
  new='模倣学習で生まれるデータ（人が操作して集めたお手本・手首カメラの録画・学習途中のモデル）は、Mac の中ではなく 2TB の外付け SSD を定位置にして、1か所に集めることにしました。決める前に、Mac の空き容量が約90GBから20GBまで減っていた原因を突き止めて片付けました。'),
 'building-a-physical-ai-lab-at-home': dict(mode='pre',
  new='ロボットの AI（Physical AI）が学習できる環境を、個人の自宅にゼロから作り、誰でも同じ手順で作り直せる形で公開するシリーズを始めました。目的はロボットを持つことではなく、学習と推論を自分の手で回せる環境を残すことです。'),
 'openpi-remote-inference-first-run': dict(mode='pre',
  new='Physical Intelligence の π0.5 は手元の Mac では動きませんが、Runpod で NVIDIA A40 の GPU を時間単位で借りれば動かせました。Mac から画像と指示文を送り、π0.5 が返すロボットアームの動きの数値を受け取るところまで通しました。'),
 'pi05-libero-benchmark-first-run': dict(mode='pre',
  new='Physical Intelligence の π0.5 は、Runpod で借りた NVIDIA A40 の上で、シミュレータ LIBERO の中のアームを動かし、「黒いボウルを拾って皿に置く」作業を20回すべて成功させました。あわせて、π0.5 が使う GPU メモリの量を測りました。'),
 'pi05-mecharm-demo-to-inference': dict(mode='pre',
  new='Physical Intelligence の π0.5 は、mechArm 270 で録ったお手本のうち2本で200ステップ追加学習しただけで、学習の誤差（loss）が0.1031から0.0162に下がり、Mac から動きの予測を受け取れるところまで進みました。実物のアームはまだ動かしていません。',
  meta='Physical Intelligenceのπ0.5をmechArm 270のお手本2本でA40で200ステップ追加学習すると、lossは0.1031から0.0162へ下がり、Macで予測を受け取れた。実機はまだ動かしていない。'),
 'pi05-mecharm-lora-2000-steps': dict(mode='pre',
  new='Physical Intelligence の π0.5 を mechArm 270 のお手本19本で2,000ステップ追加学習すると、実物のアームに送る前の予測は、お手本の最初の1秒と関節ごとに数度以内で一致しました。',
  meta='Physical Intelligenceのπ0.5をmechArm 270のお手本19本で2,000ステップ学習すると、実機に送る前の予測はお手本の最初の1秒と数度以内で一致した。lossは0.1155から0.0054へ。'),
 'pi05-mecharm-first-real-run': dict(mode='pre',
  new='お手本19本で学習した Physical Intelligence の π0.5 で mechArm 270 を初めて動かすと、アームはブロックの真上までは来ましたが、手首が指令の角度に届かず止まりました。原因は手前の爪がブロックの上に乗っていたことで、関節の記録ではなく動画で分かりました。',
  meta='お手本19本で学習したPhysical Intelligenceのπ0.5でmechArm 270を初めて動かすと、ブロックの真上で手首が指令に届かず止まった。原因は爪がブロックに乗っていたことで、動画で分かった。'),
 'pi05-mecharm-4000-steps': dict(mode='pre',
  new='Physical Intelligence の π0.5 の学習を2,000ステップから4,000ステップへ倍にしても、mechArm 270 が手を伸ばす先は変わらず、爪は2回ともブロックの奥で空を閉じました。学習の誤差（loss）は0.0030まで下がっていました。',
  meta='Physical Intelligenceのπ0.5の学習を4,000ステップに倍にしても、mechArm 270が手を伸ばす先は変わらず、爪は2回ともブロックの奥で空を閉じた。lossは0.0030まで下がっていた。'),
 'drag-teach-waypoint-replay': dict(mode='pre',
  new='mechArm 270 の姿勢を人が手で動かして教え、アームにそのまま再生させる方法（ダイレクトティーチング）で、ブロックを箱に入れる動きを4回続けて成功させました。最初は床に当たって止まりましたが、教える姿勢を高めにし、着いたかを確かめる幅を広げて直しました。',
  meta='mechArm 270に姿勢を手で教えて再生させる方法で、ブロックを箱に入れる動きを4回続けて成功させた。床に当たって止まったが、高めに教え直し確認の幅を広げて直した。π0.5に渡すお手本を作るため。'),
 'serving-robot-simulation-simpy': dict(mode='pre',
  new='配膳ロボットを入れてホールのスタッフを1人減らせるかは、店の形で分かれます。飲食店の混む2時間をパソコンで再現した試算では、35卓のファミレスは入口の待ちが7.7分から14.0分に延び、焼肉の食べ放題は8.2分から4.5分に縮みました。',
  meta='配膳ロボットでスタッフを1人減らせるかは店の形で分かれた。混む2時間をSimPyで再現した試算で、ファミレスは入店待ちが7.7分から14.0分に延び、食べ放題は8.2分から4.5分に縮んだ。'),
 'serving-robot-observation-sheet': dict(mode='pre',
  new='配膳ロボットが店の通路で何回止まるかは、公開されたデータが見つかりませんでした。そこで、止まった場所と原因、皿を下げる時間などを、店でスマホを押して数える観察シートを作りました。',
  meta='配膳ロボットが店で何回止まるかは公開データが見つからなかった。そこで、止まった場所と原因、皿を下げる時間、設定を変える前と後を、店でスマホを押して数える観察シートを作った。'),
 'pi05-retrain-five-positions': dict(mode='pre',
  new='ブロックの置き場所を5か所に広げたお手本19本で、Physical Intelligence の π0.5 を Runpod の A40 で4,000ステップ学習し直すと、学習の誤差（loss）は0.0858から0.0037に下がりました。GPU の空きを待ったため、学習を始めるまでに約4時間半かかりました。',
  meta='置き場所を5か所に広げたお手本19本で、Physical Intelligenceのπ0.5をA40で4,000ステップ学習し直すと、lossは0.0858から0.0037へ。GPUの空き待ちで起動まで約4時間半かかった。'),
 'service-robot-five-sites': dict(mode='pre',
  new='配膳の次にサービスロボットが入りそうな5つの現場（病院の検体搬送・夜間清掃・ホテルの配送・夜間警備・歩道の配送）を調べると、ロボットが人を呼ぶ回数はどの現場も公開されていませんでした。そこで、その回数を仮に置いて変えられる試算を作りました。',
  meta='病院の検体搬送・夜間清掃・ホテル配送・夜間警備・歩道の配送の5現場を調べると、ロボットが人を呼ぶ回数はどこも公開されていなかった。仮に置いて変えられるSimPyの試算を作った。'),
 'unity-family-restaurant-serving-robot': dict(mode='pre',
  new='Unity に35卓のファミレスを建て、配膳ロボット2台を走らせる3Dのシミュレーションを作ると、最初の版では往復の88%でロボットが60秒以上動けませんでした。原因はロボットより、店の間取りと人の動きの側にありました。',
  meta='Unityに35卓のファミレスを建て配膳ロボット2台を走らせると、最初の版では往復の88%でロボットが60秒以上動けなかった。原因はロボットより店の間取りと人の動きの側にあった。'),
 'pi05-learned-the-pauses': dict(mode='pre',
  new='Physical Intelligence の π0.5 は、お手本の動きと一緒に、お手本の中でアームが止まっていた待ち時間まで覚えていました。止まっている時間を詰めて学習し直すと、mechArm 270 はブロックをつかんで箱まで運びましたが、持ち上げずに箱の外で離しました。',
  meta='Physical Intelligenceのπ0.5は、お手本の中の止まっている時間まで覚えていた。停止を詰めて学習し直すと、mechArm 270はブロックをつかんで箱まで運んだが、持ち上げずに箱の外で離した。'),
 'audit-simulator-before-unity': dict(mode='pre',
  new='配膳ロボットの試算を Unity の3Dのシミュレーションに合わせる前に、試算のほうを点検し、入店待ちを「満席で待つ」と「席はあるのに片付け・案内が追いつかずに待つ」に分けました。席があるのに10分以上待たせる条件を「店が回らない」として、試算のページに出しました。',
  meta='配膳ロボットの試算をUnityに合わせる前に試算を点検し、入店待ちを満席と「席はあるのに片付け・案内が追いつかない」に分けた。席があるのに10分以上待つ条件を「店が回らない」とした。'),
 'floor-plans-into-simulator': dict(mode='pre',
  new='配膳ロボットの試算に平面図のある店を6つ足し、ロボットが卓まで何m走り、通路の一番狭い所が何cmかを、図面から測って計算に入れました。図面は、昔働いたファミレスの記憶と、席の並べ方の決まりからコードで起こしました。',
  meta='配膳ロボットの試算に平面図のある店を6つ足し、卓まで何m走るか・通路の一番狭い所が何cmかを図面から測って入れた。図面は昔働いたファミレスの記憶と席の並べ方の決まりからコードで起こした。'),
 'pi05-first-block-in-box': dict(mode=('rep', '机の上の小さなロボットアームが、AI の指示だけで赤いブロックをつかみ、持ち上げて、白い箱の中に落としました。人がお手本を見せて学ばせた AI でこのアームを動かし始めてから、ブロックが箱に入ったのはこれが初めてです。'),
  new='Physical Intelligence の π0.5 で動かす mechArm 270 が、初めて赤いブロックをつかんで持ち上げ、白い箱に入れました。AI は学習し直さず、AI に渡す肩の角度を直前の目標に変えただけで、毎回約2°ずつ足りずに箱に当てていた動きが直りました。',
  meta='Physical Intelligenceのπ0.5で動かすmechArm 270が、初めてブロックを箱に入れた。学習し直さず、AIに渡す肩の角度を直前の目標に変えただけで、毎回約2°足りず箱に当てていた動きが直った。'),
 'unity-store-from-site-json': dict(mode='pre',
  new='Unity の3Dのファミレスを、配膳ロボットの試算が使う店の図面（JSON）からそのまま建てる形にすると、卓42・席160・ロボットが止まる位置42か所がサイトと一致しました。80cm通路の店で人が21卓に入れなかった原因は、Unity に残っていた古い「通れる床」の計算でした。',
  meta='Unityのファミレスを試算の店の図面（JSON）から建てると、卓42・席160・ロボットの止まる位置42か所がサイトと一致した。80cm通路の店で人が21卓に入れない原因は古い通れる床の計算だった。'),
 'pi05-all-three-positions': dict(mode='pre',
  new='Physical Intelligence の π0.5 で動かす mechArm 270 が、お手本を録った置き場所のうち試した3か所（位置C・D・E）すべてで、ブロックを白い箱に入れました。ただ、位置D は離す前に爪から落ち、位置E は箱の縁すれすれでした。',
  meta='Physical Intelligenceのπ0.5で動かすmechArm 270が、試した3か所すべてでブロックを箱に入れた。Dは離す前に爪から落ち、Eは縁すれすれ。運ぶ間の肩はお手本より2.9〜4.0°低かった。'),
 'serving-robot-jam-points': dict(mode='pre',
  new='Unity の3Dのファミレスで配膳ロボット2台を最後まで回すと、店が止まった原因はロボットではなく、助けに行く店員がロボットに近づけない決まりの食い違いでした。詰まりを1つずつ直すと、時間切れになった往復は47のうち45から、51のうち16に減りました。',
  meta='Unityのファミレスで配膳ロボット2台を回すと、店が止まった原因は助けに行く店員がロボットに近づけない決まりの食い違いだった。詰まりを直し、時間切れの往復は47中45から51中16に減った。'),
 'serving-robot-cost-subsidy': dict(mode='pre',
  new='配膳ロボット2台を月額で借りる試算では、99条件のうち47条件で、店を回すのに要るスタッフは1人も減りませんでした。1人減る条件でも、浮く人件費（月14.1万円）はロボット2台の費用（月14.4万円）とほぼ同じでした。',
  meta='配膳ロボット2台を月額で借りる試算では、99条件のうち47条件で店が回る人数は減らなかった。1人減る条件でも浮く人件費とロボットの費用はほぼ同じ。補助金と人件費以外の変化も並べた。'),
 'serving-robot-stage-b-18-runs': dict(mode='pre',
  new='Unity の3Dのファミレスと配膳ロボットの試算は、ロボットなしなら料理の待ちが平均0.2〜0.4分の差で合いましたが、ロボットを入れると3.5〜4.5分ずれました。店2つ×ロボット0〜2台×3回の18回を回して確かめました。',
  meta='Unityのファミレスと配膳ロボットの試算は、ロボットなしなら料理の待ちが平均0.2〜0.4分差で合ったが、ロボットを入れると3.5〜4.5分ずれた。店2つ×0〜2台×3回の18回で確かめた。'),
 'serving-robot-fixed-route-jam': dict(mode=('rep', '配膳ロボットを2台入れたファミレスを、Unity（建物や人を3Dで置いて動かせるソフト）の中で動かすと、2台が通路で向かい合ったまま動けなくなる場面が何度も出ていました。直しても直しても、詰まる場所が変わるだけでした。調べていくと、**詰まりの元は、ロボットを決まった線の上しか走らせない Unity の作りでした。**'),
  new='**Unity（建物や人を3Dで置いて動かせるソフト）の中のファミレスで、配膳ロボット2台が通路で向かい合ったまま動けなくなっていた元は、ロボットを決まった線の上しか走らせない作りでした。** それまでは、直しても直しても、詰まる場所が変わるだけでした。',
  meta='Unityのファミレスで配膳ロボット2台が向かい合って止まり続けた元は、ロボットを決まった線の上しか走らせない作りだった。皿を卓に着いた時点で届いたにする直しも入れた。'),
 'serving-robot-map-planner': dict(mode=('rep', '配膳ロボットを2台入れたファミレスを Unity（建物や人を3Dで置いて動かせるソフト）の中で動かすと、2台が通路で向かい合ったまま止まる場面が何度も出ていました。原因は、ロボットに1本の線の上しか走らせない作りでした。そこで、実際の配膳ロボットと同じように、**ロボットに店の地図を渡し、行き先までの道を自分で引かせ、前がふさがったら回り込ませる形に変えると、60秒以上止まった回数は57回から20回に減りました。**'),
  new='**Unity（建物や人を3Dで置いて動かせるソフト）の中のファミレスで、配膳ロボットに店の地図を渡し、行き先までの道を自分で引かせ、前がふさがったら回り込ませる形に変えると、60秒以上止まった回数は57回から20回に減りました。** それまでは、ロボットに1本の線の上しか走らせない作りのせいで、2台が通路で向かい合ったまま止まる場面が何度も出ていました。',
  meta='Unityのファミレスで配膳ロボットに店の地図を渡し、道を自分で引いて回り込む形にすると、60秒の止まりは57回から20回に減り、料理の待ちは試算に近づいた。ドリンクバーも動かした。'),
 'serving-robot-hidden-waits': dict(mode='pre',
  new='Unity の3Dのファミレスで、配膳ロボットを入れても入店待ちが縮まなかった原因は2つあり、レジの会計が1組ずつだったことと、片付け待ちを途中で打ち切る仕組みでした。試算にもレジを入れ、Unity を直すと、ロボットを足すと待ちが縮む向きは試算とそろい、詰まる場所の違いが残りました。',
  meta='Unityのファミレスで配膳ロボットを入れても入店待ちが縮まなかった原因は、レジの決まりと片付け待ちの打ち切りだった。試算にレジを入れUnityを直すと向きはそろい、詰まる場所の違いが残った。'),
 'serving-robot-video-part2': dict(mode=('rep', '配膳ロボットを入れたら、ホールのスタッフを1人減らせるのか。ファミレスの混む2時間をパソコンの中で再現して確かめると、減らせる条件は見つかりました。'),
  new='配膳ロボットでホールのスタッフを1人減らせる条件は、ファミレスの混む2時間をパソコンの中で再現した試算で見つかりましたが、差し引きは月約7.5万円の持ち出しでした。',
  meta='配膳ロボットでホールを1人減らせる条件は試算で見つかったが、差し引きは月約7.5万円の持ち出しだった。その結果を伝える解説動画の2回目を試算v2.7で作り直した記録。'),
 'serving-robot-night-runs': dict(mode='pre',
  new='Unity の3Dのファミレスのシミュレーションを、画面を出さない実行ファイルで回し、結果を自動で「正常」「直す候補」などに振り分ける仕組みができて、人が寝ている間も回せるようになりました。1回は2〜3分で、画面を出して回すより約4.4倍速くなりました。',
  meta='Unityのファミレスのシミュレーションを、画面なしの実行ファイルと結果の自動振り分けで夜も回せるようにした。1回2〜3分でエディタの約4.4倍速い。基準の18回のずれも見つけて作り直した。'),
 'serving-robot-pass-by-standard': dict(mode='pre',
  new='Unity の3Dのファミレスのシミュレーションでは、同じ店・同じ条件でも、Mac がほかの仕事で忙しいほど配膳ロボットが動けなくなる回数が増えました（1本だけで回すと中央値1回、4本同時だと7回）。そこで夜は必ず4本同時で回すと決め、3晩200回のうち60回を、比べるときの基準にしました。',
  meta='Unityのファミレスでは、Macが忙しいほど配膳ロボットが詰まる回数が増えた。夜は4本同時に固定し、3晩200回のうち、すれ違いは止まらず通る形の60回を比べる基準にした。'),
 'serving-robot-video-ledger': dict(mode='pre',
  new='実店舗の配膳ロボットの動画5本をコマ送りで読むと、止まったロボットを店員が直す作業は1〜10秒で、店員が来るまでには18秒から45秒以上かかっていました。時間の大半は、直すことではなく、止まったことに人が気づいて来るまでに使われていました。',
  meta='実店舗の配膳ロボットの動画5本をコマ送りで読むと、止まったロボットを直す作業は1〜10秒、店員が来るまでは18秒〜45秒以上だった。台帳にして3Dのシミュレーションの前提と比べた。'),
 'small-store-second-robot-wait': dict(mode=('rep', '28卓の小さなファミレスに配膳ロボットを2台入れたら、お客さんが席に着くまでの待ち時間は、ロボットがいないときの倍になりました。'),
  new='3Dのファミレスのシミュレーションで、28卓の小さな店に配膳ロボットを2台入れると、お客さんが席に着くまでの待ち時間は、ロボットがいないときの倍になりました。',
  meta='3Dのファミレスで28卓の小さな店に配膳ロボットを2台入れると、入店待ちはロボットなしの倍、試算の約7倍に延びた。席・ドリンクバー・回し方を直し、待機場所へ戻らない作りの誤りを見つけた。'),
 'large-store-cleanup-bottleneck': dict(mode=('rep', '46卓・200席の大きなファミレスを3Dで建てて、配膳ロボットを走らせました。'),
  new='配膳ロボットを足すと入店待ちは縮みますが、大きなファミレスで詰まるのは会計のレジではなく、食べ終えた卓の片付けと空いた席への案内でした。46卓・200席の店を Unity の3Dで再現したシミュレーションで、配膳ロボットを走らせて確かめました。',
  meta='配膳ロボットを足すと入店待ちは縮むが、大きなファミレスで詰まるのはレジではなく片付けと案内だった。46卓の店をUnityの3Dで再現し、ロボットの抜け道を店の形で作って確かめた。'),
 'standby-jam-every-store': dict(mode=('rep', '38卓・158席のファミレスを3Dで建てて、配膳ロボットを0台・1台・2台で走らせました。'),
  new='38卓・158席のファミレスを Unity の3Dで再現したシミュレーションでも、配膳ロボットを足すと入店待ちは縮みましたが、詰まるのは会計のレジではなく、片付けと案内でした。ロボットは0台・1台・2台で走らせました。',
  meta='38卓のファミレスをUnityの3Dで再現しても、配膳ロボットを足すと入店待ちは縮んだが、詰まるのはレジではなく片付けと案内だった。建てる前に図面を直し、30回回して確かめた。'),
 'teach-replay-19-demos': dict(mode='pre',
  new='mechArm 270 に人が手で教えた動きを再生させながら上のカメラで録り、Physical Intelligence の π0.5 に渡すお手本を、ブロックの置き場所5か所で19本集めました。肩を約88°より深く倒した姿勢は、命令がエラーなしに捨てられ、アームが動きませんでした。',
  meta='mechArm 270に手で教えた動きを再生しながら録り、Physical Intelligenceのπ0.5に渡すお手本を5か所19本集めた。肩を約88°より深く倒した姿勢は、命令がエラーなしに捨てられていた。'),
}
```

### コード：書き出しを記事・説明文・全文のファイルに入れたスクリプト

```python
# 書き出しの直し（spec.py の SPEC）を、記事・メタディスクリプション・分けたファイルの全文に入れる（p2m-site の中で実行）
import sys,json,glob,re,os
sys.path.insert(0,'/tmp/claude-0/-home-claude/32a20279-f0a5-5df7-ae34-d5ed505a9d2f/scratchpad/lead'); from spec import SPEC
done=[];full=[];bad=[]
for k,v in SPEC.items():
    if 'meta' in v and len(v['meta'])>120: bad.append((k,'meta',len(v['meta'])))
def first_para_start(body):
    return body.lstrip()[:40]
for f in glob.glob('src/content/records/*.md'):
    t=open(f,encoding='utf-8').read(); _,fm,body=t.split('---',2)
    m=re.search(r'^slug:\s*"?([\w.-]+)"?',fm,re.M); slug=m.group(1)
    if slug not in SPEC: continue
    v=SPEC[slug]; lead=body.lstrip()
    p1=lead[:40]
    if v['mode']=='pre':
        newbody=body.replace(lead, v['new']+'\n\n'+lead,1); anchor=p1
    else:
        old=v['mode'][1]
        if not lead.startswith(old): bad.append((slug,'old not at start')); continue
        newbody=body.replace(old, v['new'],1); anchor=None
    if 'meta' in v:
        fm2=re.sub(r'^meta_description:.*$', 'meta_description: '+json.dumps(v['meta'],ensure_ascii=False), fm, count=1, flags=re.M)
        if fm2==fm: bad.append((slug,'no meta line'))
        fm=fm2
    open(f,'w',encoding='utf-8').write('---'+fm+'---'+newbody); done.append(slug)
    day=re.search(r'^day:\s*(\d+)',fm,re.M).group(1)
    for ff in glob.glob(f'public/files/LOG{day}/LOG{day}_full.*'):
        s=open(ff,encoding='utf-8').read()
        if v['mode']=='pre':
            i=s.find(p1)
            if i<0: bad.append((slug,'full: p1 not found',ff)); continue
            s=s[:i]+v['new']+'\n\n'+s[i:]
        else:
            if old not in s: bad.append((slug,'full: old not found',ff)); continue
            s=s.replace(old,v['new'],1)
        if 'meta' in v: s=re.sub(r'^meta_description:.*$', 'meta_description: '+json.dumps(v['meta'],ensure_ascii=False), s, count=1, flags=re.M)
        open(ff,'w',encoding='utf-8').write(s); full.append(ff)
for f in glob.glob('src/data/records/*.json'):
    d=json.load(open(f,encoding='utf-8'))
    if d['slug'] not in SPEC or d.get('series') not in ('フィジカルAI研究室','導入シミュレーション'): continue
    v=SPEC[d['slug']]; assert v['mode']=='pre'
    i=d['body'].find('<p'); d['body']=d['body'][:i]+'<p>'+v['new']+'</p>'+d['body'][i:]
    json.dump(d,open(f,'w',encoding='utf-8'),ensure_ascii=False,indent=2); done.append('studio:'+d['slug'])
    day=re.sub(r'\D','',d['day'])
    for ff in glob.glob(f'public/files/LOG{day}/LOG{day}_full.*'):
        s=open(ff,encoding='utf-8').read(); i=s.find('<p'); 
        if ff.endswith('.html') and i>=0: s=s[:i]+'<p>'+v['new']+'</p>'+s[i:]; open(ff,'w',encoding='utf-8').write(s); full.append(ff)
        else: bad.append((d['slug'],'studio full not html',ff))
print(len(done),'done'); print(len(full),'full files'); print('BAD',bad)
```

### 出力：書き出しを入れたスクリプトの出力（LOG352 が漏れる前の1回目）

```text
35 done
32 full files
BAD [('pi05-mecharm-demo-to-inference', 'studio full not html', 'public/files/LOG337/LOG337_full.md')]
 .../records/precision-is-not-learning-so101.json   |  64 ++++++++++++-
 src/data/records/where-learning-data-lives.json    |  52 ++++++++++-
 67 files changed, 637 insertions(+), 81 deletions(-)
```

### コード：Studio から移した記事の JSON を1行の形に戻したスクリプト

```python
# Studio から移した記事の JSON が、上の json.dump(indent=2) で整形し直されてしまったので、元の1行の形に戻す
import json,glob
for f in glob.glob('src/data/records/*.json'):
    import subprocess
    if subprocess.run(['git','diff','--quiet','--',f]).returncode==0: continue
    d=json.load(open(f,encoding='utf-8'))
    open(f,'w',encoding='utf-8').write(json.dumps(d,ensure_ascii=False))
```

### コード：ビルドしたページで書き出しを確かめたスクリプト

```python
# ビルドしたページで、本文（目次のあと）の最初に答えの文があるか、説明文（meta description）が答えで始まるかを確かめる
import sys,re,html; sys.path.insert(0,'/tmp/claude-0/-home-claude/32a20279-f0a5-5df7-ae34-d5ed505a9d2f/scratchpad/lead'); from spec import SPEC
for slug,v in SPEC.items():
    h=open(f'dist/record/{slug}.html',encoding='utf-8').read()
    body=h[h.find('class="richText"'):]
    body=re.sub(r'<nav class="toc">.*?</nav>','',body,count=1,flags=re.S)
    body=re.sub(r'^.*?<!--TOC-->','',body,count=1,flags=re.S)
    txt=html.unescape(re.sub('<[^>]+>','',body)).replace('class="richText">','')
    head=v['new'].replace('**','')[:30]
    ok=txt.lstrip()[:400].find(head)>=0
    md=html.unescape(re.search(r'<meta name="description" content="([^"]*)',h).group(1))
    print(('OK ' if ok else 'NG '), slug, '| 説明文:', md[:45])
```

### 出力：書き出しの確かめ（LOG352 を足したあと・35本）

```text
OK  precision-is-not-learning-so101 | 説明文: アームの動きを合わせる表（FKテーブル）を濃くしても、失敗から学ぶようにはならない。精度を
OK  where-learning-data-lives | 説明文: 模倣学習のデータは、Macではなく2TBの外付けSSDを定位置にして1か所に集めることにし
OK  building-a-physical-ai-lab-at-home | 説明文: ロボットのAI（Physical AI）が学習できる環境を、個人の自宅にゼロから作り、誰で
OK  openpi-remote-inference-first-run | 説明文: Physical Intelligenceのπ0.5はMacでは動かないが、Runpodで
OK  pi05-libero-benchmark-first-run | 説明文: Physical Intelligenceのπ0.5は、Runpodで借りたA40の上で、
OK  pi05-mecharm-demo-to-inference | 説明文: Physical Intelligenceのπ0.5をmechArm 270のお手本2本で
OK  pi05-mecharm-lora-2000-steps | 説明文: Physical Intelligenceのπ0.5をmechArm 270のお手本19本
OK  pi05-mecharm-first-real-run | 説明文: お手本19本で学習したPhysical Intelligenceのπ0.5でmechArm
OK  pi05-mecharm-4000-steps | 説明文: Physical Intelligenceのπ0.5の学習を4,000ステップに倍にしても
OK  drag-teach-waypoint-replay | 説明文: mechArm 270に姿勢を手で教えて再生させる方法で、ブロックを箱に入れる動きを4回続
OK  serving-robot-simulation-simpy | 説明文: 配膳ロボットでスタッフを1人減らせるかは店の形で分かれた。混む2時間をSimPyで再現した
OK  serving-robot-observation-sheet | 説明文: 配膳ロボットが店で何回止まるかは公開データが見つからなかった。そこで、止まった場所と原因、
OK  pi05-retrain-five-positions | 説明文: 置き場所を5か所に広げたお手本19本で、Physical Intelligenceのπ0.
OK  service-robot-five-sites | 説明文: 病院の検体搬送・夜間清掃・ホテル配送・夜間警備・歩道の配送の5現場を調べると、ロボットが人
OK  unity-family-restaurant-serving-robot | 説明文: Unityに35卓のファミレスを建て配膳ロボット2台を走らせると、最初の版では往復の88%
OK  pi05-learned-the-pauses | 説明文: Physical Intelligenceのπ0.5は、お手本の中の止まっている時間まで覚
OK  audit-simulator-before-unity | 説明文: 配膳ロボットの試算をUnityに合わせる前に試算を点検し、入店待ちを満席と「席はあるのに片
OK  floor-plans-into-simulator | 説明文: 配膳ロボットの試算に平面図のある店を6つ足し、卓まで何m走るか・通路の一番狭い所が何cmか
OK  pi05-first-block-in-box | 説明文: Physical Intelligenceのπ0.5で動かすmechArm 270が、初め
OK  unity-store-from-site-json | 説明文: Unityのファミレスを試算の店の図面（JSON）から建てると、卓42・席160・ロボット
OK  pi05-all-three-positions | 説明文: Physical Intelligenceのπ0.5で動かすmechArm 270が、試し
OK  serving-robot-jam-points | 説明文: Unityのファミレスで配膳ロボット2台を回すと、店が止まった原因は助けに行く店員がロボッ
OK  serving-robot-cost-subsidy | 説明文: 配膳ロボット2台を月額で借りる試算では、99条件のうち47条件で店が回る人数は減らなかった
OK  serving-robot-stage-b-18-runs | 説明文: Unityのファミレスと配膳ロボットの試算は、ロボットなしなら料理の待ちが平均0.2〜0.
OK  serving-robot-fixed-route-jam | 説明文: Unityのファミレスで配膳ロボット2台が向かい合って止まり続けた元は、ロボットを決まった
OK  serving-robot-map-planner | 説明文: Unityのファミレスで配膳ロボットに店の地図を渡し、道を自分で引いて回り込む形にすると、
OK  serving-robot-hidden-waits | 説明文: Unityのファミレスで配膳ロボットを入れても入店待ちが縮まなかった原因は、レジの決まりと
OK  serving-robot-video-part2 | 説明文: 配膳ロボットでホールを1人減らせる条件は試算で見つかったが、差し引きは月約7.5万円の持ち
OK  serving-robot-night-runs | 説明文: Unityのファミレスのシミュレーションを、画面なしの実行ファイルと結果の自動振り分けで夜
OK  serving-robot-pass-by-standard | 説明文: Unityのファミレスでは、Macが忙しいほど配膳ロボットが詰まる回数が増えた。夜は4本同
OK  serving-robot-video-ledger | 説明文: 実店舗の配膳ロボットの動画5本をコマ送りで読むと、止まったロボットを直す作業は1〜10秒、
OK  small-store-second-robot-wait | 説明文: 3Dのファミレスで28卓の小さな店に配膳ロボットを2台入れると、入店待ちはロボットなしの倍
OK  large-store-cleanup-bottleneck | 説明文: 配膳ロボットを足すと入店待ちは縮むが、大きなファミレスで詰まるのはレジではなく片付けと案内
OK  standby-jam-every-store | 説明文: 38卓のファミレスをUnityの3Dで再現しても、配膳ロボットを足すと入店待ちは縮んだが、
OK  teach-replay-19-demos | 説明文: mechArm 270に手で教えた動きを再生しながら録り、Physical Intelli
```

### 決まり：article_rules.md に足した節「最初の1〜2文は、問いへの答えにする」

```markdown
### 最初の1〜2文は、問いへの答えにする（2026-10-28 エイイチの指示）

**記事の最初の1〜2文は、その記事が答える問いへの答えとして、その文だけを切り出しても意味が通る形で書く。** 人が検索するより AI に聞いて調べることが増え、AI は答えに使える一文を探してページを読む（ChatGPT が利用者の依頼で記事を読んだ回数を、サイトのクローラーの記録 /api/cr-stats で見ている）。最初の文が経緯や場面の説明だと、答えとして引用されない。

- 書く前に、その記事が答える問いを1つ決める（例: 「配膳ロボットを入れると、店は速くなるのか」）。問いは本文に書かなくてよい
- 最初の1〜2文で、その問いに答える。主語・対象・条件・数字を入れ、「これ」「今回」「前回」「この記事」のような、前後を読まないと分からない語に頼らない
- 道具・モデル・機体は、最初に出る所で正式な名前にする（例: Physical Intelligence の π0.5、Runpod の A40）
- 実物の話か、シミュレーションの話かを、答えの文の中で分かるようにする
- 答えが出ていない記事（途中の記録・考察記事）は、「今の時点で分かっていること」か「今の考え」を1文で答える。分からないことは分からないと書く
- その次の文から、上の書き出しの決まり（何が起きていたか・なぜ気になるか・全体の見渡し）に続ける。答えの文が、冒頭の太字の1か所を兼ねてよい
- メタディスクリプションの最初の文も、同じ答えにそろえる
- Q&A の形（「Q.」「A.」）や、問いをそのまま見出しにする書き方はしない。ふだんの文章で答える
- 公開前の確かめ：最初の2文だけを読んで、問いへの答えになっているかを見る

見本（LOG397 をこの決まりで書いたとき）:

> 配膳ロボットを足すと入店待ちは縮むが、大きなファミレスで詰まるのは会計のレジではなく、食べ終えた卓の片付けと空いた席への案内だった。46卓・200席の店を Unity の3Dで再現したシミュレーションで、ロボットの台数を変えて確かめた。

この見本で見るところ：最初の文だけで「ロボットを足すとどうなるか」に答えている。「今回」「この店」のような前後に頼る語がない。2文目で、シミュレーションの話だと分かる。
```

### 差分：MASTER v2 → v2.1

```diff
--- /tmp/claude-0/-home-claude/32a20279-f0a5-5df7-ae34-d5ed505a9d2f/scratchpad/master/MASTER_before.md	2026-10-28 20:05:31.317635495 +0900
+++ /tmp/claude-0/-home-claude/32a20279-f0a5-5df7-ae34-d5ed505a9d2f/scratchpad/master/MASTER_v2.1_20261028.md	2026-10-28 20:09:16.997285436 +0900
@@ -1,7 +1,7 @@
 # Pixels to Motors — MASTER v2
 
-バージョン: v2（実行フェーズ）
-最終更新: 2026-10-26
+バージョン: v2.1（実行フェーズ）
+最終更新: 2026-10-28
 
 このドキュメントは Pixels to Motors 関連プロジェクト全てに複製される。
 すべての判断の上位参照ソース。個別プロジェクトのルールよりこちらが優先する。
@@ -16,8 +16,11 @@
 > Physical AI が学習できる環境を継続的に構築する。
 > その知見を再現可能な形で公開する。
 > 誰でも同じ環境から Physical AI 研究を始められる状態を増やす。
+> その研究を、Physical AI を導入する組織と一緒に手を動かす仕事につなげる。
 
-この 3 行が、主指標・設備投資・発信・事業化のすべての判断軸になる。迷ったときはこの 3 行に照らす。
+この 4 行が、主指標・設備投資・発信・事業化のすべての判断軸になる。迷ったときはこの 4 行に照らす。
+
+研究だけしていても意味はない。研究の先に、必ず仕事がある状態をつくる。ただし仕事のために研究を薄めない（仕事の根拠は、手を動かした研究そのものだから）。
 
 ---
 
@@ -83,7 +86,7 @@
 
 **初期構築（1台目）**
 
-Mission の 3 行を回すのに必要な最小構成で組む。用途が動くことが条件であり、余裕を持たせることは条件ではない。足りないことは実測できるが、余っていることは実測できない。
+Mission の 4 行を回すのに必要な最小構成で組む。用途が動くことが条件であり、余裕を持たせることは条件ではない。足りないことは実測できるが、余っていることは実測できない。
 
 上位グレードで迷ったら下を買う。ただし、後から交換すると他のパーツまで巻き込むもの（電源・ケース・マザーボード）は、想定する増設まで届く構成で選ぶ。挿し替えで済むもの（GPU・メモリ・SSD）は下を買う。
 
@@ -93,7 +96,7 @@
 
 1. 現在進行中の研究で、実測されたボトルネックを解消するものであること
 2. そのボトルネックが、ログまたは計測値として提示できること
-3. 解消後に何が可能になるかが、Mission の 3 行に照らして説明できること
+3. 解消後に何が可能になるかが、Mission の 4 行に照らして説明できること
 
 **買わない条件（初期構築・増強に共通）**
 
@@ -111,15 +114,15 @@
 
 **投資の性質**
 
-設備の支出は当面「費用」であって投資回収の対象としない。収入は本業（デザイン）から出続ける前提で計画する。この前提が崩れた場合、設備計画のほうを見直す。
+設備の支出は当面「費用」であって投資回収の対象としない。収入は研究以外の仕事から出続ける前提で計画する。この前提が崩れた場合、設備計画のほうを見直す。コンサルの収入が続くようになったら、この節を見直す。
 
 ---
 
 ## 主指標
 
-### 唯一の主指標
+主指標は 2 本。研究の指標と仕事の指標を同じ重さで見る。どちらか片方だけが伸びている状態を良しとしない。
 
-**再現可能な環境数**
+### 主指標 1（研究）：再現可能な環境数
 
 他人が同じ手順で同じ結果に到達できる状態にある研究資産の数。
 
@@ -131,9 +134,26 @@
 
 3 を満たさないものは「構築中」であって「再現可能な環境」に数えない。
 
+### 主指標 2（仕事）：仕事につながった数
+
+研究から仕事が生まれた数。次の 2 段で数える（曖昧にすると数が水増しされるため明示する）。
+
+1. 相談：最初の相談（オンライン30分）を実際に行った件数。問い合わせが来ただけ・日程が決まらなかったものは数えない
+2. 契約：有料の仕事（1か月の小さな試し以上）になった件数
+
+AI活用の相談・登壇・取材も、実際に行ったもの・有料になったものだけを同じ 2 段で数える。
+
+### 手前の指標（主指標 2 の手前を見る。目標にはしない）
+
+- AI 経由で人に届いた数：利用者の依頼で AI が記事を読んだ回数（ChatGPT-User など）。トップページは試しの読みが混ざるため、記事のページだけを数える
+- 相談のページ（/consult）に人が来た数と、そこから相談のフォームに進んだ数
+
+> 人が AI に聞いて調べる時代には、AI に読まれて引用されることが、人に届く道そのものになる。
+> ただし、この数を上げるために薄い記事を量産しない。主指標 1 の判定条件を満たす記録が届いて、はじめて意味がある。
+
 ### 副次（参考のみ。主指標に昇格させない）
 
-Journal 数 / 動画数 / GitHub コミット数 / 実験ログ数 / 言葉の被引用 / 相談・登壇依頼の件数 / フォロワー数
+Journal 数 / 動画数 / GitHub コミット数 / 実験ログ数 / フォロワー数
 
 > 量指標を主にすると、薄い記事を毎日出すのが最適解になる。
 > Journal・動画・GitHub は「再現可能な環境を説明するための媒体」であって、成果そのものではない。
@@ -144,18 +164,27 @@
 |---|---|---|
 | 認知層 | 業界全体・Physical AI 文脈の読み手 | 概念オーソリティ／言葉の被引用 |
 | 関係層 | コアリスト（A〜D層） | 縦の関係深化／戦略リプ |
-| 契約層 | Physical AI 導入を推進する組織 | 共同研究／R&D契約／Motion UX コンサル |
+| 契約層 | Physical AI 導入を推進する組織 | 一緒に手を動かすコンサル（主）／共同研究／R&D契約 |
 
 具体的な最優先ターゲットは市場の状況で変わる。本文書に固定しない。
 
+### 仕事の形
+
+- 主に受けるのは、一緒に手を動かすコンサル。助言だけで終えず、学習環境の立ち上げ・導入前の確かめ・運用の決め方を相手と一緒に進める
+- 形は、オンラインの定期的な打ち合わせと、必要なときの訪問。最初の相談は短い時間を無料にし、それ以降は有料にする
+- 料金・頻度・時間などの具体的な値は本文書に書かない（相談のページ /consult が正）
+- 新しい肩書き・サービス名は付けない（枝概念の追加禁止に従う）。中身をそのまま書く
+
 ---
 
 ## 運用の上位ルール
 
-- 研究を止めない。発信は研究の副産物である
+- 研究を止めない。発信は研究の副産物である。仕事は研究の先にある
+- 研究の記録は、読んだ人が「自分の仕事ならどう使えるか」が分かる形で終える
 - 研究の外側の作業（サイト・動画・発信の仕組みづくり）が続いたら、次の作業は研究に戻す。週に一度、直近の記録のうち研究の記録（学習・推論・実機・画像認識・考察）が半分を下回っていないかを見る
 - シリーズの名前は中身と一致させる。フィジカルAI研究室には学習・推論を回した記録だけを載せる。研究の外側の作業の記録はロボティクスデザイン実務フローに置く
-- AI活用の相談は研究の副産物として受ける。相談の窓口は、AI活用の記事とメッセージフォームからの導線に限る（サイトのトップ・SNSには相談の窓口を出さない）
+- 相談の窓口は、フィジカルAI は相談のページ（/consult）、AI活用は AI活用の記事の末尾に置く。相談のページへは、導入比較ガイド・サービスロボットの LP・研究の記録の末尾からつなぐ。どの窓口もメッセージのフォームに着く
+- 相談のページへのリンクは、サイトのフッターと SNS のプロフィール欄にも1つずつ置く（探した人が確実にたどり着けるように）。トップの画面の中と SNS の投稿には、相談の窓口を出さない（読みに来た人に、まず記録を読んでもらうため。発信に宣伝を混ぜない）
 - デジタルの AI の土台づくりは、フィジカルAI の研究と地続きの仕事として扱う。その土台を記録から示すページ（1年の記録の LP など）と、研究の進め方としての AI 活用は、サイトのトップ・SNS・動画に出してよい。どちらも相談の看板にはしない
 - フォロワー数を主指標にしない
 - 同じコンテンツを媒体間で単純流用しない（X / LinkedIn / Facebook で書き分け）
@@ -319,4 +348,5 @@
 - 2026-10-21: 保存先テーブルにサービスロボット導入シミュレーションの店の形の2行を追加（作り方・確かめのコードと記憶の店の原本 → p2m-site の tools/sim_layouts/・店の形のデータと解析結果 → p2m-site の public/sim/layouts/。図の png は GitHub に入れない）。サイトの試算が正で、Unity はこのデータを読んで店を建てるため。
 - 2026-10-25: 運用の上位ルールの AI活用の行を2つに分けた。相談の窓口は今までどおり記事とフォームに限る。デジタルの AI の土台を記録から示すページ（1年の記録の LP など）は、フィジカルAI の研究と地続きの仕事として、サイトのトップと SNS に出してよいとした。1年の記録の LP をトップと SNS に出すとエイイチが決め（フィジカルAI を進めるには、デジタルの AI の土台づくりが欠かせないため）、10-17 に足した行と食い違ったため。
 - 2026-10-25: Unityの絶対ルールの作業ディレクトリに ServiceSim（サービスロボット導入シミュレーション）を追加。mechArm の Robotics_UX_New に同居していたため、Assets/ServiceSim/ の外を変えられず、ビルド設定・時間・物理の設定を合わせられなかった。夜も回せる仕組み（画面なしの実行ファイル）のために分けた。
-- 2026-10-26: 保存先テーブルに SNS の分析データの行を追加（iCloud の sns_analytics/{媒体名}/）。LinkedIn の分析を書き出して投稿の反応を追うことにしたが、置き場所が決まっていなかったため。
\ No newline at end of file
+- 2026-10-26: 保存先テーブルに SNS の分析データの行を追加（iCloud の sns_analytics/{媒体名}/）。LinkedIn の分析を書き出して投稿の反応を追うことにしたが、置き場所が決まっていなかったため。
+- 2026-10-28 (v2.1): 研究の先に必ず仕事がある状態をつくると決め、Mission に4行目（研究を、導入する組織と一緒に手を動かす仕事につなげる）を足した。主指標を2本にした（研究＝再現可能な環境数、仕事＝仕事につながった数。相談を実際に行った件数と有料になった件数の2段で数える）。言葉の被引用と相談・登壇の件数を副次から外し、AI 経由で人に届いた数を「主指標2の手前の指標」とした（人が AI に聞いて調べるようになり、AI に読まれることが人に届く道になったため。目標にはしない）。契約層の主を「一緒に手を動かすコンサル」にし、仕事の形の節を足した（具体的な値は /consult が正）。相談の窓口を、フィジカルAI は /consult に置き、導入比較ガイド・サービスロボットの LP・研究の記録の末尾からつなげるよう広げた（フッターと SNS のプロフィール欄にもリンクを置く。トップの画面の中と SNS の投稿には出さない）。研究の記録は仕事でどう使えるかが分かる形で終えるとした。投資の性質の「収入は本業（デザイン）から」を、実態に合わせて「研究以外の仕事から」に直した。ウェブの改善の検証で、来た人が何を頼めばいいか分からず、相談のフォームの入力が0だったことがきっかけ。
```

