diff --git a/src/ifcchat/index.html b/src/ifcchat/index.html
index 77a57c07a8..686dce5663 100644
--- a/src/ifcchat/index.html
+++ b/src/ifcchat/index.html
@@ -5,244 +5,7 @@
IfcOpenShell AI Assistant
-
+
diff --git a/src/ifcchat/style.css b/src/ifcchat/style.css
new file mode 100644
index 0000000000..6c3af2f56e
--- /dev/null
+++ b/src/ifcchat/style.css
@@ -0,0 +1,232 @@
+* {
+ box-sizing: border-box;
+}
+
+body {
+ font-family: system-ui, sans-serif;
+ margin: 0;
+}
+
+button,
+input,
+select,
+textarea {
+ font: inherit;
+}
+
+header {
+ padding: 12px 16px;
+ border-bottom: 1px solid #ddd;
+}
+
+header input,
+header select {
+ padding: 8px;
+}
+
+main {
+ display: grid;
+ grid-template-columns: 320px 1fr;
+ height: 100vh;
+}
+
+.side {
+ border-right: 1px solid #ddd;
+ padding: 100px 12px 12px 12px;
+ overflow: auto;
+ background: #f9f9f9;
+}
+
+.chat {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+
+.msgs {
+ flex: 1;
+ overflow: auto;
+ padding: 16px;
+}
+
+.msg {
+ margin: 10px 0;
+}
+
+.msg .role {
+ font-size: 12px;
+ opacity: 0.7;
+ margin: 12px 0 4px 0;
+}
+
+.role.user {
+ text-align: right;
+}
+
+.msg .bubble {
+ padding: 0;
+ border-radius: 10px;
+ white-space: pre-wrap;
+}
+
+.msg.user .bubble {
+ padding: 10px 20px;
+ background: #eee;
+ width: 50%;
+ margin-left: auto;
+ border: solid 1px #ddd;
+}
+
+.msg.tool .bubble {
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
+ font-size: 60%;
+ max-height: 100px;
+ overflow: hidden;
+}
+
+.composer {
+ display: flex;
+ gap: 8px;
+ padding: 12px;
+ justify-content: center;
+}
+
+.composer textarea {
+ flex: 1;
+ resize: none;
+ height: 88px;
+ border: none;
+}
+
+.composer button {
+ align-self: center;
+}
+
+.composer .inner {
+ border: solid 1px #ddd;
+ border-radius: 20px;
+ padding: 10px;
+ display: flex;
+ width: 100%;
+}
+
+@keyframes spin { to { transform: rotate(360deg); } }
+.spinner {
+ width: 18px;
+ height: 18px;
+ border: 2px solid #aaa;
+ border-top-color: #333;
+ border-radius: 50%;
+ animation: spin 0.7s linear infinite;
+ display: inline-block;
+}
+
+.status {
+ font-size: 12px;
+ opacity: 0.7;
+}
+
+section > .row > label {
+ display: block;
+ font-size: 12px;
+ opacity: 0.75;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+
+section > .row > label .small {
+ font-weight: normal;
+ display: block;
+ font-size: 80%;
+}
+
+.side .row {
+ margin-bottom: 32px;
+}
+
+.row button {
+ padding: 8px 10px;
+}
+
+#model {
+ background: white;
+ color: gray;
+ border: solid 1px #eee;
+ border-radius: 6px;
+}
+
+hr {
+ border: dashed 1px #ddd;
+}
+
+.btn-row {
+ display: flex;
+ gap: 10px;
+}
+
+.btn-row > .btn,
+.btn-row > button.btn {
+ flex: 1 1 0;
+ min-width: 0;
+}
+
+.btn {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ font-size: 14px;
+
+ padding: 10px 12px;
+ border-radius: 10px;
+ border: 1px solid #d0d0d0;
+ background: #eee;
+
+ cursor: pointer;
+ user-select: none;
+ text-decoration: none;
+}
+
+.btn:hover {
+ background: #ddd;
+}
+
+.btn:active {
+ transform: translateY(1px);
+}
+
+.btn-wide {
+ width: 100%;
+}
+
+.material-icons {
+ font-size: 18px;
+ line-height: 1;
+}
+
+.btn.disabled,
+.btn:disabled {
+ opacity: 0.55;
+ cursor: not-allowed;
+ pointer-events: none;
+}
+
+#input {
+ border: none;
+ outline: none;
+}
+
+#input:focus,
+#input:focus-visible {
+ outline: none;
+ box-shadow: none;
+}
+
+.code {
+ font-family: 'Courier New', Courier, monospace;
+ font-size: 90%;
+ background-color: #eee;
+ border: solid 1px #ddd;
+ padding: 2px;
+ display: inline-block;
+}