Claude Opus 5 レビュー:Anthropicの新モデルは買う価値があるか?

Claude Opus 5 レビュー:Anthropicの新モデルは買う価値があるか?

Claude Opus 5 レビュー:Anthropicの新モデルは買う価値があるか?

2026年7月28日に事実確認済み。.

一言評価: このClaude Opus 5のレビューでは、コーディング担当者のほか、複雑なビジネスワークフローを扱うユーザー、そして常にFable 5のコストを支払うことなく最先端に近いパフォーマンスを求める購入者にとって、魅力的なハイエンドモデルであることが明らかになりました。 Anthropicの料金は、入力トークン100万トークンあたり$5、出力トークン100万トークンあたり$25ですが、このモデルは同期型Messages APIにおいて、100万トークンのコンテキストウィンドウと最大128,000トークンの出力をサポートしています。 ただし、単純なチャット、短い要約、あるいは大量かつ低価値のリクエストに対しては、必ずしも最適な選択肢とは限りません。.

最も説得力のある根拠は、大げさな主張ではなく実用的な点にある。Opus 5は、Anthropicの最先端クラスよりも管理しやすいコスト構造でありながら、本格的な推論能力を備えている。 我々が実施した1回のデバッグテストにおいて、このモデルはプレフィックスマッチングのバグを正確に特定し、最小限のパッチを提案し、対象を絞った回帰テストを追加し、ローカル環境でパスする検証コマンドを出力した。これはこのタスクにおける有用な証拠ではあるが、このモデルがあらゆるコーディング業務で勝利する証拠ではない。.

最高だ: コーディングエージェント、長文コンテキスト分析、エンタープライズ自動化、そして高額な失敗がプレミアムモデルの導入を正当化するチーム。. 次のような場合はスキップしてください: スピードと単価は、推論の質における最後の段階よりも重要である。.

Claude Opus 5とは何ですか?

Claude Opus 5は、複雑なエージェント型コーディングや企業向け業務に対応する、Anthropicのプレミアムな日常使用モデルです。. Anthropicは2026年7月24日にこれを発表した, 、このモデルを「考え抜かれた設計で、能動的であり、他のモデルよりも効率的」と評しています。このモデルはClaude Opus 4.8に取って代わり、Claude Maxのデフォルトモデルとなり、Claude Proでは利用可能な最強のモデルとなりました。.

Anthropicの告知。Claude Opusの5つのタイトル、2026年7月24日の日付、および「本日より利用可能」との記載が示されている。
Anthropicは2026年7月24日にClaude Opus 5を発表し、同日より提供開始となったと述べた。.

この製品の売り込み文句は、Opusのリリースとしては異例です。つまり、これは単に「最高レベルの知能を備えたモデル」として位置づけられているわけではないのです。Anthropicは、負荷を調整可能で、適度なレイテンシ特性を備え、日常的に利用されることを目指しています。 これにより、長時間稼働するエージェントや難易度の高い本番環境での作業への導入が正当化されやすくなり、一方で、より単純なワークロードについては、より高速で安価なモデルに振り分けることが可能です。.

利用方法はプランによって異なります。一般ユーザーは、対象となる Claude プランを通じて Opus 5 を利用できます。開発者は、Claude API および対応するクラウドプラットフォームを通じて Opus 5 を呼び出すことができます。GlobalGPT には専用の製品ページもあります。Anthropic のサブスクリプションプランを比較したい読者は、 Claudeの「Free」、「Pro」、「Max」各プランの比較 請求方法を選択する前に。.

Claude Opus 5 価格、API、および主要仕様

オフィシャル Claude API価格入力トークン100万枚あたり$5 そして 発行されるトークン100万枚につき$25. これらはAPIの基本料金であり、Claudeのコンシューマー向けサブスクリプションやサードパーティ製プラットフォームのプランの価格ではありません。プロンプトのキャッシュやバッチ処理には別途料金が設定されているため、表面上の入力価格だけを掛け合わせるのではなく、リクエストパターン全体を比較してください。.

フィールドClaude Opus 5その意味
Claude API IDclaude-opus-5公式の Claude API リクエストでは、このモデル値をそのまま使用してください。.
基準入力価格$5/エムトックキャッシュやバッチ割引が適用される前の、標準的な入力トークンレート。.
基準販売価格$25/エムトック出力負荷の高いエージェントは、すぐにコストがかさむ可能性があります。.
コンテキストウィンドウ100万トークン大規模なリポジトリや文書コレクションに適していますが、リクエストの品質や検索戦略によって異なります。.
最大出力128Kトークンこれは同期型のMessages APIに適用されます。Message Batchesについては、最大30万件まで対応する別のベータ版が提供されています。.
信頼性の高い知識のカットオフ値2026年5月モデルの基準からすれば比較的新しい手法ですが、実データからの抽出に代わるものではありません。.
遅延の比較中程度Anthropicの最速モデルというわけではありません。レイテンシは、作業内容、使用するツール、およびワークロードによって依然として変動します。.
Claude プラットフォームのドキュメントにある、Claude Opus 5 の API ID およびエイリアスを示す表
Claudeプラットフォームは、claude-opus-5を現在のOpus 5のAPI IDおよびエイリアスとして識別しています。.
Claude プラットフォームのドキュメントにある、Claude Opus 5の価格、使用環境、最大出力、およびカットオフに関する仕様をまとめた表
Claudeプラットフォームでは、Opus 5の処理コストを、入出力トークン100万単位あたり$5/$25と記載しており、コンテキストウィンドウは100万トークン、最大出力は128kトークン、適用期限は2026年5月となっています。.
Claude プラットフォームのドキュメントにおける、Claude Opus 5 のコンテキスト、出力、およびカットオフ行
Claudeプラットフォームの仕様には、1Mのコンテキストウィンドウ、最大出力128k、および2026年5月までのカットオフが記載されています。.

一般のお客様がご利用になる場合は、, Anthropic リスト Claude Pro $20は月単位、$17は月額で、$200は年額請求となります。Claude Maxは月額$100から開始されます。 Anthropicによると、Opus 5はProプランで最も高性能なモデルであり、Maxプランではデフォルト設定となっていますが、プランの割り当て量や製品の機能は、従量制のAPI使用量とは別扱いとなります。.

より詳細な費用の内訳が必要な場合は、 Claude AI プランおよび API 価格ガイド コンシューマー向けサブスクリプション、APIの課金、および利用制限を区別しています。この区別は重要です。「プランに含まれている」からといって、API呼び出しが無制限になるわけではなく、また、APIの利用制限から、コンシューマー向けチャットへのアクセス量がどれほどかを知ることはできません。.

Claude Opus 5 ベンチマーク結果

重要な境界: 以下の図は Anthropicが公開したベンチマーク, 、本レビューのために独自に実施した測定結果ではありません。これらは、Anthropicが目指す性能とコストのバランスを理解する上で有用ですが、ユーザーのプロンプト、ツール、リポジトリ、あるいはレイテンシの許容範囲において、同様の結果が得られることを保証するものではありません。.

評価Anthropicが公表した主張読み方
Frontier-Bench v0.1Opus 5は、タスクあたりのコストを抑えつつ、Opus 4.8の2倍以上の性能を発揮します。.エージェントのパフォーマンスを示す広範な兆候であり、一律に2倍の改善が見られるわけではない。.
CursorBench 3.2最大努力時、Opus 5は、タスクあたりのコストが半分であるにもかかわらず、Fable 5の最高スコアから0.5%以内の差にとどまっています。.Anthropicの実証済みの努力設定下における、強力なコーディングエージェントの経済性。.
Zapier AutomationBenchタスクあたりのコストが同じ場合、2位の合格率の約1.5倍です。.エンドツーエンドのビジネス自動化には期待が持てるが、ワークフローの設計は依然として重要である。.
OSWorld 2.0Fable 5の最高成績を上回り、そのコストはわずか3分の1強にとどまっています。.このベンチマークでは、コンピュータの利用効率が優れていることが示唆される。.
Anthropicの発表文(Claude Opus 5 CursorBench 3.2の性能およびコスト比較を含む)
Anthropicによると、Opus 5は、Fable 5のCursorBench 3.2最高スコアに0.5%差まで迫り、タスクあたりのコストは半分である。.
Zapier AutomationBenchおよびOSWorld 2.0におけるClaude Opus 5と比較したAnthropicのベンチマーク結果
Anthropicは、Zapier AutomationBenchにおいて合格率が1.5倍高いこと、およびOSWorld 2.0においてコスト面で優位性があることを報告しています。.

「エフォート」は結果の一部です。Anthropicによると、Opus 5はClaude APIおよびClaudeコードにおいてデフォルトで「高」エフォートに設定されており、その比較においても「高」、「x高」、または「最大」の設定が使用されています。 エフォートを高く設定すると、困難なタスクの成功率は向上する一方で、トークン数やレイテンシ、あるいはその両方が増加する可能性があります。したがって、タスクあたりのベンチマークコストは、トークンあたりの価格だけを見るよりも有益な情報となりますが、いずれの指標も、自社のワークロードにおけるパイロットテストに代わるものではありません。.

Claude Opus 5のテスト方法

3つのファイルからなるCommonJSフィクスチャに対して、1つのコンパクトな根本原因のデバッグタスクを実行しました。このタスクでは、モデルに対し、編集を行う前に根本原因を特定し、可能な限り最小限のパッチを提案し、対象を絞った回帰テストを追加し、無関係な変更を避け、正確な検証コマンドを提示することが求められました。.

そこで、その回答が自信に満ちた口調だったからといって正しいと決めつけるのではなく、独自にパッチを確認しました。localコマンドは次のとおりでした。 node --test test/account-summary.test.cjs. 修正前は、このテストスイートは1件の合格と1件の不合格を返していました。完全等価性のパッチを適用した後は、2件の合格と0件の不合格を返すようになりました。.

この手法は、あるデバッグ・ワークフローについて、診断、パッチ適用における規律、回帰テストの品質、および検証可能性といった点において有益な知見を与えてくれます。ただし、広範なコーディングのリーダーシップ、長期的なエージェントの信頼性、速度、あるいは言語を横断したパフォーマンスについては測定対象外です。.

Claude Opus 5 実機レビュー

根本原因のデバッグ:正確で、最小限であり、検証可能

当社のテストでは、Claude Opus 5 によって不具合の原因が正しく特定されました。 normalizedQuery.startsWith(account.id.toLowerCase()). 以下のクエリで ACCT-10, 接頭辞チェックが一致しました acct-1 まず、それで Array.prototype.find 正確なIDに到達する前に、誤ったアカウントを返してしまった。.

提案された修正により、プレフィックスの照合が完全一致に変更され、パディングが施された大文字小文字混在の ACCT-10 入力。無関係なコードは書き換えられませんでした。実際のリポジトリでは、この自制心が重要です。なぜなら、範囲が広すぎる「クリーンアップ」を行うと、元のバグよりも多くのレビュー作業が発生してしまう可能性があるからです。.

最も印象的だったのは、一連の流れ全体でした。すなわち、根本原因を特定し、既存のテストでそれが検出されなかった理由を説明し、最小限の変更を加え、適切な回帰テストを追加し、それを検証するためのコマンドを明記するという流れです。この結果は、Opus 5が掲げる「コーディングエージェント」という位置づけと一致していますが、あくまで1つのフィクスチャに過ぎません。より広範なワークフローの概要については、以下を参照してください。 コーディングのためのクロードAIの使い方.

T1~T4の全問題文、解答、およびコピー可能なコード

T1: 根本原因の特定によるデバッグ

合格 — プレフィックス一致の不具合を発見し、最小限のパッチを提案し、対象を絞った回帰テストを追加した。.

Claude Opus 5 実践的な根本原因のデバッグ結果
不具合の原因をプレフィックスマッチングであると特定した。従来のテストでこれが見逃されていた理由を説明した。完全一致に加え、1つの回帰テストの実施を提案した。.
T1のプロンプトと回答の全文を表示する
プロンプト全文
意図的に規模を小さくしたCommonJSフィクスチャのデバッグを行っています。以下の3つのファイルと、記載された再現手順のみに基づいて作業してください。

要件:
1. 修正を提案する前に、根本原因を特定してください。
2. バグを修正する最小限のパッチを提案してください。
3. 修正前には失敗し、修正後には成功する、的を絞った回帰テストを1つ追加してください。
4. フィクスチャのルートディレクトリから実行する正確な検証コマンドを記載してください。
5. 関係のないコードを書き換えないでください。ファイル名の変更、依存関係の追加、公開APIの変更は行わないでください。
6. 以下のセクションを正確にこの順序で記述してください:`ROOT CAUSE`、`PATCH`、`VERIFICATION`、`LIMITATIONS`。
7. `PATCH` セクションでは、フェンスで囲まれた `diff` ブロック内に 1 つの統一差分(unified diff)を記載してください。`VERIFICATION` セクションでは、フェンスで囲まれた `text` ブロック内に 1 つのコマンドを記載してください。

再現手順:`summarizeAccount(accounts, ' ACCT-10 ')` は `{ id: 'acct-10', name: 'Nimbus', seats: 24 }` を返すはずですが、実際には `acct-1` アカウントが返されます。

ファイル: `src/find-account.cjs`
```js
function findAccount(accounts, query) {
  const normalizedQuery = query.trim().toLowerCase();
  return accounts.find((account) =>
    normalizedQuery.startsWith(account.id.toLowerCase()),
  );
}

module.exports = { findAccount };
```

ファイル: `src/account-summary.cjs`
```js
const { findAccount } = require('./find-account.cjs');

function summarizeAccount(accounts, requestedId) {
  const account = findAccount(accounts, requestedId);
  if (!account) return null;
  return { id: account.id, name: account.name, seats: account.seats };
}

module.exports = { summarizeAccount };
```

ファイル: `test/account-summary.test.cjs`
```js
const test = require('node:test');
const assert = require('node:assert/strict');
const { summarizeAccount } = require('../src/account-summary.cjs');

const accounts = [
  { id: 'acct-1', name: 'Atlas', seats: 5 },
  { id: 'acct-10', name: 'Nimbus', seats: 24 },
];

test('特定のアカウントIDを要約する', () => {
  assert.deepEqual(summarizeAccount(accounts, 'acct-1'), {
    id: 'acct-1',
    name: 'Atlas',
    seats: 5,
  });
});
```
Claude Opus 5

根本原因

findAccount は、等価性ではなく接頭辞による一致を行います:

js
normalizedQuery.startsWith(account.id.toLowerCase())
normalizedQuery.startsWith(account.id.toLowerCase())

Array.prototype.find は、述語を満たす最初の要素を返します。 「ACCT-10」の場合、正規化されたクエリは「acct-10」となり、最初のアカウントの ID「acct-1」はその接頭辞であるため、startsWith が true となり、acct-10 がテストされる前に acct-1 によって検索がショートカットされます。.
trim().toLowerCase() による正規化は正しく行われています。空白や大文字・小文字の問題ではありません。summarizeAccount は単なる通過関数であり、問題の原因ではありません。.
既存のテストではこれを検出できません。「acct-1」はそれ自体のプレフィックスであり、かつ最初の要素であるため、この入力に対してはプレフィックスマッチングと完全一致を区別することができません。.

PATCH

diff
--- a/src/find-account.cjs+++ b/src/find-account.cjs@@ -1,8 +1,8 @@ function findAccount(accounts, query) {   const normalizedQuery = query.trim().toLowerCase();-  return accounts.find((account) =>-    normalizedQuery.startsWith(account.id.toLowerCase()),-  );+  return accounts.find(+    (account) => account.id.toLowerCase() === normalizedQuery,+  ); }  module.exports = { findAccount };--- a/test/account-summary.test.cjs+++ b/test/account-summary.test.cjs@@ -14,3 +14,11 @@ test('summarizes an exact account ID', () => {     seats: 5,   }); });++test('matches the full ID rather than a prefix, with padding and mixed case', () => {+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {+    id: 'acct-10',+    name: 'Nimbus',+    seats: 24,+  });+});
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
 function findAccount(accounts, query) {
   const normalizedQuery = query.trim().toLowerCase();
-  return accounts.find((account) =>
-    normalizedQuery.startsWith(account.id.toLowerCase()),
-  );
+  return accounts.find(
+    (account) => account.id.toLowerCase() === normalizedQuery,
+  );
 }

 module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
 test('正確なアカウントIDを要約する', () => {
 seats: 5,
   });
 });
+
+test('プレフィックスではなく、パディングや大文字小文字の混在を含む完全なIDと一致する', () => {
+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+    id: 'acct-10',
+    name: 'Nimbus',
+    seats: 24,
+  });
+});

修正前は、acct-1 / Atlas / 5 オブジェクトに対して新しいテストが失敗していましたが、修正後は合格しています。.

検証

テキスト
node --test test/account-summary.test.cjs
node --test test/account-summary.test.cjs

制限事項

• 変更範囲:オペレーターが1つ変更されました。名称の変更や新しい依存関係はなく、findAccount および summarizeAccount のシグネチャと戻り値の型は変更されていません。.
• 以前から存在していた動作で、そのまま放置されているもの(このバグの対象外):
• 文字列ではない requestedId(null、数値)の場合、.trim() を呼び出すと依然として例外が発生します。.
• アカウントID自体はトリミングされないため、保存されている「acct-10」は依然として一致しません。正規化されるのはクエリのみです。.
• ケーシングには単純な toLowerCase(); を使用しており、Unicodeの正規化やロケールに応じた折り畳みは行われていません。.
• 重複するIDについては、依然として最初の一致するレコードが返され、検索の計算量はO(n)のままです。.
• テストカバレッジ:この単一の回帰テストは、報告された再現現象を正確にターゲットとしています。見つからない(ヌル)パスや不正な形式の入力については、依然としてテストされていません。.

ROOT CAUSE
findAccount matches by prefix, not by equality:

```js
normalizedQuery.startsWith(account.id.toLowerCase())
```

Array.prototype.find returns the first element satisfying the predicate. For ' ACCT-10 ' the normalized query is 'acct-10', and the first account's ID 'acct-1' is a prefix of it, so startsWith is true and acct-1 short-circuits the search before acct-10 is ever tested.
The trim().toLowerCase() normalization is correct — whitespace and casing are not the problem. summarizeAccount is a pass-through and is not at fault.
The existing test cannot catch this: 'acct-1' is a prefix of itself and is the first element, so prefix matching and exact matching are indistinguishable for that input.
PATCH

```diff
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
 function findAccount(accounts, query) {
   const normalizedQuery = query.trim().toLowerCase();
-  return accounts.find((account) =>
-    normalizedQuery.startsWith(account.id.toLowerCase()),
-  );
+  return accounts.find(
+    (account) => account.id.toLowerCase() === normalizedQuery,
+  );
 }

 module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
 test('summarizes an exact account ID', () => {
     seats: 5,
   });
 });
+
+test('matches the full ID rather than a prefix, with padding and mixed case', () => {
+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+    id: 'acct-10',
+    name: 'Nimbus',
+    seats: 24,
+  });
+});
```

Before the fix the new test fails with the acct-1 / Atlas / 5 object; after the fix it passes.
VERIFICATION

```text
node --test test/account-summary.test.cjs
```

LIMITATIONS
• Scope: one operator changed. No renames, no new dependencies, and findAccount / summarizeAccount signatures and return shapes are unchanged.
• Pre-existing behavior left alone (out of scope for this bug):
• A non-string requestedId (null, a number) still throws on .trim().
• Account IDs themselves are not trimmed, so a stored ' acct-10' still will not match — only the query is normalized.
• Casing uses plain toLowerCase(); no Unicode normalization or locale-aware folding.
• Duplicate IDs still resolve to the first match, and lookup remains O(n).
• Test coverage: the single regression test targets exactly the reported reproduction. The not-found (null) path and malformed input remain untested.

T2: アカウントの状態分析

不完全 — 主要な指標を算出し、優先順位付けされたアクションを提示しましたが、記録された回答には、求められていた「再確認」のマークが含まれていませんでした。.

Claude Opus 5 実践的なアカウント健全性分析の結果
リスクのあるMRRを$34,800(94.31%)と算出;E-505をエスカレーションし、フォローアップ措置の優先順位を決定;要求された再確認マーカーなしで回答が終了した。.
T2のプロンプトと回答の全文を表示する
プロンプト全文
提供された `account-health.csv` を、閉じたデータセットとして分析してください。外部の事実を使用したり、欠損値を推測したりしないでください。

リスクルール(それぞれを個別に評価してください):
- `inactivity`: `days_since_login >= 30`
- `payment`: `failed_payments >= 2`
- `low_utilization`: `seats_used / seats_purchased = 80` である場合。
- `weak_health_without_risk`: アカウントが「at-risk」状態でないにもかかわらず、`health_score = 9` かつ `open_tickets >= 3` である場合。

要件:
1. すべてのアカウントについて、トリガーされたリスクフラグと矛盾フラグを算出する。
2. アカウント数、MRR、リスク状態のアカウント数、リスク状態のMRR、エスカレーション対象アカウント数、矛盾行数、購入済みシート数、使用済みシート数に関するデータセットの合計値を報告する。
3. 正確に5つの列(`アカウント | リスクトリガー | 矛盾 | 優先度 | 推奨アクション`)からなるアクションテーブルを作成する。
4. 直接計算された値は `Measured facts` 見出しの下に、判断に基づく項目は `Inference` 見出しの下に配置する。
5. `再確認` の項目では、0.50 の等価ケースを含め、すべての合計値および閾値の境界を独自に再確認できるだけの計算過程を示すこと。
6. ルールを黙って修正したり再解釈したりしてはならない。シグナルが直感に反すると感じられる場合は、その分類を変更するのではなく、矛盾として記録すること。

`account-health.csv`:
```csv
account_id,account_name,plan,mrr_usd,days_since_login,failed_payments,seats_purchased,seats_used,health_score,nps,open_tickets
A-101,Aster,Enterprise,12000,45,0,100,82,92,9,1
B-202,Beacon,Pro,4200,4,2,20,18,70,7,0
C-303,Cinder,Pro,3600,12,0,20,8,65,10,4
D-404,Dahlia,Starter,900,5,0,5,4,42,6,0
E-505,Ember,Enterprise,15000,65,3,200,70,35,3,6
F-606,Fjord,Starter,1200,29,1,4,2,85,9,3
```
Claude Opus 5

実測データ

出典:account-health.csv、6行、クローズ済みとして扱われる。補完された値はない。.

アカウントごとのルール評価

アカウント
日数≥30
失敗数≥2
util < 0.50
リスク件数
ステータス
A-101 アスター
✅ 45
❌ 0
❌ 0.82
1
リスクのある
B-202 ビーコン
❌ 4
✅ 2
❌ 0.90
1
リスクのある
C-303 シンダー
❌ 12
❌ 0
✅ 0.40
1
リスクのある
D-404 ダリア
❌ 5
❌ 0
❌ 0.80
0
リスクがない
E-505 エンバー
✅ 65
✅ 3
✅ 0.35
3
リスク対象 + エスカレーション
F-606 フィヨルド
❌ 29
❌ 1
❌ 0.50
0
リスクがない
アカウントごとの矛盾フラグ
アカウント
リスクを伴う健康
リスクのない健康状態の低下
チケットを所持しているプロモーター
A-101 アスター
✅ (92 ≥ 80、リスクあり)

❌(NPS 9 ✓、チケット 1 ✗)
B-202 ビーコン
❌ (70 < 80)
❌ (70 ≥ 50)
❌ (NPS 7)
C-303 シンダー
❌ (65 < 80)
❌ (65 ≥ 50)
✅ (NPS 10、チケット 4)
D-404 ダリア

✅ (42 < 50、リスク対象外)
❌ (NPS 6)
E-505 エンバー
❌ (35 < 80)
❌(35 < 50 だが、リスクがある)
❌ (NPS 3)
F-606 フィヨルド
❌ (85 ≥ 80 だが、リスク群には該当しない)
❌ (85 ≥ 50)
✅ (NPS 9、チケット 3)
データセットの合計
メートル法
価値
アカウント
6
MRR合計
$36,900
リスクのある口座
4(A-101、B-202、C-303、E-505)
リスクのあるMRR
$34,800(全体の94.31%)
アカウントのエスカレーション
1 (E-505)
矛盾行
4(A-101、C-303、D-404、F-606)
矛盾のフラグ
4(1:健康状態良好・リスクあり、1:健康状態不良・リスクなし、2:プロモーター・チケット負荷あり)
購入済みの座席
349
使用された座席
184
推論
以下の優先順位付けおよび推奨される対応は、判断に基づくものであり、ルールによる結果ではありません。私の優先順位付けの重み付けは、まずステータス、次にリスクのあるMRR、そして矛盾のシグナルの順に高くなっています。.
アカウント
リスクの引き金
矛盾
優先度
推奨される対応
E-505 エンバー
非稼働、支払い、利用率の低さ
-
P0
3つのルールすべてが、最大のアカウント($15,000 MRR)に対して発動しました。アクティブな解約として扱い、支払い方法を復元した後、未使用の130席について経営陣による審査を実施してください。.
A-101 アスター
不活動
リスクを伴う健康
P1
$:MRR 12,000、スコアは92であり、82%の利用状況も健全であるにもかかわらず、45日間の非アクティブ期間がある。スコアに基づいて対応を行う前に、ログイン間隔の空白が実際の離脱によるものか、それとも追跡上の要因(SSO、APIのみの利用など)によるものかを確認すること。.
C-303 シンダー
利用率の低さ
チケットを所持しているプロモーター
P1
プロモーター(NPS 10)が、40%の利用率で4件の未処理チケットを抱えている。チケットの負荷が導入の障壁となっている可能性が高い。キューを解消し、その後、座席の有効化を推進する。.
B-202 ビーコン
支払い
-
P2
明確な単一要因による事例:直近4日以内にログイン履歴があり、90%の利用状況が確認された状態で、2件の支払不履行が発生。請求に関するフォローアップのみを行い、カスタマーサービスによる対応は不要。.
F-606 フィヨルド
-
チケットを所持しているプロモーター
P3
すべての基準値をぎりぎり満たしています(29日間、支払い不履行1回、利用率は正確に0.50)。規則上はリスク対象外ですが、あと1日でも利用がない状態が続いたり、支払い不履行が1回でも発生したりすれば、状況が一変します。状況を注視し、3件のチケットを処理してください。.
D-404 ダリア
-
リスクのない健康状態の低下
P3
ルールはトリガーされず、$900 MRRにおいて80%が利用され、スコアは42でした。いずれか

測定された事実
出典:account-health.csv、6行、クローズ済みとして扱われる。補間された値はない。
アカウントごとのルール評価
アカウント
days≥30
failed≥2
util <0.50
リスクカウント
ステータス
A-101 Aster
✅ 45
❌ 0
❌ 0.82
1
リスクあり
B-202 ビーコン
❌ 4
✅ 2
❌ 0.90
1
リスクあり
C-303 シンダー
❌ 12
❌ 0
✅ 0.40
1
リスクあり
D-404 ダリア
❌ 5
❌ 0
❌ 0.80
0
リスクなし
E-505 エムバー
✅ 65
✅ 3
✅ 0.35
3
リスクあり + エスカレーション
F-606 フィヨルド
❌ 29
❌ 1
❌ 0.50
0
リスクなし
アカウントごとの矛盾フラグ
アカウント
リスクありで健全
リスクなしで脆弱
チケット負荷のあるプロモーター
A-101 アスター
✅ (92 ≥ 80、リスクあり)
❌
❌ (NPS 9 ✓, チケット 1 ✗)
B-202 ビーコン
❌ (70 < 80)
❌ (70 ≥ 50)
❌ (NPS 7)
C-303 シンダー
❌ (65 < 80)
❌ (65 ≥ 50)
✅ (NPS 10, チケット 4)
D-404 ダリア
❌
✅ (42 < 50、リスクなし)
❌ (NPS 6)
E-505 エムバー
❌ (35 < 80)
❌ (35 < 50 だがリスクあり)
❌ (NPS 3)
F-606 フィヨルド
❌ (85 ≥ 80 だがリスク対象外)
❌ (85 ≥ 50)
✅ (NPS 9、チケット数 3)
データセットの合計
指標
値
アカウント数
6
MRR合計
$36,900
リスクのあるアカウント
4 (A-101, B-202, C-303, E-505)
リスクのあるMRR
$34,800(全体の94.31%)
エスカレーション対象アカウント
1(E-505)
矛盾行
4(A-101、C-303、D-404、F-606)
矛盾フラグ
4件(1件:strong_health_with_risk、1件:weak_health_without_risk、2件:promoter_with_ticket_load)
購入済み座席数
349
利用済み座席数
184
推論
以下の優先順位付けおよび推奨措置は、ルールによる出力ではなく、判断に基づくものです。 私の優先順位付けでは、まずステータスの悪化、次にリスクのあるMRR、そして矛盾シグナルの順に重み付けしています。
アカウント
リスクトリガー
矛盾
優先度
推奨措置
E-505 Ember
非アクティブ、支払い、低利用率
—
P0
3つのルールすべてが最大規模のアカウント($15,000 MRR)で発動しています。アクティブな解約として扱い、支払い方法を復旧させた後、未使用の130席について経営陣によるレビューを実施してください。
A-101 Aster
非アクティブ
リスクを伴う健全な状態
P1
$12,000 MRRのアカウントで、スコア92、利用率82%と健全な状態にもかかわらず、45日間利用停止状態にある。スコアに基づいて対応する前に、ログイン間隔の空きの原因が実際の離反なのか、それとも追跡上の誤差(SSO、APIのみの利用など)なのかを確認すること。
C-303 Cinder
低利用率
チケット負荷のあるプロモーター
P1
プロモーター(NPS 10)で、40%の利用率に対し4件の未解決チケットを抱えている。チケットの負荷が導入の障壁となっている可能性が高い。キューを解消した上で、ライセンスの活性化を推進する。
B-202 Beacon
payment
—
P2
原因が単一の明確なケース:2回の決済失敗、ログイン履歴は4日前、利用率は90%。請求に関するフォローアップのみを行い、カスタマーサポートによる対応は不要。
F-606 Fjord
—
promoter_with_ticket_load
P3
すべての基準値(29日、支払い失敗1回、利用率正確に0.50)をわずかに下回っている。ルール上はリスク対象外だが、さらに1日利用停止状態が続くか、支払い失敗が1回増えるとリスク対象となる。 3件のチケットを監視し、解消してください。
D-404 Dahlia
—
weak_health_without_risk
P3
スコア42、ルールはトリガーされておらず、$900 MRRで80%の利用率。いずれにせよ

T3: レスポンシブUIの生成

部分的 — ページを実行時にレンダリングするのではなく、検査しただけであることを明示的に認めつつ、独立した長めの実装と自己チェックを作成した。.

Claude Opus 5つの実践的なレスポンシブUI生成結果
21,907文字の完結した回答を作成した。デスクトップ、モバイル、オーバーフロー、アクセシビリティについて網羅した。レイアウトは実行時にレンダリングされたものではなく、検査されたものであることを明示した。.
T3のプロンプトと回答の全文を表示する
プロンプト全文
以下の製品データのみを使用して、洗練された製品比較インターフェースを、単一の実行可能なHTMLファイルとして構築してください。

要件:
1. フェンスで囲まれた `html` コードブロックを正確に1つ返し、その後に `SELF-CHECK` セクションを続けてください。HTML、CSS、JavaScriptを別々のファイルに分割しないでください。
2. セマンティックHTML、埋め込みCSS、および埋め込みのVanilla JavaScriptのみを使用してください。外部のフレームワーク、パッケージ、フォント、画像、ネットワークリクエスト、ビルド工程は一切使用しないでください。
3. キーボード操作が可能な3つのタブ(`Overview`、`Pricing`、`Limits`)を用意し、正しい`tablist`、`tab`、`tabpanel`のセマンティクスを適用してください。 ArrowLeft/ArrowRightキーでタブを移動・アクティブ化でき、Home/Endキーで最初/最後のタブにジャンプしてアクティブ化する必要があります。フォーカスは常に可視状態を維持する必要があります。
4. 選択されたタブは、`aria-selected`、`tabindex`、および表示されているパネルによって反映されなければなりません。非アクティブなパネルは非表示にする必要があります。
5. デスクトップ向け:幅1440px。モバイル向け:幅390pxで、ページの水平方向のオーバーフローやコントロールの切り取りがなく、タップターゲットの高さが44px以上であり、比較カードが1列に積み重ねられていること。
6. 簡潔なヘッダー、明確な推奨事項、3つの製品カード、および1つのコンパクトな比較表を含めること。 読みやすいコントラストを維持し、装飾的な動きは避けること。
7. 以下の製品情報を正確に使用し、独自の主張を追加しないこと:
   - Atlas: `$19/mo`、`20プロジェクト`、`10 GB`、`メールサポート`、個人作業に最適。
   - Beacon:`$49/mo`、`プロジェクト数無制限`、`100 GB`、`優先サポート`、成長中のチームに最適。
   - Cove: `$99/月`、`プロジェクト数無制限`、`1 TB`、`専任サポート`、規制対象の業務に最適。
8. Beaconには「総合的に最適」というラベルを目立つように表示し、他のカードが無効化されているように見えないようにしてください。
9. `SELF-CHECK` では、セマンティックタブ、キーボード操作、1440px レイアウト、390px レイアウト、水平方向のオーバーフロー、および外部依存関係に関するチェック結果を明示的に報告してください。実際にビューポートをレンダリングしていない限り、レンダリングしたと主張しないでください。コード検査と実行時の検証を区別してください。

製品フィクスチャ(`fixtures/T3-responsive-ui/product-data.json` としても保存):
```json
{
  "products": [
    {"name":"Atlas","price":"$19/mo","projects":"20 projects","storage":"10 GB","support":"メールサポート","bestFor":"個人作業"},
    {"name":"Beacon","price":"$49/mo","projects":"無制限のプロジェクト","storage":"100 GB","support":"優先サポート","bestFor":"成長中のチーム","badge":"総合ベスト"},
    {"name":"Cove","price":"$99/mo","projects":"無制限のプロジェクト","storage":"1 TB","support":"専任サポート","bestFor":"規制対象の業務"}
  ]
}
```
Claude Opus 5
html
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Compare plans — Atlas, Beacon, Cove</title><style>  :root {    --bg: #f6f7f9;    --surface: #ffffff;    --ink: #16191f;    --ink-soft: #4a515c;    --line: #d3d8df;    --line-strong: #b6bdc7;    --accent: #10457e;    --accent-soft: #e8f0f9;    --focus: #0b2f56;    --radius: 10px;  }   * {box-sizing: border-box; }   html { -webkit-text-size-adjust: 100%; }   body {    margin: 0;    padding: 0;    background: var(--bg);    color: var(--ink);    font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;    font-size: 16px;    line-height: 1.5;    overflow-x: hidden;  }   .wrap {    width: 100%;    max-width: 1120px;    margin: 0 auto;    padding: 32px 24px 64px;  }   /* ---------- Header ---------- */   .page-header { margin-bottom: 24px; }   .page-header h1 {    margin: 0 0 8px;    font-size: 1.75rem;    line-height: 1.25;    letter-spacing: -0.01em;  }   .page-header p {    margin: 0;    max-width: 60ch;    color: var(--ink-soft);  }   /* ---------- Recommendation ---------- */   .recommendation {    display: flex;    flex-wrap: wrap;    gap: 4px 10px;    align-items: baseline;    margin: 0 0 28px;    padding: 14px 16px;    background: var(--accent-soft);    border: 1px solid #c2d5e8;    border-left: 4px solid var(--accent);    border-radius: var(--radius);  }   .recommendation strong { color: var(--accent); }   .recommendation span { color: #23405e; }   /* ---------- Tabs ---------- */   .tabs {    display: flex;    flex-wrap: wrap;    gap: 8px;    margin: 0 0 20px;    padding: 0;    border-bottom: 1px solid var(--line);  }   [role="tab"] {    appearance: none;    min-height: 44px;    padding: 10px 18px;    font: inherit;    font-weight: 600;    color: var(--ink-soft);    background: transparent;    border: 1px solid transparent;    border-bottom: 3px solid transparent;    border-radius: 8px 8px 0 0;    cursor: pointer;  }   [role="tab"]:hover { color: var(--ink); background: #eceff3; }   [role="tab"][aria-selected="true"] {    color: var(--accent);    background: var(--surface);    border-color: var(--line) var(--line) var(--accent);    border-bottom-width: 3px;  }   :focus-visible {    outline: 3px solid var(--focus);    outline-offset: 2px;  }   [role="tabpanel"] { outline: none; }   [role="tabpanel"]:focus-visible {    outline: 3px solid var(--focus);    outline-offset: 4px;    border-radius: var(--radius);  }   [hidden] { display: none !important; }   .panel-intro {    margin: 0 0 20px;    max-width: 62ch;    color: var(--ink-soft);  }   /* ---------- Cards ---------- */   .card-grid {    display: grid;    grid-template-columns: repeat(3, minmax(0, 1fr));    gap: 20px;    margin: 0;    padding: 0;    list-style: none;    align-items: start;  }   .card {    display: flex;    flex-direction: column;    height: 100%;    padding: 20px;    background: var(--surface);    border: 1px solid var(--line);    border-radius: var(--radius);  }   .card.is-featured {    border-color: var(--accent);    border-width: 2px;    padding: 19px;  }   .card-head {    display: flex;    flex-wrap: wrap;    gap: 8px;    align-items: center;    justify-content: space-between;    margin-bottom: 4px;  }   .card h3 {    margin: 0;    font-size: 1.2rem;  }   .badge {    padding: 3px 10px;    font-size: 0.75rem;    font-weight: 700;    letter-spacing: 0.02em;    text-transform: uppercase;    color: #ffffff;    background: var(--accent);    border-radius: 999px;    white-space: nowrap;  }   .price {    margin: 8px 0 2px;    font-size: 1.6rem;    font-weight: 700;    letter-spacing: -0.02em;  }   .best-for {    margin: 0 0 14px;    font-size: 0.9375rem;    color: var(--ink-soft);  }   .spec-list {    margin: 0;    padding: 14px 0 0;    border-top: 1px solid var(--line);    font-size: 0.9375rem;  }   .spec-list div {    display: flex;    gap: 12px;    justify-content: space-between;    padding: 5px 0;  }   .spec-list dt { color: var(--ink-soft); }   .spec-list dd {    margin: 0;    font-weight: 600;    text-align: right;  }   /* ---------- Table ---------- */   .table-section { margin-top: 36px; }   .table-section h2 {    margin: 0 0 12px;    font-size: 1.125rem;  }   .table-scroll {    max-width: 100%;    overflow-x: auto;    background: var(--surface);    border: 1px solid var(--line);    border-radius: var(--radius);  }   table {    width: 100%;    border-collapse: collapse;    font-size: 0.9375rem;  }   caption {    padding: 12px 14px;    text-align: left;    color: var(--ink-soft);    font-size: 0.875rem;  }   th, td {    padding: 10px 14px;    text-align: left;    border-top: 1px solid var(--line);    white-space: nowrap;  }   thead th {    background: #eef1f5;    border-top: none;    font-weight: 700;  }   tbody th { font-weight: 600; color: var(--ink-soft); }   th[scope="col"].is-featured { color: var(--accent); }   /* ---------- Mobile ---------- */   @media (max-width: 720px) {    .wrap { padding: 20px 16px 48px; }     .page-header h1 { font-size: 1.4rem; }     .tabs {      gap: 4px;      overflow-x: auto;      -webkit-overflow-scrolling: touch;      flex-wrap: nowrap;    }     [role="tab"] {      flex: 1 0 auto;      padding: 10px 12px;      font-size: 0.9375rem;    }     .card-grid { grid-template-columns: minmax(0, 1fr); }     th, td { padding: 10px 12px; }  }   @media (prefers-reduced-motion: reduce) {    * {transition: none !important; animation: none !important; }  }</style></head><body><main class="wrap">   <header class="page-header">    <h1>Compare plans</h1>    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>  </header>   <p class="recommendation">    <strong>Recommended: Beacon</strong>    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>  </p>   <div class="tabs" role="tablist" aria-label="Plan comparison views">    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>  </div>   <!-- Overview -->  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>20 projects</dd></div>          <div><dt>Storage</dt><dd>10 GB</dd></div>          <div><dt>Support</dt><dd>Email support</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>100 GB</dd></div>          <div><dt>Support</dt><dd>Priority support</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>1 TB</dd></div>          <div><dt>Support</dt><dd>Dedicated support</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>All plans at a glance</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">        <table>          <caption>Published facts for Atlas, Beacon, and Cove.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Price</th>              <th scope="col">Projects</th>              <th scope="col">Storage</th>              <th scope="col">Support</th>              <th scope="col">Best for</th>            </tr>          </thead>          <tbody>            <tr>              <th scope="row">Atlas</th>              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>            </tr>            <tr>              <th scope="row">Beacon</th>              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>            </tr>            <tr>              <th scope="row">Cove</th>              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>            </tr>          </tbody>        </table>      </div>    </section>  </section>   <!-- Pricing -->  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Email support</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Priority support</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Dedicated support</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>Price and support</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">        <table>          <caption>Monthly price, support tier, and intended fit.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Price</th>              <th scope="col">Support</th>              <th scope="col">Best for</th>            </tr>          </thead>          <tbody>            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>          </tbody>        </table>      </div>    </section>  </section>   <!-- Limits -->  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>    <p class="panel-intro">Project counts and storage allowances for each plan.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>20 projects</dd></div>          <div><dt>Storage</dt><dd>10 GB</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>100 GB</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>1 TB</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>Projects and storage</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">        <table>          <caption>Project allowance and storage per plan.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Projects</th>              <th scope="col">Storage</th>            </tr>          </thead>          <tbody>            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>          </tbody>        </table>      </div>    </section>  </section> </main> <script>(function () {  'use strict';   var tablist = document.querySelector('[role="tablist"]');  if (!tablist) return;   var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'));   function panelFor(tab) {    return document.getElementById(tab.getAttribute('aria-controls'));  }   function activate(index, moveFocus) {    if (index < 0 || index >= tabs.length) return;     tabs.forEach(function (tab, i) {      var selected = i === index;      var panel = panelFor(tab);       tab.setAttribute('aria-selected', selected ? 'true' : 'false');      tab.setAttribute('tabindex', selected ? '0' : '-1');       if (panel) {        if (selected) {          panel.removeAttribute('hidden');        }else {          panel.setAttribute('hidden', '');        }      }    });     if (moveFocus !== false) tabs[index].focus();  }   function currentIndex() {    var i = tabs.findIndex(function (tab) {      return tab.getAttribute('aria-selected') === 'true';    });    return i === -1 ? 0 : i;  }   tabs.forEach(function (tab, i) {    tab.addEventListener('click', function () {      activate(i);    });  });   tablist.addEventListener('keydown', function (event) {    var last = tabs.length - 1;    var i = currentIndex();    var next = null;     switch (event.key) {      case 'ArrowRight':        next = i === last ?0 : i + 1;        break;      case 'ArrowLeft':        next = i ===0 ? last : i - 1;        break;      case 'Home':        next =0;        break;      case 'End':        next = last;        break;      default:        return;    }     event.preventDefault();    activate(next);  });   // Normalize initial state from markup.  activate(currentIndex(), false);}());</script></body></html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compare plans — Atlas, Beacon, Cove</title>
<style>
  :root
 {
    --bg: #f6f7f9
;
    --surface: #ffffff
;
    --ink: #16191f
;
    --ink-soft: #4a515c
;
    --line: #d3d8df
;
    --line-strong: #b6bdc7
;
    --accent: #10457e
;
    --accent-soft: #e8f0f9
;
    --focus: #0b2f56
;
    --radius: 10px
;
  }

  * {
box-sizing
: border-box; }

  html { -webkit-text-size-adjust: 100%
; }

  body
 {
    margin: 0
;
    padding: 0
;
    background: var
(--bg);
    color: var
(--ink);
    font-family: system-ui, -apple-system, "Segoe UI"
, Roboto, Helvetica, Arial, sans-serif;
    font-size: 16px
;
    line-height: 1.5
;
    overflow-x
: hidden;
  }

  .wrap
 {
    width: 100%
;
    max-width: 1120px
;
    margin: 0
 auto;
    padding: 32px 24px 64px
;
  }

  /* ---------- Header ---------- */

  .page-header { margin-bottom: 24px
; }

  .page-header h1
 {
    margin: 0 0 8px
;
    font-size: 1.75rem
;
    line-height: 1.25
;
    letter-spacing: -0.01em
;
  }

  .page-header p
 {
    margin: 0
;
    max-width: 60ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Recommendation ---------- */

  .recommendation
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 4px 10px
;
    align-items
: baseline;
    margin: 0 0 28px
;
    padding: 14px 16px
;
    background: var
(--accent-soft);
    border: 1px solid #c2d5e8
;
    border-left: 4px solid var
(--accent);
    border-radius: var
(--radius);
  }

  .recommendation strong { color: var
(--accent); }

  .recommendation span { color: #23405e
; }

  /* ---------- Tabs ---------- */

  .tabs
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    margin: 0 0 20px
;
    padding: 0
;
    border-bottom: 1px solid var
(--line);
  }

  [role="tab"]
 {
    appearance
: none;
    min-height: 44px
;
    padding: 10px 18px
;
    font
: inherit;
    font-weight: 600
;
    color: var
(--ink-soft);
    background
: transparent;
    border: 1px
 solid transparent;
    border-bottom: 3px
 solid transparent;
    border-radius: 8px 8px 0 0
;
    cursor
: pointer;
  }

  [role="tab"]:hover { color: var(--ink); background: #eceff3
; }

  [role="tab"][aria-selected="true"]
 {
    color: var
(--accent);
    background: var
(--surface);
    border-color: var(--line) var(--line) var
(--accent);
    border-bottom-width: 3px
;
  }

  :focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 2px
;
  }

  [role="tabpanel"] { outline
: none; }

  [role="tabpanel"]:focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 4px
;
    border-radius: var
(--radius);
  }

  [hidden] { display: none !important
; }

  .panel-intro
 {
    margin: 0 0 20px
;
    max-width: 62ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Cards ---------- */

  .card-grid
 {
    display
: grid;
    grid-template-columns: repeat(3, minmax(0, 1
fr));
    gap: 20px
;
    margin: 0
;
    padding: 0
;
    list-style
: none;
    align-items
: start;
  }

  .card
 {
    display
: flex;
    flex-direction
: column;
    height: 100%
;
    padding: 20px
;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  .card.is-featured
 {
    border-color: var
(--accent);
    border-width: 2px
;
    padding: 19px
;
  }

  .card-head
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    align-items
: center;
    justify-content
: space-between;
    margin-bottom: 4px
;
  }

  .card h3
 {
    margin: 0
;
    font-size: 1.2rem
;
  }

  .badge
 {
    padding: 3px 10px
;
    font-size: 0.75rem
;
    font-weight: 700
;
    letter-spacing: 0.02em
;
    text-transform
: uppercase;
    color: #ffffff
;
    background: var
(--accent);
    border-radius: 999px
;
    white-space
: nowrap;
  }

  .price
 {
    margin: 8px 0 2px
;
    font-size: 1.6rem
;
    font-weight: 700
;
    letter-spacing: -0.02em
;
  }

  .best-for
 {
    margin: 0 0 14px
;
    font-size: 0.9375rem
;
    color: var
(--ink-soft);
  }

  .spec-list
 {
    margin: 0
;
    padding: 14px 0 0
;
    border-top: 1px solid var
(--line);
    font-size: 0.9375rem
;
  }

  .spec-list div
 {
    display
: flex;
    gap: 12px
;
    justify-content
: space-between;
    padding: 5px 0
;
  }

  .spec-list dt { color: var
(--ink-soft); }

  .spec-list dd
 {
    margin: 0
;
    font-weight: 600
;
    text-align
: right;
  }

  /* ---------- Table ---------- */

  .table-section { margin-top: 36px
; }

  .table-section h2
 {
    margin: 0 0 12px
;
    font-size: 1.125rem
;
  }

  .table-scroll
 {
    max-width: 100%
;
    overflow-x
: auto;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  table
 {
    width: 100%
;
    border-collapse
: collapse;
    font-size: 0.9375rem
;
  }

  caption
 {
    padding: 12px 14px
;
    text-align
: left;
    color: var
(--ink-soft);
    font-size: 0.875rem
;
  }

  th, td
 {
    padding: 10px 14px
;
    text-align
: left;
    border-top: 1px solid var
(--line);
    white-space
: nowrap;
  }

  thead th
 {
    background: #eef1f5
;
    border-top
: none;
    font-weight: 700
;
  }

  tbody th { font-weight: 600; color: var
(--ink-soft); }

  th[scope="col"].is-featured { color: var
(--accent); }

  /* ---------- Mobile ---------- */

  @media (max-width: 720px
) {
    .wrap { padding: 20px 16px 48px
; }

    .page-header h1 { font-size: 1.4rem
; }

    .tabs
 {
      gap: 4px
;
      overflow-x
: auto;
      -webkit-
overflow
-scrolling: touch;
      flex-wrap
: nowrap;
    }

    [role="tab"]
 {
      flex: 1 0
 auto;
      padding: 10px 12px
;
      font-size: 0.9375rem
;
    }

    .card-grid { grid-template-columns: minmax(0, 1
fr); }

    th, td { padding: 10px 12px
; }
  }

  @media (prefers-reduced-motion
: reduce) {
    * {
transition: none !important; animation: none !important
; }
  }
</style>
</head>
<body>
<main class="wrap">

  <header class="page-header">
    <h1>Compare plans</h1>
    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>
  </header>

  <p class="recommendation">
    <strong>Recommended: Beacon</strong>
    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>
  </p>

  <div class="tabs" role="tablist" aria-label="Plan comparison views">
    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>
    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>
  </div>

  <!-- Overview -->
  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>All plans at a glance</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">
        <table>
          <caption>Published facts for Atlas, Beacon, and Cove.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">Atlas</th>
              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>
            </tr>
            <tr>
              <th scope="row">Beacon</th>
              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>
            </tr>
            <tr>
              <th scope="row">Cove</th>
              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Pricing -->
  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>
    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Price and support</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">
        <table>
          <caption>Monthly price, support tier, and intended fit.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>
            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>
            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Limits -->
  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>
    <p class="panel-intro">Project counts and storage allowances for each plan.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Projects and storage</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">
        <table>
          <caption>Project allowance and storage per plan.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>
            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>
            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

</main>

<script>
(
function (
) {
  'use strict'
;

  var tablist = document.querySelector('[role="tablist"]'
);
  if (!tablist) return
;

  var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'
));

  function panelFor(tab
) {
    return document.getElementById(tab.getAttribute('aria-controls'
));
  }

  function activate(index, moveFocus
) {
    if (index < 0 || index >= tabs.length) return
;

    tabs.
forEach(function (tab, i
) {
      var
 selected = i === index;
      var panel = panelFor
(tab);

      tab.
setAttribute('aria-selected', selected ? 'true' : 'false'
);
      tab.
setAttribute('tabindex', selected ? '0' : '-1'
);

      if
 (panel) {
        if
 (selected) {
          panel.
removeAttribute('hidden'
);
        }
else
 {
          panel.
setAttribute('hidden', ''
);
        }
      }
    });

    if (moveFocus !== false) tabs[index].focus
();
  }

  function currentIndex(
) {
    var i = tabs.findIndex(function (tab
) {
      return tab.getAttribute('aria-selected') === 'true'
;
    });
    return i === -1 ? 0
 : i;
  }

  tabs.
forEach(function (tab, i
) {
    tab.
addEventListener('click', function (
) {
      activate
(i);
    });
  });

  tablist.
addEventListener('keydown', function (event
) {
    var last = tabs.length - 1
;
    var i = currentIndex
();
    var next = null
;

    switch (event.key
) {
      case 'ArrowRight'
:
        next = i === last ?
0 : i + 1
;
        break
;
      case 'ArrowLeft'
:
        next = i ===
0 ? last : i - 1
;
        break
;
      case 'Home'
:
        next =
0
;
        break
;
      case 'End'
:
        next = last;
        break
;
      default
:
        return
;
    }

    event.
preventDefault
();
    activate
(next);
  });

  // Normalize initial state from markup.
  activate(currentIndex(), false
);
}());
</script>
</body>
</html>

自己チェック

以下の記述はすべて、コードの検証のみに基づくものです。ブラウザを起動したり、ビューポートをレンダリングしたり、スクリーンリーダーを実行したり、キーボードハンドラを実行したりはしていないため、ここで述べられている内容はすべて実行時検証されたものではありません。主張がレイアウトエンジンの挙動に依存する場合は、その旨を明記しています。.
セマンティックタブ — 検証済み、一貫性あり
aria-label="プラン比較画面" を持つ 1 つの div[role="tablist"] には、3 つの button[type="button"][role="tab"] が含まれています。 各タブには一意のIDと、section[role="tabpanel"]を指すaria-controls属性があります。各パネルには、そのタブを指し戻すaria-labelledby属性があります。私はこれら3組のペア(tab-overview/panel-overview、tab-pricing/panel-pricing、tab-limits/panel-limits)をすべて手作業で追跡しました。 IDの重複や未参照の参照はありません。パネルには tabindex="0" が設定されているため、タブの後にパネルの本文にアクセスできます。.
キーボードの動作 — 確認のみ、実行は行わない
タブリストの単一のkeydownリスナーが、右矢印キー、左矢印キー、Homeキー、Endキーを処理し、これら4つのキーに対してのみevent.preventDefault()を呼び出し、それ以外の場合は早期に処理を終了します。 矢印キーは両端でループします。activate() は aria-selected/tabindex/hidden を更新すると同時にフォーカスを移動させるため、矢印キーおよび Home/End キーによる操作は、移動とアクティブ化を1つのステップで実行します。これは、要件で求められている「自動アクティブ化」パターンに合致しています。 Tab/Shift+Tabによる移動は、移動するtabindexに依存しています。tabindex="0"は正確に1つだけ、残りは-1となっており、これはactivate()によって維持されます。フォーカスの可視性は、3pxのアウトラインと2pxのオフセットを持つグローバルな:focus-visibleルールによって実現されています。デフォルトのアウトラインは上書きも削除もしていません。 実際のブラウザでのキー操作については確認していません。.
選択状態の反射 — 確認済み
activate() は 3 つのシグナルすべてを同じループ内で設定するため、aria-selected="true"、tabindex="0"、および hidden 属性の欠如が互いにずれることはありません。 非アクティブなパネルには `hidden` 属性が設定され、[hidden] { display: none !important; } によって、本来ならこの属性を無効にしてしまう表示ルールから保護されます。この保護措置は、パネル内に `display: grid` を指定した子要素が含まれているため重要です。activate(currentIndex(), false) はロード時に実行され、フォーカスを奪うことなくマークアップの状態を正規化します。 JavaScriptが実行されない場合、マークアップでは「Overview」が選択され、他の2つのパネルが非表示の状態となるため、ページは1つの読み取り可能なパネルに簡素化されます。.
1440px レイアウト — 検査済み、レンダリングは未実施
.wrap は max-width: 1120px、margin: 0 auto となっているため、1440px ではコンテンツが中央に配置され、幅が伸びるのではなく、約 160px の隙間が生まれます。 カードには `grid-template-columns: repeat(3, minmax(0, 1fr))` と 20px の間隔を設定し、3つの等幅の列を作成しています。`align-items: start` により、カードが共通の高さまで伸びるのを防いでいますが、`.card { height: 100% }` の指定はその効果によって打ち消されています。 minmax(0, 1fr) は意図的な設定です。1fr のみの場合、コンテンツの幅以下に縮小することを拒否し、グリッドを幅広にしてしまう可能性があるためです。実際のピクセル出力は測定していません。.
390px レイアウト — 検査済み、レンダリングされていない
max-width: 720px のブロックでは、カードグリッドが minmax(0, 1fr) の単一列に切り替わるため、カードが縦に積み重なります。パディングは各辺 16px に縮小され、コンテンツ幅は約 358px となります。 タップターゲット:すべての [role="tab"] には `min-height: 44px` が設定されており、高さが縮小されるのではなく水平方向のパディングが 12px に縮小されるため、幅が狭い場合でも 44px の下限が維持されます。 タブリストは `flex-wrap: nowrap`、`overflow-x: auto`、子要素に `flex: 1 0 auto` を設定します。これにより、3つのタブは、コントロールの中途で切り取られたり折り返されたりすることなく、タブリスト内に収まるか、スクロールして表示されます。 が設定されています。実際の 390px のビューポートでは検証されていません。.
水平方向のオーバーフロー — 確認済み、意図的に範囲内に収められたスクロールが1か所
body { overflow-x: hidden } が最終手段ですが、これだけに頼らないようにも試みました。* { box-sizing: border-box } を指定することで、パディングを宣言された幅内に収めることができます。 比較表ではセルに `white-space: nowrap` を適用しているため、6列の「概要」表はモバイル環境で358pxを超えてしまいます。これは `.table-scroll { max-width: 100%; overflow-x: auto }` によって収められており、ページ全体ではなく表領域のみがスクロールされるようになっています。 このラッパーには tabindex="0" と role="region" が設定され、ラベルも付いているため、キーボードユーザーでも操作やスクロールが可能です。通常は縮小を拒否する可能性のある Flex や Grid の子要素については、グリッド上で minmax(0, 1fr) を適用し、.card-head および .recommendation には flex-wrap: wrap を適用して処理しています。 レンダリングを行わずに完全に排除できない唯一のリスクは、テーブルセル内に長い連続した文字列が含まれる場合ですが、すべてのフィクスチャ値は短いものです。.
外部依存関係 — 確認済み、なし
いいえ <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step.
コントラストと動き — 確認済み
#f6f7f9上の本文テキスト#16191fと、白地上のサブテキスト#4a515cは、いずれも4.5:1を十分に上回っています。 バッジは#10457eを背景に白で表示され、アクティブなタブは白を背景に#10457eで表示されています。 これらはコントラスト測定ツールではなく、16進数値からの比率推定によって算出しました。どこにもトランジション、アニメーション、変形は存在しません。「prefers-reduced-motion」ブロックは、既存の動きに対する修正ではなく、何もしない安全策として設定されています。.
フィクスチャの精度 — 検査済み
3つのプランはそれぞれ、3つのパネルすべてと、各パネルの表に記載されています。価格、プロジェクト数、ストレージ容量、サポートレベルについて、JSON: Atlasと照合しました。
19
/
20
𝑝
𝑟
𝑜
𝑗
𝑒
𝑐
𝑡
𝑠
/
10
𝐺
𝐵
/
𝐸
𝑚
𝑎
𝑖
𝑙
,
𝐵
𝑒
𝑎
𝑐
𝑜
𝑛
49/無制限/100 GB/優先、Cove $99/無制限/1 TB/専用。 Beaconには「総合ベスト」バッジと2pxのアクセント枠が適用されています。AtlasとCoveは不透明度100%のテキスト、通常の枠、同一の書式設定を維持しているため、無効ではなく「利用可能」と認識されます。コストパフォーマンスに優れた製品は短いラベル(「ソロ作業に最適」)として表示されます。これは、製品仕様の値の周囲に文言を追加したものであり、新たな製品主張は含まれていません。.
既知の課題
実行時の検証は一切行われません。3つのパネルの内容は、JSONからレンダリングされるのではなく、静的なマークアップとして各パネルに複製されているため、このフィクスチャはバインディングによるものではなく、転記による「真実の源」となります。将来データが変更された場合、複数の箇所を編集する必要があります。.

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compare plans — Atlas, Beacon, Cove</title>
<style>
  :root
 {
    --bg: #f6f7f9
;
    --surface: #ffffff
;
    --ink: #16191f
;
    --ink-soft: #4a515c
;
    --line: #d3d8df
;
    --line-strong: #b6bdc7
;
    --accent: #10457e
;
    --accent-soft: #e8f0f9
;
    --focus: #0b2f56
;
    --radius: 10px
;
  }

  * {
box-sizing
: border-box; }

  html { -webkit-text-size-adjust: 100%
; }

  body
 {
    margin: 0
;
    padding: 0
;
    background: var
(--bg);
    color: var
(--ink);
    font-family: system-ui, -apple-system, "Segoe UI"
, Roboto, Helvetica, Arial, sans-serif;
    font-size: 16px
;
    line-height: 1.5
;
    overflow-x
: hidden;
  }

  .wrap
 {
    width: 100%
;
    max-width: 1120px
;
    margin: 0
 auto;
    padding: 32px 24px 64px
;
  }

  /* ---------- Header ---------- */

  .page-header { margin-bottom: 24px
; }

  .page-header h1
 {
    margin: 0 0 8px
;
    font-size: 1.75rem
;
    line-height: 1.25
;
    letter-spacing: -0.01em
;
  }

  .page-header p
 {
    margin: 0
;
    max-width: 60ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Recommendation ---------- */

  .recommendation
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 4px 10px
;
    align-items
: baseline;
    margin: 0 0 28px
;
    padding: 14px 16px
;
    background: var
(--accent-soft);
    border: 1px solid #c2d5e8
;
    border-left: 4px solid var
(--accent);
    border-radius: var
(--radius);
  }

  .recommendation strong { color: var
(--accent); }

  .recommendation span { color: #23405e
; }

  /* ---------- Tabs ---------- */

  .tabs
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    margin: 0 0 20px
;
    padding: 0
;
    border-bottom: 1px solid var
(--line);
  }

  [role="tab"]
 {
    appearance
: none;
    min-height: 44px
;
    padding: 10px 18px
;
    font
: inherit;
    font-weight: 600
;
    color: var
(--ink-soft);
    background
: transparent;
    border: 1px
 solid transparent;
    border-bottom: 3px
 solid transparent;
    border-radius: 8px 8px 0 0
;
    cursor
: pointer;
  }

  [role="tab"]:hover { color: var(--ink); background: #eceff3
; }

  [role="tab"][aria-selected="true"]
 {
    color: var
(--accent);
    background: var
(--surface);
    border-color: var(--line) var(--line) var
(--accent);
    border-bottom-width: 3px
;
  }

  :focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 2px
;
  }

  [role="tabpanel"] { outline
: none; }

  [role="tabpanel"]:focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 4px
;
    border-radius: var
(--radius);
  }

  [hidden] { display: none !important
; }

  .panel-intro
 {
    margin: 0 0 20px
;
    max-width: 62ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Cards ---------- */

  .card-grid
 {
    display
: grid;
    grid-template-columns: repeat(3, minmax(0, 1
fr));
    gap: 20px
;
    margin: 0
;
    padding: 0
;
    list-style
: none;
    align-items
: start;
  }

  .card
 {
    display
: flex;
    flex-direction
: column;
    height: 100%
;
    padding: 20px
;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  .card.is-featured
 {
    border-color: var
(--accent);
    border-width: 2px
;
    padding: 19px
;
  }

  .card-head
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    align-items
: center;
    justify-content
: space-between;
    margin-bottom: 4px
;
  }

  .card h3
 {
    margin: 0
;
    font-size: 1.2rem
;
  }

  .badge
 {
    padding: 3px 10px
;
    font-size: 0.75rem
;
    font-weight: 700
;
    letter-spacing: 0.02em
;
    text-transform
: uppercase;
    color: #ffffff
;
    background: var
(--accent);
    border-radius: 999px
;
    white-space
: nowrap;
  }

  .price
 {
    margin: 8px 0 2px
;
    font-size: 1.6rem
;
    font-weight: 700
;
    letter-spacing: -0.02em
;
  }

  .best-for
 {
    margin: 0 0 14px
;
    font-size: 0.9375rem
;
    color: var
(--ink-soft);
  }

  .spec-list
 {
    margin: 0
;
    padding: 14px 0 0
;
    border-top: 1px solid var
(--line);
    font-size: 0.9375rem
;
  }

  .spec-list div
 {
    display
: flex;
    gap: 12px
;
    justify-content
: space-between;
    padding: 5px 0
;
  }

  .spec-list dt { color: var
(--ink-soft); }

  .spec-list dd
 {
    margin: 0
;
    font-weight: 600
;
    text-align
: right;
  }

  /* ---------- Table ---------- */

  .table-section { margin-top: 36px
; }

  .table-section h2
 {
    margin: 0 0 12px
;
    font-size: 1.125rem
;
  }

  .table-scroll
 {
    max-width: 100%
;
    overflow-x
: auto;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  table
 {
    width: 100%
;
    border-collapse
: collapse;
    font-size: 0.9375rem
;
  }

  caption
 {
    padding: 12px 14px
;
    text-align
: left;
    color: var
(--ink-soft);
    font-size: 0.875rem
;
  }

  th, td
 {
    padding: 10px 14px
;
    text-align
: left;
    border-top: 1px solid var
(--line);
    white-space
: nowrap;
  }

  thead th
 {
    background: #eef1f5
;
    border-top
: none;
    font-weight: 700
;
  }

  tbody th { font-weight: 600; color: var
(--ink-soft); }

  th[scope="col"].is-featured { color: var
(--accent); }

  /* ---------- Mobile ---------- */

  @media (max-width: 720px
) {
    .wrap { padding: 20px 16px 48px
; }

    .page-header h1 { font-size: 1.4rem
; }

    .tabs
 {
      gap: 4px
;
      overflow-x
: auto;
      -webkit-
overflow
-scrolling: touch;
      flex-wrap
: nowrap;
    }

    [role="tab"]
 {
      flex: 1 0
 auto;
      padding: 10px 12px
;
      font-size: 0.9375rem
;
    }

    .card-grid { grid-template-columns: minmax(0, 1
fr); }

    th, td { padding: 10px 12px
; }
  }

  @media (prefers-reduced-motion
: reduce) {
    * {
transition: none !important; animation: none !important
; }
  }
</style>
</head>
<body>
<main class="wrap">

  <header class="page-header">
    <h1>Compare plans</h1>
    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>
  </header>

  <p class="recommendation">
    <strong>Recommended: Beacon</strong>
    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>
  </p>

  <div class="tabs" role="tablist" aria-label="Plan comparison views">
    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>
    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>
  </div>

  <!-- Overview -->
  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>All plans at a glance</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">
        <table>
          <caption>Published facts for Atlas, Beacon, and Cove.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">Atlas</th>
              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>
            </tr>
            <tr>
              <th scope="row">Beacon</th>
              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>
            </tr>
            <tr>
              <th scope="row">Cove</th>
              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Pricing -->
  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>
    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Price and support</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">
        <table>
          <caption>Monthly price, support tier, and intended fit.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>
            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>
            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Limits -->
  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>
    <p class="panel-intro">Project counts and storage allowances for each plan.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Projects and storage</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">
        <table>
          <caption>Project allowance and storage per plan.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>
            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>
            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

</main>

<script>
(
function (
) {
  'use strict'
;

  var tablist = document.querySelector('[role="tablist"]'
);
  if (!tablist) return
;

  var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'
));

  function panelFor(tab
) {
    return document.getElementById(tab.getAttribute('aria-controls'
));
  }

  function activate(index, moveFocus
) {
    if (index < 0 || index >= tabs.length) return
;

    tabs.
forEach(function (tab, i
) {
      var
 selected = i === index;
      var panel = panelFor
(tab);

      tab.
setAttribute('aria-selected', selected ? 'true' : 'false'
);
      tab.
setAttribute('tabindex', selected ? '0' : '-1'
);

      if
 (panel) {
        if
 (selected) {
          panel.
removeAttribute('hidden'
);
        }
else
 {
          panel.
setAttribute('hidden', ''
);
        }
      }
    });

    if (moveFocus !== false) tabs[index].focus
();
  }

  function currentIndex(
) {
    var i = tabs.findIndex(function (tab
) {
      return tab.getAttribute('aria-selected') === 'true'
;
    });
    return i === -1 ? 0
 : i;
  }

  tabs.
forEach(function (tab, i
) {
    tab.
addEventListener('click', function (
) {
      activate
(i);
    });
  });

  tablist.
addEventListener('keydown', function (event
) {
    var last = tabs.length - 1
;
    var i = currentIndex
();
    var next = null
;

    switch (event.key
) {
      case 'ArrowRight'
:
        next = i === last ?
0 : i + 1
;
        break
;
      case 'ArrowLeft'
:
        next = i ===
0 ? last : i - 1
;
        break
;
      case 'Home'
:
        next =
0
;
        break
;
      case 'End'
:
        next = last;
        break
;
      default
:
        return
;
    }

    event.
preventDefault
();
    activate
(next);
  });

  // Normalize initial state from markup.
  activate(currentIndex(), false
);
}());
</script>
</body>
</html>
```

SELF-CHECK
All statements below come from code inspection only. I did not open a browser, render a viewport, run a screen reader, or execute the keyboard handlers, so nothing here is runtime-verified. Where a claim depends on layout engine behavior, I say so.
Semantic tabs — inspected, consistent
One div[role="tablist"] with aria-label="Plan comparison views" holds three button[type="button"][role="tab"]. Each tab has a unique id and an aria-controls pointing at a section[role="tabpanel"]; each panel carries aria-labelledby pointing back at its tab. I traced all three pairs by hand: tab-overview/panel-overview, tab-pricing/panel-pricing, tab-limits/panel-limits. No duplicate IDs, no dangling references. Panels use tabindex="0" so the panel body is reachable after the tab.
Keyboard behavior — inspected, not executed
A single keydown listener on the tablist handles ArrowRight, ArrowLeft, Home, and End, calls event.preventDefault() for those four keys only, and returns early otherwise. Arrow keys wrap at both ends. Because activate() both updates aria-selected/tabindex/hidden and moves focus, arrow and Home/End keys move andactivate in one step, which is the automatic-activation pattern the requirement asks for. Tab/Shift+Tab traversal relies on roving tabindex: exactly one tab is tabindex="0", the rest -1, maintained by activate(). Focus visibility comes from a global :focus-visible rule with a 3px outline and 2px offset; I did not override or remove any default outline. I have not confirmed key handling in a real browser.
Selected-state reflection — inspected
activate() sets all three signals in the same loop, so aria-selected="true", tabindex="0", and the absence of hidden cannot drift apart. Inactive panels get the hidden attribute, and [hidden] { display: none !important; } guards against the display rules that would otherwise defeat it — that guard matters because the panels contain display: grid children. activate(currentIndex(), false) runs on load to normalize state from markup without stealing focus. If JavaScript does not run, the markup ships with Overview selected and the other two panels hidden, so the page degrades to one readable panel.
1440px layout — inspected, not rendered
.wrap is max-width: 1120px with margin: 0 auto, so at 1440px the content centers with roughly 160px gutters rather than stretching. Cards use grid-template-columns: repeat(3, minmax(0, 1fr)) with a 20px gap, giving three equal columns; align-items: start keeps cards from stretching to a shared height while .card { height: 100% } is neutralized by that. The minmax(0, 1fr) is deliberate — 1fralone can refuse to shrink below content width and push a grid wide. I did not measure actual pixel output.
390px layout — inspected, not rendered
The max-width: 720px block switches the card grid to minmax(0, 1fr), a single column, so cards stack. Padding drops to 16px per side, leaving about 358px of content width. Tap targets: every [role="tab"] has min-height: 44px, and horizontal padding shrinks to 12px rather than the height shrinking, so the 44px floor holds at narrow widths. The tablist becomes flex-wrap: nowrap with overflow-x: auto and flex: 1 0 auto children, so three tabs either fit or scroll within the tablist itself instead of being clipped or wrapped mid-control. <meta name="viewport" content="width=device-width, initial-scale=1"> is present. Not verified at an actual 390px viewport.
Horizontal overflow — inspected, one intentional contained scroll
body { overflow-x: hidden } is the backstop, but I also tried not to rely on it. * { box-sizing: border-box } keeps padding inside declared widths. The comparison tables use white-space: nowrap on cells, so the six-column Overview table will exceed 358px on mobile; that is contained by .table-scroll { max-width: 100%; overflow-x: auto }, which scrolls the table region rather than the page. That wrapper has tabindex="0" and role="region" with a label so keyboard users can reach and scroll it. Flex and grid children that could otherwise refuse to shrink are handled with minmax(0, 1fr) on the grid and flex-wrap: wrap on .card-head and .recommendation. The one remaining risk I cannot rule out without rendering is a long unbroken string in a table cell, but all fixture values are short.
External dependencies — inspected, none
No <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step.
Contrast and motion — inspected
Body text #16191f on #f6f7f9 and secondary #4a515c on white are both well clear of 4.5:1; the badge is white on #10457e, and the active tab is #10457e on white. I computed these by ratio estimate from the hex values, not with a contrast tool. There are no transitions, animations, or transforms anywhere; the prefers-reduced-motion block is a no-op safety net rather than a fix for existing motion.
Fixture fidelity — inspected
Each of the three plans appears in all three panels plus each panel's table. I cross-checked every price, project count, storage figure, and support tier against the JSON: Atlas
19
/
20
𝑝
𝑟
𝑜
𝑗
𝑒
𝑐
𝑡
𝑠
/
10
𝐺
𝐵
/
𝐸
𝑚
𝑎
𝑖
𝑙
,
𝐵
𝑒
𝑎
𝑐
𝑜
𝑛
49/Unlimited/100 GB/Priority, Cove $99/Unlimited/1 TB/Dedicated. Beacon carries the Best overall badge and a 2px accent border; Atlas and Cove keep full-opacity text, normal borders, and identical type treatment, so they read as available rather than disabled. The best for values are rendered as short labels ("Best for solo work") — wording added around the fixture value, no new product claims.
Known gaps
No runtime verification of any kind. Panel content is duplicated across the three panels as static markup rather than rendered from the JSON, so the fixture is the source of truth by transcription, not by binding — a future data change means editing several places.

T4:自己検証

合格 — 独自の監査中に空配列のNaNバグを発見し、1回修正を行い、提示されたすべてのケースについて確認を完了した。.

Claude Opus 5 実践的な自己検証結果
独自の監査で、空の配列に対するNaNという結果を検出しました。N/Aを返すよう一度修正し(0/0で通過)、修正後に提示された4つのケースすべてを確認しました。.
T4のプロンプトと回答の全文を表示する
プロンプト全文
番号が振られたこの制約付き課題を完了させ、その後、必要に応じて一度だけ監査を行い、修正してください。

課題の制約:
1. `summarizeChecks(checks)` という名前の純粋な JavaScript 関数を記述してください。`checks` はブール値の配列です。
2. 入力が空でない場合、正確に `% (/ passed)` を返してください。ここで、`rate` は小数点以下1桁で、`true` である値の割合を表します。 例:`[true, true, false, true]` に対しては `75.0% (3/4 passed)` を返します。
3. 入力を変更してはいけません。
4. `for`、`while`、`forEach`、`eval`、外部ライブラリ、および 2 つ目の関数を使用してはいけません。
5. 関数本体には、最大3つの文を含めることができます。初期化子を含む宣言は、1つの文としてカウントされます。
6. 独立したテスト環境から呼び出せるように、関数の宣言後に `globalThis.summarizeChecks` にその関数を代入してください。

必要な回答形式:
- `FIRST ANSWER`: 監査を行う前に、最初の解答を1つのフェンス付き `js` ブロック内に記述してください。
- `AUDIT`: 最初の解答が制約条件1~6および以下の隠れたエッジケースを満たしているか確認してください:空の入力に対しては、正確に `N/A (0/0 passed)` を返さなければなりません。各項目について合格/不合格を明記してください。
- 監査項目で不合格となったものがあれば、1回に限り修正を行ってください。2回以上修正してはなりません。
- `FINAL ANSWER`: 最終的な解決策を、1つのフェンスで囲まれた `js` ブロック内に記述してください。空の入力を扱うエッジケースを満たしつつ、元の制約をすべて維持してください。

監査では、以下の独立したチェックケースを使用してください:
```text
[] -> N/A (0/0 合格)
[true] -> 100.0% (1/1 合格)
[false] -> 0.0% (0/1 合格)
[true, true, false, true] -> 75.0% (3/4 合格)
```
Claude Opus 5

最初の回答

js
function summarizeChecks(checks) {  const total = checks.length;  const passed = checks.filter(Boolean).length;  return `${((合格数 / 総数) * 100).toFixed(1)}% (${合格数}/${総数} 合格)`;} globalThis.summarizeChecks = summarizeChecks;
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${((passed / total) * 100).toFixed(1)}% (${passed}/${total} passed)`;
}

globalThis.summarizeChecks = summarizeChecks;

監査

#
制約
結果
1
summarizeChecks(checks) という名前のプレーン関数
PASS — 単純な宣言、引数は1つ、クラスや矢印ラッパーはなし。.
2
形式 % (/ 合格)、小数点以下1桁の率
空でない入力に対するPASS — toFixed(1) によって小数点の位置が固定され、リテラルでのスペースの配置も仕様と完全に一致しています。.
3
入力の変異なし
PASS — .length と .filter はどちらも読み取り専用です。filter は新しい配列を返します。.
4
No for、while、forEach、eval、library、または second 関数
PASS — .filter は唯一の反復処理であり、Boolean は述語の参照として使用される組み込み変数であり、私が定義した関数ではありません。.
5
本文には最大3つの文を含めること
PASS — 正確に3つ:初期化された宣言が2つと、return文。.
6
宣言後に globalThis.summarizeChecks に割り当てられた
PASS — 宣言の直後に代入文が続きます。.
独立したチェックの事例:
インプット
予想される

結果
[]
該当なし(合格者 0/0)
NaN% (合格数 0/0)
失敗
[true]
100.0%(1/1 合格)
100.0%(1/1 合格)
PASS
[false]
0.0%(合格数:0/1)
0.0%(合格数:0/1)
PASS
[真、真、偽、真]
75.0%(3/4合格)
75.0%(3/4合格)
PASS
1つの失敗。空の入力(0/0)が渡されたため、結果はNaNとなります。NaN.toFixed(1)は例外をスローするのではなく、文字列「NaN」を返すため、この関数はNaN%(0/0が渡された)を黙って出力します。.
1回修正します。修正内容は既存のreturn文内に条件式として残るため、ステートメント数は変わりません。%という記号は、空でない分岐内に移動します。これは、期待される空の出力がN/A(0/0が通過)であり、パーセント記号が含まれないためです。.

最終回答

js
function summarizeChecks(checks) {  const total = checks.length;  const passed = checks.filter(Boolean).length;  `$`を返す{total === 0 ? 'N/A' : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} 合格)`;} globalThis.summarizeChecks = summarizeChecks;
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${total === 0 ? 'N/A' : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} passed)`;
}

globalThis.summarizeChecks = summarizeChecks;

4つのケースすべてにおける修正後の確認結果:[] → 該当なし(0/0 合格)、[true] → 100.0%(1/1 合格)、[false] → 0.0%(0/1 合格)、 [true, true, false, true] → 75.0% (3/4 合格)。本体は3つの文のままであり、入力も変更されておらず、禁止された構文も導入されていない。.

最初の回答

```js
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${((passed / total) * 100).toFixed(1)}% (${passed}/${total} passed)`;
}

globalThis.summarizeChecks = summarizeChecks;
```

監査
#
制約
結果
1
summarizeChecks(checks) という名前のプレーン関数
PASS — プレーンな宣言、引数は1つ、クラスや矢印関数によるラップなし。
2
形式 % (/ passed)、小数点以下1桁の率
空でない入力の場合 PASS — toFixed(1) により小数点の位置が固定され、リテラル間のスペースも仕様に完全に一致している。
3
入力の変更なし
PASS — .length と .filter はどちらも読み取り専用であり、filter は新しい配列を返す。
4
for、while、forEach、eval、ライブラリ、または 2 つ目の関数がない
PASS — .filter が唯一の反復処理であり、Boolean は述語参照として使用される組み込み関数であり、私が定義した関数ではない。
5
本体内の文は最大3つ
PASS — 正確に3つ:初期化された宣言2つとreturn文。
6
宣言後にglobalThis.summarizeChecksに代入
PASS — 代入はトップレベルでの宣言に続く。
独立したチェックケース:
入力
期待値
実測値
結果
[]
N/A (0/0 合格)
NaN% (0/0 合格)
FAIL
[true]
100.0% (1/1 合格)
100.0% (1/1 合格)
PASS
[false]
0.0% (0/1 合格)
0.0% (0/1 合格)
PASS
[true, true, false, true]
75.0% (3/4 合格)
75.0% (3/4 合格)
PASS
1件の失敗。空の入力に対して「合格」と判定され、合計が0/0となり、これはNaNとなる。NaN.toFixed(1)は例外をスローするのではなく文字列「NaN」を返すため、関数は黙ってNaN%(0/0 合格)を出力してしまう。
1回修正。修正内容は既存のreturn文内の条件式として追加されるため、文数は変わらない。期待される空の出力はパーセント記号のない「N/A(0/0 合格)」であるため、%という表記は非空の分岐内に移動する。
最終解答

```js
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${total === 0 ? "N/A" : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} passed)`;
}

globalThis.summarizeChecks = summarizeChecks;
```

4つのケースすべてにおける修正後の確認結果: [] → N/A (0/0 合格)、[true] → 100.0% (1/1 合格)、 [false] → 0.0% (0/1 合格)、[true, true, false, true] → 75.0% (3/4 合格)。本体は3つの文のままであり、入力も変更されておらず、禁止された構文も導入されていない。.

複数のベンダーから選択するチームであっても、自社のリポジトリ、ツールスタック、およびレビューの負担については、依然として検証を行う必要があります。より広範な Claude と ChatGPT のコーディング比較 この単一の結果にとどまらず、そうしたトレードオフを整理するのに役立つ。.

Claude Opus 5 対 Opus 4.8 対 Fable 5

Opus 5を最も端的に理解するならば、それは「新たなプレミアム・ワークホース」であると言えます。 Opus 4.8はその前身であり、Fable 5は依然として最先端のベンチマークです。Anthropicの発表資料によると、Opus 5はOpus 4.8と同等の基本コストを維持しつつ、特定の評価項目においてFable 5に迫る性能を発揮し、タスクあたりのコストを大幅に削減しています。.

モデル役職コストパフォーマンス指標ベストフィット
Claude Opus 5プレミアムな日常使いモデル;Opus 4.8の後継機種入出力MTokあたり$5/$25;Anthropicが公表したタスクあたりのコストに関する確かな結果複雑なコーディング、自動化、そして信頼性が求められる企業向け業務
クロード 作品4.8前のOpus世代Anthropicの発売時の比較によると、基本価格はOpus 5と同じである移行の検証がまだ必要な、既存の固定済みワークフロー
クロード・フェイブル 5フロンティア・インテリジェンス・ティアピークの基準点:Anthropicによると、Opus 5はCursorBenchにおいて、タスクあたりのコストが半分でありながら、それに迫る性能を発揮している経済性よりも最大限の性能が重視される場合、最も困難な課題とは

移行の回帰テストが可能で、ベースAPIレートを引き上げずに新しいモデルを導入したい場合は、Opus 4.8ではなくOpus 5を選択してください。独自の評価の結果、追加機能によって結果に十分な変化が見られ、追加費用を正当化できると判断した場合は、Fable 5を選択してください。 Sonnet 5も含めた最新のファミリー別内訳については、 Claude Opus 5 対 Fable 5 対 Sonnet 5 の比較.

開発者や業界の反応

ソーシャルメディア上の投稿は、初期の利用状況に関する有用な手がかりとなるが、中立的な指標というわけではない。Claudeの公式アカウントは、Opus 5について「考え抜かれた設計で先見性があり、Fable 5の最先端のインテリジェンスに匹敵する性能を半額で実現している」と評している。これはAnthropic自身の発売時のポジショニングであり、独立した裏付けではない。.

2026年7月24日、ClaudeがClaude Opus 5の発表を行ったオリジナルのX投稿
Claudeは、X上で「Opus 5」を発表し、これをFable 5のAI機能に匹敵する性能を持ちながら、価格は半額という、考え抜かれた先見性のあるモデルとして位置づけた。.

JetBrainsは、自社の評価結果によると、 45%はOpus 4.8に比べてPythonの合格率がより高い, 、さらにコードベースに対する理解の深化も伴います。これは開発者向けツールを提供する企業による具体的かつ適切な指摘ですが、この結果はJetBrainsによる評価に基づくものであり、すべてのPythonベンチマークやリポジトリに一般化すべきではありません。.

JetBrains Xの投稿によると、Claude Opus 5の導入により、Pythonの合格率が向上し、コードベースへの理解が深まったとのこと
JetBrainsによると、同社の評価では、Pythonの合格率がOpus 4.8と比較して45%向上し、コードベースの理解度も深まったことが示された。.

ハーヴェイ社は、コーポレート・ガバナンスや仲裁を含む法務ワークフロー全般において、Opus 4.8と比較して品質とトークン効率が大幅に向上したと報告した。これはリーガルテクノロジーの購入者にとって意義深いものだが、あくまでハーヴェイ社が自社の業務分野におけるワークフローについて行った評価であり、法的な正確性が普遍的に保証されているという証拠ではない。.

Harvey Xの投稿によると、法的業務の品質とトークンの効率性においてClaude Opus 5の向上が報告されている
ハーヴェイ社は、コーポレート・ガバナンスや仲裁を含む法務業務の品質とトークンの効率性において、Opus 5による改善が見られたと報告している。.

これらの投稿を総合すると、アーリーアダプターたちは、コードベースの理解度やドメイン固有の知識に基づく業務において改善が見られることに気づき始めていることがうかがえます。責任ある次のステップとしては、独自の受け入れテスト、トークン予算、および人間によるレビュープロセスを備えた、代表的なパイロットテストを実施することが依然として重要です。.

Claude Opus 5 API:モデル ID、使用例、および移行に関する注意事項

Claudeの公式APIモデルIDとエイリアスは、いずれも claude-opus-5. 以下は最小限の アンソロピックAPI リクエストの例です。これは公式の「Messages」エンドポイントのみを示したものであり、GlobalGPTのバックエンド実装について説明したり保証したりするものではありません。.

curl https://api.anthropic.com/v1/messages \
  --header "x-api-key: $ANTHROPIC_API_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --header "content-type: application/json" \
  --data '{
    "model": "claude-opus-5",
    "max_tokens": 1024,
    "messages": [
 {
 "role": "user",
 "content": "根本原因を特定し、最小限の修正案を提案し、検証コマンドを出力してください。"
      }
    ]
  }'

移行チェックリスト

  • モデルの値を次のように変更してください。 claude-opus-5, 、その後、独自の回帰分析および安全性評価を再度実行してください。.
  • MTokあたり$5の入力と$25の出力を基準に予算を設定し、出力負荷の高いエージェントループやツールの再試行を監視する。.
  • 旧来の慣習を引き継がないでください thinking.type: "enabled" 設定。. Anthropicの思考ガイド 「Opus 5についてはすでに検討が進められている」と述べ、適応型設定に関する資料を提示している。.
  • 128Kを、同期型メッセージAPIの最大出力として扱ってください。別の「メッセージバッチ(ベータ版)」では、Anthropicのドキュメントに記載されているベータ版ヘッダーを使用することで、最大300Kまで対応可能です。.
  • プロバイダー固有のモデル名とアクセス権を確認してください。Anthropicのドキュメント anthropic.claude-opus-5 Amazon Bedrock および claude-opus-5 Google Cloud向け。.

Claude Codeと並行してコマンドラインでのワークフローを利用したい開発者のための、実用的なセットアップガイドはこちらです。 ClaudeコードでGlobalGPT CLIを使用する方法. 上記の公式な Anthropic API のサンプルとは、そのワークフローを区別して、認証情報、課金、およびプロバイダーの動作が明確になるようにしてください。.

Claude Opus 5は買う価値があるか?

そうですね――失敗の代償が大きく、業務内容が本当に難しい場合です。. Opus 5は、より精度の高い診断、ツールの活用、あるいは長期的な文脈に基づく判断によって、エンジニアやアナリストの時間を節約できる場合に、その真価を発揮します。100万トークンのコンテキストウィンドウ、128Kの同期出力上限、そしてタスクあたりのコストに関する魅力的な主張が相まって、信頼性の高い「プレミアム・ワークホース」としての地位を確立しています。.

Claude Opus 5はどのような方に適していますか?

  • 大規模なリポジトリに対してコーディングエージェントを実行しているエンジニアリングチーム。.
  • 運用チームが、測定可能な受け入れ基準に基づき、多段階の業務タスクを自動化しています。.
  • モデルと、専門分野のレビューやリアルタイムの情報源を組み合わせることができる、法務、財務、または研究チーム。.
  • キャッシュ、バッチ処理、ルーティング、回帰テストを活用してコストを管理できる開発者。.

誰が別のものを選ぶべきでしょうか?

  • 単純な抽出、分類、あるいは短縮形の書き換えが中心となる、処理量が多いアプリケーション。.
  • 適度なモデルでは処理速度が不足してしまう、レイテンシに敏感な製品。.
  • 評価用データセット、コスト管理、あるいは重要な成果物に対する人間によるレビュー計画がないチーム。.
  • たまに雑談をするだけで、追加のコンテキスト機能やエージェント機能は利用しない購入者。.

Opus 5が高すぎる、あるいは専門的すぎると感じる場合は、 2026年向けのClaude AI代替製品. 市場全体を俯瞰するには、以下のガイドをご覧ください。 実世界のユースケースに最適なAIモデル ワークロードをモデルクラスに適切に割り当てるのに役立ちます。.

開発担当者は、チームのワークフローを標準化する前に、現在の選択肢を比較検討すべきです。その 2026年にプログラミングに最適なAIモデル 性能と価格をより広い視点で捉える。.

最終的な結論: Claude Opus 5は、ハードコーディング、自動化、および知識労働といったタスクにおいて、優れた結果がプレミアムトークンのコストを上回る場合、試してみる価値があります。その公式仕様は堅実であり、Anthropicのベンチマーク結果はコスト効率の面で際立っており、当社が検証したデバッグ結果も正確かつ的確でした。 すべてのタスクにOpusクラスのモデルが必要だからという理由ではなく、測定可能な成果が得られる困難な作業のために購入すべきです。.

Claude Opus 5 よくある質問

Claude Opus 5の価格はいくらですか?

Claude APIの公式基本料金は、入力トークン100万単位あたり$5、出力トークン100万単位あたり$25です。 コンシューマー向けClaudeプランは別途設定されています。Proプランは月額$20、年額払い場合は月額$17、Maxプランは月額$100からとなっています。.

Claude Opus 5にはどのようにアクセスすればよいですか?

Anthropicによると、Opus 5はClaude Maxのデフォルトモデルであり、Claude Proでは最も高性能なモデルとなっています。開発者はClaude APIを利用でき、対応するクラウドルートにはAmazon BedrockやGoogle Cloudが含まれますが、プロバイダーごとにアクセス要件が異なります。.

Claude Opus 5 APIモデルのIDは何ですか?

Claude APIの公式モデルIDおよびエイリアスは、いずれも「claude-opus-5」です。Anthropic Messages APIのリクエストにおいて、modelフィールドにはこの値を正確に入力し、本番環境への移行前に、独自の回帰テストおよび安全性評価を再度実行してください。.

Claude Opus 5のコンテキストおよび出力制限とは何ですか?

Claude Opus 5 は、同期型 Messages API において、100 万トークンのコンテキストウィンドウと、最大 128,000 トークンの出力に対応しています。Anthropic については、ベータヘッダー付きのメッセージバッチにおいて、最大 300,000 トークンの出力が可能であることが別途記載されています。.

Claude Opus 5のベンチマーク結果は、独立した機関によって検証されていますか?

ここで引用されているベンチマーク数値は、Anthropicによって公表されたものであり、本レビューのために独自に再現されたものではありません。これらはAnthropicがテストした性能とコストの状況を示していますが、購入を検討される方は、ご自身のワークロードにおいて、品質、レイテンシ、ツールの使用状況、および総コストを検証する必要があります。.

Claude Opus 5は、Opus 4.8やFable 5よりも優れていますか?

Opus 5は、Opus 4.8の後継モデルであり、基本コストは同等であるため、回帰テスト後の移行先として最適な選択肢となります。Fable 5は依然として最先端の基準モデルであり、評価の結果、その追加機能がコスト増を正当化すると判断された場合にのみ選択してください。.

Claude Opus 5はGlobalGPTで利用可能ですか?

はい。GlobalGPTには、Claude Opus専用の5ページが用意されています。利用可否はアカウントの状態やプラットフォームの状況によって異なる場合がありますので、時間的制約のあるワークフローを実行する前にアクセス可能かどうかを確認し、プラットフォームへのアクセスと公式のAnthropic APIの課金を区別して管理してください。.

Claude Opus 5の費用は誰が負担すべきか?

Opus 5は、難易度の高いコーディングや自動化、あるいは長期的な文脈を要するナレッジワークなどのタスクを処理するチームに最適です。こうしたタスクでは、より優れた回答が得られることで、人的リソースの貴重な時間を大幅に節約できます。一方、より単純で処理量が多いタスクや、応答速度が重要なタスクについては、通常、より安価で高速なモデルが適しています。.

記事を共有する

関連記事