commit cf784daf271e9ddb269ba57d042df6d602d55951 Author: Claude Date: Sat Nov 14 09:19:30 2026 +0900 課題地図のトップ:最初の画面を「まず読む3つ」(写真つき)とボタン1つに。分類の箱から課題名の一覧を外した Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LevEXS2w3GWf5pnT1ChrKx diff --git a/src/pages/issues.astro b/src/pages/issues.astro index 917dc69..f291d9e 100644 --- a/src/pages/issues.astro +++ b/src/pages/issues.astro @@ -3,11 +3,25 @@ import IssuesLayout from '../layouts/IssuesLayout.astro'; import IssueCard from '../components/issues/IssueCard.astro'; import NewsList from '../components/issues/NewsList.astro'; -import { allIssues, bySeverity, CATEGORIES, REGULATIONS, SOURCES, NEWS, LAST_CHECKED, ISSUES_TITLE, jdate } from '../lib/issues'; +import { allIssues, CATEGORIES, REGULATIONS, SOURCES, NEWS, LAST_CHECKED, ISSUES_TITLE, jdate } from '../lib/issues'; import { SITE, PUBLISHER } from '../lib/seo'; const issues = await allIssues(); const title = Object.fromEntries(issues.map((i) => [i.data.slug, i.data.title])); +const top3 = issues.slice(0, 3); +// 「まず読む3つ」のアイコン(Material Symbols)。課題を入れ替えたらここも直す +const ICON: Record = { + 'caregiving-robot-adoption': 'elderly', + 'real-robot-data-scarcity': 'database', + 'motion-portability': 'sync_alt', +}; +// 「まず読む3つ」の写真(R2 の住所)。3枚そろったら3つとも入れる。1つでも空ならアイコンで出す +const PHOTO: Record = { + 'caregiving-robot-adoption': '/media/issues-top3-caregiving.jpg', + 'real-robot-data-scarcity': '/media/issues-top3-data.jpg', + 'motion-portability': '/media/issues-top3-motion.jpg', +}; +const usePhoto = top3.every((i) => PHOTO[i.data.slug]); const nSources = SOURCES.reduce((n, g) => n + g.items.length, 0); const description = '放置すればフィジカルAI・ロボティクスの社会実装そのものが頓挫する構造的な課題を、技術・制度・体験の3つの視点を横断して抽出・整理した課題地図。週1回、最近の動きを出典つきで更新しています。'; const jsonLd = { @@ -20,19 +34,25 @@ const jsonLd = {

課題地図

{ISSUES_TITLE}

-

個別のデモ動画や製品発表ではなく、放置すればフィジカルAIの社会実装そのものが頓挫する——いま向き合うべき構造的な課題を、技術・制度・体験の3つの視点を横断して抽出・整理しました。

-
    -
  • {issues.length}課題
  • -
  • {CATEGORIES.length}分類
  • -
  • {REGULATIONS.length}規制・制度
  • -
  • {nSources}出典
  • -
  • {NEWS.length}件の最近の動き
  • -
+

放っておくと、ロボットが現場に入る前に止まってしまう課題を{issues.length}件に整理しました。まず読むなら、この3つです。

+
    + {top3.map((i) => ( +
  1. + + {usePhoto + ? + : {ICON[i.data.slug] ?? 'help'}} + {i.data.title} + {i.data.summary} + 緊急度 {i.data.urgency}・深刻度 {i.data.severity}arrow_forward + +
  2. + ))} +
-

{LAST_CHECKED ? `最後に最近の動きを調べた日:${jdate(LAST_CHECKED)}(週1回)` : '最近の動きは週1回調べて更新します'}

+

{CATEGORIES.length}分類・{nSources}出典。{LAST_CHECKED ? `最近の動きを最後に調べた日:${jdate(LAST_CHECKED)}(週1回)` : '最近の動きは週1回調べて更新します'}

@@ -48,12 +68,11 @@ const jsonLd = {

社会実装を一つのシステムとして見て、課題を9つの分類に分けています。

{CATEGORIES.map((c) => { - const list = issues.filter((i) => i.data.category_slug === c.slug).sort(bySeverity); + const n = issues.filter((i) => i.data.category_slug === c.slug).length; return ( -

{c.name}{list.length}件

+

{c.name}{n}件

{c.desc}

-
    {list.map((i) =>
  • = 4 && i.data.severity >= 4 ? 'hot' : ''}>{i.data.title}緊{i.data.urgency}・深{i.data.severity}
  • )}
); })} @@ -77,7 +96,7 @@ const jsonLd = {

すべての課題({issues.length}件)

-

深刻度・緊急度の高い順に並べています。カードの点数はどちらも5段階です。

+

深刻度・緊急度の高い順に並べています。カードの点数はどちらも5段階です。課題どうしのつながりは課題マップでたどれます。

{issues.map((i) => )}
@@ -97,10 +116,23 @@ const jsonLd = { .ihero-k { margin: 0; font: 500 13px/20px var(--sans); color: var(--ink-3); } .ihero-h { margin: 8px 0 16px; font: 600 36px/1.4 var(--sans); max-width: 900px; } .ihero-lead { margin: 0; font: 400 17px/2 var(--sans); max-width: 820px; } - .ihero-stats { list-style: none; display: flex; flex-wrap: wrap; gap: 8px 28px; margin: 24px 0 0; padding: 0; font: 400 13px/20px var(--sans); color: var(--ink-2); } - .ihero-stats b { font: 500 24px/28px var(--sans); color: var(--ink); margin-right: 4px; } .ihero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; } .ihero-upd { margin: 16px 0 0; font: 400 12px/18px var(--sans); color: var(--ink-3); } + .top3 { list-style: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 32px 0 0; padding: 0; } + .t3 { display: flex; flex-direction: column; gap: 10px; height: 100%; padding: 24px; background: #fff; border-radius: 8px; + box-shadow: 0 8px 16px rgba(0,0,0,.08); transition: box-shadow .15s; } + .t3:hover { box-shadow: 0 8px 24px rgba(0,0,0,.16); } + .t3:hover .t3-title { text-decoration: underline; } + .t3-ph { display: block; margin: -24px -24px 6px; aspect-ratio: 16 / 10; overflow: hidden; border-radius: 8px 8px 0 0; background: #eee; } + .t3-ph img { width: 100%; height: 100%; object-fit: cover; display: block; } + .t3-ic { display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 8px; background: var(--dark, #222); } + .t3-ic .ms { font-size: 28px; color: #fff; } + .t3-title { font: 600 20px/1.5 var(--sans); color: var(--ink); } + .t3-sum { font: 400 14px/1.8 var(--sans); color: var(--ink-2); } + .t3-meta { display: flex; justify-content: space-between; align-items: center; margin-top: auto; padding-top: 12px; border-top: 1px solid #eee; + font: 400 12px/20px var(--sans); color: var(--ink-3); } + .t3-meta .ms { font-size: 20px; color: var(--ink); } + .ilink { text-decoration: underline; color: var(--ink); } .more { margin: 24px 0 0; } .empty { margin: 0; padding: 20px; border-radius: 8px; background: #f5f5f5; font: 400 14px/1.8 var(--sans); color: var(--ink-3); } @@ -108,11 +140,7 @@ const jsonLd = { .cbox:hover { border-color: var(--ink); } .cbox h3 { display: flex; justify-content: space-between; gap: 8px; margin: 0 0 6px; font: 600 16px/1.5 var(--sans); } .cbox h3 span { font: 400 12px/24px var(--sans); color: var(--ink-3); white-space: nowrap; } - .cbox p { margin: 0 0 12px; font: 400 13px/1.7 var(--sans); color: var(--ink-2); } - .cbox ul { list-style: none; margin: auto 0 0; padding: 0; border-top: 1px solid #eee; } - .cbox li { display: flex; justify-content: space-between; gap: 8px; padding: 6px 0; border-bottom: 1px solid #f2f2f2; font: 400 13px/1.6 var(--sans); color: var(--ink-2); } - .cbox li.hot span { color: var(--ink); font-weight: 500; } - .cbox li small { font-size: 11px; color: var(--ink-3); white-space: nowrap; } + .cbox p { margin: 0; font: 400 13px/1.7 var(--sans); color: var(--ink-2); } .regs { display: flex; flex-direction: column; gap: 16px; } .reg { padding: 20px; border: 1px solid #e3e3e3; border-radius: 8px; } @@ -129,9 +157,23 @@ const jsonLd = { .about li { margin: 0 0 12px; font: 400 15px/1.9 var(--sans); color: var(--ink-2); } .about b { color: var(--ink); font-weight: 600; } .about a { text-decoration: underline; } + @media (max-width: 899px) and (min-width: 600px) { + .top3 { grid-template-columns: 1fr; } + } @media (max-width: 599px) { .ihero { padding-top: 32px; } .ihero-h { font-size: 26px; } .ihero-lead { font-size: 15px; } + .top3 { grid-template-columns: 1fr; } + .t3 { padding: 18px 20px; gap: 6px; } + .t3-ph + .t3-title { margin-top: 0; } + .t3:has(.t3-ph) { display: grid; grid-template-columns: 96px 1fr; column-gap: 14px; row-gap: 4px; padding: 14px; align-items: start; } + .t3:has(.t3-ph) .t3-ph { grid-row: 1 / span 3; margin: 0; width: 96px; aspect-ratio: 1; border-radius: 6px; } + .t3:has(.t3-ph) .t3-meta { grid-column: 2; padding-top: 8px; } + .t3-ic { width: 40px; height: 40px; } + .t3-ic .ms { font-size: 24px; } + .t3-title { font-size: 17px; } + .t3-sum { font-size: 13px; line-height: 1.7; } + .top3 { gap: 12px; margin-top: 24px; } }