A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
1/* ========================================
2 TAILWIND + DAISYUI
3 ======================================== */
4@import "tailwindcss";
5
6/* Content sources for class detection */
7@source "../../templates/**/*.html";
8@source "../../public/js/**/*.js";
9
10@plugin "@tailwindcss/typography";
11
12@plugin "daisyui" {
13 themes:
14 light --default,
15 dark --prefersdark;
16}
17
18/* ============================================
19 DARK - "Deep Ocean"
20 ============================================ */
21@plugin "daisyui/theme" {
22 name: "dark";
23 default: false;
24 prefersdark: true;
25 color-scheme: "dark";
26 --color-base-100: oklch(19.5% 0.036 257.7);
27 --color-base-200: oklch(23.2% 0.041 253.9);
28 --color-base-300: oklch(28% 0.049 252);
29 --color-base-content: oklch(95.4% 0.022 211);
30 --color-primary: oklch(60% 0.126 221.723);
31 --color-primary-content: oklch(10% 0.126 221.723);
32 --color-secondary: oklch(76.43% 0.135 57.94);
33 --color-secondary-content: oklch(26% 0.079 36.259);
34 --color-accent: oklch(77.32% 0.1 187.98);
35 --color-accent-content: oklch(27% 0.046 192.524);
36 --color-neutral: oklch(32.3% 0.032 259.7);
37 --color-neutral-content: oklch(93.3% 0.026 208.7);
38 --color-info: oklch(74% 0.16 232.661);
39 --color-info-content: oklch(29% 0.066 243.157);
40 --color-success: oklch(76% 0.177 163.223);
41 --color-success-content: oklch(37% 0.077 168.94);
42 --color-warning: oklch(82% 0.189 84.429);
43 --color-warning-content: oklch(41% 0.112 45.904);
44 --color-error: oklch(71% 0.194 13.428);
45 --color-error-content: oklch(27% 0.105 12.094);
46 --radius-selector: 0.5rem;
47 --radius-field: 0.25rem;
48 --radius-box: 0.5rem;
49 --size-selector: 0.25rem;
50 --size-field: 0.25rem;
51 --border: 1px;
52 --depth: 1;
53 --noise: 0;
54}
55
56/* ============================================
57 LIGHT - "Surface / Shallow Water"
58 ============================================ */
59@plugin "daisyui/theme" {
60 name: "light";
61 default: true
62 prefersdark: false;
63 color-scheme: "light";
64 --color-base-100: oklch(99.4% 0.004 214.3);
65 --color-base-200: oklch(97.3% 0.01 212.5);
66 --color-base-300: oklch(93.7% 0.02 212.5);
67 --color-base-content: oklch(21.1% 0.037 254.4);
68 --color-primary: oklch(60% 0.126 221.723);
69 --color-primary-content: oklch(10% 0.126 221.723);
70 --color-secondary: oklch(76.43% 0.135 57.94);
71 --color-secondary-content: oklch(26% 0.079 36.259);
72 --color-accent: oklch(77.32% 0.1 187.98);
73 --color-accent-content: oklch(27% 0.046 192.524);
74 --color-neutral: oklch(32.3% 0.032 259.7);
75 --color-neutral-content: oklch(93.3% 0.026 208.7);
76 --color-info: oklch(74% 0.16 232.661);
77 --color-info-content: oklch(29% 0.066 243.157);
78 --color-success: oklch(76% 0.177 163.223);
79 --color-success-content: oklch(37% 0.077 168.94);
80 --color-warning: oklch(82% 0.189 84.429);
81 --color-warning-content: oklch(41% 0.112 45.904);
82 --color-error: oklch(71% 0.194 13.428);
83 --color-error-content: oklch(27% 0.105 12.094);
84 --radius-selector: 0.5rem;
85 --radius-field: 0.25rem;
86 --radius-box: 0.5rem;
87 --size-selector: 0.25rem;
88 --size-field: 0.25rem;
89 --border: 1px;
90 --depth: 1;
91 --noise: 0;
92}
93
94/* ========================================
95 ADDITIONAL CSS VARIABLES
96 ======================================== */
97:root {
98 --shadow-card-hover:
99 0 8px 25px oklch(67.1% 0.05 145 / 0.25), 0 4px 12px oklch(0% 0 0 / 0.1);
100}
101
102[data-theme="dark"] {
103 --shadow-card-hover:
104 0 8px 25px oklch(67.1% 0.05 145 / 0.2), 0 4px 12px oklch(0% 0 0 / 0.2);
105}
106
107[data-theme="light"] {
108 --shadow-card-hover:
109 0 8px 25px oklch(53.1% 0.1 144.8 / 0.25), 0 4px 12px oklch(0% 0 0 / 0.1);
110}
111
112[data-theme="dark"] {
113 --shadow-card-hover:
114 0 8px 25px oklch(63.1% 0.07 144.7 / 0.2), 0 4px 12px oklch(0% 0 0 / 0.2);
115}
116
117/* ========================================
118 NAVBAR GHOST BUTTON HOVER
119 Override DaisyUI's neutral hover for nav icons
120 ======================================== */
121.navbar .btn-ghost:hover {
122 --btn-bg: oklch(from var(--color-secondary) l c h / 0.15);
123 --btn-border: transparent;
124}
125
126/* ========================================
127 THEME-AWARE ICON SWITCHING
128 ======================================== */
129.icon-light {
130 display: block;
131}
132.icon-dark {
133 display: none;
134}
135[data-theme="dark"] .icon-light {
136 display: none;
137}
138[data-theme="dark"] .icon-dark {
139 display: block;
140}
141
142/* ========================================
143 STICKY FOOTER LAYOUT
144 ======================================== */
145@layer base {
146 body {
147 @apply min-h-screen flex flex-col;
148 }
149
150 main {
151 @apply flex-1;
152 }
153}
154
155/* ========================================
156 TYPOGRAPHY (PROSE) THEME INTEGRATION
157 ======================================== */
158@layer base {
159 /* Make prose inherit DaisyUI theme colors */
160 .prose {
161 --tw-prose-body: var(--color-base-content);
162 --tw-prose-headings: var(--color-base-content);
163 --tw-prose-lead: var(--color-base-content);
164 --tw-prose-links: var(--color-primary);
165 --tw-prose-bold: var(--color-base-content);
166 --tw-prose-counters: var(--color-base-content);
167 --tw-prose-bullets: var(--color-base-content);
168 --tw-prose-hr: var(--color-base-300);
169 --tw-prose-quotes: var(--color-base-content);
170 --tw-prose-quote-borders: var(--color-base-300);
171 --tw-prose-captions: var(--color-base-content);
172 --tw-prose-code: var(--color-base-content);
173 --tw-prose-pre-code: var(--color-base-content);
174 --tw-prose-pre-bg: var(--color-base-200);
175 --tw-prose-th-borders: var(--color-base-300);
176 --tw-prose-td-borders: var(--color-base-300);
177 }
178}
179
180/* ========================================
181 SVG SPRITE ICONS
182 ======================================== */
183.icon {
184 display: inline-block;
185 width: 1em;
186 height: 1em;
187 stroke: currentColor;
188 stroke-width: 2;
189 stroke-linecap: round;
190 stroke-linejoin: round;
191 fill: none;
192 vertical-align: -0.125em;
193}
194
195/* Icon sizes (matching Tailwind size-* utilities) */
196.icon.size-3 { width: 0.75rem; height: 0.75rem; }
197.icon.size-4 { width: 1rem; height: 1rem; }
198.icon.size-5 { width: 1.25rem; height: 1.25rem; }
199.icon.size-6 { width: 1.5rem; height: 1.5rem; }
200.icon.size-8 { width: 2rem; height: 2rem; }
201
202/* Special size for slightly larger than 1rem (used in star/pull count) */
203.icon.size-\[1\.1rem\] { width: 1.1rem; height: 1.1rem; }
204
205/* Animate spin for loader icons */
206.icon.animate-spin {
207 animation: spin 1s linear infinite;
208}
209
210/* ========================================
211 ACCESSIBILITY UTILITIES
212 ======================================== */
213@layer utilities {
214 /* Screen reader only - visually hidden but accessible */
215 .sr-only {
216 @apply absolute w-px h-px p-0 -m-px overflow-hidden;
217 clip: rect(0, 0, 0, 0);
218 white-space: nowrap;
219 border-width: 0;
220 }
221}
222
223/* ========================================
224 CUSTOM COMPONENTS (Not in DaisyUI)
225 ======================================== */
226@layer components {
227 /* ----------------------------------------
228 COMMAND / CODE DISPLAY
229 ---------------------------------------- */
230 .cmd {
231 @apply flex items-center gap-2 relative w-fit max-w-full overflow-hidden;
232 @apply bg-base-200 border border-base-300 rounded-md;
233 @apply px-3 py-2;
234 }
235
236 .cmd code {
237 @apply font-mono text-sm truncate;
238 }
239
240 /* ----------------------------------------
241 EXPANDABLE SEARCH (nav-specific)
242 Uses transform instead of width for GPU-accelerated animation
243 ---------------------------------------- */
244 .nav-search-wrapper {
245 @apply relative flex items-center;
246 }
247
248 .nav-search-form {
249 @apply absolute right-full mr-2;
250 @apply w-62 opacity-0;
251 @apply transition-[transform,opacity] duration-300;
252 transform: scaleX(0);
253 transform-origin: right;
254 }
255
256 .nav-search-wrapper.expanded .nav-search-form {
257 @apply opacity-100;
258 transform: scaleX(1);
259 }
260
261 /* ----------------------------------------
262 HELM BRAND COLOR (official Helm blue #0F1689)
263 ---------------------------------------- */
264 .text-helm {
265 @apply text-[oklch(31%_0.181_267.5)];
266 }
267
268 [data-theme="dark"] .text-helm {
269 @apply text-[oklch(64.6%_0.19_273.2)];
270 }
271
272 .badge-helm {
273 --badge-color: oklch(31% 0.181 267.5);
274 }
275
276 [data-theme="dark"] .badge-helm {
277 --badge-color: oklch(64.6% 0.19 273.2);
278 }
279
280 /* ----------------------------------------
281 TIER BADGE COLORS
282 ---------------------------------------- */
283
284 .supporter-badge {
285 @apply badge-accent;
286 }
287
288 .supporter-badge-owner {
289 @apply badge-primary;
290 }
291
292 /* ----------------------------------------
293 CARD EXTENSIONS
294 ---------------------------------------- */
295 .card-interactive {
296 @apply cursor-pointer duration-500;
297 transition-property: box-shadow, transform;
298 }
299
300 .card-interactive:hover {
301 box-shadow: var(--shadow-card-hover);
302 transform: translateY(-2px);
303 }
304
305 /* ----------------------------------------
306 ACTOR-TYPEAHEAD COMPONENT STYLING
307 ---------------------------------------- */
308 actor-typeahead {
309 /* Use DaisyUI CSS variables - they auto-switch with theme */
310 --color-background: var(--color-base-100);
311 --color-border: var(--color-base-300);
312 --color-shadow: var(--color-base-content);
313 --color-hover: var(--color-base-200);
314 --color-avatar-fallback: var(--color-base-300);
315 --radius: 0.5rem;
316 --padding-menu: 0.25rem;
317 z-index: 50;
318 }
319
320 actor-typeahead::part(handle) {
321 @apply text-base-content;
322 }
323
324 actor-typeahead::part(menu) {
325 @apply shadow-lg;
326 margin-top: 0.25rem;
327 }
328
329 /* ----------------------------------------
330 RECENT ACCOUNTS DROPDOWN
331 ---------------------------------------- */
332 .recent-accounts-dropdown {
333 @apply absolute top-full left-0 right-0;
334 @apply bg-base-100 border border-base-300;
335 @apply rounded-lg shadow-lg;
336 @apply max-h-60 overflow-y-auto z-50;
337 margin-top: 0.25rem;
338 }
339
340 .recent-accounts-header {
341 @apply px-3 py-2 text-xs font-semibold uppercase;
342 @apply text-base-content/60 border-b border-base-300;
343 }
344
345 .recent-accounts-item {
346 @apply px-3 py-2.5;
347 @apply cursor-pointer transition-colors duration-150;
348 @apply text-base-content;
349 }
350
351 .recent-accounts-item:hover,
352 .recent-accounts-item.focused {
353 @apply bg-base-200;
354 }
355
356 /* ----------------------------------------
357 MENU FORM ITEM (styled like menu <a>)
358 For forms inside DaisyUI menu dropdowns
359 Uses label as visible element, button is sr-only
360 ---------------------------------------- */
361 .menu li > form {
362 @apply w-full;
363 }
364
365 .menu li > form > label {
366 @apply block w-full;
367 }
368
369 /* ----------------------------------------
370 OFFLINE MANIFEST FILTERING
371 Hide offline manifests by default;
372 show when "Show offline images" is checked
373 ---------------------------------------- */
374 .manifests-list > [data-reachable="false"] {
375 display: none;
376 }
377
378 .manifests-list.show-offline > [data-reachable="false"] {
379 display: block;
380 }
381
382 /* ----------------------------------------
383 VULNERABILITY SEVERITY BOX STRIP
384 Docker Hub-style connected severity boxes
385 ---------------------------------------- */
386 .vuln-strip {
387 @apply inline-flex items-stretch text-xs font-semibold leading-none;
388 }
389 .vuln-strip > span {
390 @apply px-1 py-1 min-w-5 text-center cursor-pointer sm:px-2 sm:min-w-7;
391 }
392 .vuln-strip > span:first-child { @apply rounded-l-sm; }
393 .vuln-strip > span:last-child { @apply rounded-r-sm; }
394 .vuln-box-critical { background-color: oklch(45% 0.16 20); color: oklch(97% 0.01 20); }
395 .vuln-box-high { background-color: oklch(58% 0.18 35); color: oklch(97% 0.01 35); }
396 .vuln-box-medium { background-color: oklch(72% 0.15 70); color: oklch(25% 0.05 70); }
397 .vuln-box-low { background-color: oklch(80% 0.1 85); color: oklch(25% 0.05 85); }
398}
399
400/* ========================================
401 TOAST CONTAINER
402 ======================================== */
403#toast-container {
404 pointer-events: none;
405}
406#toast-container > * {
407 pointer-events: auto;
408}
409
410/* ========================================
411 SUPPORTER BADGE TEXT COLOR OVERRIDES
412 Unlayered — wins over DaisyUI's layered
413 .badge base class (utilities layer)
414 ======================================== */
415.supporter-badge { color: var(--color-accent-content); }
416.supporter-badge-owner { color: var(--color-primary-content); }