@@ -88,6 +88,80 @@ body {
8888}
8989` ;
9090
91+ // Snippet kit: element defaults and SVG utility classes baked into every
92+ // snippet doc so agents publish compact markup instead of hand-writing inline
93+ // CSS. Documented as a reference table in guide/DESIGN_GUIDE.md — keep the
94+ // two in sync. Note: CSS rules override SVG presentation attributes, so bare
95+ // element selectors here must never set properties snippets commonly set via
96+ // attributes (fill/font-size on text, etc.) — that's why text styling is
97+ // opt-in via classes.
98+ const KIT_CSS = `
99+ :root {
100+ color-scheme: light dark;
101+ --c-teal-bg: #e1f4f1; --c-teal-line: #1fa996; --c-teal-text: #0c6e62;
102+ --c-coral-bg: #fdece5; --c-coral-line: #e8835e; --c-coral-text: #a44f28;
103+ }
104+ @media (prefers-color-scheme: dark) {
105+ :root {
106+ --c-teal-bg: rgba(31, 169, 150, 0.18); --c-teal-text: #6fd0c2;
107+ --c-coral-bg: rgba(232, 131, 94, 0.18); --c-coral-text: #f0a987;
108+ }
109+ }
110+ button {
111+ font: 500 14px/1.4 var(--font-sans);
112+ color: var(--color-text-primary);
113+ background: none;
114+ border: 0.5px solid var(--color-border-secondary);
115+ border-radius: var(--border-radius-md);
116+ padding: 6px 14px;
117+ cursor: pointer;
118+ }
119+ button:hover { background: var(--color-background-secondary); }
120+ input:not([type=checkbox]):not([type=radio]):not([type=range]), select, textarea {
121+ font: 14px/1.4 var(--font-sans);
122+ color: var(--color-text-primary);
123+ background: var(--color-background-primary);
124+ border: 0.5px solid var(--color-border-secondary);
125+ border-radius: var(--border-radius-md);
126+ padding: 6px 10px;
127+ outline: none;
128+ }
129+ input:focus, select:focus, textarea:focus { border-color: var(--color-border-info); }
130+ input::placeholder, textarea::placeholder { color: var(--color-text-tertiary); }
131+ textarea { resize: vertical; }
132+ input[type=checkbox], input[type=radio], input[type=range], progress {
133+ accent-color: var(--color-border-info);
134+ }
135+ svg { font-family: var(--font-sans); fill: var(--color-text-primary); }
136+ .t { font-size: 14px; }
137+ .ts { font-size: 12px; fill: var(--color-text-secondary); }
138+ .th { font-size: 14px; font-weight: 500; }
139+ .box { fill: var(--color-background-secondary); stroke: var(--color-border-tertiary); rx: 8px; }
140+ .arr { stroke: var(--color-text-secondary); stroke-width: 1.2; fill: none; }
141+ .leader { stroke: var(--color-border-secondary); stroke-width: 1; stroke-dasharray: 3 4; fill: none; }
142+ .node { cursor: pointer; }
143+ .node:hover { opacity: 0.75; }
144+ .c-blue, .c-blue .box { fill: var(--color-background-info); stroke: var(--color-border-info); }
145+ .c-blue text, text.c-blue { fill: var(--color-text-info); stroke: none; }
146+ .c-teal, .c-teal .box { fill: var(--c-teal-bg); stroke: var(--c-teal-line); }
147+ .c-teal text, text.c-teal { fill: var(--c-teal-text); stroke: none; }
148+ .c-amber, .c-amber .box { fill: var(--color-background-warning); stroke: var(--color-border-warning); }
149+ .c-amber text, text.c-amber { fill: var(--color-text-warning); stroke: none; }
150+ .c-coral, .c-coral .box { fill: var(--c-coral-bg); stroke: var(--c-coral-line); }
151+ .c-coral text, text.c-coral { fill: var(--c-coral-text); stroke: none; }
152+ .c-green, .c-green .box { fill: var(--color-background-success); stroke: var(--color-border-success); }
153+ .c-green text, text.c-green { fill: var(--color-text-success); stroke: none; }
154+ .c-red, .c-red .box { fill: var(--color-background-danger); stroke: var(--color-border-danger); }
155+ .c-red text, text.c-red { fill: var(--color-text-danger); stroke: none; }
156+ .c-gray, .c-gray .box { fill: var(--color-background-secondary); stroke: var(--color-border-secondary); }
157+ .c-gray text, text.c-gray { fill: var(--color-text-secondary); stroke: none; }
158+ ` ;
159+
160+ // Shared SVG defs injected into every snippet doc. Inline SVGs anywhere in
161+ // the document can reference these by id; the arrowhead inherits the
162+ // referencing line's stroke color via context-stroke.
163+ const SVG_DEFS = `<svg width="0" height="0" style="position:absolute" aria-hidden="true"><defs><marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="context-stroke"/></marker></defs></svg>` ;
164+
91165// Bridge to the host viewer: sendPrompt/openLink mirror Claude's widget
92166// globals, and a ResizeObserver reports content height so the parent can
93167// size the sandboxed (opaque-origin) iframe.
@@ -135,9 +209,10 @@ export function renderSnippetPage(snippet: Snippet): string {
135209<meta name="viewport" content="width=device-width, initial-scale=1">
136210<meta http-equiv="Content-Security-Policy" content="${ CSP } ">
137211<title>${ escapeHtml ( snippet . title ) } </title>
138- <style>${ TOKENS_CSS } </style>
212+ <style>${ TOKENS_CSS } ${ KIT_CSS } </style>
139213</head>
140214<body>
215+ ${ SVG_DEFS }
141216${ snippet . html }
142217<script>${ BRIDGE_JS } </script>
143218</body>
0 commit comments