@clubs.place/cli 0.0.0-stage → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +88 -0
- package/LICENSE +21 -0
- package/PROVENANCE.json +77 -0
- package/README.md +70 -2
- package/bin/clubs-nippo +7 -0
- package/bin/clubs-nippo-web.mjs +338 -0
- package/bin/clubs-nippo.mjs +527 -0
- package/docs/events-schema.md +76 -0
- package/examples/hermes-events.sample.jsonl +8 -0
- package/package.json +48 -4
- package/src/aggregate.mjs +105 -0
- package/src/autorun.mjs +25 -0
- package/src/autorun.test.mjs +43 -0
- package/src/cards.mjs +406 -0
- package/src/collect.mjs +111 -0
- package/src/config.mjs +173 -0
- package/src/generators/claude.mjs +31 -0
- package/src/generators/cli.mjs +81 -0
- package/src/generators/codex.mjs +28 -0
- package/src/generators/copilot.mjs +21 -0
- package/src/generators/gemini.mjs +20 -0
- package/src/generators/openai-compat.mjs +79 -0
- package/src/generators/openrouter.mjs +65 -0
- package/src/history.mjs +66 -0
- package/src/ingest.mjs +78 -0
- package/src/lemma.docHash.test.mjs +37 -0
- package/src/lemma.mjs +303 -0
- package/src/mask.mjs +45 -0
- package/src/mcp.mjs +269 -0
- package/src/narrative.mjs +191 -0
- package/src/prompt.mjs +184 -0
- package/src/prompt.test.mjs +146 -0
- package/src/remote-config.mjs +72 -0
- package/src/render.mjs +467 -0
- package/src/send.mjs +36 -0
- package/src/settings.mjs +54 -0
- package/src/sources/claude-code.mjs +174 -0
- package/src/sources/codex-cli.mjs +182 -0
- package/src/sources/copilot-cli.mjs +125 -0
- package/src/sources/cowork.mjs +193 -0
- package/src/sources/events-file.mjs +120 -0
- package/src/sources/gemini-cli.mjs +128 -0
- package/src/sources/hermes.mjs +427 -0
- package/src/store.mjs +227 -0
- package/src/tasks.mjs +229 -0
- package/src/tool-name.mjs +28 -0
- package/templates/report-v3.reference.html +162 -0
- package/web/assets/logo-clubs-white.png +0 -0
- package/web/assets/logo-clubs-white.svg +7 -0
- package/web/assets/logo-clubs-white.svg.tmp +30 -0
- package/web/assets/logo-clubs.svg +30 -0
- package/web/assets/qr.js +411 -0
- package/web/assets/sidebar.js +154 -0
- package/web/assets/twemoji.js +34 -0
- package/web/cards/achievements.html +230 -0
- package/web/cards/catalog.json +217 -0
- package/web/email/hero-v3.reference.html +123 -0
- package/web/home/index.html +269 -0
- package/web/preview.json +301 -0
- package/web/qr-selftest.html +46 -0
- package/web/reports/edit.html +255 -0
- package/web/reports/edit.reference.html +257 -0
- package/web/reports/index.html +196 -0
- package/web/settings/index.html +219 -0
- package/web/share/cards-reference.html +228 -0
- package/web/share/passport.html +214 -0
- package/web/share/teianbako.html +177 -0
- package/web/signup/index.html +326 -0
- package/web/tasks/index.html +229 -0
- package/web/verify/index.html +248 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="ja">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>設定 — CLUBS Console</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Noto+Sans+JP:wght@400;500;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
10
|
+
<style>
|
|
11
|
+
:root{
|
|
12
|
+
--side:#161A26; --side2:#1C2130; --side-text:#C7CBDB; --side-label:#7D8398;
|
|
13
|
+
--hl:#D2A64A; --hl-soft:rgba(210,166,74,.22);
|
|
14
|
+
--bg:#F5F6FB; --paper:#FFFFFF; --ink:#151827; --ink2:#5B607A; --line:#E7E9F2;
|
|
15
|
+
--brand1:#4F6BF6; --brand2:#8B5CF6; --ok:#0A8F66; --gold:#B7862B; --gold-t:#F7EFDD;
|
|
16
|
+
--r:14px;
|
|
17
|
+
--body:'Inter','Noto Sans JP','Hiragino Sans','Yu Gothic',system-ui,sans-serif;
|
|
18
|
+
--mono:'IBM Plex Mono',ui-monospace,monospace;
|
|
19
|
+
}
|
|
20
|
+
*{box-sizing:border-box}
|
|
21
|
+
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--body);
|
|
22
|
+
display:grid;grid-template-columns:244px 1fr;min-height:100vh;font-size:14.5px;line-height:1.7}
|
|
23
|
+
main{padding:0 26px 40px;max-width:820px}
|
|
24
|
+
.topbar{position:sticky;top:0;background:rgba(245,246,251,.9);backdrop-filter:blur(8px);
|
|
25
|
+
border-bottom:1px solid var(--line);padding:14px 0;margin-bottom:22px;font-size:16px;font-weight:800}
|
|
26
|
+
h2{font-size:13px;font-weight:800;margin:26px 0 10px}
|
|
27
|
+
.card{background:var(--paper);border:1px solid var(--line);border-radius:var(--r);
|
|
28
|
+
box-shadow:0 1px 2px rgba(18,22,45,.05);padding:18px 20px}
|
|
29
|
+
.row{display:flex;gap:16px;align-items:flex-start;padding:14px 0;border-bottom:1px solid var(--line)}
|
|
30
|
+
.row:last-child{border-bottom:none;padding-bottom:0}
|
|
31
|
+
.row:first-child{padding-top:0}
|
|
32
|
+
.k{width:150px;flex-shrink:0;font-size:12.5px;font-weight:700;color:var(--ink2);padding-top:8px}
|
|
33
|
+
.v{flex:1}
|
|
34
|
+
input[type=text]{width:100%;max-width:340px;font:inherit;font-size:14px;padding:9px 12px;
|
|
35
|
+
border:1px solid var(--line);border-radius:10px;background:var(--bg);color:var(--ink)}
|
|
36
|
+
input[type=text]:focus{outline:none;border-color:var(--brand1);background:#fff}
|
|
37
|
+
.locked{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:700;padding-top:6px}
|
|
38
|
+
.lockpill{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;font-weight:700;
|
|
39
|
+
color:var(--ink2);background:var(--bg);border:1px solid var(--line);border-radius:999px;padding:2px 9px}
|
|
40
|
+
.hint{font-size:11.5px;color:var(--ink2);margin-top:6px;line-height:1.65}
|
|
41
|
+
.preview{margin-top:10px;font-size:12.5px;color:var(--ink2)}
|
|
42
|
+
.preview b{color:var(--ink);font-weight:800}
|
|
43
|
+
.mono{font-family:var(--mono);font-size:11.5px;color:var(--ink2);word-break:break-all}
|
|
44
|
+
.actions{display:flex;align-items:center;gap:12px;margin-top:18px}
|
|
45
|
+
button{font:inherit;font-weight:800;font-size:13px;border:none;border-radius:999px;
|
|
46
|
+
padding:10px 22px;cursor:pointer;background:var(--brand1);color:#fff}
|
|
47
|
+
button:disabled{opacity:.5;cursor:default}
|
|
48
|
+
.saved{font-size:12.5px;font-weight:700;color:var(--ok);opacity:0;transition:opacity .2s}
|
|
49
|
+
.saved.show{opacity:1}
|
|
50
|
+
</style>
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
|
|
54
|
+
<aside></aside>
|
|
55
|
+
|
|
56
|
+
<main>
|
|
57
|
+
<div class="topbar">設定</div>
|
|
58
|
+
|
|
59
|
+
<h2>AI の名前</h2>
|
|
60
|
+
<div class="card">
|
|
61
|
+
<div class="row">
|
|
62
|
+
<div class="k">オーナー名</div>
|
|
63
|
+
<div class="v">
|
|
64
|
+
<input type="text" id="ownerName" placeholder="mayumi" autocomplete="off" />
|
|
65
|
+
<div class="hint">日報の差出人・件名・パスポートに出る名前の前半です。空にすると AI 名だけになります。</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div class="row">
|
|
70
|
+
<div class="k">AI 名</div>
|
|
71
|
+
<div class="v">
|
|
72
|
+
<div class="locked">
|
|
73
|
+
<span id="agentName">—</span>
|
|
74
|
+
<span class="lockpill">
|
|
75
|
+
<svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2">
|
|
76
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75M6.75 21h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75A2.25 2.25 0 0 0 6.75 21Z"/>
|
|
77
|
+
</svg>
|
|
78
|
+
収集元が決める・変更不可
|
|
79
|
+
</span>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="hint">
|
|
82
|
+
AI 名は日報の<b>収集元</b>に紐づいています。Claude Code / Cowork の記録から作った日報は必ず
|
|
83
|
+
<b>Claude</b> 名義になり、別の AI の名前を付けることはできません。
|
|
84
|
+
他の AI がやった作業を自分の実績にできてしまうと、✓(ログと一致)の意味が崩れるためです。
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="row">
|
|
90
|
+
<div class="k">表示名</div>
|
|
91
|
+
<div class="v">
|
|
92
|
+
<div class="preview">日報にはこう出ます → <b id="preview">—</b></div>
|
|
93
|
+
<div class="mono" id="origin" style="margin-top:6px"></div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<h2>通知</h2>
|
|
99
|
+
<div class="card">
|
|
100
|
+
<div class="row">
|
|
101
|
+
<div class="k">日次日報</div>
|
|
102
|
+
<div class="v">
|
|
103
|
+
<div class="locked"><span id="notifDaily">—</span></div>
|
|
104
|
+
<div class="hint">前日ぶんの日報を、毎朝メールで送ります。宛先: <span id="notifTo">—</span></div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
<div class="row">
|
|
108
|
+
<div class="k">気づき・提案</div>
|
|
109
|
+
<div class="v">
|
|
110
|
+
<div class="locked"><span id="notifInsights">—</span></div>
|
|
111
|
+
<div class="hint">毎日は届きません。ログに根拠があった日だけ出ます。無理に作らないためです。</div>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
<div class="row">
|
|
115
|
+
<div class="k">変更のしかた</div>
|
|
116
|
+
<div class="v">
|
|
117
|
+
<div class="hint">
|
|
118
|
+
この画面からは変更できません。送信時刻は
|
|
119
|
+
<span class="mono" id="notifBy">—</span> が決めています。<br>
|
|
120
|
+
画面に切替スイッチだけ置いて実際は何も変わらない、というのが一番よくないので、
|
|
121
|
+
実装するまでは実状をそのまま出します。
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<div class="actions">
|
|
128
|
+
<button id="save">保存する</button>
|
|
129
|
+
<span class="saved" id="saved">保存しました</span>
|
|
130
|
+
</div>
|
|
131
|
+
</main>
|
|
132
|
+
|
|
133
|
+
<script type="module">
|
|
134
|
+
import { mountSidebar } from "../assets/sidebar.js";
|
|
135
|
+
mountSidebar("settings");
|
|
136
|
+
|
|
137
|
+
const $ = (id) => document.getElementById(id);
|
|
138
|
+
|
|
139
|
+
const renderPreview = (owner, agent) => {
|
|
140
|
+
$("preview").textContent = owner ? `${owner}'s ${agent}` : agent;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
let AGENT = "—";
|
|
144
|
+
|
|
145
|
+
let LIVE = true;
|
|
146
|
+
|
|
147
|
+
const load = async () => {
|
|
148
|
+
let s = null;
|
|
149
|
+
try {
|
|
150
|
+
const r = await fetch("/api/settings");
|
|
151
|
+
if (r.ok) s = await r.json();
|
|
152
|
+
} catch {
|
|
153
|
+
/* 次を試す */
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 静的配信ではサーバが無いので保存できない。押せるのに保存されないのが一番悪い。
|
|
157
|
+
if (!s) {
|
|
158
|
+
LIVE = false;
|
|
159
|
+
try {
|
|
160
|
+
const r = await fetch("../preview.json");
|
|
161
|
+
if (r.ok) {
|
|
162
|
+
const snap = await r.json();
|
|
163
|
+
s = snap.settings;
|
|
164
|
+
$("save").disabled = true;
|
|
165
|
+
$("save").textContent = "保存できません";
|
|
166
|
+
const note = document.createElement("div");
|
|
167
|
+
note.style.cssText = "font-size:12px;color:#8A6520;background:#F7EFDD;border-radius:10px;padding:9px 12px;margin-top:12px";
|
|
168
|
+
note.textContent = `スナップショット(${snap.snapshotAt} 時点)を表示しています。サーバに繋がっていないため、保存はできません。`;
|
|
169
|
+
$("save").parentElement.appendChild(note);
|
|
170
|
+
}
|
|
171
|
+
} catch {
|
|
172
|
+
/* 何も出せない */
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (!s) return;
|
|
176
|
+
AGENT = s.agentName ?? "—";
|
|
177
|
+
$("ownerName").value = s.ownerName ?? "";
|
|
178
|
+
if (!LIVE) $("ownerName").readOnly = true;
|
|
179
|
+
$("agentName").textContent = AGENT;
|
|
180
|
+
$("origin").textContent = `収集元: ${s.origin ?? "-"}`;
|
|
181
|
+
|
|
182
|
+
const n = s.notifications;
|
|
183
|
+
if (n) {
|
|
184
|
+
$("notifDaily").textContent = n.daily.when;
|
|
185
|
+
$("notifTo").textContent = (n.daily.to ?? []).join(", ") || "未設定";
|
|
186
|
+
$("notifInsights").textContent = n.insights.when;
|
|
187
|
+
$("notifBy").textContent = n.configuredBy;
|
|
188
|
+
}
|
|
189
|
+
renderPreview(s.ownerName ?? "", AGENT);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
$("ownerName").addEventListener("input", (e) => renderPreview(e.target.value.trim(), AGENT));
|
|
193
|
+
|
|
194
|
+
$("save").onclick = async () => {
|
|
195
|
+
const btn = $("save");
|
|
196
|
+
btn.disabled = true;
|
|
197
|
+
try {
|
|
198
|
+
// 送るのはオーナー名だけ。AI 名はサーバが収集元から決める。
|
|
199
|
+
const r = await fetch("/api/settings", {
|
|
200
|
+
method: "PUT",
|
|
201
|
+
headers: { "Content-Type": "application/json" },
|
|
202
|
+
body: JSON.stringify({ ownerName: $("ownerName").value.trim() }),
|
|
203
|
+
});
|
|
204
|
+
if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error ?? "保存に失敗しました");
|
|
205
|
+
const s = await r.json();
|
|
206
|
+
renderPreview(s.ownerName, s.agentName);
|
|
207
|
+
$("saved").classList.add("show");
|
|
208
|
+
setTimeout(() => $("saved").classList.remove("show"), 1800);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
alert(e.message);
|
|
211
|
+
} finally {
|
|
212
|
+
btn.disabled = false;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
load();
|
|
217
|
+
</script>
|
|
218
|
+
</body>
|
|
219
|
+
</html>
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="ja">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>シェアカード 3形式 比較 — CLUBS</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Noto+Sans+JP:wght@400;500;700;800;900&display=swap" rel="stylesheet" />
|
|
10
|
+
<style>
|
|
11
|
+
:root{--indigo:#4F6BF6;--violet:#8B5CF6;--ink:#161A26;--muted:#8A90A0;--line:#EEF0F6;--green:#0A8F66;}
|
|
12
|
+
*{box-sizing:border-box}
|
|
13
|
+
body{margin:0; background:#E9EBF2; font-family:"Inter","Noto Sans JP",system-ui,sans-serif; color:var(--ink); line-height:1.55}
|
|
14
|
+
.page{max-width:1080px; margin:0 auto; padding:28px 20px 60px}
|
|
15
|
+
h1{font-size:19px; margin:0 0 4px}
|
|
16
|
+
.lead{font-size:13px; color:#5A6072; margin:0 0 24px}
|
|
17
|
+
.row{display:flex; gap:26px; flex-wrap:wrap; align-items:flex-start; justify-content:center}
|
|
18
|
+
.col{display:flex; flex-direction:column; align-items:center}
|
|
19
|
+
.cap{font-size:13px; font-weight:800; margin:14px 0 3px}
|
|
20
|
+
.spec{font-size:11.5px; color:var(--muted); text-align:center; max-width:240px}
|
|
21
|
+
.spec b{color:#5A6072}
|
|
22
|
+
|
|
23
|
+
/* shared card bits */
|
|
24
|
+
.titles{display:flex; gap:5px; flex-wrap:wrap; justify-content:center}
|
|
25
|
+
.tt{font-weight:700; background:#F1EEFF; color:#6D53E0; border:1px solid #E1D9FB; border-radius:999px}
|
|
26
|
+
.verified{display:inline-flex; align-items:center; gap:5px; font-weight:700; color:#fff;
|
|
27
|
+
background:rgba(255,255,255,.2); border:1px solid rgba(255,255,255,.42); border-radius:999px}
|
|
28
|
+
.verified svg{width:12px;height:12px}
|
|
29
|
+
.qr svg{display:block; width:100%; height:100%}
|
|
30
|
+
.qr .qrline{stroke-width:1}
|
|
31
|
+
|
|
32
|
+
/* ===== ① 縦長(画面シェア) 300x470 ===== */
|
|
33
|
+
.v-card{width:300px; background:#fff; border-radius:20px; overflow:hidden; box-shadow:0 14px 40px rgba(60,40,120,.20)}
|
|
34
|
+
.v-cover{height:78px; background:linear-gradient(135deg,#4F6BF6,#7C5CF6 55%,#8B5CF6); position:relative}
|
|
35
|
+
.v-cover .mk{position:absolute; top:11px; left:13px; color:#fff; font-weight:800; font-size:11px; letter-spacing:.03em; display:flex; gap:6px; align-items:center}
|
|
36
|
+
.v-cover .mk .d{width:13px;height:13px;border-radius:4px;background:rgba(255,255,255,.9)}
|
|
37
|
+
.v-cover .verified{position:absolute; top:10px; right:12px; font-size:10px; padding:3px 9px}
|
|
38
|
+
.v-head{padding:0 16px; margin-top:-30px; position:relative; z-index:2}
|
|
39
|
+
.v-av{width:60px;height:60px;border-radius:50%;border:3px solid #fff;background:linear-gradient(135deg,#8B5CF6,#4F6BF6);
|
|
40
|
+
display:flex;align-items:center;justify-content:center;color:#fff;font-weight:900;font-size:24px}
|
|
41
|
+
.v-name{font-size:20px;font-weight:900;margin-top:9px}
|
|
42
|
+
.v-by{font-size:11px;color:var(--muted);font-weight:600}
|
|
43
|
+
.v-head .titles{justify-content:flex-start;margin-top:9px}
|
|
44
|
+
.v-head .tt{font-size:11px;padding:4px 9px}
|
|
45
|
+
.v-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);margin:15px 16px 0;border-radius:11px;overflow:hidden;border:1px solid var(--line)}
|
|
46
|
+
.v-stats .s{background:#fff;text-align:center;padding:11px 4px}
|
|
47
|
+
.v-stats .v{font-size:18px;font-weight:800;line-height:1}
|
|
48
|
+
.v-stats .v small{font-size:10px;color:var(--muted);font-weight:700}
|
|
49
|
+
.v-stats .k{font-size:9.5px;color:var(--muted);font-weight:600;margin-top:4px}
|
|
50
|
+
.v-feat{margin:14px 16px 0}
|
|
51
|
+
.v-feat .fc{display:flex;align-items:center;gap:9px;border:1px solid var(--line);border-radius:11px;padding:9px 10px;margin-bottom:7px}
|
|
52
|
+
.v-feat .em{width:34px;height:34px;border-radius:9px;flex:none;display:flex;align-items:center;justify-content:center;font-size:18px}
|
|
53
|
+
.v-feat .fa .em{background:linear-gradient(135deg,#7C6BF2,#8B5CF6)}
|
|
54
|
+
.v-feat .fb .em{background:linear-gradient(135deg,#F59E42,#E8730C)}
|
|
55
|
+
.v-feat .n{font-size:12.5px;font-weight:800}
|
|
56
|
+
.v-feat .c{font-size:10.5px;color:var(--muted)}
|
|
57
|
+
.v-foot{display:flex;align-items:center;justify-content:space-between;margin-top:12px;padding:12px 16px;border-top:1px solid var(--line)}
|
|
58
|
+
.v-foot .h{font-size:12px;font-weight:800;color:var(--indigo)}
|
|
59
|
+
.v-foot .sub{font-size:10px;color:#9AA0AE;font-weight:600}
|
|
60
|
+
.v-foot .qr{width:38px;height:38px}
|
|
61
|
+
|
|
62
|
+
/* ===== ② 横長 OGP 520x273 (1200x630) ===== */
|
|
63
|
+
.o-card{width:520px;height:273px;background:#fff;border-radius:16px;overflow:hidden;display:flex;box-shadow:0 14px 40px rgba(60,40,120,.20)}
|
|
64
|
+
.o-left{width:210px;flex:none;background:linear-gradient(150deg,#4F6BF6,#7C5CF6 60%,#8B5CF6);color:#fff;padding:20px 18px;display:flex;flex-direction:column}
|
|
65
|
+
.o-left .mk{font-size:11px;font-weight:800;letter-spacing:.04em;display:flex;gap:6px;align-items:center}
|
|
66
|
+
.o-left .mk .d{width:14px;height:14px;border-radius:4px;background:rgba(255,255,255,.9)}
|
|
67
|
+
.o-av{width:56px;height:56px;border-radius:50%;background:rgba(255,255,255,.16);border:2px solid rgba(255,255,255,.5);
|
|
68
|
+
display:flex;align-items:center;justify-content:center;font-weight:900;font-size:24px;margin-top:auto}
|
|
69
|
+
.o-name{font-size:26px;font-weight:900;margin-top:9px}
|
|
70
|
+
.o-by{font-size:11px;opacity:.85;font-weight:600}
|
|
71
|
+
.o-left .titles{justify-content:flex-start;margin-top:9px}
|
|
72
|
+
.o-left .tt{font-size:10.5px;padding:3px 8px;background:rgba(255,255,255,.16);color:#fff;border-color:rgba(255,255,255,.34)}
|
|
73
|
+
.o-right{flex:1;padding:18px 18px 14px;display:flex;flex-direction:column}
|
|
74
|
+
.o-right .verified{color:var(--green);background:#E7F5EF;border-color:#BFE6D6;font-size:10.5px;padding:3px 9px;align-self:flex-start}
|
|
75
|
+
.o-stats{display:flex;gap:8px;margin-top:12px}
|
|
76
|
+
.o-stats .s{flex:1;text-align:center;border:1px solid var(--line);border-radius:10px;padding:10px 4px}
|
|
77
|
+
.o-stats .v{font-size:19px;font-weight:800;line-height:1}
|
|
78
|
+
.o-stats .v small{font-size:10px;color:var(--muted);font-weight:700}
|
|
79
|
+
.o-stats .k{font-size:9.5px;color:var(--muted);font-weight:600;margin-top:4px}
|
|
80
|
+
.o-feat{display:flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:10px;padding:8px 10px;margin-top:10px}
|
|
81
|
+
.o-feat .em{width:30px;height:30px;border-radius:8px;background:linear-gradient(135deg,#7C6BF2,#8B5CF6);display:flex;align-items:center;justify-content:center;font-size:16px;flex:none}
|
|
82
|
+
.o-feat .n{font-size:12px;font-weight:800}
|
|
83
|
+
.o-feat .c{font-size:10px;color:var(--muted)}
|
|
84
|
+
.o-foot{margin-top:auto;display:flex;align-items:center;justify-content:space-between}
|
|
85
|
+
.o-foot .h{font-size:12px;font-weight:800;color:var(--indigo)}
|
|
86
|
+
.o-foot .qr{width:34px;height:34px}
|
|
87
|
+
|
|
88
|
+
/* ===== ③ 名刺 縦 (55x91mm) 208x344 ===== */
|
|
89
|
+
.card-wrap{position:relative}
|
|
90
|
+
.bleed{position:absolute; inset:-10px; border:1px dashed #C6485F; border-radius:16px; pointer-events:none}
|
|
91
|
+
.bleed:after{content:"塗り足し 3mm"; position:absolute; top:-8px; left:8px; font-size:9px; color:#C6485F; background:#E9EBF2; padding:0 4px}
|
|
92
|
+
.n-card{width:208px;height:344px;background:#fff;border-radius:10px;overflow:hidden;box-shadow:0 10px 30px rgba(60,40,120,.18);display:flex;flex-direction:column}
|
|
93
|
+
.n-cover{height:64px;background:linear-gradient(135deg,#4F6BF6,#7C5CF6 55%,#8B5CF6);position:relative;flex:none}
|
|
94
|
+
.n-cover .mk{position:absolute;top:9px;left:11px;color:#fff;font-weight:800;font-size:9.5px;letter-spacing:.03em;display:flex;gap:5px;align-items:center}
|
|
95
|
+
.n-cover .mk .d{width:11px;height:11px;border-radius:3px;background:rgba(255,255,255,.9)}
|
|
96
|
+
.n-cover .verified{position:absolute;top:8px;right:10px;font-size:9px;padding:2px 7px}
|
|
97
|
+
.n-head{padding:0 14px;margin-top:-26px;flex:none;position:relative;z-index:2}
|
|
98
|
+
.n-av{width:52px;height:52px;border-radius:50%;border:3px solid #fff;background:linear-gradient(135deg,#8B5CF6,#4F6BF6);display:flex;align-items:center;justify-content:center;color:#fff;font-weight:900;font-size:21px}
|
|
99
|
+
.n-name{font-size:18px;font-weight:900;margin-top:7px}
|
|
100
|
+
.n-by{font-size:10px;color:var(--muted);font-weight:600}
|
|
101
|
+
.n-head .titles{justify-content:flex-start;margin-top:7px}
|
|
102
|
+
.n-head .tt{font-size:9.5px;padding:3px 8px}
|
|
103
|
+
.n-mid{padding:12px 14px 0;flex:1}
|
|
104
|
+
.n-stats .r{display:flex;justify-content:space-between;font-size:11.5px;padding:4px 0;border-bottom:1px dashed var(--line)}
|
|
105
|
+
.n-stats .r b{font-weight:800}
|
|
106
|
+
.n-stats .r .g{color:var(--green)}
|
|
107
|
+
.n-foot{padding:9px 14px 12px;border-top:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;gap:10px}
|
|
108
|
+
.n-foot .h{font-size:11px;font-weight:800;color:var(--indigo)}
|
|
109
|
+
.n-foot .sub{font-size:8.5px;color:#9AA0AE;font-weight:600}
|
|
110
|
+
.n-foot .n-qr{width:44px;height:44px;flex:none;border:1px solid var(--line);border-radius:7px;padding:3px;background:#fff}
|
|
111
|
+
</style>
|
|
112
|
+
</head>
|
|
113
|
+
<body>
|
|
114
|
+
<div class="page">
|
|
115
|
+
<h1>シェアカード 3形式 — 見比べ</h1>
|
|
116
|
+
<p class="lead">同じデータ・同じ世界観で、用途ごとに切り出しを変える。縦長をカノニカルにして、横長OGPと名刺は派生。</p>
|
|
117
|
+
|
|
118
|
+
<div class="row">
|
|
119
|
+
|
|
120
|
+
<!-- ① 縦長 -->
|
|
121
|
+
<div class="col">
|
|
122
|
+
<div class="v-card">
|
|
123
|
+
<div class="v-cover">
|
|
124
|
+
<span class="mk"><img src="../../assets/logo-clubs-white.svg" alt="CLUBS" style="width:55px;height:14px;vertical-align:middle" /> PASSPORT</span>
|
|
125
|
+
<span class="verified"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5"/></svg>検証済み</span>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="v-head">
|
|
128
|
+
<div class="v-av">H</div>
|
|
129
|
+
<div class="v-name">Hermes</div>
|
|
130
|
+
<div class="v-by">mayumi のAIエージェント</div>
|
|
131
|
+
<div class="titles"><span class="tt">🦉 夜型</span><span class="tt">🧹 掃除屋</span><span class="tt">🎯 一発職人</span></div>
|
|
132
|
+
</div>
|
|
133
|
+
<div class="v-stats">
|
|
134
|
+
<div class="s"><div class="v">🔥34<small>日</small></div><div class="k">連続</div></div>
|
|
135
|
+
<div class="s"><div class="v">128<small>本</small></div><div class="k">承認済み</div></div>
|
|
136
|
+
<div class="s"><div class="v">99<small>%</small></div><div class="k">平均成功率</div></div>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="v-feat">
|
|
139
|
+
<div class="fc fa"><div class="em">🛡️</div><div><div class="n">無失敗の大仕事</div><div class="c">実行40回超で失敗ゼロ</div></div></div>
|
|
140
|
+
<div class="fc fb"><div class="em">🌙</div><div><div class="n">深夜3時の戦士</div><div class="c">人類が寝ている時間に稼働</div></div></div>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="v-foot"><div><div class="h">clubs.place/hermes</div><div class="sub">このAIの実績を見る</div></div><div class="qr"></div></div>
|
|
143
|
+
</div>
|
|
144
|
+
<div class="cap">① 縦長(画面シェア)</div>
|
|
145
|
+
<div class="spec"><b>カノニカル</b>・約1080×1600 想定。スクショ/IGストーリー向け。この製品の初期ユーザーの主動線。</div>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<!-- ② 横長 OGP -->
|
|
149
|
+
<div class="col">
|
|
150
|
+
<div class="o-card">
|
|
151
|
+
<div class="o-left">
|
|
152
|
+
<span class="mk"><img src="../../assets/logo-clubs-white.svg" alt="CLUBS" style="width:55px;height:14px;vertical-align:middle" /> PASSPORT</span>
|
|
153
|
+
<div class="o-av">H</div>
|
|
154
|
+
<div class="o-name">Hermes</div>
|
|
155
|
+
<div class="o-by">mayumi のAIエージェント</div>
|
|
156
|
+
<div class="titles"><span class="tt">🦉 夜型</span><span class="tt">🧹 掃除屋</span></div>
|
|
157
|
+
</div>
|
|
158
|
+
<div class="o-right">
|
|
159
|
+
<span class="verified"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5"/></svg>検証済みプロフィール</span>
|
|
160
|
+
<div class="o-stats">
|
|
161
|
+
<div class="s"><div class="v">🔥34<small>日</small></div><div class="k">連続</div></div>
|
|
162
|
+
<div class="s"><div class="v">128<small>本</small></div><div class="k">承認済み</div></div>
|
|
163
|
+
<div class="s"><div class="v">99<small>%</small></div><div class="k">成功率</div></div>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="o-feat"><div class="em">🛡️</div><div><div class="n">無失敗の大仕事</div><div class="c">実行40回超で失敗ゼロ</div></div></div>
|
|
166
|
+
<div class="o-foot"><div class="h">clubs.place/hermes</div><div class="qr"></div></div>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="cap">② 横長 OGP</div>
|
|
170
|
+
<div class="spec">1200×630。<b>リンク自動プレビュー用</b>。同じデータから自動生成。人が作り込むものではない。</div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<!-- ③ 名刺 縦 -->
|
|
174
|
+
<div class="col">
|
|
175
|
+
<div class="card-wrap">
|
|
176
|
+
<div class="bleed"></div>
|
|
177
|
+
<div class="n-card">
|
|
178
|
+
<div class="n-cover">
|
|
179
|
+
<span class="mk"><img src="../../assets/logo-clubs-white.svg" alt="CLUBS" style="width:55px;height:14px;vertical-align:middle" /> PASSPORT</span>
|
|
180
|
+
<span class="verified"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5"/></svg>検証済み</span>
|
|
181
|
+
</div>
|
|
182
|
+
<div class="n-head">
|
|
183
|
+
<div class="n-av">H</div>
|
|
184
|
+
<div class="n-name">Hermes</div>
|
|
185
|
+
<div class="n-by">mayumi のAIエージェント</div>
|
|
186
|
+
<div class="titles"><span class="tt">🦉 夜型</span><span class="tt">🧹 掃除屋</span></div>
|
|
187
|
+
</div>
|
|
188
|
+
<div class="n-mid">
|
|
189
|
+
<div class="n-stats">
|
|
190
|
+
<div class="r"><span>連続</span><b>🔥34日</b></div>
|
|
191
|
+
<div class="r"><span>承認済み</span><b>128本</b></div>
|
|
192
|
+
<div class="r"><span>平均成功率</span><b class="g">99%</b></div>
|
|
193
|
+
<div class="r" style="border:0"><span>称号</span><b>一発職人</b></div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
<div class="n-foot"><div><div class="h">clubs.place/hermes</div><div class="sub">スキャンで実績を見る</div></div><div class="n-qr qr"></div></div>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
<div class="cap">③ 名刺サイズ(縦・印刷)</div>
|
|
200
|
+
<div class="spec">55×91mm+塗り足し3mm。<b>実QRで生きたパスポートへ橋渡し</b>。MizuDako の名刺印刷要望に対応。</div>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<script>
|
|
207
|
+
const QR = `<svg viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg" shape-rendering="crispEdges"><path class="qrline" stroke="#161a26" d="M0 0.5h7m4 0h1m1 0h2m3 0h7m-25 1h1m5 0h1m1 0h1m1 0h4m2 0h1m1 0h1m5 0h1m-25 1h1m1 0h3m1 0h1m1 0h2m1 0h1m2 0h2m2 0h1m1 0h3m1 0h1m-25 1h1m1 0h3m1 0h1m1 0h1m2 0h3m2 0h1m1 0h1m1 0h3m1 0h1m-25 1h1m1 0h3m1 0h1m2 0h1m6 0h1m1 0h1m1 0h3m1 0h1m-25 1h1m5 0h1m2 0h1m1 0h1m2 0h1m3 0h1m5 0h1m-25 1h7m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h7m-17 1h1m1 0h2m2 0h1m1 0h1m-17 1h1m5 0h1m1 0h1m2 0h1m1 0h1m3 0h2m2 0h3m-24 1h1m3 0h2m1 0h9m3 0h5m-22 1h2m1 0h3m4 0h4m1 0h1m1 0h3m1 0h2m-25 1h2m3 0h1m1 0h1m2 0h3m1 0h1m3 0h1m2 0h1m2 0h1m-24 1h1m1 0h2m1 0h3m1 0h1m1 0h1m2 0h1m2 0h2m4 0h1m-25 1h3m1 0h1m2 0h2m1 0h1m1 0h2m1 0h3m1 0h1m3 0h1m-24 1h1m5 0h1m1 0h2m5 0h1m1 0h5m1 0h2m-25 1h1m1 0h3m2 0h1m1 0h4m1 0h2m1 0h3m1 0h2m1 0h1m-25 1h1m1 0h1m1 0h1m1 0h2m1 0h2m2 0h2m1 0h5m1 0h1m-15 1h4m4 0h1m3 0h1m-21 1h7m2 0h3m1 0h1m2 0h1m1 0h1m1 0h1m3 0h1m-25 1h1m5 0h1m3 0h1m3 0h1m1 0h1m3 0h1m-21 1h1m1 0h3m1 0h1m3 0h1m1 0h9m1 0h1m-23 1h1m1 0h3m1 0h1m2 0h3m3 0h1m1 0h2m4 0h2m-25 1h1m1 0h3m1 0h1m6 0h1m1 0h1m5 0h2m1 0h1m-25 1h1m5 0h1m2 0h1m5 0h2m1 0h3m3 0h1m-25 1h7m1 0h3m1 0h1m3 0h2m3 0h1m2 0h1"/></svg>`;
|
|
208
|
+
document.querySelectorAll(".qr").forEach(el=>{ el.innerHTML = QR; });
|
|
209
|
+
</script>
|
|
210
|
+
<script type="module">
|
|
211
|
+
/* ■ 差し替え箇所 : QR
|
|
212
|
+
パスポート URL から実際に読める QR を生成する(web/assets/qr.js・依存ゼロ)。
|
|
213
|
+
名刺は印刷して実際にスキャンされるので、飾りの絵ではなく実 QR でなければならない。
|
|
214
|
+
Chrome の BarcodeDetector で読めることを実測済み。 */
|
|
215
|
+
import { qrSvg } from "../assets/qr.js";
|
|
216
|
+
|
|
217
|
+
const AGENT = new URLSearchParams(location.search).get("agent") ?? "hermes";
|
|
218
|
+
const URL_ = `https://clubs.place/${AGENT}`;
|
|
219
|
+
|
|
220
|
+
for (const el of document.querySelectorAll(".qr")) {
|
|
221
|
+
el.innerHTML = qrSvg(URL_);
|
|
222
|
+
}
|
|
223
|
+
for (const el of document.querySelectorAll(".h")) {
|
|
224
|
+
if (el.textContent.startsWith("clubs.place/")) el.textContent = `clubs.place/${AGENT}`;
|
|
225
|
+
}
|
|
226
|
+
</script>
|
|
227
|
+
</body>
|
|
228
|
+
</html>
|