@apliteni/apliteni-ui 0.2.4

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.
@@ -0,0 +1,72 @@
1
+ /* ============================================================================
2
+ * Code snippet — .ui-snippet (header bar + copyable body + shell highlighting)
3
+ * Reveal variant (.ui-snippet--reveal) tints green for a live token/secret.
4
+ * ========================================================================== */
5
+
6
+ .ui-snippet {
7
+ background: var(--surface-2);
8
+ border-radius: var(--radius-md);
9
+ overflow: hidden;
10
+ }
11
+ .ui-snippet__bar {
12
+ display: flex;
13
+ justify-content: space-between;
14
+ align-items: center;
15
+ padding: 10px 15px;
16
+ }
17
+ .ui-snippet__bar span {
18
+ font-size: 11.5px;
19
+ letter-spacing: 0.12em;
20
+ text-transform: uppercase;
21
+ color: var(--muted);
22
+ font-weight: var(--weight-semibold);
23
+ }
24
+ .ui-snippet pre {
25
+ margin: 0;
26
+ padding: 0 15px 14px;
27
+ overflow-x: auto;
28
+ font-size: var(--text-sm);
29
+ line-height: 1.55;
30
+ color: var(--text);
31
+ white-space: pre;
32
+ font-family: var(--font-mono);
33
+ }
34
+ .ui-snippet__copy {
35
+ background: none;
36
+ border: 0;
37
+ color: var(--muted);
38
+ cursor: pointer;
39
+ font-family: var(--font-sans);
40
+ font-size: 12px;
41
+ display: inline-flex;
42
+ align-items: center;
43
+ gap: 6px;
44
+ padding: 2px 4px;
45
+ transition: color var(--dur-fast) var(--ease);
46
+ }
47
+ .ui-snippet__copy:hover { color: var(--accent); }
48
+ .ui-snippet__copy svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 1.8; }
49
+
50
+ /* Shell token highlighting (matches viz/account.mjs classes) */
51
+ .ui-snippet pre .k { color: var(--purple-mid); font-weight: var(--weight-medium); }
52
+ .ui-snippet pre .f { color: var(--cyan); }
53
+ .ui-snippet pre .s { color: var(--green); }
54
+ .ui-snippet pre .u { color: var(--cyan); }
55
+ .ui-snippet pre .c { color: var(--muted); }
56
+
57
+ /* Reveal: a live secret/token, tinted green */
58
+ .ui-snippet--reveal {
59
+ background: color-mix(in srgb, var(--green) 10%, var(--surface));
60
+ }
61
+ .ui-snippet--reveal .ui-snippet__bar span { color: var(--green); }
62
+ .ui-snippet--reveal pre { color: var(--green); word-break: break-all; white-space: pre-wrap; }
63
+
64
+ /* Inline code */
65
+ .ui-code {
66
+ font-family: var(--font-mono);
67
+ font-size: 0.9em;
68
+ background: var(--surface-2);
69
+ padding: 2px 6px;
70
+ border-radius: var(--radius-xs);
71
+ color: var(--text);
72
+ }
@@ -0,0 +1,113 @@
1
+ /* ============================================================================
2
+ * Inline feedback widget — .ui-fb*
3
+ * A "Give feedback" pill on text selection + a composer modal (quoted excerpt,
4
+ * note, Send, spinner, success check, error). Ported from the strategy portal,
5
+ * remapped onto kit tokens and made accent-aware: the pill and primary button
6
+ * follow --accent / --accent-strong, so the widget re-themes with the sub-theme.
7
+ * Behaviour lives in wireFeedback(); markup in feedbackWidget().
8
+ * ========================================================================== */
9
+
10
+ :root {
11
+ --ui-fb-pill-grad: linear-gradient(135deg, var(--accent), var(--accent-strong));
12
+ --ui-fb-pill-glow: color-mix(in srgb, var(--accent) 45%, transparent);
13
+ --ui-fb-sel: color-mix(in srgb, var(--accent) 22%, transparent);
14
+ }
15
+
16
+ /* Selection highlight kept while the composer is open */
17
+ .ui-fbmark { background: var(--ui-fb-sel); border-radius: 3px; box-shadow: 0 0 0 3px var(--ui-fb-sel); }
18
+
19
+ /* The floating pill anchored above the selection */
20
+ .ui-fbpill {
21
+ position: absolute; z-index: 60; left: 0; top: 0; opacity: 0; pointer-events: none;
22
+ transform: translate(-50%, -100%) translateY(-4px) scale(.82); transform-origin: bottom center;
23
+ display: inline-flex; align-items: center; gap: 9px;
24
+ background: var(--ui-fb-pill-grad); color: var(--accent-contrast);
25
+ font-family: var(--font-sans); font-size: 13px; font-weight: var(--weight-semibold); letter-spacing: .01em;
26
+ padding: 9px 17px 9px 15px; border-radius: 999px; cursor: pointer; white-space: nowrap; overflow: hidden;
27
+ box-shadow: 0 10px 26px var(--ui-fb-pill-glow), 0 2px 6px rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.28);
28
+ transition: transform .2s cubic-bezier(.34,1.56,.64,1), opacity .16s ease, box-shadow .2s ease;
29
+ }
30
+ .ui-fbpill.show { opacity: 1; pointer-events: auto; transform: translate(-50%, -100%) translateY(-9px) scale(1); }
31
+ .ui-fbpill:hover { box-shadow: 0 14px 34px var(--ui-fb-pill-glow), 0 3px 9px rgba(0,0,0,.3), inset 0 1px 0 rgba(255,255,255,.34); }
32
+ .ui-fbpill.show:hover { transform: translate(-50%, -100%) translateY(-12px) scale(1.04); }
33
+ .ui-fbpill:active { transform: translate(-50%, -100%) translateY(-8px) scale(.98); }
34
+ .ui-fbpill svg { width: 16px; height: 16px; color: currentColor; filter: drop-shadow(0 1px 1px rgba(0,0,0,.25)); }
35
+ .ui-fbpill::before {
36
+ content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%;
37
+ background: linear-gradient(100deg, transparent, rgba(255,255,255,.55), transparent); transform: skewX(-18deg);
38
+ }
39
+ .ui-fbpill.show::before { animation: uiFbSheen 1.15s ease .12s 1; }
40
+ .ui-fbpill:hover::before { animation: uiFbSheen .7s ease 1; }
41
+ @keyframes uiFbSheen { 0% { left: -60%; } 100% { left: 130%; } }
42
+
43
+ /* Scrim behind the open composer */
44
+ .ui-fbscrim {
45
+ position: fixed; inset: 0; z-index: 70; background: rgba(6,8,12,.44);
46
+ opacity: 0; pointer-events: none; transition: opacity .2s ease;
47
+ }
48
+ .ui-fbscrim.show { opacity: 1; pointer-events: auto; }
49
+
50
+ /* The composer panel (bottom-centre) */
51
+ .ui-fbcomposer {
52
+ position: fixed; z-index: 71; left: 50%; bottom: 26px; transform: translateX(-50%) translateY(14px);
53
+ width: min(520px, calc(100vw - 32px)); background: var(--bg-elevated); border-radius: 18px;
54
+ box-shadow: var(--shadow-lg); opacity: 0; pointer-events: none;
55
+ transition: opacity .2s ease, transform .2s ease; overflow: hidden;
56
+ }
57
+ .ui-fbcomposer.show { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
58
+
59
+ .ui-fbc__head { display: flex; align-items: center; gap: 12px; padding: 17px 20px 0; }
60
+ .ui-fbc__chip { display: inline-flex; align-items: center; gap: 8px; color: var(--accent); font-size: 13px; font-weight: var(--weight-semibold); letter-spacing: .01em; white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
61
+ .ui-fbc__chip svg { width: 14px; height: 14px; flex: none; opacity: .85; }
62
+ .ui-fbc__x { margin-left: auto; background: var(--surface-2); color: var(--dim); border: 0; width: 28px; height: 28px; border-radius: 8px; cursor: pointer; display: grid; place-items: center; flex: none; }
63
+ .ui-fbc__x:hover { color: var(--strong); }
64
+ .ui-fbc__x svg { width: 14px; height: 14px; }
65
+ .ui-fbc__quote { margin: 14px 20px 0; background: var(--surface-2); border-radius: 12px; padding: 12px 15px; display: flex; gap: 11px; }
66
+ .ui-fbc__qm { color: var(--accent); font-size: 22px; font-weight: var(--weight-bold); line-height: .9; flex: none; opacity: .55; }
67
+ .ui-fbc__quote q { quotes: none; color: var(--dim); font-style: italic; font-size: 13.5px; line-height: 1.55; }
68
+ .ui-fbc__body { padding: 14px 20px 0; }
69
+ .ui-fbcomposer textarea {
70
+ width: 100%; min-height: 96px; resize: vertical; font-family: var(--font-sans); font-size: 14.5px; line-height: 1.55;
71
+ color: var(--strong); background: var(--surface-2); border: 0; border-radius: 12px; padding: 13px 15px; transition: box-shadow .18s ease;
72
+ }
73
+ .ui-fbcomposer textarea::placeholder { color: var(--muted); }
74
+ .ui-fbcomposer textarea:focus { outline: none; box-shadow: 0 0 0 2px var(--accent); }
75
+ .ui-fbc__foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; padding: 16px 20px 18px; }
76
+
77
+ .ui-fbbtn { font-family: var(--font-sans); font-size: 13.5px; font-weight: var(--weight-semibold); border-radius: 10px; padding: 9px 17px; cursor: pointer; border: 0; transition: filter .15s, background .15s, color .15s; }
78
+ .ui-fbbtn.ghost { background: transparent; color: var(--dim); }
79
+ .ui-fbbtn.ghost:hover { color: var(--strong); background: var(--surface-2); }
80
+ .ui-fbbtn.primary { background: var(--accent-strong); color: var(--accent-contrast); display: inline-flex; align-items: center; gap: 9px; }
81
+ .ui-fbbtn.primary:hover { filter: brightness(1.08); }
82
+ .ui-fbbtn.primary:disabled { opacity: .6; cursor: default; filter: none; }
83
+ .ui-fbc__send { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
84
+ .ui-fbspin { flex: none; width: 14px; height: 14px; box-sizing: border-box; border-radius: 50%; border: 2px solid color-mix(in srgb, currentColor 40%, transparent); border-top-color: currentColor; animation: uiFbSpin .7s linear infinite; }
85
+ @keyframes uiFbSpin { to { transform: rotate(360deg); } }
86
+
87
+ /* Success state */
88
+ .ui-fbc__done { padding: 30px 26px 24px; text-align: center; background: radial-gradient(112% 60% at 50% 0%, var(--glow-green), transparent 62%); }
89
+ .ui-fbc__ck { width: 88px; height: 88px; margin: 0 auto 13px; display: grid; place-items: center; }
90
+ .ui-fbck { width: 88px; height: 88px; overflow: visible; display: block; transform-origin: center; animation: uiFbCkSpring 1s cubic-bezier(.22,1,.3,1) both; }
91
+ .ui-fbck-t { fill: none; stroke: var(--surface-2); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; }
92
+ .ui-fbck-m { fill: none; stroke: var(--green); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 118; stroke-dashoffset: 118; animation: uiFbCkDraw .6s cubic-bezier(.5,0,.3,1) .1s forwards; }
93
+ .ui-fbck-s { fill: none; stroke: #fff; stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 15 400; stroke-dashoffset: 133; filter: drop-shadow(0 0 8px var(--green)) drop-shadow(0 0 15px var(--green)); opacity: 0; animation: uiFbCkComet .6s cubic-bezier(.5,0,.3,1) .1s forwards; }
94
+ .ui-fbc__done h4 { color: var(--strong); font-size: 19px; font-weight: var(--weight-semibold); letter-spacing: -.01em; margin-bottom: 7px; }
95
+ .ui-fbc__done p { color: var(--dim); font-size: 13.5px; line-height: 1.55; max-width: 38ch; margin: 0 auto; }
96
+ .ui-fbc__done p b { color: var(--text); font-weight: var(--weight-semibold); }
97
+ .ui-fbc__done .row { margin-top: 18px; display: flex; gap: 10px; justify-content: center; }
98
+ @keyframes uiFbCkDraw { to { stroke-dashoffset: 0; } }
99
+ @keyframes uiFbCkComet { 0% { stroke-dashoffset: 133; opacity: 1; } 82% { opacity: 1; } 100% { stroke-dashoffset: 15; opacity: 0; } }
100
+ @keyframes uiFbCkSpring { 0% { transform: scale(1.32); } 62% { transform: scale(.965); } 82% { transform: scale(1.02); } 100% { transform: scale(1); } }
101
+
102
+ /* Error banner */
103
+ .ui-fbc__err { margin: 14px 20px 0; background: color-mix(in srgb, var(--pink) 14%, transparent); color: var(--pink); font-size: 13px; padding: 11px 15px; border-radius: 11px; display: none; }
104
+ .ui-fbc__err.show { display: block; }
105
+
106
+ @media (prefers-reduced-motion: reduce) {
107
+ .ui-fbpill, .ui-fbpill::before, .ui-fbcomposer, .ui-fbscrim, .ui-fbck, .ui-fbck-m, .ui-fbck-s { animation: none !important; transition: none !important; }
108
+ .ui-fbck-m { stroke-dashoffset: 0; } .ui-fbck-s { display: none; } .ui-fbck { transform: scale(1); }
109
+ }
110
+ @media (max-width: 560px) {
111
+ .ui-fbcomposer { left: 8px; right: 8px; transform: none; bottom: 8px; width: auto; }
112
+ .ui-fbcomposer.show { transform: none; }
113
+ }
@@ -0,0 +1,155 @@
1
+ /* ============================================================================
2
+ * Form controls — input, textarea, select, field, checkbox/radio, switch
3
+ * ========================================================================== */
4
+
5
+ .ui-field { display: block; }
6
+ .ui-field__label {
7
+ display: block;
8
+ color: var(--strong);
9
+ font-size: var(--text-base);
10
+ font-weight: var(--weight-medium);
11
+ margin-bottom: 8px;
12
+ }
13
+ .ui-field__hint { color: var(--muted); font-size: var(--text-sm); margin-top: 7px; line-height: 1.5; }
14
+ .ui-field__error { color: var(--pink); font-size: var(--text-sm); margin-top: 7px; display: flex; align-items: center; gap: 6px; }
15
+
16
+ .ui-input,
17
+ .ui-textarea,
18
+ .ui-select {
19
+ font-family: var(--font-sans);
20
+ font-size: var(--text-base);
21
+ color: var(--strong);
22
+ background: var(--surface-2);
23
+ border: 1px solid var(--border);
24
+ border-radius: var(--radius-md);
25
+ padding: 12px 15px;
26
+ width: 100%;
27
+ transition: border-color var(--dur-med) var(--ease), box-shadow var(--dur-med) var(--ease);
28
+ }
29
+ .ui-textarea { resize: vertical; min-height: 96px; line-height: 1.55; }
30
+
31
+ .ui-input:hover,
32
+ .ui-textarea:hover,
33
+ .ui-select:hover { border-color: var(--border-strong); }
34
+
35
+ .ui-input:focus,
36
+ .ui-textarea:focus,
37
+ .ui-select:focus {
38
+ outline: none;
39
+ border-color: var(--accent);
40
+ box-shadow: var(--ring);
41
+ }
42
+
43
+ .ui-input::placeholder,
44
+ .ui-textarea::placeholder { color: var(--muted); opacity: 0.9; }
45
+
46
+ .ui-input:disabled,
47
+ .ui-textarea:disabled { opacity: 0.5; cursor: not-allowed; }
48
+
49
+ .ui-input.is-invalid,
50
+ .ui-textarea.is-invalid { border-color: var(--pink); }
51
+ .ui-input.is-invalid:focus { box-shadow: 0 0 0 3px var(--glow-pink); }
52
+
53
+ /* Input with a leading icon / adornment */
54
+ .ui-input-group { position: relative; display: flex; align-items: center; }
55
+ .ui-input-group .ui-input { padding-left: 42px; }
56
+ .ui-input-group__icon {
57
+ position: absolute;
58
+ left: 14px;
59
+ width: 17px;
60
+ height: 17px;
61
+ color: var(--muted);
62
+ pointer-events: none;
63
+ }
64
+ .ui-input-group__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 1.8; }
65
+
66
+ .ui-select {
67
+ appearance: none;
68
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23948fa8' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
69
+ background-repeat: no-repeat;
70
+ background-position: right 15px center;
71
+ padding-right: 40px;
72
+ cursor: pointer;
73
+ }
74
+
75
+ /* Checkbox / radio — custom, token-driven */
76
+ .ui-check {
77
+ display: inline-flex;
78
+ align-items: flex-start;
79
+ gap: 11px;
80
+ cursor: pointer;
81
+ font-size: var(--text-base);
82
+ color: var(--text);
83
+ line-height: 1.5;
84
+ }
85
+ .ui-check input {
86
+ appearance: none;
87
+ width: 19px;
88
+ height: 19px;
89
+ flex: none;
90
+ margin-top: 1px;
91
+ border: 1.5px solid var(--border-strong);
92
+ border-radius: var(--radius-xs);
93
+ background: var(--surface-2);
94
+ cursor: pointer;
95
+ transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
96
+ position: relative;
97
+ }
98
+ .ui-check input[type="radio"] { border-radius: 50%; }
99
+ .ui-check input:hover { border-color: var(--accent); }
100
+ .ui-check input:checked { background: var(--accent); border-color: var(--accent); }
101
+ .ui-check input[type="checkbox"]:checked::after {
102
+ content: "";
103
+ position: absolute;
104
+ left: 5px; top: 1.5px;
105
+ width: 5px; height: 10px;
106
+ border: solid var(--accent-contrast);
107
+ border-width: 0 2px 2px 0;
108
+ transform: rotate(45deg);
109
+ }
110
+ .ui-check input[type="radio"]:checked::after {
111
+ content: "";
112
+ position: absolute;
113
+ inset: 4px;
114
+ border-radius: 50%;
115
+ background: var(--accent-contrast);
116
+ }
117
+ .ui-check input:focus-visible { outline: none; box-shadow: var(--ring); }
118
+
119
+ /* Toggle switch */
120
+ .ui-switch {
121
+ --sw-w: 44px;
122
+ --sw-h: 26px;
123
+ position: relative;
124
+ display: inline-block;
125
+ width: var(--sw-w);
126
+ height: var(--sw-h);
127
+ flex: none;
128
+ }
129
+ .ui-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
130
+ .ui-switch__track {
131
+ position: absolute;
132
+ inset: 0;
133
+ background: var(--surface-3);
134
+ border-radius: var(--radius-pill);
135
+ cursor: pointer;
136
+ transition: background var(--dur-med) var(--ease);
137
+ }
138
+ .ui-switch__track::before {
139
+ content: "";
140
+ position: absolute;
141
+ top: 3px;
142
+ left: 3px;
143
+ width: calc(var(--sw-h) - 6px);
144
+ height: calc(var(--sw-h) - 6px);
145
+ background: #fff;
146
+ border-radius: 50%;
147
+ box-shadow: var(--shadow-sm);
148
+ transition: transform var(--dur-med) var(--ease);
149
+ }
150
+ .ui-switch input:checked + .ui-switch__track { background: var(--accent); }
151
+ .ui-switch input:checked + .ui-switch__track::before {
152
+ transform: translateX(calc(var(--sw-w) - var(--sw-h)));
153
+ }
154
+ .ui-switch input:focus-visible + .ui-switch__track { box-shadow: var(--ring); }
155
+ .ui-switch input:disabled + .ui-switch__track { opacity: 0.5; cursor: not-allowed; }
@@ -0,0 +1,164 @@
1
+ /* ============================================================================
2
+ * Layout primitives — account sidebar, page shell, auth card, landing hero.
3
+ * These compose the example apps; each stays token-driven and themeable.
4
+ * ========================================================================== */
5
+
6
+ /* -- Account sidebar (from viz/account.mjs .side) ------------------------ */
7
+ .ui-side { position: sticky; top: 80px; align-self: start; }
8
+ .ui-side .cap {
9
+ font-size: 11px;
10
+ letter-spacing: 0.18em;
11
+ text-transform: uppercase;
12
+ color: var(--muted);
13
+ padding: 0 12px 11px;
14
+ }
15
+ .ui-side a {
16
+ display: flex;
17
+ align-items: center;
18
+ gap: 11px;
19
+ padding: 10px 13px;
20
+ border-radius: 10px;
21
+ color: var(--text);
22
+ text-decoration: none;
23
+ font-size: 14.5px;
24
+ }
25
+ .ui-side a:hover { background: var(--surface-2); }
26
+ .ui-side a.on { background: var(--surface); color: var(--strong); font-weight: 500; }
27
+ .ui-side a svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.7; opacity: 0.7; }
28
+ .ui-side a.on svg { opacity: 1; stroke: var(--accent); }
29
+ .ui-side .ssep { height: 1px; background: var(--border); margin: 8px 12px; }
30
+ .ui-side a.out { color: var(--muted); }
31
+ .ui-side a.out:hover { color: var(--accent); }
32
+
33
+ /* -- Account shell grid -------------------------------------------------- */
34
+ .ui-shell {
35
+ position: relative;
36
+ z-index: 1;
37
+ max-width: 960px;
38
+ margin: 0 auto;
39
+ padding: 40px 26px 96px;
40
+ display: grid;
41
+ grid-template-columns: 200px 1fr;
42
+ gap: 44px;
43
+ }
44
+ .ui-shell__page { min-width: 0; }
45
+ .ui-shell__crumbs { font-size: 13px; color: var(--dim); margin-bottom: 8px; }
46
+ .ui-shell__crumbs b { color: var(--text); font-weight: 500; }
47
+ .ui-shell__page h1 { color: var(--strong); font-weight: 600; font-size: 30px; letter-spacing: -0.01em; margin-bottom: 7px; }
48
+ .ui-shell__page .sub { color: var(--dim); font-size: 15.5px; margin-bottom: 30px; }
49
+ @media (max-width: 720px) {
50
+ .ui-shell { grid-template-columns: 1fr; gap: 20px; }
51
+ .ui-side { position: static; }
52
+ }
53
+
54
+ /* -- Auth card (sign-in / consent) — centered, glowing --------------------- */
55
+ .ui-auth {
56
+ min-height: 100vh;
57
+ display: grid;
58
+ place-items: center;
59
+ padding: 40px 20px;
60
+ position: relative;
61
+ overflow: hidden;
62
+ }
63
+ .ui-auth__card {
64
+ position: relative;
65
+ z-index: 1;
66
+ width: 100%;
67
+ max-width: 420px;
68
+ background: var(--surface);
69
+ border-radius: 22px;
70
+ padding: 38px 36px 32px;
71
+ box-shadow: var(--shadow-lg);
72
+ }
73
+ .ui-auth__brand { display: inline-flex; align-items: center; gap: 10px; margin-bottom: 26px; }
74
+ .ui-auth__brand span { font-size: 15px; font-weight: 600; color: var(--strong); }
75
+ .ui-auth__title { color: var(--strong); font-size: 24px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 7px; }
76
+ .ui-auth__sub { color: var(--dim); font-size: 14.5px; line-height: 1.55; margin-bottom: 26px; }
77
+ .ui-auth__foot { margin-top: 24px; text-align: center; font-size: 13px; color: var(--muted); }
78
+ .ui-auth__foot a { color: var(--accent); }
79
+ .ui-divider { display: flex; align-items: center; gap: 14px; margin: 22px 0; color: var(--muted); font-size: 12px; }
80
+ .ui-divider::before, .ui-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
81
+
82
+ /* App scope grant list (OAuth consent) */
83
+ .ui-scopes { display: flex; flex-direction: column; gap: 2px; margin: 4px 0 8px; }
84
+ .ui-scope { display: flex; gap: 13px; padding: 13px 4px; }
85
+ .ui-scope + .ui-scope { border-top: 1px solid var(--border); }
86
+ .ui-scope__icon {
87
+ width: 38px; height: 38px; flex: none;
88
+ border-radius: 11px;
89
+ display: grid; place-items: center;
90
+ background: var(--glow-purple);
91
+ color: var(--accent);
92
+ }
93
+ .ui-scope__icon svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 1.7; }
94
+ .ui-scope__t { color: var(--strong); font-size: 14px; font-weight: 500; }
95
+ .ui-scope__d { color: var(--dim); font-size: 13px; margin-top: 2px; line-height: 1.5; }
96
+
97
+ /* -- Landing hero -------------------------------------------------------- */
98
+ .ui-hero {
99
+ position: relative;
100
+ overflow: hidden;
101
+ padding: clamp(60px, 12vh, 130px) 0 clamp(50px, 9vh, 100px);
102
+ text-align: center;
103
+ }
104
+ .ui-hero__eyebrow {
105
+ display: inline-flex;
106
+ align-items: center;
107
+ gap: 8px;
108
+ font-size: 12px;
109
+ letter-spacing: 0.06em;
110
+ color: var(--purple-mid);
111
+ background: var(--glow-purple);
112
+ border-radius: 999px;
113
+ padding: 6px 14px;
114
+ margin-bottom: 26px;
115
+ white-space: nowrap;
116
+ }
117
+ .ui-hero__title {
118
+ font-size: clamp(38px, 6.4vw, 66px);
119
+ line-height: 1.04;
120
+ letter-spacing: -0.025em;
121
+ font-weight: 700;
122
+ color: var(--strong);
123
+ max-width: 14ch;
124
+ margin: 0 auto 22px;
125
+ }
126
+ .ui-hero__title .grad {
127
+ background: linear-gradient(120deg, var(--grad-from), var(--grad-to));
128
+ -webkit-background-clip: text;
129
+ background-clip: text;
130
+ -webkit-text-fill-color: transparent;
131
+ }
132
+ .ui-hero__sub {
133
+ font-size: clamp(16px, 2.1vw, 20px);
134
+ color: var(--dim);
135
+ max-width: 52ch;
136
+ margin: 0 auto 34px;
137
+ line-height: 1.6;
138
+ }
139
+ .ui-hero__cta { display: inline-flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
140
+
141
+ /* Feature grid */
142
+ .ui-features {
143
+ display: grid;
144
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
145
+ gap: 20px;
146
+ max-width: 1080px;
147
+ margin: 0 auto;
148
+ padding: 0 26px;
149
+ }
150
+ .ui-feature__icon {
151
+ width: 46px; height: 46px;
152
+ border-radius: 13px;
153
+ display: grid; place-items: center;
154
+ background: var(--glow-purple);
155
+ color: var(--accent);
156
+ margin-bottom: 16px;
157
+ }
158
+ .ui-feature__icon svg { width: 25px; height: 25px; stroke: currentColor; fill: none; stroke-width: 1.8; }
159
+ .ui-feature h3 { color: var(--strong); font-size: 17px; font-weight: 600; margin-bottom: 7px; }
160
+ .ui-feature p { color: var(--dim); font-size: 14.5px; line-height: 1.6; }
161
+
162
+ .ui-section-head { text-align: center; max-width: 620px; margin: 0 auto clamp(40px, 6vh, 64px); }
163
+ .ui-section-head h2 { color: var(--strong); font-size: clamp(28px, 4vw, 40px); font-weight: 700; letter-spacing: -0.02em; margin-bottom: 14px; }
164
+ .ui-section-head p { color: var(--dim); font-size: 17px; line-height: 1.6; }
@@ -0,0 +1,55 @@
1
+ /* ============================================================================
2
+ * Segmented control — .ui-seg (the deck's pill switch: theme, Deck/Text, plan)
3
+ * The selected button rides on a raised surface with a soft shadow.
4
+ * ========================================================================== */
5
+
6
+ .ui-seg {
7
+ display: inline-flex;
8
+ background: var(--surface-2);
9
+ border-radius: var(--radius-2xl);
10
+ padding: 3px;
11
+ gap: 2px;
12
+ }
13
+ .ui-seg button {
14
+ font-family: var(--font-sans);
15
+ font-size: 13.5px;
16
+ font-weight: var(--weight-semibold);
17
+ letter-spacing: 0.02em;
18
+ color: var(--dim);
19
+ background: none;
20
+ border: 0;
21
+ padding: 7px 18px;
22
+ border-radius: var(--radius-2xl);
23
+ cursor: pointer;
24
+ transition: color var(--dur-med) var(--ease), background var(--dur-med) var(--ease);
25
+ }
26
+ .ui-seg button:hover { color: var(--text); }
27
+ .ui-seg button.is-active,
28
+ .ui-seg button[aria-selected="true"] {
29
+ color: var(--strong);
30
+ background: var(--seg-active-bg);
31
+ box-shadow: var(--shadow-seg);
32
+ }
33
+
34
+ .ui-seg--sm button { padding: 5px 13px; font-size: 12px; }
35
+ .ui-seg--block { display: flex; }
36
+ .ui-seg--block button { flex: 1; }
37
+
38
+ /* Accent picker — round colour swatches, active gets a ring */
39
+ .ui-accent-picker { display: inline-flex; gap: 10px; align-items: center; }
40
+ .ui-accent-picker button {
41
+ width: 26px;
42
+ height: 26px;
43
+ border-radius: 50%;
44
+ border: 0;
45
+ padding: 0;
46
+ cursor: pointer;
47
+ background: var(--swatch, var(--accent));
48
+ box-shadow: 0 0 0 2px var(--surface), 0 0 0 2px var(--surface);
49
+ transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
50
+ }
51
+ .ui-accent-picker button:hover { transform: scale(1.08); }
52
+ .ui-accent-picker button.is-active {
53
+ box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--swatch, var(--accent));
54
+ }
55
+ .ui-accent-picker button:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--swatch, var(--accent)); }
@@ -0,0 +1,51 @@
1
+ /* ============================================================================
2
+ * Table — .ui-table (borderless-body, hairline rows, uppercase head)
3
+ * Row modifiers: .is-dead (revoked/struck), right-aligned .ui-table__act
4
+ * ========================================================================== */
5
+
6
+ .ui-table {
7
+ width: 100%;
8
+ border-collapse: collapse;
9
+ font-size: var(--text-base);
10
+ }
11
+ .ui-table th {
12
+ text-align: left;
13
+ font-size: var(--text-xs);
14
+ letter-spacing: 0.09em;
15
+ text-transform: uppercase;
16
+ color: var(--muted);
17
+ font-weight: var(--weight-semibold);
18
+ padding: 0 16px 11px 0;
19
+ border-bottom: 1px solid var(--border);
20
+ }
21
+ .ui-table td {
22
+ padding: 15px 16px 15px 0;
23
+ border-bottom: 1px solid var(--border);
24
+ color: var(--dim);
25
+ vertical-align: middle;
26
+ white-space: nowrap;
27
+ }
28
+ .ui-table tr:last-child td { border-bottom: 0; }
29
+ .ui-table td.ui-table__title { color: var(--strong); font-weight: var(--weight-medium); width: 99%; white-space: normal; }
30
+ .ui-table th:last-child,
31
+ .ui-table td.ui-table__act { padding-right: 0; text-align: right; }
32
+ .ui-table tr.is-dead td { color: var(--muted); }
33
+ .ui-table tr.is-dead td.ui-table__title { text-decoration: line-through; }
34
+ .ui-table tbody tr { transition: background var(--dur-fast) var(--ease); }
35
+ .ui-table--hover tbody tr:hover { background: var(--surface-2); }
36
+
37
+ /* Empty state inside a table area */
38
+ .ui-empty {
39
+ text-align: center;
40
+ padding: 48px 24px;
41
+ color: var(--muted);
42
+ }
43
+ .ui-empty__icon {
44
+ width: 44px; height: 44px;
45
+ margin: 0 auto 14px;
46
+ color: var(--muted);
47
+ opacity: 0.6;
48
+ }
49
+ .ui-empty__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 1.5; }
50
+ .ui-empty__title { color: var(--text); font-size: var(--text-md); font-weight: var(--weight-medium); margin-bottom: 5px; }
51
+ .ui-empty__sub { font-size: var(--text-sm); max-width: 320px; margin: 0 auto; line-height: 1.55; }