agentgui 1.0.8 → 1.0.10
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/acp-launcher.js +150 -205
- package/color-table.html +41 -0
- package/database.js +145 -96
- package/package.json +1 -1
- package/server.js +1 -1
- package/static/app.js +114 -53
- package/static/index.html +37 -36
- package/static/styles.css +27 -39
- package/test-block.html +181 -0
- package/static/rippleui.css +0 -208
package/static/index.html
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>GMGUI - Chat with CLI Agents</title>
|
|
7
|
-
<
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rippleui@1.12.1/dist/css/styles.css" />
|
|
8
9
|
<link rel="stylesheet" href="styles.css">
|
|
9
10
|
</head>
|
|
10
11
|
<body>
|
|
@@ -93,12 +94,12 @@
|
|
|
93
94
|
|
|
94
95
|
<div class="setting-group">
|
|
95
96
|
<label for="connectTimeout">Connection Timeout (seconds)</label>
|
|
96
|
-
<input type="number" id="connectTimeout" value="30" class="input" />
|
|
97
|
+
<input type="number" id="connectTimeout" value="30" class="gm-input" />
|
|
97
98
|
</div>
|
|
98
99
|
|
|
99
100
|
<div class="setting-group">
|
|
100
101
|
<label for="screenshotFormat">Screenshot Format</label>
|
|
101
|
-
<select id="screenshotFormat" class="input">
|
|
102
|
+
<select id="screenshotFormat" class="gm-input">
|
|
102
103
|
<option value="png">PNG</option>
|
|
103
104
|
<option value="jpg">JPEG</option>
|
|
104
105
|
</select>
|
|
@@ -108,13 +109,13 @@
|
|
|
108
109
|
</div>
|
|
109
110
|
|
|
110
111
|
<!-- Modal for new chat options -->
|
|
111
|
-
<div id="newChatModal" class="modal">
|
|
112
|
-
<div class="modal-content" style="max-width: 400px;">
|
|
113
|
-
<div class="modal-header">
|
|
112
|
+
<div id="newChatModal" class="gm-modal">
|
|
113
|
+
<div class="gm-modal-content" style="max-width: 400px;">
|
|
114
|
+
<div class="gm-modal-header">
|
|
114
115
|
<h3>New Chat</h3>
|
|
115
|
-
<button onclick="closeNewChatModal()" class="btn-close">×</button>
|
|
116
|
+
<button onclick="closeNewChatModal()" class="gm-btn-close">×</button>
|
|
116
117
|
</div>
|
|
117
|
-
<div class="modal-body" style="gap: 1rem; flex-direction: column; padding: 2rem;">
|
|
118
|
+
<div class="gm-modal-body" style="gap: 1rem; flex-direction: column; padding: 2rem;">
|
|
118
119
|
<button class="chat-option-btn" onclick="createChatInWorkspace()">
|
|
119
120
|
<span class="chat-option-icon">💬</span>
|
|
120
121
|
<div class="chat-option-content">
|
|
@@ -141,65 +142,65 @@
|
|
|
141
142
|
</div>
|
|
142
143
|
|
|
143
144
|
<!-- Modal for folder browser -->
|
|
144
|
-
<div id="folderBrowserModal" class="modal">
|
|
145
|
-
<div class="modal-content" style="max-width: 600px; height: 500px;">
|
|
146
|
-
<div class="modal-header">
|
|
145
|
+
<div id="folderBrowserModal" class="gm-modal">
|
|
146
|
+
<div class="gm-modal-content" style="max-width: 600px; height: 500px;">
|
|
147
|
+
<div class="gm-modal-header">
|
|
147
148
|
<h3>Select a Folder</h3>
|
|
148
|
-
<button class="btn-close" onclick="closeFolderBrowser()">×</button>
|
|
149
|
+
<button class="gm-btn-close" onclick="closeFolderBrowser()">×</button>
|
|
149
150
|
</div>
|
|
150
|
-
<div class="modal-body" style="flex-direction: column; gap: 0; padding: 0;">
|
|
151
|
+
<div class="gm-modal-body" style="flex-direction: column; gap: 0; padding: 0;">
|
|
151
152
|
<div style="padding: 1rem 1.5rem; border-bottom: 1px solid var(--border-color); display: flex; gap: 0.5rem; align-items: center;">
|
|
152
|
-
<input type="text" id="folderPath" class="input" placeholder="/home or ~" style="flex: 1; margin: 0;" />
|
|
153
|
-
<button onclick="browseFolders()" class="btn btn-primary" style="margin: 0;">Browse</button>
|
|
153
|
+
<input type="text" id="folderPath" class="gm-input" placeholder="/home or ~" style="flex: 1; margin: 0;" />
|
|
154
|
+
<button onclick="browseFolders()" class="gm-btn gm-btn-primary" style="margin: 0;">Browse</button>
|
|
154
155
|
</div>
|
|
155
156
|
<div id="folderBrowserList" style="flex: 1; overflow-y: auto; padding: 0; border: none;"></div>
|
|
156
157
|
</div>
|
|
157
|
-
<div class="modal-footer">
|
|
158
|
-
<button onclick="confirmFolderSelection()" class="btn btn-primary">Select</button>
|
|
159
|
-
<button onclick="closeFolderBrowser()" class="btn btn-secondary">Cancel</button>
|
|
158
|
+
<div class="gm-modal-footer">
|
|
159
|
+
<button onclick="confirmFolderSelection()" class="gm-btn gm-btn-primary">Select</button>
|
|
160
|
+
<button onclick="closeFolderBrowser()" class="gm-btn gm-btn-secondary">Cancel</button>
|
|
160
161
|
</div>
|
|
161
162
|
</div>
|
|
162
163
|
</div>
|
|
163
164
|
|
|
164
165
|
<!-- Modal for delete confirmation -->
|
|
165
|
-
<div id="deleteConfirmModal" class="modal">
|
|
166
|
-
<div class="modal-content" style="max-width: 400px;">
|
|
167
|
-
<div class="modal-header">
|
|
166
|
+
<div id="deleteConfirmModal" class="gm-modal">
|
|
167
|
+
<div class="gm-modal-content" style="max-width: 400px;">
|
|
168
|
+
<div class="gm-modal-header">
|
|
168
169
|
<h3>Delete Chat</h3>
|
|
169
|
-
<button class="btn-close" onclick="app.closeDeleteConfirmDialog()">×</button>
|
|
170
|
+
<button class="gm-btn-close" onclick="app.closeDeleteConfirmDialog()">×</button>
|
|
170
171
|
</div>
|
|
171
|
-
<div class="modal-body" style="flex-direction: column; gap: 1rem; text-align: center;">
|
|
172
|
+
<div class="gm-modal-body" style="flex-direction: column; gap: 1rem; text-align: center;">
|
|
172
173
|
<p style="margin: 0; color: var(--text-primary);">Are you sure you want to delete this chat?</p>
|
|
173
174
|
<p style="margin: 0; font-size: 0.875rem; color: var(--text-tertiary);">This action cannot be undone.</p>
|
|
174
175
|
</div>
|
|
175
|
-
<div class="modal-footer">
|
|
176
|
-
<button class="btn-confirm btn btn-danger">Delete</button>
|
|
177
|
-
<button class="btn-cancel btn btn-secondary">Cancel</button>
|
|
176
|
+
<div class="gm-modal-footer">
|
|
177
|
+
<button class="gm-btn-confirm gm-btn gm-btn-danger">Delete</button>
|
|
178
|
+
<button class="gm-btn-cancel gm-btn gm-btn-secondary">Cancel</button>
|
|
178
179
|
</div>
|
|
179
180
|
</div>
|
|
180
181
|
</div>
|
|
181
182
|
|
|
182
183
|
<!-- Modal for screenshot preview -->
|
|
183
|
-
<div id="screenshotModal" class="modal">
|
|
184
|
-
<div class="modal-content">
|
|
185
|
-
<div class="modal-header">
|
|
184
|
+
<div id="screenshotModal" class="gm-modal">
|
|
185
|
+
<div class="gm-modal-content">
|
|
186
|
+
<div class="gm-modal-header">
|
|
186
187
|
<h3>Screenshot Captured</h3>
|
|
187
|
-
<button onclick="closeScreenshotModal()" class="btn-close">×</button>
|
|
188
|
+
<button onclick="closeScreenshotModal()" class="gm-btn-close">×</button>
|
|
188
189
|
</div>
|
|
189
|
-
<div class="modal-body">
|
|
190
|
+
<div class="gm-modal-body">
|
|
190
191
|
<img id="screenshotImage" src="" alt="Screenshot" style="max-width: 100%; max-height: 60vh; border-radius: 0.5rem;" />
|
|
191
192
|
</div>
|
|
192
|
-
<div class="modal-footer">
|
|
193
|
-
<button onclick="sendScreenshot()" class="btn btn-success">Send to Agent</button>
|
|
194
|
-
<button onclick="downloadScreenshot()" class="btn btn-secondary">Download</button>
|
|
195
|
-
<button onclick="closeScreenshotModal()" class="btn btn-secondary">Close</button>
|
|
193
|
+
<div class="gm-modal-footer">
|
|
194
|
+
<button onclick="sendScreenshot()" class="gm-btn gm-btn-success">Send to Agent</button>
|
|
195
|
+
<button onclick="downloadScreenshot()" class="gm-btn gm-btn-secondary">Download</button>
|
|
196
|
+
<button onclick="closeScreenshotModal()" class="gm-btn gm-btn-secondary">Close</button>
|
|
196
197
|
</div>
|
|
197
198
|
</div>
|
|
198
199
|
</div>
|
|
199
200
|
|
|
200
201
|
<!-- Loading overlay -->
|
|
201
202
|
<div id="loadingOverlay" class="loading-overlay">
|
|
202
|
-
<div class="spinner"></div>
|
|
203
|
+
<div class="gm-spinner"></div>
|
|
203
204
|
</div>
|
|
204
205
|
|
|
205
206
|
<script src="theme.js"></script>
|
package/static/styles.css
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
margin: 0;
|
|
3
|
-
padding: 0;
|
|
1
|
+
*, *::before, *::after {
|
|
4
2
|
box-sizing: border-box;
|
|
5
3
|
}
|
|
6
4
|
|
|
@@ -594,7 +592,7 @@ html, body {
|
|
|
594
592
|
cursor: pointer;
|
|
595
593
|
}
|
|
596
594
|
|
|
597
|
-
.input {
|
|
595
|
+
.gm-input {
|
|
598
596
|
width: 100%;
|
|
599
597
|
padding: 0.75rem;
|
|
600
598
|
border: 1px solid var(--border-color);
|
|
@@ -607,7 +605,7 @@ html, body {
|
|
|
607
605
|
margin-top: 0.5rem;
|
|
608
606
|
}
|
|
609
607
|
|
|
610
|
-
.input:focus {
|
|
608
|
+
.gm-input:focus {
|
|
611
609
|
outline: none;
|
|
612
610
|
border-color: var(--color-primary);
|
|
613
611
|
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
|
|
@@ -619,6 +617,7 @@ html, body {
|
|
|
619
617
|
flex-wrap: wrap;
|
|
620
618
|
gap: 1rem;
|
|
621
619
|
animation: slideUp 0.2s ease;
|
|
620
|
+
width: 100%;
|
|
622
621
|
}
|
|
623
622
|
|
|
624
623
|
.message-bubble {
|
|
@@ -627,6 +626,7 @@ html, body {
|
|
|
627
626
|
padding: 0.75rem 1rem;
|
|
628
627
|
border-radius: 0.5rem;
|
|
629
628
|
word-wrap: break-word;
|
|
629
|
+
white-space: pre-wrap;
|
|
630
630
|
}
|
|
631
631
|
|
|
632
632
|
.message.user .message-bubble {
|
|
@@ -819,9 +819,9 @@ html, body {
|
|
|
819
819
|
flex: 0 1 100%;
|
|
820
820
|
border: 1px solid var(--border-color);
|
|
821
821
|
border-radius: 0.5rem;
|
|
822
|
-
overflow:
|
|
822
|
+
overflow: visible;
|
|
823
823
|
background: var(--bg-secondary);
|
|
824
|
-
max-width:
|
|
824
|
+
max-width: 100%;
|
|
825
825
|
}
|
|
826
826
|
|
|
827
827
|
.html-header {
|
|
@@ -835,22 +835,10 @@ html, body {
|
|
|
835
835
|
|
|
836
836
|
.html-content {
|
|
837
837
|
padding: 0.75rem;
|
|
838
|
-
font-size: 0.9rem;
|
|
839
|
-
color: var(--text-primary);
|
|
840
838
|
overflow-x: auto;
|
|
841
839
|
}
|
|
842
840
|
|
|
843
|
-
.html-content > * {
|
|
844
|
-
margin: 0.5rem 0;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
.html-content > *:first-child {
|
|
848
|
-
margin-top: 0;
|
|
849
|
-
}
|
|
850
841
|
|
|
851
|
-
.html-content > *:last-child {
|
|
852
|
-
margin-bottom: 0;
|
|
853
|
-
}
|
|
854
842
|
|
|
855
843
|
.image-block {
|
|
856
844
|
flex: 0 1 100%;
|
|
@@ -938,7 +926,7 @@ html, body {
|
|
|
938
926
|
}
|
|
939
927
|
|
|
940
928
|
/* Modal */
|
|
941
|
-
.modal {
|
|
929
|
+
.gm-modal {
|
|
942
930
|
display: none;
|
|
943
931
|
position: fixed;
|
|
944
932
|
inset: 0;
|
|
@@ -971,11 +959,11 @@ html, body {
|
|
|
971
959
|
}
|
|
972
960
|
}
|
|
973
961
|
|
|
974
|
-
.modal.active {
|
|
962
|
+
.gm-modal.active {
|
|
975
963
|
display: flex;
|
|
976
964
|
}
|
|
977
965
|
|
|
978
|
-
.modal-content {
|
|
966
|
+
.gm-modal-content {
|
|
979
967
|
background: var(--bg-primary);
|
|
980
968
|
border-radius: 0.75rem;
|
|
981
969
|
box-shadow: var(--shadow-xl);
|
|
@@ -988,7 +976,7 @@ html, body {
|
|
|
988
976
|
transition: var(--transition-smooth);
|
|
989
977
|
}
|
|
990
978
|
|
|
991
|
-
.modal-header {
|
|
979
|
+
.gm-modal-header {
|
|
992
980
|
padding: 1.5rem;
|
|
993
981
|
border-bottom: 1px solid var(--border-color);
|
|
994
982
|
display: flex;
|
|
@@ -996,12 +984,12 @@ html, body {
|
|
|
996
984
|
align-items: center;
|
|
997
985
|
}
|
|
998
986
|
|
|
999
|
-
.modal-header h3 {
|
|
987
|
+
.gm-modal-header h3 {
|
|
1000
988
|
margin: 0;
|
|
1001
989
|
color: var(--text-primary);
|
|
1002
990
|
}
|
|
1003
991
|
|
|
1004
|
-
.modal-body {
|
|
992
|
+
.gm-modal-body {
|
|
1005
993
|
padding: 1.5rem;
|
|
1006
994
|
overflow-y: auto;
|
|
1007
995
|
flex: 1;
|
|
@@ -1010,7 +998,7 @@ html, body {
|
|
|
1010
998
|
justify-content: center;
|
|
1011
999
|
}
|
|
1012
1000
|
|
|
1013
|
-
.modal-footer {
|
|
1001
|
+
.gm-modal-footer {
|
|
1014
1002
|
padding: 1rem 1.5rem;
|
|
1015
1003
|
border-top: 1px solid var(--border-color);
|
|
1016
1004
|
display: flex;
|
|
@@ -1069,7 +1057,7 @@ html, body {
|
|
|
1069
1057
|
color: var(--text-tertiary);
|
|
1070
1058
|
}
|
|
1071
1059
|
|
|
1072
|
-
.btn {
|
|
1060
|
+
.gm-btn {
|
|
1073
1061
|
padding: 0.625rem 1rem;
|
|
1074
1062
|
border: none;
|
|
1075
1063
|
border-radius: 0.5rem;
|
|
@@ -1083,47 +1071,47 @@ html, body {
|
|
|
1083
1071
|
white-space: nowrap;
|
|
1084
1072
|
}
|
|
1085
1073
|
|
|
1086
|
-
.btn-primary {
|
|
1074
|
+
.gm-btn-primary {
|
|
1087
1075
|
background: var(--color-primary);
|
|
1088
1076
|
color: white;
|
|
1089
1077
|
}
|
|
1090
1078
|
|
|
1091
|
-
.btn-primary:hover {
|
|
1079
|
+
.gm-btn-primary:hover {
|
|
1092
1080
|
background: var(--color-primary-light);
|
|
1093
1081
|
transform: translateY(-1px);
|
|
1094
1082
|
}
|
|
1095
1083
|
|
|
1096
|
-
.btn-success {
|
|
1084
|
+
.gm-btn-success {
|
|
1097
1085
|
background: var(--color-success);
|
|
1098
1086
|
color: white;
|
|
1099
1087
|
}
|
|
1100
1088
|
|
|
1101
|
-
.btn-success:hover {
|
|
1089
|
+
.gm-btn-success:hover {
|
|
1102
1090
|
background: #059669;
|
|
1103
1091
|
transform: translateY(-1px);
|
|
1104
1092
|
}
|
|
1105
1093
|
|
|
1106
|
-
.btn-secondary {
|
|
1094
|
+
.gm-btn-secondary {
|
|
1107
1095
|
background: var(--bg-tertiary);
|
|
1108
1096
|
color: var(--text-primary);
|
|
1109
1097
|
border: 1px solid var(--border-color);
|
|
1110
1098
|
}
|
|
1111
1099
|
|
|
1112
|
-
.btn-secondary:hover {
|
|
1100
|
+
.gm-btn-secondary:hover {
|
|
1113
1101
|
background: var(--border-color);
|
|
1114
1102
|
}
|
|
1115
1103
|
|
|
1116
|
-
.btn-danger {
|
|
1104
|
+
.gm-btn-danger {
|
|
1117
1105
|
background: var(--color-danger);
|
|
1118
1106
|
color: white;
|
|
1119
1107
|
}
|
|
1120
1108
|
|
|
1121
|
-
.btn-danger:hover {
|
|
1109
|
+
.gm-btn-danger:hover {
|
|
1122
1110
|
background: #dc2626;
|
|
1123
1111
|
transform: translateY(-1px);
|
|
1124
1112
|
}
|
|
1125
1113
|
|
|
1126
|
-
.btn-close {
|
|
1114
|
+
.gm-btn-close {
|
|
1127
1115
|
background: none;
|
|
1128
1116
|
border: none;
|
|
1129
1117
|
font-size: 2rem;
|
|
@@ -1138,7 +1126,7 @@ html, body {
|
|
|
1138
1126
|
transition: var(--transition-fast);
|
|
1139
1127
|
}
|
|
1140
1128
|
|
|
1141
|
-
.btn-close:hover {
|
|
1129
|
+
.gm-btn-close:hover {
|
|
1142
1130
|
color: var(--text-primary);
|
|
1143
1131
|
}
|
|
1144
1132
|
|
|
@@ -1157,7 +1145,7 @@ html, body {
|
|
|
1157
1145
|
display: flex;
|
|
1158
1146
|
}
|
|
1159
1147
|
|
|
1160
|
-
.spinner {
|
|
1148
|
+
.gm-spinner {
|
|
1161
1149
|
width: 48px;
|
|
1162
1150
|
height: 48px;
|
|
1163
1151
|
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
@@ -1420,7 +1408,7 @@ html, body {
|
|
|
1420
1408
|
.sidebar,
|
|
1421
1409
|
.chat-input-section,
|
|
1422
1410
|
.chat-footer,
|
|
1423
|
-
.modal,
|
|
1411
|
+
.gm-modal,
|
|
1424
1412
|
.loading-overlay {
|
|
1425
1413
|
display: none;
|
|
1426
1414
|
}
|
package/test-block.html
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Hero Card</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,700;1,700&family=DM+Sans:wght@400;500&display=swap" rel="stylesheet">
|
|
8
|
+
<style>
|
|
9
|
+
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
|
|
10
|
+
|
|
11
|
+
:root {
|
|
12
|
+
--ink: #0a0a0a;
|
|
13
|
+
--cream: #f4f0eb;
|
|
14
|
+
--accent: #c8553d;
|
|
15
|
+
--accent-light: #e8886e;
|
|
16
|
+
--glass: rgba(244, 240, 235, 0.06);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
html, body {
|
|
20
|
+
height: 100%;
|
|
21
|
+
font-family: 'DM Sans', sans-serif;
|
|
22
|
+
background: var(--ink);
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
body::before {
|
|
30
|
+
content: '';
|
|
31
|
+
position: fixed;
|
|
32
|
+
inset: 0;
|
|
33
|
+
background:
|
|
34
|
+
radial-gradient(ellipse 80% 60% at 20% 80%, rgba(200, 85, 61, 0.12), transparent),
|
|
35
|
+
radial-gradient(ellipse 60% 50% at 80% 20%, rgba(232, 136, 110, 0.08), transparent);
|
|
36
|
+
pointer-events: none;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.noise {
|
|
40
|
+
position: fixed;
|
|
41
|
+
inset: 0;
|
|
42
|
+
opacity: 0.035;
|
|
43
|
+
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
|
44
|
+
background-size: 200px;
|
|
45
|
+
pointer-events: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.card {
|
|
49
|
+
position: relative;
|
|
50
|
+
width: min(520px, 90vw);
|
|
51
|
+
padding: 56px 48px 48px;
|
|
52
|
+
border: 1px solid rgba(244, 240, 235, 0.08);
|
|
53
|
+
border-radius: 2px;
|
|
54
|
+
background: var(--glass);
|
|
55
|
+
backdrop-filter: blur(40px);
|
|
56
|
+
-webkit-backdrop-filter: blur(40px);
|
|
57
|
+
animation: cardIn 1s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@keyframes cardIn {
|
|
61
|
+
from { opacity: 0; transform: translateY(32px) scale(0.97); }
|
|
62
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.card::before {
|
|
66
|
+
content: '';
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: -1px; left: 48px; right: 48px;
|
|
69
|
+
height: 1px;
|
|
70
|
+
background: linear-gradient(90deg, transparent, var(--accent), transparent);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.label {
|
|
74
|
+
font-size: 10px;
|
|
75
|
+
font-weight: 500;
|
|
76
|
+
letter-spacing: 0.25em;
|
|
77
|
+
text-transform: uppercase;
|
|
78
|
+
color: var(--accent-light);
|
|
79
|
+
margin-bottom: 28px;
|
|
80
|
+
animation: fadeUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.heading {
|
|
84
|
+
font-family: 'Playfair Display', serif;
|
|
85
|
+
font-size: clamp(2rem, 5vw, 2.75rem);
|
|
86
|
+
font-weight: 700;
|
|
87
|
+
line-height: 1.15;
|
|
88
|
+
color: var(--cream);
|
|
89
|
+
margin-bottom: 20px;
|
|
90
|
+
animation: fadeUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.25s both;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.heading em {
|
|
94
|
+
font-style: italic;
|
|
95
|
+
color: var(--accent-light);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.desc {
|
|
99
|
+
font-size: 15px;
|
|
100
|
+
line-height: 1.7;
|
|
101
|
+
color: rgba(244, 240, 235, 0.5);
|
|
102
|
+
max-width: 38ch;
|
|
103
|
+
margin-bottom: 40px;
|
|
104
|
+
animation: fadeUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.35s both;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.cta {
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
gap: 12px;
|
|
111
|
+
padding: 14px 32px;
|
|
112
|
+
font-family: 'DM Sans', sans-serif;
|
|
113
|
+
font-size: 13px;
|
|
114
|
+
font-weight: 500;
|
|
115
|
+
letter-spacing: 0.12em;
|
|
116
|
+
text-transform: uppercase;
|
|
117
|
+
color: var(--cream);
|
|
118
|
+
background: var(--accent);
|
|
119
|
+
border: none;
|
|
120
|
+
border-radius: 1px;
|
|
121
|
+
cursor: pointer;
|
|
122
|
+
transition: background 0.3s, transform 0.2s, box-shadow 0.3s;
|
|
123
|
+
animation: fadeUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.45s both;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.cta:hover {
|
|
127
|
+
background: var(--accent-light);
|
|
128
|
+
transform: translateY(-1px);
|
|
129
|
+
box-shadow: 0 8px 32px rgba(200, 85, 61, 0.3);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.cta:active {
|
|
133
|
+
transform: translateY(0);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.cta svg {
|
|
137
|
+
width: 16px;
|
|
138
|
+
height: 16px;
|
|
139
|
+
transition: transform 0.3s;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.cta:hover svg {
|
|
143
|
+
transform: translateX(3px);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.rule {
|
|
147
|
+
display: block;
|
|
148
|
+
width: 40px;
|
|
149
|
+
height: 1px;
|
|
150
|
+
background: rgba(244, 240, 235, 0.12);
|
|
151
|
+
margin-bottom: 24px;
|
|
152
|
+
animation: ruleIn 1s cubic-bezier(0.16, 1, 0.3, 1) 0.3s both;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@keyframes fadeUp {
|
|
156
|
+
from { opacity: 0; transform: translateY(16px); }
|
|
157
|
+
to { opacity: 1; transform: translateY(0); }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@keyframes ruleIn {
|
|
161
|
+
from { opacity: 0; width: 0; }
|
|
162
|
+
to { opacity: 1; width: 40px; }
|
|
163
|
+
}
|
|
164
|
+
</style>
|
|
165
|
+
</head>
|
|
166
|
+
<body>
|
|
167
|
+
<div class="noise"></div>
|
|
168
|
+
<div class="card">
|
|
169
|
+
<p class="label">Introducing</p>
|
|
170
|
+
<h1 class="heading">Craft something<br><em>extraordinary</em></h1>
|
|
171
|
+
<span class="rule"></span>
|
|
172
|
+
<p class="desc">Where restraint meets ambition. Build interfaces that command attention through precision, not noise.</p>
|
|
173
|
+
<button class="cta">
|
|
174
|
+
Get started
|
|
175
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
176
|
+
<path d="M3 8h10M9 4l4 4-4 4"/>
|
|
177
|
+
</svg>
|
|
178
|
+
</button>
|
|
179
|
+
</div>
|
|
180
|
+
</body>
|
|
181
|
+
</html>
|