@phillipsharring/graspr-framework 0.1.0

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,165 @@
1
+ /* Graspr Framework — base styles
2
+ Import this from your app's CSS after @import 'tailwindcss' and @source directives. */
3
+
4
+ /* Override inline FOUC prevention — body becomes visible once this stylesheet loads */
5
+ body { opacity: 1; }
6
+
7
+ /* Form error styles */
8
+ .field-error {
9
+ @apply border-red-600;
10
+ }
11
+
12
+ .field-error:focus {
13
+ @apply ring-red-600;
14
+ }
15
+
16
+ .field-error-text {
17
+ @apply text-sm text-red-600 mt-1;
18
+ }
19
+
20
+ .form-error-banner {
21
+ @apply rounded border border-red-200 bg-red-50 text-red-800 px-4 py-3 text-sm;
22
+ }
23
+
24
+ /* Disabled buttons — visual feedback when HTMX or JS disables a button */
25
+ button:disabled,
26
+ button[disabled] {
27
+ opacity: 0.5;
28
+ cursor: not-allowed;
29
+ }
30
+
31
+ /* HTMX request indicator - dims content during fetch */
32
+ .htmx-request,
33
+ .search-loading {
34
+ opacity: 0.3;
35
+ transition: opacity 75ms ease-out;
36
+ }
37
+
38
+ .htmx-settling {
39
+ transition: opacity 150ms ease-in;
40
+ }
41
+
42
+ /* Modal animation */
43
+ #global-modal {
44
+ transition: visibility 0s linear 150ms, opacity 150ms ease-out;
45
+ opacity: 0;
46
+ visibility: hidden;
47
+ }
48
+
49
+ #global-modal.modal-open {
50
+ transition: visibility 0s linear 0s, opacity 150ms ease-out;
51
+ opacity: 1;
52
+ visibility: visible;
53
+ }
54
+
55
+ #global-modal [role="dialog"] {
56
+ transition: transform 150ms ease-out;
57
+ transform: translateY(2rem);
58
+ outline: none;
59
+ }
60
+
61
+ #global-modal.modal-open [role="dialog"] {
62
+ transform: translateY(0);
63
+ }
64
+
65
+ /* Darker backdrop when examples layout is active */
66
+ body:has(#app[data-layout="examples"]) #global-modal .absolute.inset-0 {
67
+ background: rgba(255, 255, 255, 0.50);
68
+ }
69
+
70
+ /* Modal size variants */
71
+ #global-modal [role="dialog"].modal-sm {
72
+ max-width: 24rem;
73
+ }
74
+
75
+ #global-modal [role="dialog"].modal-lg {
76
+ max-width: 56rem;
77
+ }
78
+
79
+ /* Takeover modal - fullscreen with blurred backdrop */
80
+ #global-modal.modal-takeover .absolute.inset-0 {
81
+ backdrop-filter: blur(8px);
82
+ background: rgba(0, 0, 0, 0.3);
83
+ }
84
+
85
+ #global-modal.modal-takeover > .relative.z-10 {
86
+ padding: 0;
87
+ align-items: stretch;
88
+ }
89
+
90
+ #global-modal.modal-takeover [role="dialog"] {
91
+ max-width: none;
92
+ max-height: none;
93
+ width: 100%;
94
+ height: 100dvh;
95
+ border-radius: 0;
96
+ border: none;
97
+ background: transparent;
98
+ }
99
+
100
+ /* Hide default header in takeover mode - template provides its own UI */
101
+ #global-modal.modal-takeover #global-modal-header {
102
+ display: none;
103
+ }
104
+
105
+ /* Show takeover close button only in takeover mode */
106
+ #global-modal.modal-takeover .takeover-close-btn {
107
+ display: block;
108
+ }
109
+
110
+ /* Takeover content should fill available space */
111
+ #global-modal.modal-takeover #global-modal-content {
112
+ flex: 1;
113
+ display: flex;
114
+ flex-direction: column;
115
+ padding: 0;
116
+ }
117
+
118
+ /* Takeover modal animation - fade/scale instead of slide */
119
+ #global-modal.modal-takeover [role="dialog"] {
120
+ transform: scale(0.98);
121
+ opacity: 0;
122
+ transition: transform 200ms ease-out, opacity 200ms ease-out;
123
+ }
124
+
125
+ #global-modal.modal-takeover.modal-open [role="dialog"] {
126
+ transform: scale(1);
127
+ opacity: 1;
128
+ }
129
+
130
+ /* Sortable drag-and-drop */
131
+ .sortable-ghost { opacity: 0.4; background-color: #dbeafe; }
132
+ .sortable-chosen { background-color: #eff6ff; }
133
+ .sortable-disabled .drag-handle { visibility: hidden; pointer-events: none; }
134
+
135
+ /* Active nav link — faux-bold via text-shadow to avoid layout shift */
136
+ .active-nav {
137
+ text-shadow: 0 0 0.01px currentColor, 0 0 0.01px currentColor;
138
+ }
139
+
140
+ /* ---- Confirm dialog: default (admin/base) ---- */
141
+ .confirm-message { color: rgb(15 23 42); } /* slate-900 */
142
+ .confirm-subtext { color: rgb(71 85 105); } /* slate-600 */
143
+ .confirm-checkbox { color: rgb(51 65 85); } /* slate-700 */
144
+ .confirm-cancel-btn {
145
+ border-color: rgb(203 213 225); /* slate-300 */
146
+ color: rgb(51 65 85);
147
+ }
148
+ .confirm-cancel-btn:hover { background: rgb(248 250 252); } /* slate-50 */
149
+ .confirm-ok-btn {
150
+ background: rgb(15 23 42); /* slate-900 */
151
+ color: white;
152
+ }
153
+ .confirm-ok-btn:hover { background: rgb(30 41 59); } /* slate-800 */
154
+
155
+ /* Table column sort headers */
156
+ th[data-sort] { cursor: pointer; user-select: none; }
157
+ th[data-sort]:hover { background-color: rgba(0, 0, 0, 0.04); }
158
+ th[data-sort]::after { content: '\21C5'; opacity: 0.3; margin-left: 0.25rem; font-size: 0.75em; }
159
+ th[data-sort].sort-asc::after { content: '\2191'; opacity: 1; }
160
+ th[data-sort].sort-desc::after { content: '\2193'; opacity: 1; }
161
+
162
+ /* Confirm dialog progress bar */
163
+ .confirm-progress-bar {
164
+ transition: width 1s ease-out;
165
+ }