diff --git a/DESIGN.md b/DESIGN.md index ef61480091..4d09b5c562 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -29,11 +29,14 @@ change. soft outer box with a small title row. - **Tactile buttons.** Buttons and navigation icon tiles have a 2px bottom edge. They lift 1px on hover and press down on click. -- **Dark gray, not black.** Dark mode is a pure neutral dark gray (page - canvas about sRGB 10,10,10). Light mode is pure neutral - gray. -- **One accent per theme.** Purple in light mode, yellow in dark mode (purple - has too little contrast on dark surfaces). Everything else is neutral. +- **Dark gray, not black.** Dark mode page canvas and the top bar are neutral + sRGB 10,10,10 (`#0a0a0a`). Cards sit one step up (`#121212`). Light mode is + pure neutral gray. +- **One accent.** Coolify purple in both themes (`#6b16ed`, hover `#7317ff`, + pressed `#5a12c7`, depth `#4a0fa3`, light text and icons `#a391ff`). Yellow + is only for real warnings. The dark sidebar, including the logo cell, is + purple-black (`#120e1a`) with a faint brand wash. The page canvas stays + neutral. - **Quiet text.** Sentence case. A clear text ladder: primary, dim, faint. No em dashes in UI copy. @@ -94,8 +97,8 @@ follow the theme. .dark { /* Surfaces (dark: pure neutral dark gray) */ - --ui-canvas: oklch(14.48% 0 0); /* sRGB 10,10,10 */ - --ui-panel: oklch(19.13% 0 0); /* sRGB 20,20,20: header bar, card and table headers */ + --ui-canvas: #0a0a0a; /* page and top bar */ + --ui-panel: #121212; /* cards and table headers, not the top bar */ --ui-card-bg: rgb(255 255 255 / 6%); --ui-card-border: rgb(255 255 255 / 8%); --ui-well-bg: rgb(0 0 0 / 34%); @@ -114,8 +117,15 @@ follow the theme. --ui-fg-dim: oklch(76.99% 0 0); --ui-fg-faint: oklch(65% 0 0); - /* Accent and status: yellow accent in dark mode */ - --ui-accent: oklch(88.13% 0.1507 91.7); + /* Accent stays purple. Yellow is the warning color, not the accent. */ + --ui-accent: #6b16ed; + --ui-accent-top: #7317ff; + --ui-accent-bottom: #5a12c7; + --ui-accent-edge: #4a0fa3; + --ui-accent-fg: #ffffff; + --ui-accent-light: #a391ff; + --ui-sidebar: #120e1a; + --ui-card: #121212; --ui-success: oklch(72.27% 0.192 149.58); --ui-warning: oklch(88.13% 0.1507 91.7); --ui-error: oklch(66% 0.2 27.33); @@ -131,16 +141,16 @@ Rules for the tokens: - Floating surfaces (menus, popovers, tooltips, modals) must be opaque. Use `--ui-menu-bg`, never a translucent value, or the content behind shows through. -- Keep the dark surfaces pure neutral (chroma 0). A brand tint on the - surfaces was tried and removed. +- Keep the page canvas, cards, menus, and logs pure neutral (chroma 0). The + dark sidebar and the logo cell above it are the tinted surface. - **Dark lightness level.** The canvas is at 14.48% and the header panel at 19.13%. To change the level, move every dark surface and border token by the same amount (canvas, panel, menu, hover, borders, and the Coolify surface ladder), so the steps between layers stay the same. If you move only some of them, a hover fill can become darker than its menu. -- The primary buttons use purple in both themes. Only focus rings, active - navigation, and other accent states change to yellow in dark mode. +- Primary buttons, focus rings, and active navigation use purple in both + themes. Warning yellow is not an accent. ## P3. Scales @@ -182,9 +192,14 @@ Class names below are examples. Keep the values and structure. - In dark mode, the header bar, the outer box of a top-level card, and the header row of a table use the same color (`--ui-panel`). The card wells and table rows are the darker content layer below them. -- The sidebar is the canvas color and has a 1px `--ui-chrome-border` right - edge. The brand block (product name and version) at the top of the sidebar - column also uses the canvas color, with a 1px bottom border. +- In light mode the sidebar is the canvas color and has a 1px + `--ui-chrome-border` right edge. In dark mode the sidebar column, including + the logo cell, is `#120e1a` with a brand-purple wash at the top (about 9%, + fading out) and a faint lavender right edge (`rgb(163 145 255 / 0.10)`). +- The top bar matches the canvas. It has no bottom border at rest. After the + page scrolls under it, dark mode draws a lavender hairline + (`rgb(163 145 255 / 0.12)`), a translucent bar, blur, and a soft shadow. + The logo cell stays the solid sidebar color. - Keep the chrome borders faint. A strong border on near-black looks like a line drawn on the page. @@ -205,21 +220,28 @@ Class names below are examples. Keep the values and structure. box-shadow: 0 2px 0 var(--ui-depth-color); transition: transform 80ms, box-shadow 80ms, border-color 120ms, background-color 120ms; } -.dark .nav-tile { border-color: rgb(255 255 255 / 9%); background: rgb(255 255 255 / 4%); } +.dark .nav-tile { + border-color: rgb(163 145 255 / 0.13); + background: rgb(107 22 237 / 0.07); + color: #b9adff; +} .nav-item:hover .nav-tile { transform: translateY(-1px); box-shadow: 0 3px 0 var(--ui-depth-color); } .nav-item:active .nav-tile { transform: translateY(2px); box-shadow: none; } .nav-item.is-active .nav-tile { - color: var(--ui-accent); - border-color: color-mix(in oklab, var(--ui-accent) 45%, transparent); - --ui-depth-color: color-mix(in oklab, var(--ui-accent) 45%, transparent); + color: #fff; + border-color: #8a4dff; + background: linear-gradient(180deg, var(--ui-accent-top), var(--ui-accent-bottom)); + --ui-depth-color: var(--ui-accent-edge); + box-shadow: 0 2px 0 var(--ui-accent-edge), 0 0 16px rgb(115 23 255 / 0.50); } ``` - Use outline icons (1.5px stroke) at 16px. A brand item can use a one-color brand mark when it is clearer than an outline icon. -- Rows with a submenu end in a 12px chevron: accent in light mode, faint gray - in dark mode. -- Group rows under 11px section labels, and separate groups with a 1px divider. +- Rows with a submenu end in a 12px chevron. In dark mode the chevron is + hidden until the row is hovered, focused, or current. +- Group rows under section labels (11px in light mode; 10.5px uppercase muted + lavender in dark mode), and separate groups with a 1px divider. ### Card (outer box, title row, well) @@ -444,10 +466,10 @@ The interface is compact and product-focused: heavy borders or a strong floating shadow; - full-width data tables for dense collections; - outline Reicon glyphs through ``; -- the Coolify purple brand accent in light mode; -- the readable Coolify yellow accent in dark mode; -- solid active-item fills (neutral black/white opacity), not accent gradients; - active state is a flat selected surface with no accent rail; +- the Coolify purple brand accent in both themes (`#6b16ed`); yellow only for + real warnings, such as "Update available"; +- the active sidebar item is a purple gradient tile with a soft glow. The row + itself stays transparent; - sentence-case labels and headings; - never use the em dash (`—`) in UI copy. Prefer a period, colon, comma, or ASCII hyphen (`-`) for empty cells and separators. @@ -527,19 +549,18 @@ the card well (`.dark .application-settings-section-body :is(.listbox-panel, ...)`). | `--coollabs-subtle` | 50% neutral | 70.8% neutral | labels and muted titles (light darkened for WCAG AA 4.5:1) | -Accent behavior is intentionally theme-aware: +Accent behavior uses Coolify purple in both themes. Brand tokens live in +`@theme` as `--color-brand` (`#6b16ed`), `--color-brand-hover` (`#7317ff`), +`--color-brand-press` (`#5a12c7`), `--color-brand-depth` (`#4a0fa3`), and +`--color-brand-light` (`#a391ff`). Dark mode sets `--color-accent` to +`--color-brand`. `--color-warning` stays yellow and is only for real warnings. -- **Light mode:** Coolify purple (`coollabs`) for active controls, focus, - primary actions, and navigation accents. -- **Dark mode:** Coolify yellow (`warning`) for the same states because the - original purple did not provide sufficient text and ring contrast. - -Do not hard-code blue focus rings or leave yellow accent utilities active in -light mode. Primary action patterns should normally follow: +Do not hard-code blue focus rings, and do not use `dark:text-warning` as a +stand-in for the accent. Selected chips follow: ```html bg-coollabs/10 text-coollabs ring-coollabs/25 -dark:bg-warning/15 dark:text-warning dark:ring-warning/25 +dark:bg-brand/15 dark:text-brand-light dark:ring-brand-light/25 ``` The filled top-level action/tab treatment uses the same palette at a restrained @@ -554,16 +575,20 @@ lift off the content: - **Content canvas** is the base layer: `bg-app` in dark (deepest, `--color-app` `oklch(14.48% 0 0)`, sRGB 10,10,10), `bg-neutral-50` in light. The `
` content area and page body use it. -- **Topbar chrome** uses `bg-panel` in dark (`--color-panel` - `oklch(19.13% 0 0)`, sRGB 20,20,20, a clear step lighter than the content canvas) - and `bg-white` in light, so the header reads as a separate panel. In dark - mode, top-level layer cards and table header rows use the same `--color-panel`. +- **Topbar chrome** uses the canvas color in dark (`#0a0a0a`) and `bg-white` + in light. It has no bottom border until the page scrolls under it. Scrolling + adds `is-scrolled` on `` (see `layouts/app.blade.php`) and the dark bar + becomes `rgb(10 10 10 / 0.72)` with blur and a lavender hairline. In dark + mode, top-level cards and table header rows use `--color-card` (`#121212`), + not the top bar. - **Desktop sidebar and the topbar brand block** (Coolify name and version) - use the content canvas color (`bg-neutral-50` / `dark:bg-app`). The sidebar - has a 1px right border, and the brand block has a 1px bottom border. These - chrome borders stay faint (`border-black/[0.06]`, `dark:border-white/[0.04]`); - do not use `dark:border-white/[0.06]`, which a global rule forces to the - solid hairline grey. The mobile drawer keeps `bg-panel` / `bg-white`. + use the canvas color in light mode. In dark mode they use `--color-sidebar` + (`#120e1a`): a vertical brand wash on the nav, a radial wash on the logo + cell, and a lavender right edge. Section labels are 10.5px uppercase mono in + muted lavender. Chevrons are hidden until the row is hovered, focused, or + current. The Admin icon stays neutral. The footer is transparent so the + wash continues. Do not use `dark:border-white/[0.06]` on these chrome edges; + a global rule forces that utility to the solid hairline grey. Dark surface tokens are exact oklch equivalents of chosen sRGB steps. oklch lightness compresses toward pure black below ~15%, so check the rendered sRGB @@ -571,22 +596,26 @@ value. The dark ladder is `--color-app` 10, `--color-panel` 20, `--coollabs-elevated` 22, `--coollabs-base` 28, `--coollabs-recessed` 34 (sRGB, r=g=b), which reads as distinct surfaces. -Temperature: in both modes every panel is **pure neutral gray** (r=g=b). -In dark mode, every surface token (`--color-app`, `--color-panel`, -`--coollabs-*`, `--color-surface`, `--color-raised`, `--color-selected`, -`--color-log`) has chroma 0, so menus, listbox panels, modals, logs, and the -command palette match the canvas. Do not give one surface a cast (blue, warm, -or purple). The light page canvas uses `bg-neutral-50` (not +Temperature: the page canvas, cards, menus, listboxes, modals, logs, and the +command palette stay **pure neutral gray** (r=g=b). Do not tint those. The +dark sidebar (`--color-sidebar`, `#120e1a`) is the exception: it carries a +faint brand-purple wash. The light page canvas uses `bg-neutral-50` (not `bg-gray-50`, which is faintly cool) so it matches the neutral cards and chrome. -The only intentional color is the purple/yellow brand accent. +The only intentional color is the purple brand accent. Yellow is for warnings. - **Layer cards** use the outer box and inset well from section 5. +- **Top-level pages** (Projects, Servers, and the other section roots) do not + repeat the page title in the breadcrumb when that title is the visible `h1`. + Nested pages keep the full trail (project, environment, resource). +- **Pagination** is hidden when there is only one page (both arrows disabled). +- **Project cards** spell out their counts: "1 environment · 35 resources". +- **The view switcher** shows every view. The current one is a purple pill. - **Tables and collection tiles** outside a layer card use the `rounded-xl border … dark:bg-white/[0.05]` shell plus the crisp `--coollabs-hairline` ring; in light they are `bg-white` with the ring and the restrained card lift. In dark mode these shells are painted like layer cards. A tile, a separate pagination bar, or an empty box is a card without a - well, so it is `--color-panel`. A table (a shell whose first child is a - `border-b` header row) has a `--color-panel` header row and rows in the well + well, so it is `--color-card` (`#121212`). A table (a shell whose first child is a + `border-b` header row) has a `--color-card` header row and rows in the well color (`color-mix(in srgb, var(--color-panel) 66%, black)`). These rules match the Tailwind classes in `resources/css/app.css`, because the table shells are copied markup without a shared class. diff --git a/resources/css/app.css b/resources/css/app.css index afdae048ed..6eb6c15cfd 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -39,6 +39,13 @@ --color-coollabs-100: oklch(52.34% 0.287 289.16); --color-coollabs-200: oklch(43.76% 0.2369 289.82); --color-coollabs-300: oklch(38.04% 0.2031 290.47); + /* coolLabs brand purple. Primary actions, focus, and active navigation + use these in both themes. Warning yellow is not an accent. */ + --color-brand: #6b16ed; + --color-brand-hover: #7317ff; + --color-brand-press: #5a12c7; + --color-brand-depth: #4a0fa3; + --color-brand-light: #a391ff; --color-coolgray-100: oklch(20.9% 0 0); --color-coolgray-200: oklch(24.35% 0 0); --color-coolgray-300: oklch(26.03% 0 0); @@ -102,7 +109,33 @@ } .dark .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) { - --button-depth-color: rgb(255 255 255 / 0.08); + --button-depth-color: rgb(107 22 237 / 0.35); + background-color: rgb(107 22 237 / 0.14); + border-color: rgb(163 145 255 / 0.24); + color: #ece8ff; +} + +.dark .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):hover { + background-color: rgb(107 22 237 / 0.18); + border-color: rgb(163 145 255 / 0.34); +} + +.dark .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) svg { + color: var(--color-brand-light); + opacity: 1; +} + +.dark .button.button-highlighted:not(:disabled), +.dark .button[isHighlighted]:not(:disabled) { + background: var(--color-brand); + border-color: transparent; + color: #fff; + --button-depth-color: var(--color-brand-depth); +} + +.dark .button.button-highlighted:not(:disabled):hover, +.dark .button[isHighlighted]:not(:disabled):hover { + background: var(--color-brand-hover); } .button.button-error:not(:disabled) { @@ -1261,7 +1294,13 @@ html:not(.dark) .application-console-shell[data-console-theme="system"] .termina } .dark { - --color-accent: oklch(88.13% 0.1507 91.7); + /* Purple is the accent in dark mode too. Warning yellow stays on + --color-warning for real warnings only (update available, attention). */ + --color-accent: var(--color-brand); + /* Cards sit one step above the #0a0a0a canvas. The top bar uses the canvas, + not this color. The sidebar uses --color-sidebar. */ + --color-card: #121212; + --color-sidebar: #120e1a; /* Dark surface ladder in hex (sRGB), not oklch: oklch lightness compresses to near-black below ~15%, so oklch(15%) rendered as sRGB 11 and cards could not lift off the content canvas (sRGB 10). These give clear, @@ -1842,25 +1881,28 @@ html[data-theme="custom"]:not(.dark) :is(.application-settings-section, .applica background: linear-gradient(var(--well-bg), var(--well-bg)), var(--card-underlay); } -/* Dark mode: top-level cards use the topbar color (see DESIGN.md). */ +/* Dark mode: top-level cards are #121212, a step above the canvas. The top bar + matches the canvas instead (see the brand shell below). */ .dark :is(.application-settings-section, .empty-state):not(:is(.application-settings-section, .application-settings-section-body) *) { - background: var(--color-panel); + background: var(--color-card); + box-shadow: none; } /* Dark mode: collection tiles, pagination bars, and tables match the cards. - A tile is a card without a well, so it takes the topbar color. A table (a - shell with a header row) takes the topbar color on the header row and the - box content (well) color on the rows. */ + A tile is a card without a well. A table (a shell with a header row) takes + the card color on the header row and a darker mix on the rows. */ .dark [class~="rounded-xl"][class~="dark:bg-white/[0.05]"] { - background: var(--color-panel); + background-color: var(--color-card) !important; + border-color: rgb(255 255 255 / 0.08) !important; + box-shadow: none; } .dark [class~="rounded-xl"][class~="dark:bg-white/[0.05]"]:has(> [class~="border-b"]:first-child) { - background: color-mix(in srgb, var(--color-panel) 66%, black); + background: color-mix(in srgb, var(--color-card) 66%, black) !important; } .dark [class~="rounded-xl"][class~="dark:bg-white/[0.05]"] > [class~="border-b"]:first-child { - background: var(--color-panel); + background: var(--color-card) !important; } /* Brief accent ring when a settings nav sub-item scrolls a section into view. @@ -5552,10 +5594,17 @@ html:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-a --button-depth-color: color-mix(in oklab, var(--color-coollabs) 45%, transparent) !important; } -html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-active) .menu-item-icon { - color: var(--color-warning); - border-color: color-mix(in oklab, var(--color-warning) 40%, transparent) !important; - --button-depth-color: color-mix(in oklab, var(--color-warning) 35%, transparent) !important; +html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-active) .menu-item-icon:not(.text-error) { + color: #fff; + border-color: #8a4dff !important; + background: linear-gradient(180deg, var(--color-brand-hover) 0%, var(--color-brand-press) 100%) !important; + --button-depth-color: var(--color-brand-depth) !important; + box-shadow: 0 2px 0 var(--color-brand-depth), 0 0 16px rgb(115 23 255 / 0.50) !important; +} + +html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-active):active .menu-item-icon:not(.text-error) { + transform: translateY(2px); + box-shadow: none !important; } /* Danger Zone icons () stay red, also when active. */ @@ -5644,9 +5693,11 @@ html:where(:not([data-nav-items="flat"])) :is(.menu-item, .menu-subitem):not(.si box-shadow: none; } -html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item, .menu-subitem):not(.sidebar-toggle) .menu-item-icon { - border-color: oklch(100% 0 0 / 0.09); - background: oklch(100% 0 0 / 0.04); +html.dark:where(:not([data-nav-items="flat"])) .app-sidebar :is(.menu-item, .menu-subitem):not(.sidebar-toggle):not(.menu-search):not(.nav-admin):not(.menu-item-active):not(.menu-subitem-active) .menu-item-icon { + border-color: rgb(163 145 255 / 0.13); + background: rgb(107 22 237 / 0.07); + color: #b9adff; + --button-depth-color: rgb(255 255 255 / 0.05); } html:where(:not([data-nav-items="flat"])) :is(.menu-item, .menu-subitem):not(.sidebar-toggle):hover .menu-item-icon, @@ -5655,10 +5706,17 @@ html:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-a background: #fff; } -html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item, .menu-subitem):not(.sidebar-toggle):hover .menu-item-icon, -html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-active) .menu-item-icon { - border-color: oklch(100% 0 0 / 0.18); - background: oklch(100% 0 0 / 0.08); +html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item, .menu-subitem):not(.sidebar-toggle):not(.menu-item-active):not(.menu-subitem-active):hover .menu-item-icon { + border-color: rgb(255 255 255 / 0.14); + background: rgb(255 255 255 / 0.06); + color: #fff; +} + +/* Admin stays a neutral tile unless it is the current page. */ +html.dark .app-sidebar .nav-admin:not(.menu-item-active) .menu-item-icon { + color: oklch(72% 0 0); + background: rgb(255 255 255 / 0.03); + border-color: rgb(255 255 255 / 0.07); } /* Search keeps its original input look while the sidebar is expanded (always on @@ -5948,6 +6006,188 @@ html.dark .canvas-zoom-max { } } +/* Brand shell (dark): black canvas and top bar, purple-black sidebar, scroll hairline. + Light mode keeps the neutral shell. Floating navigation keeps its own frame. */ +html.dark .app-sidebar nav.sidebar-nav, +html.dark .mobile-sidebar-sheet [role="dialog"] { + background-color: var(--color-sidebar); + background-image: linear-gradient(180deg, rgb(107 22 237 / 0.09), transparent 520px); + border-right-color: rgb(163 145 255 / 0.10); + --color-nav-text: oklch(80% 0.02 300); + --color-nav-muted: oklch(58% 0.04 300); +} + +html.dark .app-topbar-brand { + background-color: var(--color-sidebar); + background-image: radial-gradient(140% 260% at 0% 0%, rgb(107 22 237 / 0.12), transparent 70%); + border-right-color: rgb(163 145 255 / 0.10); +} + +html.dark .app-sidebar .sidebar-footer { + background-color: transparent; +} + +html.dark .app-sidebar .menu-search { + background-color: rgb(163 145 255 / 0.06) !important; + box-shadow: inset 0 0 0 1px rgb(163 145 255 / 0.10) !important; +} + +html.dark .app-sidebar .menu-search:hover { + background-color: rgb(163 145 255 / 0.10) !important; +} + +html.dark .app-sidebar .menu-search kbd { + border-color: rgb(163 145 255 / 0.18) !important; +} + +html.dark .app-sidebar nav:not(.sidebar-collapsed) .nav-section { + font-family: var(--font-mono); + font-size: 10.5px; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: uppercase; + color: rgb(163 145 255 / 0.55); + opacity: 1; +} + +html.dark .app-sidebar .nav-chevron { + transition: opacity 120ms ease; +} + +html.dark .app-sidebar .menu-item:not(:hover):not(:focus-visible):not(.menu-item-active) > .nav-chevron { + opacity: 0; +} + +html.dark:not([data-nav-style="floating"]) .app-topbar { + background-color: #0a0a0a; + backdrop-filter: none; + transition: background-color 180ms ease; +} + +html.dark:not([data-nav-style="floating"]) .app-topbar > div:not(.app-topbar-brand) { + border-bottom-color: transparent; + transition: border-color 180ms ease, box-shadow 180ms ease, background-color 180ms ease; +} + +html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar { + background-color: rgb(10 10 10 / 0.72); + backdrop-filter: blur(12px) saturate(140%); +} + +html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar > .app-topbar-brand { + background-color: var(--color-sidebar); +} + +html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar > div:not(.app-topbar-brand) { + border-bottom-color: rgb(163 145 255 / 0.12); + box-shadow: 0 10px 30px -14px rgb(0 0 0 / 0.95), 0 1px 0 rgb(107 22 237 / 0.06); +} + +html.dark .view-toggle { + gap: 2px; + padding: 2px; + background-color: rgb(107 22 237 / 0.06); + border-color: rgb(163 145 255 / 0.16); +} + +html.dark .view-toggle > :is(a, button) { + color: oklch(80% 0.02 300); +} + +html.dark .view-toggle > :is(a, button) svg { + color: var(--color-brand-light); +} + +html.dark .view-toggle > :is(a, button):not(.is-selected):hover { + background-color: rgb(107 22 237 / 0.14); + color: #fff; +} + +html.dark .view-toggle > .is-selected { + background: linear-gradient(180deg, var(--color-brand-hover), var(--color-brand-press)); + color: #fff; + box-shadow: 0 1px 0 var(--color-brand-depth), inset 0 0 0 1px #8a4dff; +} + +html.dark .view-toggle > .is-selected svg { + color: #fff; +} + +html.dark .view-toggle .bg-coollabs { + background-color: rgb(163 145 255 / 0.18); + color: #d9d0ff; +} + +html.dark .resource-glyph { + border-color: rgb(163 145 255 / 0.20); + background: rgb(107 22 237 / 0.10); + color: var(--color-brand-light); +} + +html.dark .card-icon-button { + color: var(--color-brand-light); +} + +html.dark .card-icon-button:hover { + background-color: rgb(107 22 237 / 0.16); + color: #fff; +} + +html.dark .app-main :is(article.group, a.group).rounded-xl { + background-color: var(--color-card) !important; + border-color: rgb(255 255 255 / 0.08) !important; + box-shadow: none; +} + +html.dark .app-main :is(article.group, a.group).rounded-xl:hover { + border-color: rgb(163 145 255 / 0.30) !important; + box-shadow: none; +} + +.project-card-stats { + color: oklch(40% 0 0); + font-size: 11.5px; + font-weight: 500; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.project-card-stats b { + color: oklch(20% 0 0); + font-weight: 600; +} + +.project-card-stats-dot { + margin-inline: 5px; + color: oklch(70% 0 0); +} + +html.dark .project-card-stats { + color: oklch(72% 0 0); +} + +html.dark .project-card-stats b { + color: #f2f2f2; +} + +html.dark .project-card-stats-dot { + color: oklch(45% 0 0); +} + +.dark .application-settings-form :is(.input, select, textarea):focus, +.dark .application-settings-form :is(.input, select, textarea):focus-visible, +.dark .application-settings-workspace :is(.input, select, textarea):focus, +.dark .application-settings-workspace :is(.input, select, textarea):focus-visible { + border-color: var(--color-brand); + box-shadow: 0 0 0 3px rgb(107 22 237 / 0.25) !important; +} + +/* One page of results: the bar is noise. !important beats the flex utility and Alpine x-show. */ +.pager[hidden] { + display: none !important; +} + /* Dark mode (both navigation styles): the floating dotted backdrop shows through see-through surfaces (dark:bg-white/[x] with or without `!`, .button, …). Give the outermost ones the same color as an opaque mix with the app background, like the @@ -5979,7 +6219,8 @@ html.dark .canvas-zoom-max { html.dark .app-main [class*="dark:bg-white/[0.09]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in oklab, #fff 9%, var(--color-app)) !important; } html.dark .app-main [class*="dark:bg-white/[0.14]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in oklab, #fff 14%, var(--color-app)) !important; } html.dark .app-main [class*="dark:bg-white/[0.1]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in oklab, #fff 10%, var(--color-app)) !important; } - html.dark .app-main :is(.button, .view-toggle):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in oklab, #fff 6%, var(--color-app)) !important; } + html.dark .app-main .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: rgb(107 22 237 / 0.14) !important; border-color: rgb(163 145 255 / 0.24) !important; color: #ece8ff !important; } + html.dark .app-main .view-toggle:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: rgb(107 22 237 / 0.06) !important; border-color: rgb(163 145 255 / 0.16) !important; } html.dark .app-main [class*="dark:hover:bg-white/10"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 10%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.025]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 2.5%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.035]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 3.5%, var(--color-app)) !important; } @@ -5991,7 +6232,13 @@ html.dark .canvas-zoom-max { html.dark .app-main [class*="dark:hover:bg-white/[0.08]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 8%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.12]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 12%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.1]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 10%, var(--color-app)) !important; } - html.dark .app-main .button:not(:disabled):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 10%, var(--color-app)) !important; } + html.dark .app-main .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: rgb(107 22 237 / 0.18) !important; border-color: rgb(163 145 255 / 0.34) !important; } + + /* Collection shells are #121212. Same selector as the 5% mix, plus .rounded-xl, so it wins. */ + html.dark .app-main [class*="dark:bg-white/[0.05]"].rounded-xl:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { + background-color: #121212 !important; + border-color: rgb(255 255 255 / 0.08) !important; + } } /* Resource menu in the collapsed main sidebar: icons only. */ diff --git a/resources/css/utilities.css b/resources/css/utilities.css index a35cb76471..9f6d6eb582 100644 --- a/resources/css/utilities.css +++ b/resources/css/utilities.css @@ -142,7 +142,7 @@ } @utility loading-indicator { - @apply text-coollabs dark:text-warning; + @apply text-coollabs dark:text-brand-light; } /* Compact icon-only control (gear, chevrons, etc.) */ @@ -162,7 +162,7 @@ /* Active resource tab (used with aria-current="page") */ @utility app-tab-active { - @apply bg-coollabs/10 text-coollabs shadow-sm ring-1 ring-coollabs/25 hover:bg-coollabs/15 dark:bg-warning/15 dark:text-warning dark:ring-warning/25 dark:hover:bg-warning/20; + @apply bg-coollabs/10 text-coollabs shadow-sm ring-1 ring-coollabs/25 hover:bg-coollabs/15 dark:bg-brand/15 dark:text-brand-light dark:ring-brand-light/25 dark:hover:bg-brand/20; } @utility auth-tooltip { @@ -271,7 +271,7 @@ } @utility heading-item-active { - @apply text-black rounded-sm dark:bg-coolgray-200 dark:text-warning; + @apply text-black rounded-sm dark:bg-coolgray-200 dark:text-brand-light; } @utility icon { @@ -299,7 +299,7 @@ } @utility kbd-custom { - @apply px-2 text-xs rounded-sm border border-dashed border-neutral-700 dark:text-warning; + @apply px-2 text-xs rounded-sm border border-dashed border-neutral-700 dark:text-brand-light; } @utility box { diff --git a/resources/views/components/backup-tabs.blade.php b/resources/views/components/backup-tabs.blade.php index d1c436e09b..9aebda0496 100644 --- a/resources/views/components/backup-tabs.blade.php +++ b/resources/views/components/backup-tabs.blade.php @@ -35,7 +35,7 @@ @if ($context === 'service-schedule') diff --git a/resources/views/components/client-pagination.blade.php b/resources/views/components/client-pagination.blade.php index 924ec6e74b..f017a53a59 100644 --- a/resources/views/components/client-pagination.blade.php +++ b/resources/views/components/client-pagination.blade.php @@ -9,7 +9,7 @@ 'nextDisabled' => 'page >= totalPages', ]) -