feat: centralize frontend Vuetify styling
All checks were successful
deploy-socialize / image (push) Successful in 50s
deploy-socialize / deploy (push) Successful in 19s

This commit is contained in:
2026-05-08 13:45:42 -04:00
parent e81c9f42c9
commit 1ca6ab7117
54 changed files with 1461 additions and 1304 deletions

View File

@@ -0,0 +1,27 @@
# Task: Add frontend style system baseline
## Goal
Remove app-shell styling drift by routing shared chrome controls through Vuetify components and centralized theme-backed tokens.
## Scope
- Expose reusable CSS variables backed by the Vuetify theme.
- Add shared app-shell primitives for navigation buttons, icon buttons, popovers, and menu items.
- Replace native shell buttons with Vuetify controls in `App.vue`, `AppBar`, `AppSidebar`, `SidebarUserMenu`, and `WorkspaceSelector`.
- Leave feature-screen native button migration to a follow-up task because it crosses many workflows.
## Validation
```bash
cd frontend
npm run build
```
## Done
- [x] Tailwind preflight loads before Vuetify styles.
- [x] App-owned CSS loads after Vuetify styles.
- [x] Shared Vuetify defaults are centralized.
- [x] Legacy global native button/card selectors were removed.
- [x] App-shell styles use shared theme-backed tokens.

View File

@@ -0,0 +1,31 @@
# Task: Replace native feature buttons with Vuetify controls
## Goal
Move remaining interactive feature-screen buttons from native `<button>` elements to Vuetify controls so button styling consistently flows through Vuetify.
## Scope
- Replace action buttons with `v-btn`.
- Replace icon-only buttons with `v-btn` using icon-sized styling.
- Preserve specialized non-button native controls only when Vuetify would reduce capability, such as file inputs.
- Keep behavior unchanged while converting one feature area at a time.
## Likely Files
- `frontend/src/components/ImageCropperDialog.vue`
- `frontend/src/features/**/**/*.vue`
- `frontend/src/static/**/*.vue`
## Validation
```bash
cd frontend
npm run build
```
## Done
- [x] Native `<button>` elements under `frontend/src/**/*.vue` were migrated to `v-btn`.
- [x] Public SSR rendering installs the shared Vuetify plugin.
- [x] Frontend build and public prerender pass.

View File

@@ -5,13 +5,14 @@
<div class="shell-sidebar-wrap"> <div class="shell-sidebar-wrap">
<app-sidebar :is-expanded="isSidebarExpanded" /> <app-sidebar :is-expanded="isSidebarExpanded" />
<button <v-btn
class="sidebar-boundary-toggle" class="sidebar-boundary-toggle"
type="button" variant="text"
:ripple="false"
@click="isSidebarExpanded = !isSidebarExpanded" @click="isSidebarExpanded = !isSidebarExpanded"
> >
<v-icon :icon="isSidebarExpanded ? mdiChevronLeft : mdiChevronRight" /> <v-icon :icon="isSidebarExpanded ? mdiChevronLeft : mdiChevronRight" />
</button> </v-btn>
</div> </div>
</template> </template>
@@ -69,8 +70,8 @@
background: background:
radial-gradient(circle at top left, rgba(255, 174, 94, 0.18), transparent 28%), radial-gradient(circle at top left, rgba(255, 174, 94, 0.18), transparent 28%),
radial-gradient(circle at top right, rgba(52, 211, 153, 0.16), transparent 24%), radial-gradient(circle at top right, rgba(52, 211, 153, 0.16), transparent 24%),
linear-gradient(180deg, #fffaf2 0%, #f6efe2 100%); linear-gradient(180deg, var(--app-color-on-primary) 0%, #f6efe2 100%);
color: #172033; color: var(--app-color-on-surface);
} }
.shell-main { .shell-main {
@@ -86,16 +87,17 @@
} }
.sidebar-boundary-toggle { .sidebar-boundary-toggle {
@apply absolute left-full top-[1.48rem] z-40 flex h-[1.8rem] w-[1.8rem] -translate-x-1/2 items-center justify-center rounded-full border transition-colors; @apply absolute left-full top-[1.48rem] z-40 flex h-[1.8rem] min-w-0 w-[1.8rem] -translate-x-1/2 items-center justify-center rounded-full border p-0 normal-case transition-colors;
background: rgba(255, 250, 242, 0.98); background: rgba(255, 250, 242, 0.98);
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
color: #44516a; color: #44516a;
box-shadow: 0 12px 28px rgba(23, 32, 51, 0.12); box-shadow: 0 12px 28px var(--app-border-subtle);
letter-spacing: 0;
} }
.sidebar-boundary-toggle:hover { .sidebar-boundary-toggle:hover {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.sidebar-boundary-toggle :deep(.v-icon) { .sidebar-boundary-toggle :deep(.v-icon) {

View File

@@ -24,86 +24,110 @@ body,
background: #f4f6f3; background: #f4f6f3;
} }
html {
--app-color-background: rgb(var(--v-theme-background));
--app-color-on-background: rgb(var(--v-theme-on-background));
--app-color-surface: rgb(var(--v-theme-surface));
--app-color-surface-muted: rgb(var(--v-theme-surface-muted));
--app-color-on-surface: rgb(var(--v-theme-on-surface));
--app-color-control: rgb(var(--v-theme-control));
--app-color-control-hover: rgb(var(--v-theme-control-hover));
--app-color-control-focus: rgb(var(--v-theme-control-focus));
--app-color-border: rgb(var(--v-theme-border));
--app-color-border-strong: rgb(var(--v-theme-border-strong));
--app-color-primary: rgb(var(--v-theme-primary));
--app-color-on-primary: rgb(var(--v-theme-on-primary));
--app-color-secondary: rgb(var(--v-theme-secondary));
--app-color-on-secondary: rgb(var(--v-theme-on-secondary));
--app-color-tertiary: rgb(var(--v-theme-tertiary));
--app-color-on-tertiary: rgb(var(--v-theme-on-tertiary));
--app-color-accent: rgb(var(--v-theme-accent));
--app-color-accent-strong: rgb(var(--v-theme-accent-strong));
--app-color-highlight: rgb(var(--v-theme-highlight));
--app-color-danger: rgb(var(--v-theme-error));
--app-color-on-danger: rgb(var(--v-theme-on-error));
--app-text-muted: #526178;
--app-text-subtle: #7a8799;
--app-border-subtle: rgba(23, 32, 51, 0.08);
--app-border-muted: rgba(23, 32, 51, 0.06);
--app-surface-glass: rgba(251, 250, 246, 0.84);
--app-surface-raised: #ffffff;
--app-control-subtle: rgb(var(--v-theme-control));
--app-control-hover: rgb(var(--v-theme-control-hover));
--app-control-active: rgba(23, 32, 51, 0.1);
--app-danger-muted: rgb(var(--v-theme-error));
--app-shadow-popover: 0 18px 40px var(--app-border-subtle);
}
a {
color: inherit;
}
input::placeholder, input::placeholder,
textarea::placeholder { textarea::placeholder {
color: #68778a; color: #68778a;
opacity: 1;
} }
@layer components { @layer components {
.btn { .app-sidebar .sidebar-control {
@apply min-w-24 w-full; @apply flex min-w-0 items-center gap-3 rounded-[1.1rem] px-4 py-3 text-sm font-semibold no-underline transition-colors;
@apply p-4; background: transparent;
@apply flex flex-nowrap gap-4 items-center justify-center; color: #44516a;
@apply rounded-lg;
@apply capitalize text-base font-sans font-medium;
@apply px-10;
@apply cursor-pointer;
} }
button.primary { .app-sidebar .sidebar-control:hover {
@apply min-w-24 w-full; background: var(--app-control-hover);
@apply p-4; color: var(--app-color-on-surface);
@apply flex flex-nowrap gap-4 items-center justify-center;
@apply rounded-lg;
@apply capitalize text-base font-sans font-medium;
@apply px-10;
@apply cursor-pointer;
@apply bg-hPrimary text-hOnPrimary;
@apply hover:brightness-125;
} }
button.secondary { .app-sidebar .sidebar-control-active {
@apply min-w-24 w-full; background: linear-gradient(135deg, rgba(255, 138, 61, 0.14), rgba(239, 68, 68, 0.1));
@apply p-4; box-shadow: inset 0 0 0 1px rgba(255, 138, 61, 0.2);
@apply flex flex-nowrap gap-4 items-center justify-center; color: var(--app-color-on-surface);
@apply rounded-lg;
@apply capitalize text-base font-sans font-medium;
@apply px-10;
@apply cursor-pointer;
@apply bg-hSecondary text-hOnSecondary;
@apply hover:brightness-125;
} }
div.dialog { .app-sidebar .sidebar-icon-button {
@apply max-h-[90vh]; @apply flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-[1rem] transition-colors no-underline;
@apply place-self-center; background: transparent;
color: var(--app-text-muted);
} }
div.card { .app-sidebar .sidebar-icon-button:hover {
@apply w-full max-w-[1024px]; background: var(--app-control-hover);
@apply rounded-xl p-4; color: var(--app-color-on-surface);
@apply flex flex-col gap-4;
@apply bg-hSurface text-hOnSurface;
} }
/* Specific styling for dialog cards */ .app-sidebar .sidebar-menu-surface {
div.card.dialog { @apply z-30 flex flex-col gap-1 rounded-[1.25rem] border p-2;
@apply bg-hSurface text-hOnSurface; background: var(--app-surface-raised);
@apply rounded-xl; border-color: var(--app-border-subtle);
@apply shadow-lg; box-shadow: var(--app-shadow-popover);
} }
div.card-title { .app-sidebar .sidebar-menu-option {
@apply font-sans font-bold text-2xl; @apply flex items-center gap-3 rounded-[0.95rem] px-4 py-3 text-left text-sm font-semibold transition-colors;
@apply p-2; color: var(--app-color-on-surface);
@apply text-hOnSurface;
} }
div.card-content { .app-sidebar .sidebar-menu-option:hover {
@apply flex flex-col gap-4; background: var(--app-control-hover);
@apply p-2;
@apply text-hOnSurface;
@apply overflow-y-auto max-h-[60vh];
} }
div.card-actions { .app-sidebar .sidebar-menu-option .v-icon {
@apply p-2; @apply text-base;
@apply flex flex-row gap-4 justify-end; color: var(--app-text-muted);
} }
div.card-actions > * { .app-sidebar .sidebar-menu-option-danger {
@apply w-fit; color: var(--app-danger-muted);
@apply sm:min-w-40 min-w-0; }
.app-sidebar .sidebar-menu-option-danger .v-icon {
color: var(--app-danger-muted);
}
.app-sidebar .sidebar-menu-separator {
@apply my-1;
border-top: 1px solid var(--app-border-subtle);
} }
} }

View File

@@ -0,0 +1,2 @@
@import "vuetify/styles";
@import "./main.css";

View File

@@ -59,7 +59,7 @@
.avatar { .avatar {
@apply inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full font-black uppercase; @apply inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full font-black uppercase;
background: linear-gradient(135deg, rgba(15, 118, 110, 0.16) 0%, rgba(255, 138, 61, 0.18) 100%); background: linear-gradient(135deg, rgba(15, 118, 110, 0.16) 0%, rgba(255, 138, 61, 0.18) 100%);
color: #172033; color: var(--app-color-on-surface);
} }
.avatar img { .avatar img {

View File

@@ -148,13 +148,13 @@
<div class="cropper-eyebrow">Image editor</div> <div class="cropper-eyebrow">Image editor</div>
<h2>{{ title }}</h2> <h2>{{ title }}</h2>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="plain-button" class="plain-button"
:disabled="isSaving" :disabled="isSaving"
@click="closeDialog" @click="closeDialog"
> >
Close Close
</button> </v-btn>
</div> </div>
<div class="cropper-actions"> <div class="cropper-actions">
@@ -178,42 +178,42 @@
variant="outlined" variant="outlined"
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="action-button secondary" class="action-button secondary"
:disabled="isSaving" :disabled="isSaving"
@click="loadImageFromUrl" @click="loadImageFromUrl"
> >
{{ loadLabel }} {{ loadLabel }}
</button> </v-btn>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="action-button secondary" class="action-button secondary"
:disabled="!isReady || isSaving" :disabled="!isReady || isSaving"
@click="zoom(1.15)" @click="zoom(1.15)"
> >
Zoom in Zoom in
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="action-button secondary" class="action-button secondary"
:disabled="!isReady || isSaving" :disabled="!isReady || isSaving"
@click="zoom(0.85)" @click="zoom(0.85)"
> >
Zoom out Zoom out
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="action-button secondary" class="action-button secondary"
:disabled="!isReady || isSaving" :disabled="!isReady || isSaving"
@click="rotate(-90)" @click="rotate(-90)"
> >
Rotate left Rotate left
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="action-button secondary" class="action-button secondary"
:disabled="!isReady || isSaving" :disabled="!isReady || isSaving"
@click="rotate(90)" @click="rotate(90)"
> >
Rotate right Rotate right
</button> </v-btn>
</div> </div>
<div <div
@@ -242,14 +242,14 @@
</div> </div>
<div class="footer-actions"> <div class="footer-actions">
<button <v-btn variant="text" :ripple="false"
class="action-button secondary" class="action-button secondary"
:disabled="isSaving" :disabled="isSaving"
@click="closeDialog" @click="closeDialog"
> >
Cancel Cancel
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="action-button" class="action-button"
:disabled="!isReady || isSaving" :disabled="!isReady || isSaving"
@click="saveCrop" @click="saveCrop"
@@ -261,7 +261,7 @@
:width="2" :width="2"
/> />
<span>{{ isSaving ? 'Saving...' : confirmLabel }}</span> <span>{{ isSaving ? 'Saving...' : confirmLabel }}</span>
</button> </v-btn>
</div> </div>
</div> </div>
</v-dialog> </v-dialog>
@@ -271,8 +271,8 @@
@reference "@/assets/main.css"; @reference "@/assets/main.css";
.cropper-card { .cropper-card {
@apply flex flex-col gap-5 rounded-[1.75rem] border p-5; @apply flex flex-col gap-5 rounded-[1.75rem] border p-5;
background: rgba(255, 255, 255, 0.98); background: var(--app-surface-raised);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.cropper-header { .cropper-header {
@@ -281,12 +281,12 @@
.cropper-eyebrow { .cropper-eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.cropper-header h2 { .cropper-header h2 {
@apply mt-2 text-2xl font-black; @apply mt-2 text-2xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.cropper-actions, .cropper-actions,
@@ -300,9 +300,9 @@
.url-input { .url-input {
@apply min-w-0 flex-1 rounded-full border px-4 py-3 text-sm; @apply min-w-0 flex-1 rounded-full border px-4 py-3 text-sm;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
color: #172033; color: var(--app-color-on-surface);
} }
.footer-actions { .footer-actions {
@@ -315,22 +315,22 @@
} }
.action-button { .action-button {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.action-button.secondary, .action-button.secondary,
.plain-button { .plain-button {
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
color: #172033; color: var(--app-color-on-surface);
border: 1px solid rgba(23, 32, 51, 0.12); border: 1px solid var(--app-border-subtle);
} }
.cropper-stage { .cropper-stage {
@apply overflow-hidden rounded-[1.5rem] border; @apply overflow-hidden rounded-[1.5rem] border;
height: 28rem; height: 28rem;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: #fffaf2; background: var(--app-color-on-primary);
} }
.empty-state, .empty-state,
@@ -339,14 +339,14 @@
} }
.empty-state { .empty-state {
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
background: rgba(255, 250, 242, 0.9); background: rgba(255, 250, 242, 0.9);
} }
.error-message { .error-message {
border-color: rgba(185, 28, 28, 0.12); border-color: rgba(185, 28, 28, 0.12);
color: #b91c1c; color: var(--app-danger-muted);
background: rgba(254, 226, 226, 0.75); background: rgba(254, 226, 226, 0.75);
} }

View File

@@ -12,7 +12,8 @@ import ProductFeaturePage from '@/static/views/ProductFeaturePage.vue';
import PricingPage from '@/static/views/PricingPage.vue'; import PricingPage from '@/static/views/PricingPage.vue';
import BlogsPage from '@/static/views/BlogsPage.vue'; import BlogsPage from '@/static/views/BlogsPage.vue';
import GuidesPage from '@/static/views/GuidesPage.vue'; import GuidesPage from '@/static/views/GuidesPage.vue';
import './assets/main.css'; import { createSocializeVuetify } from '@/plugins/vuetify.js';
import './assets/styles.css';
const publicRoutes = [ const publicRoutes = [
{ path: '/', component: Landing }, { path: '/', component: Landing },
@@ -45,6 +46,7 @@ export async function render(routePath) {
render: () => h(RouterView), render: () => h(RouterView),
}); });
app.use(createSocializeVuetify());
app.use(createPinia()); app.use(createPinia());
app.use(router); app.use(router);
app.use(head); app.use(head);

View File

@@ -18,16 +18,16 @@
:callback="googleCallback" :callback="googleCallback"
popup-type="TOKEN" popup-type="TOKEN"
> >
<button class="secondary"> <v-btn variant="text" :ripple="false" class="secondary">
<v-icon <v-icon
:icon="mdiGoogle" :icon="mdiGoogle"
class="mr-2" class="mr-2"
/> />
{{ t('continueWithGoogle') }} {{ t('continueWithGoogle') }}
</button> </v-btn>
</google-login> </google-login>
<button <v-btn variant="text" :ripple="false"
class="secondary" class="secondary"
type="button" type="button"
@click="handleFacebookLogin" @click="handleFacebookLogin"
@@ -37,7 +37,7 @@
class="mr-2" class="mr-2"
/> />
{{ t('continueWithFacebook') }} {{ t('continueWithFacebook') }}
</button> </v-btn>
</div> </div>
<div class="my-4 flex items-center"> <div class="my-4 flex items-center">
@@ -225,13 +225,13 @@
.login-card { .login-card {
@apply flex min-h-0 w-full flex-1 flex-col justify-center gap-10 bg-white/80 px-5 py-8 sm:flex-none sm:rounded-[1.5rem] sm:border sm:p-8; @apply flex min-h-0 w-full flex-1 flex-col justify-center gap-10 bg-white/80 px-5 py-8 sm:flex-none sm:rounded-[1.5rem] sm:border sm:p-8;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: none; box-shadow: none;
} }
@media (min-width: 640px) { @media (min-width: 640px) {
.login-card { .login-card {
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.08); box-shadow: 0 18px 40px var(--app-border-subtle);
} }
} }

View File

@@ -137,7 +137,7 @@
.content-card { .content-card {
@apply rounded-[1.5rem] border; @apply rounded-[1.5rem] border;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.hero { .hero {
@@ -146,7 +146,7 @@
.breadcrumb-row { .breadcrumb-row {
@apply flex items-center gap-2 text-sm; @apply flex items-center gap-2 text-sm;
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.breadcrumb, .breadcrumb,
@@ -157,18 +157,18 @@
.status-row small, .status-row small,
.status-row em { .status-row em {
@apply text-sm leading-6 not-italic; @apply text-sm leading-6 not-italic;
color: #526178; color: var(--app-text-muted);
} }
.breadcrumb { .breadcrumb {
@apply font-bold uppercase tracking-[0.16em]; @apply font-bold uppercase tracking-[0.16em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.hero h1, .hero h1,
.section-header strong, .section-header strong,
.content-card strong { .content-card strong {
color: #172033; color: var(--app-color-on-surface);
} }
.hero h1 { .hero h1 {
@@ -182,8 +182,8 @@
.meta-chip, .meta-chip,
.version-chip { .version-chip {
@apply rounded-full px-4 py-2 text-xs font-bold uppercase tracking-[0.16em]; @apply rounded-full px-4 py-2 text-xs font-bold uppercase tracking-[0.16em];
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.section-header { .section-header {
@@ -196,8 +196,8 @@
.scope-button { .scope-button {
@apply inline-flex items-center justify-center rounded-full px-5 py-3 text-sm font-bold no-underline transition; @apply inline-flex items-center justify-center rounded-full px-5 py-3 text-sm font-bold no-underline transition;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.scope-button:hover { .scope-button:hover {
@@ -223,11 +223,11 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 text-sm font-medium; @apply rounded-[1.25rem] border p-4 text-sm font-medium;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -178,14 +178,14 @@
</div> </div>
<div class="panel-actions"> <div class="panel-actions">
<button <v-btn variant="text" :ripple="false"
class="secondary" class="secondary"
:disabled="campaignsStore.isCreating" :disabled="campaignsStore.isCreating"
@click="isCreateFormVisible = false" @click="isCreateFormVisible = false"
> >
{{ t('common.cancel') }} {{ t('common.cancel') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="primary" class="primary"
:disabled="campaignsStore.isCreating" :disabled="campaignsStore.isCreating"
@click="submitForm" @click="submitForm"
@@ -197,7 +197,7 @@
:width="2" :width="2"
/> />
<span>{{ campaignsStore.isCreating ? t('common.creating') : t('campaigns.createTitle') }}</span> <span>{{ campaignsStore.isCreating ? t('common.creating') : t('campaigns.createTitle') }}</span>
</button> </v-btn>
</div> </div>
</div> </div>
@@ -250,12 +250,12 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.header h1 { .header h1 {
@apply mt-2 text-4xl font-black; @apply mt-2 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.header p, .header p,
@@ -264,7 +264,7 @@
.campaign-meta span, .campaign-meta span,
.campaign-meta em { .campaign-meta em {
@apply text-sm leading-6 not-italic; @apply text-sm leading-6 not-italic;
color: #526178; color: var(--app-text-muted);
} }
.primary, .primary,
@@ -273,20 +273,20 @@
} }
.primary { .primary {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.secondary { .secondary {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.create-panel, .create-panel,
.campaign-row { .campaign-row {
@apply rounded-[1.5rem] border; @apply rounded-[1.5rem] border;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.create-panel { .create-panel {
@@ -299,7 +299,7 @@
.panel-header strong, .panel-header strong,
.campaign-row strong { .campaign-row strong {
color: #172033; color: var(--app-color-on-surface);
} }
.form-grid { .form-grid {
@@ -308,7 +308,7 @@
.field { .field {
@apply flex flex-col gap-2 text-sm font-semibold; @apply flex flex-col gap-2 text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field-wide { .field-wide {
@@ -317,16 +317,16 @@
.field input { .field input {
@apply rounded-2xl border px-4 py-3 text-sm; @apply rounded-2xl border px-4 py-3 text-sm;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
color: #172033; color: var(--app-color-on-surface);
} }
.field textarea { .field textarea {
@apply min-h-28 rounded-2xl border px-4 py-3 text-sm; @apply min-h-28 rounded-2xl border px-4 py-3 text-sm;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
color: #172033; color: var(--app-color-on-surface);
resize: vertical; resize: vertical;
} }
@@ -353,11 +353,11 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 text-sm font-medium; @apply rounded-[1.25rem] border p-4 text-sm font-medium;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -134,7 +134,7 @@
</div> </div>
<div class="network-tabs"> <div class="network-tabs">
<button <v-btn variant="text" :ripple="false"
v-for="network in networkOptions" v-for="network in networkOptions"
:key="network.value" :key="network.value"
type="button" type="button"
@@ -144,7 +144,7 @@
> >
<v-icon :icon="network.icon" /> <v-icon :icon="network.icon" />
<span>{{ network.value }}</span> <span>{{ network.value }}</span>
</button> </v-btn>
</div> </div>
<div <div
@@ -173,21 +173,21 @@
</div> </div>
<div class="panel-actions"> <div class="panel-actions">
<button <v-btn variant="text" :ripple="false"
class="secondary" class="secondary"
type="button" type="button"
@click="isCreateFormVisible = false" @click="isCreateFormVisible = false"
> >
{{ t('common.cancel') }} {{ t('common.cancel') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="primary" class="primary"
type="button" type="button"
:disabled="channelsStore.isCreating" :disabled="channelsStore.isCreating"
@click="submitForm" @click="submitForm"
> >
{{ channelsStore.isCreating ? t('common.saving') : t('channels.createTitle') }} {{ channelsStore.isCreating ? t('common.saving') : t('channels.createTitle') }}
</button> </v-btn>
</div> </div>
</div> </div>
@@ -241,7 +241,7 @@
</article> </article>
</div> </div>
<button <v-btn variant="text" :ripple="false"
v-else v-else
type="button" type="button"
class="empty-state" class="empty-state"
@@ -249,7 +249,7 @@
> >
<v-icon :icon="mdiPlus" /> <v-icon :icon="mdiPlus" />
<span>{{ t('channels.emptyAction', { network: activeNetwork }) }}</span> <span>{{ t('channels.emptyAction', { network: activeNetwork }) }}</span>
</button> </v-btn>
</section> </section>
</template> </template>
@@ -261,7 +261,7 @@
.header h1 { .header h1 {
@apply text-4xl font-black; @apply text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.header p, .header p,
@@ -273,7 +273,7 @@
.page-message, .page-message,
.empty-state span { .empty-state span {
@apply text-sm leading-6 not-italic; @apply text-sm leading-6 not-italic;
color: #526178; color: var(--app-text-muted);
} }
.network-tabs { .network-tabs {
@@ -282,16 +282,16 @@
.network-tab { .network-tab {
@apply inline-flex items-center gap-2 rounded-full border px-4 py-3 transition; @apply inline-flex items-center gap-2 rounded-full border px-4 py-3 transition;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
color: #526178; color: var(--app-text-muted);
} }
.network-tab.active, .network-tab.active,
.network-tab:hover { .network-tab:hover {
border-color: rgba(255, 138, 61, 0.28); border-color: rgba(255, 138, 61, 0.28);
background: rgba(255, 138, 61, 0.1); background: rgba(255, 138, 61, 0.1);
color: #172033; color: var(--app-color-on-surface);
} }
.channel-grid { .channel-grid {
@@ -303,7 +303,7 @@
.empty-state { .empty-state {
@apply flex flex-col gap-5 rounded-[1.5rem] border p-5; @apply flex flex-col gap-5 rounded-[1.5rem] border p-5;
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.empty-state { .empty-state {
@@ -317,13 +317,13 @@
} }
.primary { .primary {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.secondary { .secondary {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.panel-header { .panel-header {
@@ -334,12 +334,12 @@
.field, .field,
.channel-header strong, .channel-header strong,
.channel-metrics strong { .channel-metrics strong {
color: #172033; color: var(--app-color-on-surface);
} }
.panel-header span { .panel-header span {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #526178; color: var(--app-text-muted);
} }
.form-grid { .form-grid {
@@ -352,7 +352,7 @@
.field input { .field input {
@apply rounded-2xl border px-4 py-3 text-sm; @apply rounded-2xl border px-4 py-3 text-sm;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
} }
@@ -371,8 +371,8 @@
.channel-metrics { .channel-metrics {
@apply grid grid-cols-3 gap-3 rounded-[1rem] border p-4; @apply grid grid-cols-3 gap-3 rounded-[1rem] border p-4;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.channel-metrics div { .channel-metrics div {
@@ -386,10 +386,10 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 font-medium; @apply rounded-[1.25rem] border p-4 font-medium;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -220,13 +220,13 @@
<div class="section details-section"> <div class="section details-section">
<div class="section-header"> <div class="section-header">
<strong>Client details</strong> <strong>Client details</strong>
<button <v-btn variant="text" :ripple="false"
v-if="authStore.isManager" v-if="authStore.isManager"
class="scope-button scope-button-secondary" class="scope-button scope-button-secondary"
@click="isEditFormVisible ? (isEditFormVisible = false) : openEditForm()" @click="isEditFormVisible ? (isEditFormVisible = false) : openEditForm()"
> >
{{ isEditFormVisible ? 'Close editor' : 'Edit details' }} {{ isEditFormVisible ? 'Close editor' : 'Edit details' }}
</button> </v-btn>
</div> </div>
<div <div
@@ -311,20 +311,20 @@
<small>Use a local file or a remote image URL, then crop and scale it.</small> <small>Use a local file or a remote image URL, then crop and scale it.</small>
</div> </div>
<div class="image-picker-actions"> <div class="image-picker-actions">
<button <v-btn variant="text" :ripple="false"
class="scope-button scope-button-secondary" class="scope-button scope-button-secondary"
:disabled="clientsStore.isUpdating" :disabled="clientsStore.isUpdating"
@click="openPortraitDialog('client')" @click="openPortraitDialog('client')"
> >
Change image Change image
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="scope-button scope-button-secondary" class="scope-button scope-button-secondary"
:disabled="clientsStore.isUpdating || !form.portraitUrl" :disabled="clientsStore.isUpdating || !form.portraitUrl"
@click="clearPortrait('client')" @click="clearPortrait('client')"
> >
Remove Remove
</button> </v-btn>
</div> </div>
</div> </div>
</div> </div>
@@ -359,34 +359,34 @@
<small>Use a local file or a remote image URL, then crop and scale it.</small> <small>Use a local file or a remote image URL, then crop and scale it.</small>
</div> </div>
<div class="image-picker-actions"> <div class="image-picker-actions">
<button <v-btn variant="text" :ripple="false"
class="scope-button scope-button-secondary" class="scope-button scope-button-secondary"
:disabled="clientsStore.isUpdating" :disabled="clientsStore.isUpdating"
@click="openPortraitDialog('contact')" @click="openPortraitDialog('contact')"
> >
Change image Change image
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="scope-button scope-button-secondary" class="scope-button scope-button-secondary"
:disabled="clientsStore.isUpdating || !form.primaryContactPortraitUrl" :disabled="clientsStore.isUpdating || !form.primaryContactPortraitUrl"
@click="clearPortrait('contact')" @click="clearPortrait('contact')"
> >
Remove Remove
</button> </v-btn>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="panel-actions"> <div class="panel-actions">
<button <v-btn variant="text" :ripple="false"
class="scope-button scope-button-secondary" class="scope-button scope-button-secondary"
:disabled="clientsStore.isUpdating" :disabled="clientsStore.isUpdating"
@click="isEditFormVisible = false" @click="isEditFormVisible = false"
> >
Cancel Cancel
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="scope-button" class="scope-button"
:disabled="clientsStore.isUpdating" :disabled="clientsStore.isUpdating"
@click="submitEditForm" @click="submitEditForm"
@@ -398,7 +398,7 @@
:width="2" :width="2"
/> />
<span>{{ clientsStore.isUpdating ? 'Saving...' : 'Save client' }}</span> <span>{{ clientsStore.isUpdating ? 'Saving...' : 'Save client' }}</span>
</button> </v-btn>
</div> </div>
</template> </template>
</div> </div>
@@ -489,7 +489,7 @@
.campaign-card { .campaign-card {
@apply rounded-[1.5rem] border; @apply rounded-[1.5rem] border;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.hero { .hero {
@@ -500,7 +500,7 @@
.stat-card strong, .stat-card strong,
.campaign-card strong, .campaign-card strong,
.contact-card strong { .contact-card strong {
color: #172033; color: var(--app-color-on-surface);
} }
.hero-main h1 { .hero-main h1 {
@@ -515,12 +515,12 @@
.campaign-card em, .campaign-card em,
.section-header span { .section-header span {
@apply text-sm leading-6 not-italic; @apply text-sm leading-6 not-italic;
color: #526178; color: var(--app-text-muted);
} }
.breadcrumb { .breadcrumb {
@apply font-bold uppercase tracking-[0.18em]; @apply font-bold uppercase tracking-[0.18em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.hero-meta { .hero-meta {
@@ -530,7 +530,7 @@
.hero-status { .hero-status {
@apply inline-flex items-center rounded-full px-3 py-1 text-xs font-bold uppercase tracking-[0.18em]; @apply inline-flex items-center rounded-full px-3 py-1 text-xs font-bold uppercase tracking-[0.18em];
background: rgba(15, 118, 110, 0.12); background: rgba(15, 118, 110, 0.12);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.stats-grid { .stats-grid {
@@ -552,7 +552,7 @@
.details-section { .details-section {
@apply rounded-[1.5rem] border p-5; @apply rounded-[1.5rem] border p-5;
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.scope-actions { .scope-actions {
@@ -561,8 +561,8 @@
.scope-button { .scope-button {
@apply inline-flex items-center justify-center gap-2 rounded-full px-5 py-3 text-sm font-bold no-underline transition; @apply inline-flex items-center justify-center gap-2 rounded-full px-5 py-3 text-sm font-bold no-underline transition;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.scope-button:hover { .scope-button:hover {
@@ -571,12 +571,12 @@
.scope-button-secondary { .scope-button-secondary {
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
color: #172033; color: var(--app-color-on-surface);
border: 1px solid rgba(23, 32, 51, 0.12); border: 1px solid var(--app-border-subtle);
} }
.scope-button-secondary:hover { .scope-button-secondary:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
} }
.details-grid { .details-grid {
@@ -585,8 +585,8 @@
.detail-row { .detail-row {
@apply flex flex-col gap-2 rounded-[1.25rem] border p-4; @apply flex flex-col gap-2 rounded-[1.25rem] border p-4;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.detail-row-wide { .detail-row-wide {
@@ -595,7 +595,7 @@
.detail-row small { .detail-row small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.identity-row { .identity-row {
@@ -608,7 +608,7 @@
.identity-row strong { .identity-row strong {
@apply truncate text-base font-bold; @apply truncate text-base font-bold;
color: #172033; color: var(--app-color-on-surface);
} }
.form-grid { .form-grid {
@@ -617,7 +617,7 @@
.field { .field {
@apply flex flex-col gap-2 text-sm font-semibold; @apply flex flex-col gap-2 text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field-wide { .field-wide {
@@ -627,9 +627,9 @@
.field input, .field input,
.field select { .field select {
@apply rounded-2xl border px-4 py-3 text-sm; @apply rounded-2xl border px-4 py-3 text-sm;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
background: white; background: white;
color: #172033; color: var(--app-color-on-surface);
} }
.image-field { .image-field {
@@ -638,8 +638,8 @@
.image-picker-card { .image-picker-card {
@apply flex flex-col gap-4 rounded-[1.25rem] border p-4 lg:flex-row lg:items-center lg:justify-between; @apply flex flex-col gap-4 rounded-[1.25rem] border p-4 lg:flex-row lg:items-center lg:justify-between;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.image-picker-copy { .image-picker-copy {
@@ -647,12 +647,12 @@
} }
.image-picker-copy strong { .image-picker-copy strong {
color: #172033; color: var(--app-color-on-surface);
} }
.image-picker-copy small { .image-picker-copy small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.image-picker-actions { .image-picker-actions {
@@ -669,7 +669,7 @@
.section-header strong { .section-header strong {
@apply text-lg font-black; @apply text-lg font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.campaign-list { .campaign-list {
@@ -699,11 +699,11 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 text-sm font-medium; @apply rounded-[1.25rem] border p-4 text-sm font-medium;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -75,13 +75,13 @@
</div> </div>
<div class="action-row"> <div class="action-row">
<button <v-btn variant="text" :ripple="false"
v-if="authStore.isManager" v-if="authStore.isManager"
class="create-button" class="create-button"
@click="openCreateForm" @click="openCreateForm"
> >
{{ t('clients.newClient') }} {{ t('clients.newClient') }}
</button> </v-btn>
</div> </div>
<div <div
@@ -151,14 +151,14 @@
</div> </div>
<div class="panel-actions"> <div class="panel-actions">
<button <v-btn variant="text" :ripple="false"
class="secondary" class="secondary"
:disabled="clientsStore.isCreating" :disabled="clientsStore.isCreating"
@click="isCreateFormVisible = false" @click="isCreateFormVisible = false"
> >
{{ t('common.cancel') }} {{ t('common.cancel') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="primary" class="primary"
:disabled="clientsStore.isCreating" :disabled="clientsStore.isCreating"
@click="submitForm" @click="submitForm"
@@ -170,7 +170,7 @@
:width="2" :width="2"
/> />
<span>{{ clientsStore.isCreating ? t('common.creating') : t('clients.createTitle') }}</span> <span>{{ clientsStore.isCreating ? t('common.creating') : t('clients.createTitle') }}</span>
</button> </v-btn>
</div> </div>
</div> </div>
@@ -227,17 +227,17 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.header h1 { .header h1 {
@apply mt-2 text-4xl font-black; @apply mt-2 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.header p { .header p {
@apply mt-2 text-sm leading-6; @apply mt-2 text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.header { .header {
@@ -261,7 +261,7 @@
.create-button, .create-button,
.primary { .primary {
background: #172033; background: var(--app-color-on-surface);
color: white; color: white;
} }
@@ -272,14 +272,14 @@
.secondary { .secondary {
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid rgba(23, 32, 51, 0.12); border: 1px solid var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.create-panel { .create-panel {
@apply flex flex-col gap-5 rounded-[1.75rem] border p-5 md:p-6; @apply flex flex-col gap-5 rounded-[1.75rem] border p-5 md:p-6;
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.panel-header { .panel-header {
@@ -288,12 +288,12 @@
.panel-header strong { .panel-header strong {
@apply text-lg font-black; @apply text-lg font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.panel-header span { .panel-header span {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #526178; color: var(--app-text-muted);
} }
.form-grid { .form-grid {
@@ -302,7 +302,7 @@
.field { .field {
@apply flex flex-col gap-2 text-sm font-semibold; @apply flex flex-col gap-2 text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field.field-wide { .field.field-wide {
@@ -311,9 +311,9 @@
.field input { .field input {
@apply rounded-2xl border px-4 py-3 text-sm; @apply rounded-2xl border px-4 py-3 text-sm;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
background: white; background: white;
color: #172033; color: var(--app-color-on-surface);
} }
.panel-actions { .panel-actions {
@@ -327,18 +327,18 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 text-sm font-medium; @apply rounded-[1.25rem] border p-4 text-sm font-medium;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
.client-card { .client-card {
@apply flex flex-col gap-3 rounded-[1.5rem] border p-5; @apply flex flex-col gap-3 rounded-[1.5rem] border p-5;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
text-decoration: none; text-decoration: none;
} }
@@ -348,7 +348,7 @@
.client-card strong { .client-card strong {
@apply text-xl font-black; @apply text-xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.client-card span { .client-card span {
@@ -358,7 +358,7 @@
.client-card em { .client-card em {
@apply text-sm leading-6 not-italic; @apply text-sm leading-6 not-italic;
color: #526178; color: var(--app-text-muted);
} }
.client-card small { .client-card small {

View File

@@ -24,7 +24,7 @@
<template> <template>
<div class="color-palette"> <div class="color-palette">
<button <v-btn variant="text" :ripple="false"
v-for="color in props.colors" v-for="color in props.colors"
:key="color" :key="color"
class="color-option" class="color-option"
@@ -44,10 +44,10 @@
gap: 0.5rem; gap: 0.5rem;
width: max-content; width: max-content;
padding: 0.5rem; padding: 0.5rem;
border: 1px solid rgba(23, 32, 51, 0.1); border: 1px solid var(--app-control-active);
border-radius: 0.75rem; border-radius: 0.75rem;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.14); box-shadow: 0 18px 40px rgba(23, 32, 51, 0.14);
} }
@@ -57,13 +57,13 @@
border: 1px solid rgba(255, 255, 255, 0.9); border: 1px solid rgba(255, 255, 255, 0.9);
border-radius: 9999px; border-radius: 9999px;
border-color: rgba(255, 255, 255, 0.9); border-color: rgba(255, 255, 255, 0.9);
box-shadow: 0 0 0 1px rgba(23, 32, 51, 0.12); box-shadow: 0 0 0 1px var(--app-border-subtle);
transition: box-shadow 0.15s ease, transform 0.15s ease; transition: box-shadow 0.15s ease, transform 0.15s ease;
} }
.color-option:hover, .color-option:hover,
.color-option.active { .color-option.active {
transform: scale(1.08); transform: scale(1.08);
box-shadow: 0 0 0 2px #172033; box-shadow: 0 0 0 2px var(--app-color-on-surface);
} }
</style> </style>

View File

@@ -255,7 +255,7 @@
class="approval-step" class="approval-step"
:class="`is-${step.status}`" :class="`is-${step.status}`"
> >
<button <v-btn variant="text" :ripple="false"
class="step-circle" class="step-circle"
type="button" type="button"
:disabled="step.kind !== 'approval' || !canRecordDecision(step.approval) || isSubmittingDecision" :disabled="step.kind !== 'approval' || !canRecordDecision(step.approval) || isSubmittingDecision"
@@ -263,7 +263,7 @@
@click="submitDecision(step.approval.id)" @click="submitDecision(step.approval.id)"
> >
{{ index + 1 }} {{ index + 1 }}
</button> </v-btn>
<div class="step-popover"> <div class="step-popover">
<div class="popover-heading"> <div class="popover-heading">
@@ -342,7 +342,7 @@
.popover-heading strong, .popover-heading strong,
.popover-meta strong, .popover-meta strong,
.decision-row strong { .decision-row strong {
color: #172033; color: var(--app-color-on-surface);
} }
.approval-empty span, .approval-empty span,
@@ -352,7 +352,7 @@
.decision-row span, .decision-row span,
.decision-row small { .decision-row small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.approval-stepper, .approval-stepper,
@@ -378,9 +378,9 @@
.step-circle { .step-circle {
@apply relative z-10 flex h-9 w-9 items-center justify-center rounded-full border text-xs font-black transition; @apply relative z-10 flex h-9 w-9 items-center justify-center rounded-full border text-xs font-black transition;
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(23, 32, 51, 0.16); border-color: rgba(23, 32, 51, 0.16);
color: #526178; color: var(--app-text-muted);
} }
button.step-circle:not(:disabled) { button.step-circle:not(:disabled) {
@@ -397,37 +397,37 @@
} }
.step-circle.is-muted { .step-circle.is-muted {
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
} }
.approval-step.is-approved .step-circle { .approval-step.is-approved .step-circle {
background: #0f766e; background: var(--app-color-on-tertiary);
border-color: #0f766e; border-color: var(--app-color-on-tertiary);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.approval-step.is-scheduled .step-circle { .approval-step.is-scheduled .step-circle {
background: #b45309; background: #b45309;
border-color: #b45309; border-color: #b45309;
color: #fffaf2; color: var(--app-color-on-primary);
} }
.approval-step.is-published .step-circle { .approval-step.is-published .step-circle {
background: #7c3aed; background: #7c3aed;
border-color: #7c3aed; border-color: #7c3aed;
color: #fffaf2; color: var(--app-color-on-primary);
} }
.approval-step.is-current .step-circle { .approval-step.is-current .step-circle {
background: #172033; background: var(--app-color-on-surface);
border-color: #172033; border-color: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.step-popover { .step-popover {
@apply pointer-events-none absolute left-[calc(100%+0.75rem)] top-0 z-20 flex w-[18rem] translate-y-2 flex-col gap-3 rounded-[1rem] border p-4 opacity-0 shadow-xl transition; @apply pointer-events-none absolute left-[calc(100%+0.75rem)] top-0 z-20 flex w-[18rem] translate-y-2 flex-col gap-3 rounded-[1rem] border p-4 opacity-0 shadow-xl transition;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
} }
.approval-step:hover .step-popover, .approval-step:hover .step-popover,
@@ -447,7 +447,7 @@
.decision-row { .decision-row {
@apply flex items-start gap-3 rounded-[0.875rem] border p-3; @apply flex items-start gap-3 rounded-[0.875rem] border p-3;
background: #f8fafc; background: #f8fafc;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.decision-row div { .decision-row div {

View File

@@ -114,13 +114,13 @@
<span>Replying to</span> <span>Replying to</span>
<strong>{{ replyTarget.authorDisplayName }}</strong> <strong>{{ replyTarget.authorDisplayName }}</strong>
</div> </div>
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
title="Cancel reply" title="Cancel reply"
@click="emit('cancel-reply')" @click="emit('cancel-reply')"
> >
<v-icon :icon="mdiClose" /> <v-icon :icon="mdiClose" />
</button> </v-btn>
</div> </div>
<div class="comment-composer-main"> <div class="comment-composer-main">
@@ -148,20 +148,20 @@
class="selected-media-file" class="selected-media-file"
> >
<span>{{ form.mediaFile.name }}</span> <span>{{ form.mediaFile.name }}</span>
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
title="Remove selected media" title="Remove selected media"
@click="clearMediaFile" @click="clearMediaFile"
> >
<v-icon :icon="mdiClose" /> <v-icon :icon="mdiClose" />
</button> </v-btn>
</div> </div>
<div <div
v-if="form.showMentionPicker" v-if="form.showMentionPicker"
class="mention-picker" class="mention-picker"
> >
<button <v-btn variant="text" :ripple="false"
v-for="member in members" v-for="member in members"
:key="member.id" :key="member.id"
class="mention-option" class="mention-option"
@@ -174,7 +174,7 @@
size="sm" size="sm"
/> />
<span>{{ member.displayName }}</span> <span>{{ member.displayName }}</span>
</button> </v-btn>
<div <div
v-if="!members.length" v-if="!members.length"
@@ -208,7 +208,7 @@
hide-details hide-details
@update:model-value="selectMediaFile" @update:model-value="selectMediaFile"
/> />
<button <v-btn variant="text" :ripple="false"
class="icon-tool-button" class="icon-tool-button"
type="button" type="button"
title="Mention a member" title="Mention a member"
@@ -216,8 +216,8 @@
@click="toggleMentionPicker" @click="toggleMentionPicker"
> >
<v-icon :icon="mdiAt" /> <v-icon :icon="mdiAt" />
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="post-button" class="post-button"
type="button" type="button"
:disabled="!canSubmit" :disabled="!canSubmit"
@@ -225,7 +225,7 @@
> >
<v-icon :icon="mdiSend" /> <v-icon :icon="mdiSend" />
{{ isPosting ? 'Posting...' : 'Post' }} {{ isPosting ? 'Posting...' : 'Post' }}
</button> </v-btn>
</div> </div>
</div> </div>
</div> </div>
@@ -235,8 +235,8 @@
@reference "@/assets/main.css"; @reference "@/assets/main.css";
.comment-composer { .comment-composer {
@apply flex flex-col gap-3 rounded-[1.25rem] border p-4; @apply flex flex-col gap-3 rounded-[1.25rem] border p-4;
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
} }
.comment-composer.reply { .comment-composer.reply {
@@ -259,28 +259,28 @@
} }
.reply-context span { .reply-context span {
color: #526178; color: var(--app-text-muted);
} }
.reply-context strong { .reply-context strong {
@apply truncate; @apply truncate;
color: #172033; color: var(--app-color-on-surface);
} }
.reply-context button { .reply-context button {
@apply inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition; @apply inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition;
color: #526178; color: var(--app-text-muted);
} }
.reply-context button:hover, .reply-context button:hover,
.reply-context button:focus-visible { .reply-context button:focus-visible {
background: rgba(15, 118, 110, 0.12); background: rgba(15, 118, 110, 0.12);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.comment-textarea { .comment-textarea {
@apply min-h-24 flex-1 resize-y border-0 bg-transparent text-sm leading-6; @apply min-h-24 flex-1 resize-y border-0 bg-transparent text-sm leading-6;
color: #172033; color: var(--app-color-on-surface);
outline: none; outline: none;
} }
@@ -291,49 +291,49 @@
.selected-media-file { .selected-media-file {
@apply flex items-center justify-between gap-3 rounded-[1rem] border px-3 py-2 text-sm; @apply flex items-center justify-between gap-3 rounded-[1rem] border px-3 py-2 text-sm;
background: rgba(23, 32, 51, 0.03); background: rgba(23, 32, 51, 0.03);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.selected-media-file span { .selected-media-file span {
@apply min-w-0 truncate font-semibold; @apply min-w-0 truncate font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.selected-media-file button { .selected-media-file button {
@apply inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition; @apply inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition;
color: #526178; color: var(--app-text-muted);
} }
.selected-media-file button:hover, .selected-media-file button:hover,
.selected-media-file button:focus-visible { .selected-media-file button:focus-visible {
background: rgba(185, 28, 28, 0.1); background: rgba(185, 28, 28, 0.1);
color: #b91c1c; color: var(--app-danger-muted);
} }
.mention-picker { .mention-picker {
@apply grid max-h-52 gap-2 overflow-y-auto rounded-[1rem] border p-2; @apply grid max-h-52 gap-2 overflow-y-auto rounded-[1rem] border p-2;
background: rgba(23, 32, 51, 0.03); background: rgba(23, 32, 51, 0.03);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.mention-option { .mention-option {
@apply flex items-center gap-3 rounded-[0.875rem] px-2 py-2 text-left text-sm font-semibold transition; @apply flex items-center gap-3 rounded-[0.875rem] px-2 py-2 text-left text-sm font-semibold transition;
color: #172033; color: var(--app-color-on-surface);
} }
.mention-option:hover { .mention-option:hover {
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.empty-note { .empty-note {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.comment-composer-toolbar { .comment-composer-toolbar {
@apply flex items-center justify-end gap-2 border-t pt-3; @apply flex items-center justify-end gap-2 border-t pt-3;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.internal-toggle { .internal-toggle {
@@ -355,20 +355,20 @@
.icon-tool-button { .icon-tool-button {
@apply w-10; @apply w-10;
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #526178; color: var(--app-text-muted);
} }
.icon-tool-button:hover, .icon-tool-button:hover,
.icon-tool-button.active { .icon-tool-button.active {
background: rgba(15, 118, 110, 0.12); background: rgba(15, 118, 110, 0.12);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.post-button { .post-button {
@apply px-4; @apply px-4;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.post-button:disabled { .post-button:disabled {

View File

@@ -85,28 +85,28 @@
</div> </div>
<div class="comment-actions"> <div class="comment-actions">
<button <v-btn variant="text" :ripple="false"
class="comment-action-button" class="comment-action-button"
type="button" type="button"
title="Add reaction" title="Add reaction"
> >
<v-icon :icon="mdiEmoticonPlusOutline" /> <v-icon :icon="mdiEmoticonPlusOutline" />
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="comment-action-button" class="comment-action-button"
type="button" type="button"
title="Resolve" title="Resolve"
> >
<v-icon :icon="mdiCheckCircleOutline" /> <v-icon :icon="mdiCheckCircleOutline" />
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="comment-action-button" class="comment-action-button"
type="button" type="button"
title="Reply" title="Reply"
@click="activeReplyCommentId = thread.comment.id" @click="activeReplyCommentId = thread.comment.id"
> >
<v-icon :icon="mdiReplyOutline" /> <v-icon :icon="mdiReplyOutline" />
</button> </v-btn>
<details class="comment-more-menu"> <details class="comment-more-menu">
<summary <summary
class="comment-action-button" class="comment-action-button"
@@ -115,20 +115,20 @@
<v-icon :icon="mdiDotsVertical" /> <v-icon :icon="mdiDotsVertical" />
</summary> </summary>
<div class="comment-action-menu"> <div class="comment-action-menu">
<button <v-btn variant="text" :ripple="false"
class="comment-menu-item" class="comment-menu-item"
type="button" type="button"
> >
<v-icon :icon="mdiPencilOutline" /> <v-icon :icon="mdiPencilOutline" />
Edit Edit
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="comment-menu-item danger" class="comment-menu-item danger"
type="button" type="button"
> >
<v-icon :icon="mdiDeleteOutline" /> <v-icon :icon="mdiDeleteOutline" />
Delete Delete
</button> </v-btn>
</div> </div>
</details> </details>
</div> </div>
@@ -219,22 +219,22 @@
.empty-note { .empty-note {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.comment-row { .comment-row {
@apply relative flex flex-col gap-3 rounded-[1rem] border p-4 transition; @apply relative flex flex-col gap-3 rounded-[1rem] border p-4 transition;
background: #f8fafc; background: #f8fafc;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
outline: none; outline: none;
} }
.comment-row:hover, .comment-row:hover,
.comment-row:focus-within, .comment-row:focus-within,
.comment-row:focus { .comment-row:focus {
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(15, 118, 110, 0.24); border-color: rgba(15, 118, 110, 0.24);
box-shadow: 0 16px 34px rgba(23, 32, 51, 0.08); box-shadow: 0 16px 34px var(--app-border-subtle);
} }
.comment-row-header { .comment-row-header {
@@ -251,7 +251,7 @@
.comment-author strong { .comment-author strong {
@apply truncate text-sm; @apply truncate text-sm;
color: #172033; color: var(--app-color-on-surface);
} }
.comment-author small { .comment-author small {
@@ -262,7 +262,7 @@
.comment-actions { .comment-actions {
@apply absolute right-3 top-3 z-20 flex items-center gap-1 rounded-full border px-1 py-1 opacity-0 shadow-lg transition; @apply absolute right-3 top-3 z-20 flex items-center gap-1 rounded-full border px-1 py-1 opacity-0 shadow-lg transition;
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
pointer-events: none; pointer-events: none;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
} }
@@ -276,13 +276,13 @@
.comment-action-button { .comment-action-button {
@apply inline-flex h-8 w-8 items-center justify-center rounded-full transition; @apply inline-flex h-8 w-8 items-center justify-center rounded-full transition;
color: #526178; color: var(--app-text-muted);
} }
.comment-action-button:hover, .comment-action-button:hover,
.comment-action-button:focus-visible { .comment-action-button:focus-visible {
background: rgba(15, 118, 110, 0.12); background: rgba(15, 118, 110, 0.12);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.comment-more-menu { .comment-more-menu {
@@ -299,7 +299,7 @@
.comment-more-menu[open] .comment-action-button { .comment-more-menu[open] .comment-action-button {
background: rgba(15, 118, 110, 0.12); background: rgba(15, 118, 110, 0.12);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.comment-more-menu[open] .comment-action-menu, .comment-more-menu[open] .comment-action-menu,
@@ -311,38 +311,38 @@
.comment-action-menu { .comment-action-menu {
@apply absolute right-0 top-[calc(100%+0.375rem)] z-20 hidden min-w-36 flex-col gap-1 rounded-[0.875rem] border p-1 shadow-xl; @apply absolute right-0 top-[calc(100%+0.375rem)] z-20 hidden min-w-36 flex-col gap-1 rounded-[0.875rem] border p-1 shadow-xl;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.comment-menu-item { .comment-menu-item {
@apply flex items-center gap-2 rounded-[0.625rem] px-3 py-2 text-sm font-semibold transition; @apply flex items-center gap-2 rounded-[0.625rem] px-3 py-2 text-sm font-semibold transition;
color: #172033; color: var(--app-color-on-surface);
} }
.comment-menu-item:hover, .comment-menu-item:hover,
.comment-menu-item:focus-visible { .comment-menu-item:focus-visible {
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.comment-menu-item.danger { .comment-menu-item.danger {
color: #b91c1c; color: var(--app-danger-muted);
} }
.comment-menu-item.danger:hover, .comment-menu-item.danger:hover,
.comment-menu-item.danger:focus-visible { .comment-menu-item.danger:focus-visible {
background: rgba(185, 28, 28, 0.1); background: rgba(185, 28, 28, 0.1);
color: #b91c1c; color: var(--app-danger-muted);
} }
.comment-body { .comment-body {
@apply whitespace-pre-line text-sm leading-6; @apply whitespace-pre-line text-sm leading-6;
color: #172033; color: var(--app-color-on-surface);
} }
.comment-attachment { .comment-attachment {
@apply block w-fit max-w-full overflow-hidden rounded-[0.875rem] border; @apply block w-fit max-w-full overflow-hidden rounded-[0.875rem] border;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
background: #ffffff; background: #ffffff;
} }
@@ -372,7 +372,7 @@
.reply-meta strong { .reply-meta strong {
@apply truncate text-sm; @apply truncate text-sm;
color: #172033; color: var(--app-color-on-surface);
} }
.reply-meta small { .reply-meta small {
@@ -382,6 +382,6 @@
.reply-row p { .reply-row p {
@apply whitespace-pre-line text-sm leading-6; @apply whitespace-pre-line text-sm leading-6;
color: #172033; color: var(--app-color-on-surface);
} }
</style> </style>

View File

@@ -583,7 +583,7 @@
} }
function calendarEventColor(event) { function calendarEventColor(event) {
return calendarEventSource(event)?.color ?? '#0f766e'; return calendarEventSource(event)?.color ?? 'var(--app-color-on-tertiary)';
} }
function formatDateTime(value) { function formatDateTime(value) {
@@ -704,14 +704,14 @@
<template> <template>
<section class="editor-shell"> <section class="editor-shell">
<button <v-btn variant="text" :ripple="false"
class="back-button" class="back-button"
type="button" type="button"
@click="navigateBackToContent" @click="navigateBackToContent"
> >
<v-icon :icon="mdiArrowLeft" /> <v-icon :icon="mdiArrowLeft" />
Back to content Back to content
</button> </v-btn>
<div <div
v-if="!isCreateMode && detailStore.isLoading" v-if="!isCreateMode && detailStore.isLoading"
@@ -749,7 +749,7 @@
<span class="meta-chip">{{ item.currentRevisionLabel }}</span> <span class="meta-chip">{{ item.currentRevisionLabel }}</span>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
:disabled="contentItemsStore.isCreating || detailStore.actions.revision" :disabled="contentItemsStore.isCreating || detailStore.actions.revision"
@click="saveContent" @click="saveContent"
@@ -757,7 +757,7 @@
{{ isCreateMode {{ isCreateMode
? (contentItemsStore.isCreating ? 'Creating...' : 'Create content') ? (contentItemsStore.isCreating ? 'Creating...' : 'Create content')
: (detailStore.actions.revision ? 'Saving...' : 'Save revision') }} : (detailStore.actions.revision ? 'Saving...' : 'Save revision') }}
</button> </v-btn>
</div> </div>
</div> </div>
@@ -815,7 +815,7 @@
<div class="date-context field-wide"> <div class="date-context field-wide">
<div class="date-context-days"> <div class="date-context-days">
<button <v-btn variant="text" :ripple="false"
v-for="day in dateContextDays" v-for="day in dateContextDays"
:key="day.key" :key="day.key"
class="date-context-day" class="date-context-day"
@@ -828,14 +828,14 @@
> >
<span>{{ formatContextDay(day.date) }}</span> <span>{{ formatContextDay(day.date) }}</span>
<strong>{{ day.events.length }}</strong> <strong>{{ day.events.length }}</strong>
</button> </v-btn>
</div> </div>
<div <div
v-if="selectedDateCalendarEvents.length" v-if="selectedDateCalendarEvents.length"
class="date-context-panel" class="date-context-panel"
> >
<button <v-btn variant="text" :ripple="false"
v-for="event in selectedDateCalendarEvents" v-for="event in selectedDateCalendarEvents"
:key="event.id" :key="event.id"
class="calendar-context-pill" class="calendar-context-pill"
@@ -844,7 +844,7 @@
@click="showCalendarEvent(event)" @click="showCalendarEvent(event)"
> >
{{ event.title }} {{ event.title }}
</button> </v-btn>
</div> </div>
<div <div
@@ -910,20 +910,20 @@
<div class="content-section"> <div class="content-section">
<div class="section-title-row"> <div class="section-title-row">
<strong>Channels and variants</strong> <strong>Channels and variants</strong>
<button <v-btn variant="text" :ripple="false"
class="secondary-button" class="secondary-button"
type="button" type="button"
@click="addPlacement()" @click="addPlacement()"
> >
Add channel Add channel
</button> </v-btn>
</div> </div>
<div <div
v-if="groupedChannels.length" v-if="groupedChannels.length"
class="channel-suggestions" class="channel-suggestions"
> >
<button <v-btn variant="text" :ripple="false"
v-for="group in groupedChannels" v-for="group in groupedChannels"
:key="group.network" :key="group.network"
class="network-pill" class="network-pill"
@@ -931,7 +931,7 @@
@click="addPlacement(group.channels[0])" @click="addPlacement(group.channels[0])"
> >
{{ group.network }} {{ group.network }}
</button> </v-btn>
</div> </div>
<div <div
@@ -948,13 +948,13 @@
<strong>{{ placement.channelName || placement.network || 'Channel' }}</strong> <strong>{{ placement.channelName || placement.network || 'Channel' }}</strong>
<span>{{ placement.variantLabel || 'Custom variant' }}</span> <span>{{ placement.variantLabel || 'Custom variant' }}</span>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="link-button" class="link-button"
type="button" type="button"
@click="removePlacement(placement.id)" @click="removePlacement(placement.id)"
> >
Remove Remove
</button> </v-btn>
</div> </div>
<div class="form-grid compact-grid"> <div class="form-grid compact-grid">
@@ -1018,13 +1018,13 @@
<div class="media-section"> <div class="media-section">
<div class="section-title-row"> <div class="section-title-row">
<strong>Media</strong> <strong>Media</strong>
<button <v-btn variant="text" :ripple="false"
class="secondary-button" class="secondary-button"
type="button" type="button"
@click="addMedia(placement)" @click="addMedia(placement)"
> >
Add media Add media
</button> </v-btn>
</div> </div>
<div <div
@@ -1063,13 +1063,13 @@
/> />
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="link-button" class="link-button"
type="button" type="button"
@click="removeMedia(placement, media.id)" @click="removeMedia(placement, media.id)"
> >
Remove media Remove media
</button> </v-btn>
</div> </div>
</div> </div>
@@ -1108,7 +1108,7 @@
<template v-else> <template v-else>
<div class="tab-strip"> <div class="tab-strip">
<button <v-btn variant="text" :ripple="false"
v-for="tab in productionTabs" v-for="tab in productionTabs"
:key="tab.key" :key="tab.key"
class="tab-button" class="tab-button"
@@ -1118,7 +1118,7 @@
> >
{{ tab.label }} {{ tab.label }}
<span>{{ tab.count }}</span> <span>{{ tab.count }}</span>
</button> </v-btn>
</div> </div>
<template v-if="activeProductionTab === 'comments'"> <template v-if="activeProductionTab === 'comments'">
@@ -1200,13 +1200,13 @@
variant="outlined" variant="outlined"
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="primary-button field-wide" class="primary-button field-wide"
:disabled="detailStore.actions.asset" :disabled="detailStore.actions.asset"
@click="linkGoogleDriveAsset" @click="linkGoogleDriveAsset"
> >
{{ detailStore.actions.asset ? 'Linking...' : 'Link asset' }} {{ detailStore.actions.asset ? 'Linking...' : 'Link asset' }}
</button> </v-btn>
</div> </div>
<div class="timeline-list"> <div class="timeline-list">
@@ -1262,13 +1262,13 @@
variant="outlined" variant="outlined"
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="secondary-button" class="secondary-button"
:disabled="detailStore.actions.assetRevision" :disabled="detailStore.actions.assetRevision"
@click="addAssetRevision(asset)" @click="addAssetRevision(asset)"
> >
{{ detailStore.actions.assetRevision ? 'Adding...' : 'Add revision' }} {{ detailStore.actions.assetRevision ? 'Adding...' : 'Add revision' }}
</button> </v-btn>
</div> </div>
</article> </article>
@@ -1319,13 +1319,13 @@
<span>{{ activeCalendarEvent.source?.displayTitle ?? t('contentItems.calendar.importedEvent') }}</span> <span>{{ activeCalendarEvent.source?.displayTitle ?? t('contentItems.calendar.importedEvent') }}</span>
<strong>{{ activeCalendarEvent.title }}</strong> <strong>{{ activeCalendarEvent.title }}</strong>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="link-button" class="link-button"
type="button" type="button"
@click="closeCalendarEvent" @click="closeCalendarEvent"
> >
{{ t('close') }} {{ t('close') }}
</button> </v-btn>
</div> </div>
<p>{{ formatCalendarDate(activeCalendarEvent.startDate) }}</p> <p>{{ formatCalendarDate(activeCalendarEvent.startDate) }}</p>
@@ -1333,13 +1333,13 @@
<p v-if="activeCalendarEvent.location">{{ activeCalendarEvent.location }}</p> <p v-if="activeCalendarEvent.location">{{ activeCalendarEvent.location }}</p>
<div class="calendar-event-actions"> <div class="calendar-event-actions">
<button <v-btn variant="text" :ripple="false"
class="secondary-button" class="secondary-button"
type="button" type="button"
@click="navigateToCalendarDay(activeCalendarEvent)" @click="navigateToCalendarDay(activeCalendarEvent)"
> >
{{ t('contentItems.dateContext.viewDay') }} {{ t('contentItems.dateContext.viewDay') }}
</button> </v-btn>
</div> </div>
</div> </div>
</div> </div>
@@ -1356,28 +1356,28 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 text-sm; @apply rounded-[1.25rem] border p-4 text-sm;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
.editor-header { .editor-header {
@apply flex flex-col gap-4 rounded-[1.75rem] border p-6 lg:flex-row lg:items-start lg:justify-between; @apply flex flex-col gap-4 rounded-[1.75rem] border p-6 lg:flex-row lg:items-start lg:justify-between;
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.editor-header h1 { .editor-header h1 {
@apply mt-2 text-4xl font-black; @apply mt-2 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.editor-header p, .editor-header p,
@@ -1388,7 +1388,7 @@
.placement-header span, .placement-header span,
.section-title-row span { .section-title-row span {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.header-actions, .header-actions,
@@ -1398,8 +1398,8 @@
.meta-chip { .meta-chip {
@apply rounded-full px-4 py-2 text-xs font-bold uppercase tracking-[0.16em]; @apply rounded-full px-4 py-2 text-xs font-bold uppercase tracking-[0.16em];
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.back-button, .back-button,
@@ -1411,23 +1411,23 @@
.back-button { .back-button {
@apply w-fit border; @apply w-fit border;
background: rgba(255, 255, 255, 0.88); background: rgba(255, 255, 255, 0.88);
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.back-button:hover { .back-button:hover {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.primary-button { .primary-button {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.secondary-button { .secondary-button {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.editor-grid { .editor-grid {
@@ -1437,13 +1437,13 @@
.work-panel { .work-panel {
@apply grid min-w-0 grid-cols-[2.75rem_minmax(0,1fr)] items-start gap-4 rounded-[1.75rem] border p-5; @apply grid min-w-0 grid-cols-[2.75rem_minmax(0,1fr)] items-start gap-4 rounded-[1.75rem] border p-5;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.panel { .panel {
@apply flex min-h-0 flex-col gap-5 rounded-[1.75rem] border p-5; @apply flex min-h-0 flex-col gap-5 rounded-[1.75rem] border p-5;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.side-panel { .side-panel {
@@ -1464,7 +1464,7 @@
.section-title-row strong, .section-title-row strong,
.placement-header strong, .placement-header strong,
.timeline-row strong { .timeline-row strong {
color: #172033; color: var(--app-color-on-surface);
} }
.panel-stack, .panel-stack,
@@ -1495,16 +1495,16 @@
.field span { .field span {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field input, .field input,
.field select, .field select,
.field textarea { .field textarea {
@apply rounded-[1rem] border px-4 py-3 text-sm; @apply rounded-[1rem] border px-4 py-3 text-sm;
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
outline: none; outline: none;
} }
@@ -1526,8 +1526,8 @@
.date-context-day { .date-context-day {
@apply flex min-h-14 flex-col items-start justify-between rounded-[0.875rem] border px-3 py-2 text-left transition; @apply flex min-h-14 flex-col items-start justify-between rounded-[0.875rem] border px-3 py-2 text-left transition;
background: rgba(255, 253, 248, 0.9); background: rgba(255, 253, 248, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.date-context-day span { .date-context-day span {
@@ -1536,25 +1536,25 @@
.date-context-day strong { .date-context-day strong {
@apply h-5 min-w-5 rounded-full px-1.5 text-center text-xs leading-5; @apply h-5 min-w-5 rounded-full px-1.5 text-center text-xs leading-5;
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.date-context-day.marked { .date-context-day.marked {
border-color: rgba(15, 118, 110, 0.32); border-color: rgba(15, 118, 110, 0.32);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.date-context-day.marked strong, .date-context-day.marked strong,
.date-context-day.active strong { .date-context-day.active strong {
background: #0f766e; background: var(--app-color-on-tertiary);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.date-context-day.active { .date-context-day.active {
background: #172033; background: var(--app-color-on-surface);
border-color: #172033; border-color: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.date-context-panel { .date-context-panel {
@@ -1565,23 +1565,23 @@
@apply rounded-full border px-3 py-1.5 text-xs font-bold transition; @apply rounded-full border px-3 py-1.5 text-xs font-bold transition;
background: color-mix(in srgb, var(--calendar-color) 12%, white); background: color-mix(in srgb, var(--calendar-color) 12%, white);
border-color: color-mix(in srgb, var(--calendar-color) 34%, white); border-color: color-mix(in srgb, var(--calendar-color) 34%, white);
color: #172033; color: var(--app-color-on-surface);
} }
.calendar-context-pill:hover { .calendar-context-pill:hover {
background: var(--calendar-color); background: var(--calendar-color);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.date-context-empty { .date-context-empty {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.hashtags-input-shell { .hashtags-input-shell {
@apply flex flex-wrap items-center gap-2 rounded-[1rem] border px-4 py-3; @apply flex flex-wrap items-center gap-2 rounded-[1rem] border px-4 py-3;
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
} }
.hashtags-editor { .hashtags-editor {
@@ -1590,7 +1590,7 @@
.hashtags-inline-input { .hashtags-inline-input {
@apply min-w-[12rem] flex-1 border-0 bg-transparent p-0 text-sm; @apply min-w-[12rem] flex-1 border-0 bg-transparent p-0 text-sm;
color: #172033; color: var(--app-color-on-surface);
outline: none; outline: none;
} }
@@ -1600,9 +1600,9 @@
.network-pill { .network-pill {
@apply rounded-full border px-4 py-2 text-xs font-bold uppercase tracking-[0.16em]; @apply rounded-full border px-4 py-2 text-xs font-bold uppercase tracking-[0.16em];
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.channel-suggestions { .channel-suggestions {
@@ -1612,8 +1612,8 @@
.placement-card, .placement-card,
.media-card { .media-card {
@apply rounded-[1.25rem] border p-4; @apply rounded-[1.25rem] border p-4;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.identity-row { .identity-row {
@@ -1627,7 +1627,7 @@
.timeline-row { .timeline-row {
@apply flex flex-col gap-3 rounded-[1rem] border p-4; @apply flex flex-col gap-3 rounded-[1rem] border p-4;
background: #f8fafc; background: #f8fafc;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.timeline-row-header { .timeline-row-header {
@@ -1637,7 +1637,7 @@
.timeline-row p, .timeline-row p,
.asset-revision-row p { .asset-revision-row p {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #172033; color: var(--app-color-on-surface);
} }
.timeline-actions { .timeline-actions {
@@ -1654,14 +1654,14 @@
.tab-button { .tab-button {
@apply flex items-center justify-between gap-2 rounded-[1rem] border px-3 py-2 text-sm font-bold transition; @apply flex items-center justify-between gap-2 rounded-[1rem] border px-3 py-2 text-sm font-bold transition;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.tab-button.active { .tab-button.active {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.tab-button span { .tab-button span {
@@ -1675,25 +1675,25 @@
.asset-card { .asset-card {
@apply flex flex-col gap-4 rounded-[1rem] border p-4; @apply flex flex-col gap-4 rounded-[1rem] border p-4;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.asset-card .timeline-row-header span, .asset-card .timeline-row-header span,
.asset-revision-row small { .asset-revision-row small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.asset-link { .asset-link {
@apply w-fit text-sm font-semibold; @apply w-fit text-sm font-semibold;
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.revision-pill { .revision-pill {
@apply rounded-full px-3 py-1 text-xs font-bold; @apply rounded-full px-3 py-1 text-xs font-bold;
background: rgba(15, 118, 110, 0.12); background: rgba(15, 118, 110, 0.12);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.asset-revisions { .asset-revisions {
@@ -1703,12 +1703,12 @@
.asset-revision-row { .asset-revision-row {
@apply rounded-[0.875rem] border px-3 py-2; @apply rounded-[0.875rem] border px-3 py-2;
background: rgba(255, 255, 255, 0.7); background: rgba(255, 255, 255, 0.7);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.asset-revision-row span { .asset-revision-row span {
@apply mr-2 text-sm font-bold; @apply mr-2 text-sm font-bold;
color: #172033; color: var(--app-color-on-surface);
} }
.compact-form { .compact-form {
@@ -1717,7 +1717,7 @@
.link-button { .link-button {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.calendar-event-popover { .calendar-event-popover {
@@ -1726,8 +1726,8 @@
.calendar-event-card { .calendar-event-card {
@apply flex w-full max-w-md flex-col gap-4 rounded-[1.25rem] border p-5 shadow-2xl; @apply flex w-full max-w-md flex-col gap-4 rounded-[1.25rem] border p-5 shadow-2xl;
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.calendar-event-header { .calendar-event-header {
@@ -1741,12 +1741,12 @@
.calendar-event-header span, .calendar-event-header span,
.calendar-event-card p { .calendar-event-card p {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.calendar-event-header strong { .calendar-event-header strong {
@apply text-xl font-black; @apply text-xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.calendar-event-actions { .calendar-event-actions {

View File

@@ -484,6 +484,12 @@
calendarStore.toggleSourceVisibility(sourceId); calendarStore.toggleSourceVisibility(sourceId);
} }
function setSourceVisibility(sourceId, visible) {
if (sourceIsVisible(sourceId) !== visible) {
calendarStore.toggleSourceVisibility(sourceId);
}
}
function toggleColorPalette(sourceId) { function toggleColorPalette(sourceId) {
activeColorSourceId.value = activeColorSourceId.value === sourceId ? '' : sourceId; activeColorSourceId.value = activeColorSourceId.value === sourceId ? '' : sourceId;
} }
@@ -866,26 +872,26 @@
> >
<div class="calendar-toolbar"> <div class="calendar-toolbar">
<div class="range-selector"> <div class="range-selector">
<button <v-btn variant="text" :ripple="false"
class="toggle-button" class="toggle-button"
:class="{ 'toggle-button-active': viewMode === 'month' }" :class="{ 'toggle-button-active': viewMode === 'month' }"
type="button" type="button"
@click="setView('month')" @click="setView('month')"
> >
{{ t('dashboard.month') }} {{ t('dashboard.month') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="toggle-button" class="toggle-button"
:class="{ 'toggle-button-active': viewMode === 'week' }" :class="{ 'toggle-button-active': viewMode === 'week' }"
type="button" type="button"
@click="setView('week')" @click="setView('week')"
> >
{{ t('dashboard.week') }} {{ t('dashboard.week') }}
</button> </v-btn>
</div> </div>
<div class="calendar-nav"> <div class="calendar-nav">
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
:title="previousPeriodLabel" :title="previousPeriodLabel"
@@ -893,11 +899,11 @@
@click="shiftPeriod(-1)" @click="shiftPeriod(-1)"
> >
<v-icon :icon="mdiChevronLeft" /> <v-icon :icon="mdiChevronLeft" />
</button> </v-btn>
<div class="calendar-period">{{ periodLabel }}</div> <div class="calendar-period">{{ periodLabel }}</div>
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
:title="nextPeriodLabel" :title="nextPeriodLabel"
@@ -905,20 +911,20 @@
@click="shiftPeriod(1)" @click="shiftPeriod(1)"
> >
<v-icon :icon="mdiChevronRight" /> <v-icon :icon="mdiChevronRight" />
</button> </v-btn>
</div> </div>
<button <v-btn variant="text" :ripple="false"
v-if="!isTodayVisible" v-if="!isTodayVisible"
class="text-button" class="text-button"
type="button" type="button"
@click="jumpToToday" @click="jumpToToday"
> >
{{ t('dashboard.today') }} {{ t('dashboard.today') }}
</button> </v-btn>
<div class="calendar-selector"> <div class="calendar-selector">
<button <v-btn variant="text" :ripple="false"
class="calendar-selector-button" class="calendar-selector-button"
type="button" type="button"
@click="isCalendarSelectorOpen = !isCalendarSelectorOpen" @click="isCalendarSelectorOpen = !isCalendarSelectorOpen"
@@ -926,7 +932,7 @@
<span>{{ t('contentItems.calendar.calendars') }}</span> <span>{{ t('contentItems.calendar.calendars') }}</span>
<strong>{{ visibleCalendarSourceCount }}/{{ availableCalendarSources.length }}</strong> <strong>{{ visibleCalendarSourceCount }}/{{ availableCalendarSources.length }}</strong>
<v-icon :icon="mdiChevronDown" /> <v-icon :icon="mdiChevronDown" />
</button> </v-btn>
<div <div
v-if="isCalendarSelectorOpen" v-if="isCalendarSelectorOpen"
@@ -938,7 +944,7 @@
class="calendar-selector-row" class="calendar-selector-row"
> >
<span class="source-color-control"> <span class="source-color-control">
<button <v-btn variant="text" :ripple="false"
class="source-swatch-button" class="source-swatch-button"
type="button" type="button"
:disabled="source.isReadOnly" :disabled="source.isReadOnly"
@@ -949,7 +955,7 @@
class="source-swatch" class="source-swatch"
:style="{ background: source.color }" :style="{ background: source.color }"
/> />
</button> </v-btn>
<ColorPalette <ColorPalette
v-if="activeColorSourceId === source.id" v-if="activeColorSourceId === source.id"
@@ -960,19 +966,23 @@
@update:model-value="color => updateSourceColor(source, color)" @update:model-value="color => updateSourceColor(source, color)"
/> />
</span> </span>
<button <v-btn variant="text" :ripple="false"
class="calendar-selector-title" class="calendar-selector-title"
type="button" type="button"
@click="toggleSource(source.id)" @click="toggleSource(source.id)"
> >
{{ source.displayTitle }} {{ source.displayTitle }}
</button> </v-btn>
<button <v-switch
class="visibility-switch" class="visibility-switch"
:class="{ active: sourceIsVisible(source.id) }" :model-value="sourceIsVisible(source.id)"
type="button"
:aria-label="source.displayTitle" :aria-label="source.displayTitle"
@click="toggleSource(source.id)" color="primary"
density="compact"
hide-details
inset
@click.stop
@update:model-value="visible => setSourceVisibility(source.id, visible)"
/> />
</div> </div>
@@ -983,14 +993,14 @@
{{ t('contentItems.calendar.noCalendars') }} {{ t('contentItems.calendar.noCalendars') }}
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="calendar-selector-add" class="calendar-selector-add"
type="button" type="button"
@click="openAddCalendar" @click="openAddCalendar"
> >
<v-icon :icon="mdiCalendarPlus" /> <v-icon :icon="mdiCalendarPlus" />
<span>{{ t('contentItems.calendar.addCalendar') }}</span> <span>{{ t('contentItems.calendar.addCalendar') }}</span>
</button> </v-btn>
</div> </div>
</div> </div>
</div> </div>
@@ -1031,7 +1041,7 @@
v-for="entry in viewMode === 'month' ? day.entries.slice(0, 3) : day.entries" v-for="entry in viewMode === 'month' ? day.entries.slice(0, 3) : day.entries"
:key="`${entry.type}-${entry.id}`" :key="`${entry.type}-${entry.id}`"
> >
<button <v-btn variant="text" :ripple="false"
v-if="entry.type === 'imported-calendar'" v-if="entry.type === 'imported-calendar'"
class="calendar-entry calendar-context-entry" class="calendar-entry calendar-context-entry"
:class="entry.tone" :class="entry.tone"
@@ -1041,7 +1051,7 @@
@click="createFromImportedEvent(entry)" @click="createFromImportedEvent(entry)"
> >
<span class="calendar-event-chip">{{ entry.title }}</span> <span class="calendar-event-chip">{{ entry.title }}</span>
</button> </v-btn>
<router-link <router-link
v-else-if="entry.type === 'content'" v-else-if="entry.type === 'content'"
@@ -1136,7 +1146,7 @@
v-for="entry in upcomingEntries" v-for="entry in upcomingEntries"
:key="`${entry.type}-${entry.id}`" :key="`${entry.type}-${entry.id}`"
> >
<button <v-btn variant="text" :ripple="false"
v-if="entry.type === 'imported-calendar'" v-if="entry.type === 'imported-calendar'"
class="item-card calendar-upcoming-card" class="item-card calendar-upcoming-card"
:style="entryStyle(entry)" :style="entryStyle(entry)"
@@ -1150,7 +1160,7 @@
<em>{{ entry.timeLabel }}</em> <em>{{ entry.timeLabel }}</em>
<small>{{ formatEntryDate(entry.scheduledAt) }}</small> <small>{{ formatEntryDate(entry.scheduledAt) }}</small>
</div> </div>
</button> </v-btn>
<router-link <router-link
v-else-if="entry.type === 'content'" v-else-if="entry.type === 'content'"
@@ -1274,32 +1284,32 @@
<div class="calendar-dialog"> <div class="calendar-dialog">
<div class="dialog-header"> <div class="dialog-header">
<strong>{{ t('contentItems.calendar.addCalendar') }}</strong> <strong>{{ t('contentItems.calendar.addCalendar') }}</strong>
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
@click="isAddCalendarOpen = false" @click="isAddCalendarOpen = false"
> >
<v-icon :icon="mdiClose" /> <v-icon :icon="mdiClose" />
</button> </v-btn>
</div> </div>
<div class="add-mode-toggle"> <div class="add-mode-toggle">
<button <v-btn variant="text" :ripple="false"
class="toggle-button" class="toggle-button"
:class="{ 'toggle-button-active': activeAddMode === 'catalog' }" :class="{ 'toggle-button-active': activeAddMode === 'catalog' }"
type="button" type="button"
@click="activeAddMode = 'catalog'" @click="activeAddMode = 'catalog'"
> >
{{ t('contentItems.calendar.catalog') }} {{ t('contentItems.calendar.catalog') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="toggle-button" class="toggle-button"
:class="{ 'toggle-button-active': activeAddMode === 'custom' }" :class="{ 'toggle-button-active': activeAddMode === 'custom' }"
type="button" type="button"
@click="activeAddMode = 'custom'" @click="activeAddMode = 'custom'"
> >
{{ t('contentItems.calendar.customIcs') }} {{ t('contentItems.calendar.customIcs') }}
</button> </v-btn>
</div> </div>
<v-radio-group <v-radio-group
@@ -1344,18 +1354,18 @@
hide-details hide-details
:placeholder="t('contentItems.calendar.category')" :placeholder="t('contentItems.calendar.category')"
/> />
<button <v-btn variant="text" :ripple="false"
class="text-button" class="text-button"
type="button" type="button"
@click="searchCatalog" @click="searchCatalog"
> >
<v-icon :icon="mdiMagnify" /> <v-icon :icon="mdiMagnify" />
<span>{{ t('contentItems.calendar.search') }}</span> <span>{{ t('contentItems.calendar.search') }}</span>
</button> </v-btn>
</div> </div>
<div class="catalog-results"> <div class="catalog-results">
<button <v-btn variant="text" :ripple="false"
v-for="entry in calendarStore.catalogEntries" v-for="entry in calendarStore.catalogEntries"
:key="entry.id" :key="entry.id"
class="catalog-entry" class="catalog-entry"
@@ -1374,7 +1384,7 @@
? t('contentItems.calendar.alreadyAdded') ? t('contentItems.calendar.alreadyAdded')
: `${entry.providerName} · ${entry.category}` }} : `${entry.providerName} · ${entry.category}` }}
</span> </span>
</button> </v-btn>
</div> </div>
</div> </div>
@@ -1413,13 +1423,13 @@
hide-details hide-details
:placeholder="t('contentItems.calendar.category')" :placeholder="t('contentItems.calendar.category')"
/> />
<button <v-btn variant="text" :ripple="false"
class="text-button" class="text-button"
type="submit" type="submit"
> >
<v-icon :icon="mdiPlus" /> <v-icon :icon="mdiPlus" />
<span>{{ t('contentItems.calendar.addCalendar') }}</span> <span>{{ t('contentItems.calendar.addCalendar') }}</span>
</button> </v-btn>
</div> </div>
</v-form> </v-form>
@@ -1444,13 +1454,13 @@
.status-row em, .status-row em,
.status-row small { .status-row small {
@apply text-sm leading-6 not-italic; @apply text-sm leading-6 not-italic;
color: #526178; color: var(--app-text-muted);
} }
.range-selector { .range-selector {
@apply inline-flex w-fit rounded-full border p-1; @apply inline-flex w-fit rounded-full border p-1;
background: #f8fafc; background: #f8fafc;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.calendar-selector { .calendar-selector {
@@ -1460,26 +1470,26 @@
.calendar-selector-button { .calendar-selector-button {
@apply inline-flex min-h-11 w-full items-center justify-between gap-2 rounded-full border px-4 py-2 text-sm font-bold transition sm:w-auto; @apply inline-flex min-h-11 w-full items-center justify-between gap-2 rounded-full border px-4 py-2 text-sm font-bold transition sm:w-auto;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
} }
.calendar-selector-button strong { .calendar-selector-button strong {
@apply rounded-full px-2 py-0.5 text-xs; @apply rounded-full px-2 py-0.5 text-xs;
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.calendar-selector-menu { .calendar-selector-menu {
@apply absolute right-0 top-[calc(100%+0.5rem)] z-30 flex w-full min-w-72 flex-col gap-1 rounded-[1rem] border p-2 shadow-xl sm:w-80; @apply absolute right-0 top-[calc(100%+0.5rem)] z-30 flex w-full min-w-72 flex-col gap-1 rounded-[1rem] border p-2 shadow-xl sm:w-80;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.calendar-selector-row, .calendar-selector-row,
.calendar-selector-add { .calendar-selector-add {
@apply flex min-h-11 w-full items-center gap-3 rounded-[0.75rem] px-3 text-left text-sm font-semibold transition; @apply flex min-h-11 w-full items-center gap-3 rounded-[0.75rem] px-3 text-left text-sm font-semibold transition;
color: #172033; color: var(--app-color-on-surface);
} }
.calendar-selector-row:hover, .calendar-selector-row:hover,
@@ -1500,7 +1510,7 @@
} }
.source-swatch-button:not(:disabled):hover { .source-swatch-button:not(:disabled):hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
} }
.source-swatch-button:disabled { .source-swatch-button:disabled {
@@ -1513,32 +1523,17 @@
.calendar-selector-empty { .calendar-selector-empty {
@apply px-3 py-2 text-sm; @apply px-3 py-2 text-sm;
color: #526178; color: var(--app-text-muted);
} }
.calendar-selector-add { .calendar-selector-add {
@apply border-t; @apply border-t;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.visibility-switch { .visibility-switch {
@apply relative h-6 w-10 shrink-0 rounded-full transition; @apply shrink-0;
background: rgba(148, 163, 184, 0.35);
}
.visibility-switch::after {
@apply absolute left-1 top-1 h-4 w-4 rounded-full bg-white transition;
content: '';
box-shadow: 0 1px 4px rgba(23, 32, 51, 0.2);
}
.visibility-switch.active {
background: #0f766e;
}
.visibility-switch.active::after {
transform: translateX(1rem);
} }
.toggle-button, .toggle-button,
@@ -1546,8 +1541,8 @@
.text-button { .text-button {
@apply inline-flex items-center justify-center rounded-full border px-3 py-2 text-sm font-semibold transition; @apply inline-flex items-center justify-center rounded-full border px-3 py-2 text-sm font-semibold transition;
background: #f8fafc; background: #f8fafc;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
} }
.toggle-button { .toggle-button {
@@ -1555,7 +1550,7 @@
} }
.toggle-button-active { .toggle-button-active {
background: #172033; background: var(--app-color-on-surface);
color: #ffffff; color: #ffffff;
} }
@@ -1573,16 +1568,16 @@
.item-card { .item-card {
@apply rounded-[1.5rem] border; @apply rounded-[1.5rem] border;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.page-message { .page-message {
@apply p-5 text-sm; @apply p-5 text-sm;
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
.calendar-card { .calendar-card {
@@ -1604,7 +1599,7 @@
.calendar-period { .calendar-period {
@apply min-w-0 px-2 text-base font-bold md:text-lg; @apply min-w-0 px-2 text-base font-bold md:text-lg;
color: #172033; color: var(--app-color-on-surface);
} }
.source-swatch { .source-swatch {
@@ -1622,12 +1617,12 @@
.weekday-label { .weekday-label {
@apply px-2 text-xs font-bold uppercase tracking-[0.16em]; @apply px-2 text-xs font-bold uppercase tracking-[0.16em];
color: #526178; color: var(--app-text-muted);
} }
.calendar-day { .calendar-day {
@apply min-h-[8rem] overflow-visible rounded-[1rem] border p-2.5; @apply min-h-[8rem] overflow-visible rounded-[1rem] border p-2.5;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.calendar-day-week { .calendar-day-week {
@@ -1645,7 +1640,7 @@
.day-number { .day-number {
@apply mb-2 text-sm font-bold; @apply mb-2 text-sm font-bold;
color: #172033; color: var(--app-color-on-surface);
} }
.day-entries, .day-entries,
@@ -1674,12 +1669,12 @@
.calendar-entry strong, .calendar-entry strong,
.item-card strong { .item-card strong {
@apply text-sm font-bold; @apply text-sm font-bold;
color: #172033; color: var(--app-color-on-surface);
} }
.calendar-entry span { .calendar-entry span {
@apply text-xs leading-5; @apply text-xs leading-5;
color: #526178; color: var(--app-text-muted);
} }
.content-calendar-entry, .content-calendar-entry,
@@ -1707,13 +1702,13 @@
} }
.campaign-chip { .campaign-chip {
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.hashtag-chip { .hashtag-chip {
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.content-preview { .content-preview {
@@ -1734,7 +1729,7 @@
.content-preview span { .content-preview span {
@apply text-xs leading-5; @apply text-xs leading-5;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
color: #526178; color: var(--app-text-muted);
} }
.content-meta-row { .content-meta-row {
@@ -1747,7 +1742,7 @@
.planned-time { .planned-time {
@apply gap-1 text-[0.7rem] font-bold uppercase; @apply gap-1 text-[0.7rem] font-bold uppercase;
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.planned-time i, .planned-time i,
@@ -1757,12 +1752,12 @@
.channel-icons { .channel-icons {
@apply justify-end gap-1; @apply justify-end gap-1;
color: #526178; color: var(--app-text-muted);
} }
.entry-time { .entry-time {
@apply text-[0.7rem] font-bold uppercase tracking-[0.12em]; @apply text-[0.7rem] font-bold uppercase tracking-[0.12em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.calendar-event-chip { .calendar-event-chip {
@@ -1773,7 +1768,7 @@
.entry-more, .entry-more,
.day-empty { .day-empty {
@apply px-1 text-xs font-semibold; @apply px-1 text-xs font-semibold;
color: #526178; color: var(--app-text-muted);
} }
.calendar-entry.production { .calendar-entry.production {
@@ -1825,7 +1820,7 @@
.calendar-dialog { .calendar-dialog {
@apply flex flex-col gap-4 rounded-[1.5rem] border bg-white p-5; @apply flex flex-col gap-4 rounded-[1.5rem] border bg-white p-5;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.dialog-header, .dialog-header,
@@ -1842,13 +1837,13 @@
.dialog-header strong { .dialog-header strong {
@apply text-lg font-black; @apply text-lg font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.scope-option { .scope-option {
@apply inline-flex items-center gap-2 rounded-full border px-3 py-2 text-sm font-semibold; @apply inline-flex items-center gap-2 rounded-full border px-3 py-2 text-sm font-semibold;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
} }
.catalog-panel, .catalog-panel,
@@ -1860,8 +1855,8 @@
.catalog-search input, .catalog-search input,
.custom-calendar-form input { .custom-calendar-form input {
@apply min-h-11 rounded-[0.75rem] border px-3 text-sm; @apply min-h-11 rounded-[0.75rem] border px-3 text-sm;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.catalog-search input[type='search'], .catalog-search input[type='search'],
@@ -1876,7 +1871,7 @@
.catalog-entry { .catalog-entry {
@apply grid min-h-14 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-3 rounded-[0.75rem] border px-3 py-2 text-left transition; @apply grid min-h-14 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-3 rounded-[0.75rem] border px-3 py-2 text-left transition;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: #ffffff; background: #ffffff;
} }
@@ -1895,17 +1890,17 @@
.catalog-entry strong { .catalog-entry strong {
@apply text-sm font-bold; @apply text-sm font-bold;
color: #172033; color: var(--app-color-on-surface);
} }
.catalog-entry span:last-child { .catalog-entry span:last-child {
@apply col-start-2 text-xs; @apply col-start-2 text-xs;
color: #526178; color: var(--app-text-muted);
} }
.dialog-error { .dialog-error {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #b91c1c; color: var(--app-danger-muted);
} }
.item-grid { .item-grid {
@@ -1918,8 +1913,8 @@
.version-chip { .version-chip {
@apply w-fit rounded-full px-4 py-2 text-xs font-bold uppercase tracking-[0.16em]; @apply w-fit rounded-full px-4 py-2 text-xs font-bold uppercase tracking-[0.16em];
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.version-chip.calendar-event-chip { .version-chip.calendar-event-chip {
@@ -1933,39 +1928,39 @@
.content-table-shell { .content-table-shell {
@apply overflow-x-auto rounded-[1.5rem] border; @apply overflow-x-auto rounded-[1.5rem] border;
background: rgba(255, 255, 255, 0.94); background: var(--app-surface-glass);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.content-table { .content-table {
@apply w-full min-w-[52rem] border-collapse text-left text-sm; @apply w-full min-w-[52rem] border-collapse text-left text-sm;
color: #526178; color: var(--app-text-muted);
} }
.content-table th { .content-table th {
@apply px-5 py-4 text-xs font-black uppercase tracking-[0.14em]; @apply px-5 py-4 text-xs font-black uppercase tracking-[0.14em];
background: #f8fafc; background: #f8fafc;
color: #172033; color: var(--app-color-on-surface);
} }
.content-table td { .content-table td {
@apply border-t px-5 py-4 align-middle; @apply border-t px-5 py-4 align-middle;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.content-table-title { .content-table-title {
@apply font-bold no-underline; @apply font-bold no-underline;
color: #172033; color: var(--app-color-on-surface);
} }
.content-table-title:hover { .content-table-title:hover {
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.table-status { .table-status {
@apply inline-flex rounded-full px-3 py-1 text-xs font-bold; @apply inline-flex rounded-full px-3 py-1 text-xs font-bold;
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
@media (max-width: 960px) { @media (max-width: 960px) {

View File

@@ -109,7 +109,7 @@
.panel, .panel,
.status-panel { .status-panel {
@apply rounded-[1.75rem] border; @apply rounded-[1.75rem] border;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
} }
@@ -117,17 +117,17 @@
@apply p-6 md:p-8; @apply p-6 md:p-8;
background: background:
radial-gradient(circle at top left, rgba(14, 165, 164, 0.18), transparent 45%), radial-gradient(circle at top left, rgba(14, 165, 164, 0.18), transparent 45%),
linear-gradient(135deg, rgba(255, 255, 255, 0.98), rgba(240, 249, 255, 0.92)); linear-gradient(135deg, var(--app-surface-raised), rgba(240, 249, 255, 0.92));
} }
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.hero-copy h1 { .hero-copy h1 {
@apply mt-3 text-4xl font-black; @apply mt-3 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.hero-copy p, .hero-copy p,
@@ -138,7 +138,7 @@
.status-copy p, .status-copy p,
.status-label span { .status-label span {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.hero-card { .hero-card {
@@ -158,13 +158,13 @@
.media-type-item { .media-type-item {
@apply w-fit rounded-full px-3 py-2; @apply w-fit rounded-full px-3 py-2;
background: rgba(15, 118, 110, 0.08); background: rgba(15, 118, 110, 0.08);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.hero-card strong, .hero-card strong,
.panel-header strong, .panel-header strong,
.status-copy strong { .status-copy strong {
color: #172033; color: var(--app-color-on-surface);
} }
.hero-card strong { .hero-card strong {
@@ -196,16 +196,16 @@
.media-type-item, .media-type-item,
.workflow-item { .workflow-item {
@apply rounded-[1.1rem] border px-4 py-3; @apply rounded-[1.1rem] border px-4 py-3;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(248, 250, 252, 0.9); background: rgba(248, 250, 252, 0.9);
} }
.workflow-icon { .workflow-icon {
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.status-panel { .status-panel {
background: linear-gradient(135deg, rgba(255, 247, 237, 0.95), rgba(255, 255, 255, 0.98)); background: linear-gradient(135deg, rgba(255, 247, 237, 0.95), var(--app-surface-raised));
} }
.status-copy { .status-copy {
@@ -214,7 +214,7 @@
.status-label { .status-label {
@apply text-xs font-bold uppercase tracking-[0.2em]; @apply text-xs font-bold uppercase tracking-[0.2em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.status-copy strong { .status-copy strong {

View File

@@ -14,7 +14,7 @@
class="feedback-entry" class="feedback-entry"
data-feedback-ui="true" data-feedback-ui="true"
> >
<button <v-btn variant="text" :ripple="false"
class="feedback-entry-button" class="feedback-entry-button"
type="button" type="button"
:title="t('feedback.open')" :title="t('feedback.open')"
@@ -22,7 +22,7 @@
> >
<v-icon :icon="mdiMessageAlertOutline" /> <v-icon :icon="mdiMessageAlertOutline" />
<span>{{ t('feedback.button') }}</span> <span>{{ t('feedback.button') }}</span>
</button> </v-btn>
<FeedbackSubmissionDialog v-model="isDialogOpen" /> <FeedbackSubmissionDialog v-model="isDialogOpen" />
</div> </div>

View File

@@ -136,7 +136,7 @@
await nextTick(); await nextTick();
const target = document.querySelector('.shell-container') ?? document.body; const target = document.querySelector('.shell-container') ?? document.body;
const canvas = await html2canvas(target, { const canvas = await html2canvas(target, {
backgroundColor: '#fffaf2', backgroundColor: 'var(--app-color-on-primary)',
height: window.innerHeight, height: window.innerHeight,
ignoreElements: element => element.dataset?.feedbackUi === 'true', ignoreElements: element => element.dataset?.feedbackUi === 'true',
scale: Math.min(window.devicePixelRatio || 1, 2), scale: Math.min(window.devicePixelRatio || 1, 2),
@@ -484,14 +484,14 @@
<p>{{ t('feedback.eyebrow') }}</p> <p>{{ t('feedback.eyebrow') }}</p>
<h2>{{ t('feedback.title') }}</h2> <h2>{{ t('feedback.title') }}</h2>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="feedback-icon-button" class="feedback-icon-button"
type="button" type="button"
:title="t('close')" :title="t('close')"
@click="requestClose" @click="requestClose"
> >
<v-icon :icon="mdiClose" /> <v-icon :icon="mdiClose" />
</button> </v-btn>
</header> </header>
<div class="feedback-dialog-body"> <div class="feedback-dialog-body">
@@ -549,7 +549,7 @@
class="feedback-editor" class="feedback-editor"
> >
<div class="feedback-toolstrip"> <div class="feedback-toolstrip">
<button <v-btn variant="text" :ripple="false"
v-for="tool in annotationTools" v-for="tool in annotationTools"
:key="tool.value" :key="tool.value"
class="feedback-tool-button" class="feedback-tool-button"
@@ -559,24 +559,24 @@
@click="selectedTool = tool.value" @click="selectedTool = tool.value"
> >
<v-icon :icon="tool.icon" /> <v-icon :icon="tool.icon" />
</button> </v-btn>
<span class="feedback-tool-divider"></span> <span class="feedback-tool-divider"></span>
<button <v-btn variant="text" :ripple="false"
class="feedback-tool-button" class="feedback-tool-button"
type="button" type="button"
:title="t('feedback.tools.undo')" :title="t('feedback.tools.undo')"
@click="undoAnnotation" @click="undoAnnotation"
> >
<v-icon :icon="mdiUndoVariant" /> <v-icon :icon="mdiUndoVariant" />
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="feedback-tool-button" class="feedback-tool-button"
type="button" type="button"
:title="t('feedback.tools.clear')" :title="t('feedback.tools.clear')"
@click="clearAnnotations" @click="clearAnnotations"
> >
<v-icon :icon="mdiRedoVariant" /> <v-icon :icon="mdiRedoVariant" />
</button> </v-btn>
</div> </div>
<canvas <canvas
@@ -623,26 +623,26 @@
@reference "@/assets/main.css"; @reference "@/assets/main.css";
.feedback-dialog { .feedback-dialog {
@apply overflow-hidden rounded-lg border; @apply overflow-hidden rounded-lg border;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.feedback-dialog-header, .feedback-dialog-header,
.feedback-dialog-footer { .feedback-dialog-footer {
@apply flex items-center justify-between gap-4 px-5 py-4; @apply flex items-center justify-between gap-4 px-5 py-4;
border-bottom: 1px solid rgba(23, 32, 51, 0.08); border-bottom: 1px solid var(--app-border-subtle);
} }
.feedback-dialog-footer { .feedback-dialog-footer {
@apply justify-end; @apply justify-end;
border-bottom: 0; border-bottom: 0;
border-top: 1px solid rgba(23, 32, 51, 0.08); border-top: 1px solid var(--app-border-subtle);
} }
.feedback-dialog-header p { .feedback-dialog-header p {
@apply text-xs font-black uppercase; @apply text-xs font-black uppercase;
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.feedback-dialog-header h2 { .feedback-dialog-header h2 {
@@ -652,15 +652,15 @@
.feedback-icon-button, .feedback-icon-button,
.feedback-tool-button { .feedback-tool-button {
@apply flex h-10 w-10 items-center justify-center rounded-full transition-colors; @apply flex h-10 w-10 items-center justify-center rounded-full transition-colors;
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.feedback-icon-button:hover, .feedback-icon-button:hover,
.feedback-tool-button:hover, .feedback-tool-button:hover,
.feedback-tool-button-active { .feedback-tool-button-active {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.feedback-dialog-body { .feedback-dialog-body {
@@ -694,7 +694,7 @@
@apply block w-full rounded-md border; @apply block w-full rounded-md border;
max-height: 58vh; max-height: 58vh;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
cursor: crosshair; cursor: crosshair;
object-fit: contain; object-fit: contain;
} }
@@ -703,7 +703,7 @@
@apply flex min-h-[18rem] flex-col items-center justify-center gap-3 rounded-md border border-dashed text-sm; @apply flex min-h-[18rem] flex-col items-center justify-center gap-3 rounded-md border border-dashed text-sm;
background: rgba(23, 32, 51, 0.03); background: rgba(23, 32, 51, 0.03);
border-color: rgba(23, 32, 51, 0.16); border-color: rgba(23, 32, 51, 0.16);
color: #526178; color: var(--app-text-muted);
} }
.feedback-empty-preview i { .feedback-empty-preview i {

View File

@@ -184,14 +184,14 @@
<template> <template>
<section class="feedback-detail-page"> <section class="feedback-detail-page">
<button <v-btn variant="text" :ripple="false"
class="back-button" class="back-button"
type="button" type="button"
@click="router.push({ name: 'developer-feedback' })" @click="router.push({ name: 'developer-feedback' })"
> >
<v-icon :icon="mdiArrowLeft" /> <v-icon :icon="mdiArrowLeft" />
{{ t('feedback.review.detail.back') }} {{ t('feedback.review.detail.back') }}
</button> </v-btn>
<div <div
v-if="feedbackStore.isDetailLoading" v-if="feedbackStore.isDetailLoading"
@@ -242,7 +242,7 @@
<section class="panel"> <section class="panel">
<div class="panel-header"> <div class="panel-header">
<strong>{{ t('feedback.review.detail.screenshot') }}</strong> <strong>{{ t('feedback.review.detail.screenshot') }}</strong>
<button <v-btn variant="text" :ripple="false"
v-if="report.screenshot" v-if="report.screenshot"
class="small-button" class="small-button"
type="button" type="button"
@@ -250,8 +250,8 @@
> >
<v-icon :icon="mdiDownloadOutline" /> <v-icon :icon="mdiDownloadOutline" />
{{ t('feedback.review.detail.download') }} {{ t('feedback.review.detail.download') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
v-if="report.screenshot" v-if="report.screenshot"
class="small-button" class="small-button"
type="button" type="button"
@@ -259,7 +259,7 @@
> >
<v-icon :icon="mdiOpenInNew" /> <v-icon :icon="mdiOpenInNew" />
{{ t('feedback.review.detail.openOriginal') }} {{ t('feedback.review.detail.openOriginal') }}
</button> </v-btn>
</div> </div>
<div <div
@@ -329,13 +329,13 @@
variant="outlined" variant="outlined"
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="submit" type="submit"
:disabled="!canSubmitComment" :disabled="!canSubmitComment"
> >
{{ feedbackStore.isCommenting ? t('feedback.review.detail.commenting') : t('feedback.review.detail.addComment') }} {{ feedbackStore.isCommenting ? t('feedback.review.detail.commenting') : t('feedback.review.detail.addComment') }}
</button> </v-btn>
</v-form> </v-form>
</section> </section>
</main> </main>
@@ -384,14 +384,14 @@
</template> </template>
</v-combobox> </v-combobox>
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="button" type="button"
:disabled="feedbackStore.isSaving" :disabled="feedbackStore.isSaving"
@click="saveReviewChanges" @click="saveReviewChanges"
> >
{{ feedbackStore.isSaving ? t('common.saving') : t('save') }} {{ feedbackStore.isSaving ? t('common.saving') : t('save') }}
</button> </v-btn>
</section> </section>
<section class="panel"> <section class="panel">
@@ -459,20 +459,20 @@
.back-button, .back-button,
.small-button { .small-button {
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.88); background: rgba(255, 255, 255, 0.88);
color: #172033; color: var(--app-color-on-surface);
} }
.back-button:hover, .back-button:hover,
.small-button:hover { .small-button:hover {
background: #172033; background: var(--app-color-on-surface);
color: white; color: white;
} }
.primary-button { .primary-button {
border-color: #0f766e; border-color: var(--app-color-on-tertiary);
background: #0f766e; background: var(--app-color-on-tertiary);
color: white; color: white;
} }
@@ -482,18 +482,18 @@
.detail-header { .detail-header {
@apply rounded-lg border p-5; @apply rounded-lg border p-5;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.88); background: rgba(255, 255, 255, 0.88);
} }
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.22em]; @apply text-xs font-bold uppercase tracking-[0.22em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.detail-header h1 { .detail-header h1 {
@apply mt-2 line-clamp-3 text-2xl font-black md:text-3xl; @apply mt-2 line-clamp-3 text-2xl font-black md:text-3xl;
color: #172033; color: var(--app-color-on-surface);
} }
.header-meta, .header-meta,
@@ -505,7 +505,7 @@
.file-meta span { .file-meta span {
@apply rounded-md px-2.5 py-1 text-xs font-bold; @apply rounded-md px-2.5 py-1 text-xs font-bold;
background: rgba(15, 118, 110, 0.08); background: rgba(15, 118, 110, 0.08);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.detail-grid { .detail-grid {
@@ -519,7 +519,7 @@
.panel { .panel {
@apply rounded-lg border p-5; @apply rounded-lg border p-5;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
} }
@@ -529,7 +529,7 @@
.panel-header strong { .panel-header strong {
@apply text-base font-black; @apply text-base font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.description { .description {
@@ -545,7 +545,7 @@
.screenshot-frame { .screenshot-frame {
@apply overflow-hidden rounded-lg border; @apply overflow-hidden rounded-lg border;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
background: #0f172a; background: #0f172a;
} }
@@ -556,14 +556,14 @@
.empty-block, .empty-block,
.page-message { .page-message {
@apply rounded-lg border p-4 text-sm font-semibold; @apply rounded-lg border p-4 text-sm font-semibold;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(248, 250, 252, 0.9); background: rgba(248, 250, 252, 0.9);
color: #526178; color: var(--app-text-muted);
} }
.page-message-error { .page-message-error {
border-color: rgba(220, 38, 38, 0.24); border-color: rgba(220, 38, 38, 0.24);
color: #b91c1c; color: var(--app-danger-muted);
} }
.timeline { .timeline {
@@ -572,7 +572,7 @@
.timeline-item { .timeline-item {
@apply rounded-lg border p-4; @apply rounded-lg border p-4;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(248, 250, 252, 0.78); background: rgba(248, 250, 252, 0.78);
} }
@@ -586,7 +586,7 @@
.timeline-item strong { .timeline-item strong {
@apply text-sm font-black; @apply text-sm font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.timeline-item span, .timeline-item span,
@@ -619,6 +619,6 @@
.info-list dd { .info-list dd {
@apply mt-1 break-words text-sm font-semibold; @apply mt-1 break-words text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
</style> </style>

View File

@@ -70,14 +70,14 @@
<p>{{ t('feedback.review.description') }}</p> <p>{{ t('feedback.review.description') }}</p>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
:title="t('feedback.review.refresh')" :title="t('feedback.review.refresh')"
@click="feedbackStore.loadReports" @click="feedbackStore.loadReports"
> >
<v-icon :icon="mdiRefresh" /> <v-icon :icon="mdiRefresh" />
</button> </v-btn>
</header> </header>
<section class="metric-grid"> <section class="metric-grid">
@@ -186,14 +186,14 @@
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="filter-reset" class="filter-reset"
type="button" type="button"
:title="t('feedback.review.filters.clear')" :title="t('feedback.review.filters.clear')"
@click="feedbackStore.resetFilters" @click="feedbackStore.resetFilters"
> >
<v-icon :icon="mdiFilterOffOutline" /> <v-icon :icon="mdiFilterOffOutline" />
</button> </v-btn>
</section> </section>
<div <div
@@ -214,7 +214,7 @@
v-else v-else
class="report-table" class="report-table"
> >
<button <v-btn variant="text" :ripple="false"
v-for="report in feedbackStore.filteredReports" v-for="report in feedbackStore.filteredReports"
:key="report.id" :key="report.id"
class="report-row" class="report-row"
@@ -263,7 +263,7 @@
/> />
</small> </small>
</span> </span>
</button> </v-btn>
<div <div
v-if="!feedbackStore.filteredReports.length" v-if="!feedbackStore.filteredReports.length"
@@ -287,30 +287,30 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.22em]; @apply text-xs font-bold uppercase tracking-[0.22em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.review-header h1 { .review-header h1 {
@apply mt-2 text-3xl font-black md:text-4xl; @apply mt-2 text-3xl font-black md:text-4xl;
color: #172033; color: var(--app-color-on-surface);
} }
.review-header p { .review-header p {
@apply mt-2 max-w-3xl text-sm leading-6; @apply mt-2 max-w-3xl text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.icon-button, .icon-button,
.filter-reset { .filter-reset {
@apply inline-flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-lg border transition-colors; @apply inline-flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-lg border transition-colors;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
color: #172033; color: var(--app-color-on-surface);
} }
.icon-button:hover, .icon-button:hover,
.filter-reset:hover { .filter-reset:hover {
background: #172033; background: var(--app-color-on-surface);
color: white; color: white;
} }
@@ -320,7 +320,7 @@
.metric { .metric {
@apply rounded-lg border p-4; @apply rounded-lg border p-4;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.86); background: rgba(255, 255, 255, 0.86);
} }
@@ -331,12 +331,12 @@
.metric strong { .metric strong {
@apply mt-2 block text-3xl font-black; @apply mt-2 block text-3xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.filter-panel { .filter-panel {
@apply grid gap-3 rounded-lg border p-4 lg:grid-cols-[minmax(15rem,1.5fr)_repeat(4,minmax(9rem,1fr))_repeat(2,minmax(8rem,0.8fr))_minmax(10rem,1fr)_auto]; @apply grid gap-3 rounded-lg border p-4 lg:grid-cols-[minmax(15rem,1.5fr)_repeat(4,minmax(9rem,1fr))_repeat(2,minmax(8rem,0.8fr))_minmax(10rem,1fr)_auto];
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
} }
@@ -345,7 +345,7 @@
@apply flex h-10 items-center gap-2 rounded-lg border px-3 text-sm; @apply flex h-10 items-center gap-2 rounded-lg border px-3 text-sm;
border-color: rgba(23, 32, 51, 0.16); border-color: rgba(23, 32, 51, 0.16);
background: white; background: white;
color: #172033; color: var(--app-color-on-surface);
} }
.filter-search input { .filter-search input {
@@ -362,7 +362,7 @@
.report-row { .report-row {
@apply grid gap-4 rounded-lg border p-4 text-left transition-colors lg:grid-cols-[minmax(0,1.55fr)_minmax(12rem,0.8fr)_minmax(12rem,0.8fr)_minmax(12rem,0.7fr)] lg:items-center; @apply grid gap-4 rounded-lg border p-4 text-left transition-colors lg:grid-cols-[minmax(0,1.55fr)_minmax(12rem,0.8fr)_minmax(12rem,0.8fr)_minmax(12rem,0.7fr)] lg:items-center;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.86); background: rgba(255, 255, 255, 0.86);
} }
@@ -383,13 +383,13 @@
.report-title strong { .report-title strong {
@apply text-sm font-black; @apply text-sm font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.report-title em { .report-title em {
@apply rounded-md px-2 py-1 text-xs font-bold not-italic; @apply rounded-md px-2 py-1 text-xs font-bold not-italic;
background: rgba(15, 118, 110, 0.08); background: rgba(15, 118, 110, 0.08);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.status-dot { .status-dot {
@@ -402,7 +402,7 @@
} }
.status-planned { .status-planned {
background: #0f766e; background: var(--app-color-on-tertiary);
} }
.status-resolved { .status-resolved {
@@ -416,7 +416,7 @@
.report-description { .report-description {
@apply line-clamp-2 text-sm leading-6; @apply line-clamp-2 text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.report-tags { .report-tags {
@@ -425,7 +425,7 @@
.report-tags span { .report-tags span {
@apply inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-semibold; @apply inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-semibold;
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #44516a; color: #44516a;
} }
@@ -433,7 +433,7 @@
.report-context, .report-context,
.report-activity strong { .report-activity strong {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.report-secondary small, .report-secondary small,
@@ -449,13 +449,13 @@
.page-message { .page-message {
@apply rounded-lg border p-4 text-sm font-semibold; @apply rounded-lg border p-4 text-sm font-semibold;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.86); background: rgba(255, 255, 255, 0.86);
color: #526178; color: var(--app-text-muted);
} }
.page-message-error { .page-message-error {
border-color: rgba(220, 38, 38, 0.24); border-color: rgba(220, 38, 38, 0.24);
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -100,14 +100,14 @@
<template> <template>
<section class="feedback-detail-page"> <section class="feedback-detail-page">
<button <v-btn variant="text" :ripple="false"
class="back-button" class="back-button"
type="button" type="button"
@click="router.push({ name: 'my-feedback' })" @click="router.push({ name: 'my-feedback' })"
> >
<v-icon :icon="mdiArrowLeft" /> <v-icon :icon="mdiArrowLeft" />
{{ t('feedback.mine.detail.back') }} {{ t('feedback.mine.detail.back') }}
</button> </v-btn>
<div <div
v-if="feedbackStore.isDetailLoading" v-if="feedbackStore.isDetailLoading"
@@ -134,7 +134,7 @@
</div> </div>
</div> </div>
<button <v-btn variant="text" :ripple="false"
v-if="canCancel" v-if="canCancel"
class="cancel-button" class="cancel-button"
type="button" type="button"
@@ -143,7 +143,7 @@
> >
<v-icon :icon="mdiCancel" /> <v-icon :icon="mdiCancel" />
{{ feedbackStore.isCancelling ? t('common.saving') : t('feedback.mine.detail.cancel') }} {{ feedbackStore.isCancelling ? t('common.saving') : t('feedback.mine.detail.cancel') }}
</button> </v-btn>
</header> </header>
<div class="detail-grid"> <div class="detail-grid">
@@ -230,14 +230,14 @@
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="button" type="button"
:disabled="!canSubmitComment" :disabled="!canSubmitComment"
@click="submitComment" @click="submitComment"
> >
{{ feedbackStore.isCommenting ? t('feedback.review.detail.commenting') : t('feedback.review.detail.addComment') }} {{ feedbackStore.isCommenting ? t('feedback.review.detail.commenting') : t('feedback.review.detail.addComment') }}
</button> </v-btn>
</section> </section>
</aside> </aside>
</div> </div>
@@ -258,19 +258,19 @@
} }
.back-button { .back-button {
color: #0f766e; color: var(--app-color-on-tertiary);
background: rgba(15, 118, 110, 0.08); background: rgba(15, 118, 110, 0.08);
} }
.cancel-button { .cancel-button {
border: 1px solid rgba(220, 38, 38, 0.24); border: 1px solid rgba(220, 38, 38, 0.24);
color: #b91c1c; color: var(--app-danger-muted);
background: white; background: white;
} }
.primary-button { .primary-button {
@apply mt-3 justify-center; @apply mt-3 justify-center;
background: #172033; background: var(--app-color-on-surface);
color: white; color: white;
} }
@@ -285,12 +285,12 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.22em]; @apply text-xs font-bold uppercase tracking-[0.22em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.detail-header h1 { .detail-header h1 {
@apply mt-2 max-w-4xl text-2xl font-black leading-tight md:text-4xl; @apply mt-2 max-w-4xl text-2xl font-black leading-tight md:text-4xl;
color: #172033; color: var(--app-color-on-surface);
} }
.header-meta { .header-meta {
@@ -300,7 +300,7 @@
.header-meta span { .header-meta span {
@apply rounded-md px-2 py-1; @apply rounded-md px-2 py-1;
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
} }
.detail-grid { .detail-grid {
@@ -315,7 +315,7 @@
.panel, .panel,
.page-message { .page-message {
@apply rounded-lg border p-4; @apply rounded-lg border p-4;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
} }
@@ -325,18 +325,18 @@
.panel-header strong { .panel-header strong {
@apply text-sm font-black; @apply text-sm font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.description { .description {
@apply whitespace-pre-wrap text-sm leading-6; @apply whitespace-pre-wrap text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.path-link { .path-link {
@apply mt-3 inline-flex max-w-full items-center gap-2 truncate rounded-md px-2 py-1 text-sm font-semibold; @apply mt-3 inline-flex max-w-full items-center gap-2 truncate rounded-md px-2 py-1 text-sm font-semibold;
background: rgba(15, 118, 110, 0.08); background: rgba(15, 118, 110, 0.08);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.tag-row { .tag-row {
@@ -345,7 +345,7 @@
.tag-row span { .tag-row span {
@apply inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-semibold; @apply inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-semibold;
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #44516a; color: #44516a;
} }
@@ -360,7 +360,7 @@
.timeline li { .timeline li {
@apply rounded-lg border p-3; @apply rounded-lg border p-3;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(248, 250, 252, 0.75); background: rgba(248, 250, 252, 0.75);
} }
@@ -372,7 +372,7 @@
.timeline strong { .timeline strong {
@apply text-sm font-black; @apply text-sm font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.timeline span, .timeline span,
@@ -385,11 +385,11 @@
.timeline p { .timeline p {
@apply my-2 whitespace-pre-wrap text-sm leading-6; @apply my-2 whitespace-pre-wrap text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.page-message-error { .page-message-error {
border-color: rgba(220, 38, 38, 0.24); border-color: rgba(220, 38, 38, 0.24);
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -43,14 +43,14 @@
<p>{{ t('feedback.mine.description') }}</p> <p>{{ t('feedback.mine.description') }}</p>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
:title="t('feedback.mine.refresh')" :title="t('feedback.mine.refresh')"
@click="feedbackStore.loadReports" @click="feedbackStore.loadReports"
> >
<v-icon :icon="mdiRefresh" /> <v-icon :icon="mdiRefresh" />
</button> </v-btn>
</header> </header>
<section class="metric-grid"> <section class="metric-grid">
@@ -98,14 +98,14 @@
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
:title="t('feedback.review.filters.clear')" :title="t('feedback.review.filters.clear')"
@click="feedbackStore.resetFilters" @click="feedbackStore.resetFilters"
> >
<v-icon :icon="mdiFilterOffOutline" /> <v-icon :icon="mdiFilterOffOutline" />
</button> </v-btn>
</section> </section>
<div <div
@@ -126,7 +126,7 @@
v-else v-else
class="report-list" class="report-list"
> >
<button <v-btn variant="text" :ripple="false"
v-for="report in feedbackStore.filteredReports" v-for="report in feedbackStore.filteredReports"
:key="report.id" :key="report.id"
class="report-row" class="report-row"
@@ -160,7 +160,7 @@
<span>{{ t('feedback.review.lastActivity') }}</span> <span>{{ t('feedback.review.lastActivity') }}</span>
<strong>{{ formatDate(report.lastActivityAt) }}</strong> <strong>{{ formatDate(report.lastActivityAt) }}</strong>
</span> </span>
</button> </v-btn>
<div <div
v-if="!feedbackStore.filteredReports.length" v-if="!feedbackStore.filteredReports.length"
@@ -184,17 +184,17 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.22em]; @apply text-xs font-bold uppercase tracking-[0.22em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.page-header h1 { .page-header h1 {
@apply mt-2 text-3xl font-black md:text-4xl; @apply mt-2 text-3xl font-black md:text-4xl;
color: #172033; color: var(--app-color-on-surface);
} }
.page-header p { .page-header p {
@apply mt-2 max-w-3xl text-sm leading-6; @apply mt-2 max-w-3xl text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.metric-grid { .metric-grid {
@@ -206,7 +206,7 @@
.report-row, .report-row,
.page-message { .page-message {
@apply rounded-lg border; @apply rounded-lg border;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
} }
@@ -221,7 +221,7 @@
.metric strong { .metric strong {
@apply mt-2 block text-3xl font-black; @apply mt-2 block text-3xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.filter-panel { .filter-panel {
@@ -230,13 +230,13 @@
.icon-button { .icon-button {
@apply inline-flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-lg border transition-colors; @apply inline-flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-lg border transition-colors;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
color: #172033; color: var(--app-color-on-surface);
} }
.icon-button:hover { .icon-button:hover {
background: #172033; background: var(--app-color-on-surface);
color: white; color: white;
} }
@@ -256,7 +256,7 @@
.unread-dot { .unread-dot {
@apply h-2.5 w-2.5 rounded-full; @apply h-2.5 w-2.5 rounded-full;
background: #0f766e; background: var(--app-color-on-tertiary);
} }
.report-main, .report-main,
@@ -271,18 +271,18 @@
.report-title strong, .report-title strong,
.report-activity strong { .report-activity strong {
@apply text-sm font-black; @apply text-sm font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.report-title em { .report-title em {
@apply rounded-md px-2 py-1 text-xs font-bold not-italic; @apply rounded-md px-2 py-1 text-xs font-bold not-italic;
background: rgba(15, 118, 110, 0.08); background: rgba(15, 118, 110, 0.08);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.report-description { .report-description {
@apply line-clamp-2 text-sm leading-6; @apply line-clamp-2 text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.report-tags { .report-tags {
@@ -291,7 +291,7 @@
.report-tags span { .report-tags span {
@apply inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-semibold; @apply inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-semibold;
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #44516a; color: #44516a;
} }
@@ -302,11 +302,11 @@
.page-message { .page-message {
@apply p-4 text-sm font-semibold; @apply p-4 text-sm font-semibold;
color: #526178; color: var(--app-text-muted);
} }
.page-message-error { .page-message-error {
border-color: rgba(220, 38, 38, 0.24); border-color: rgba(220, 38, 38, 0.24);
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -245,7 +245,7 @@
.hero, .hero,
.panel { .panel {
@apply rounded-lg border; @apply rounded-lg border;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
} }
@@ -255,18 +255,18 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.22em]; @apply text-xs font-bold uppercase tracking-[0.22em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.hero h1 { .hero h1 {
@apply mt-2 text-3xl font-black md:text-4xl; @apply mt-2 text-3xl font-black md:text-4xl;
color: #172033; color: var(--app-color-on-surface);
} }
.hero p, .hero p,
.panel-header span { .panel-header span {
@apply mt-2 text-sm leading-6; @apply mt-2 text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.onboarding-grid { .onboarding-grid {
@@ -283,12 +283,12 @@
.panel-header .v-icon { .panel-header .v-icon {
@apply mt-1; @apply mt-1;
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.panel-header strong { .panel-header strong {
@apply block text-xl font-black; @apply block text-xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.form-stack { .form-stack {
@@ -297,13 +297,13 @@
.page-message { .page-message {
@apply rounded-lg border p-3 text-sm font-semibold; @apply rounded-lg border p-3 text-sm font-semibold;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
border-color: rgba(220, 38, 38, 0.24); border-color: rgba(220, 38, 38, 0.24);
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -253,7 +253,7 @@
<div class="eyebrow">{{ t('organizationSettings.eyebrow') }}</div> <div class="eyebrow">{{ t('organizationSettings.eyebrow') }}</div>
<p>{{ t('organizationSettings.description') }}</p> <p>{{ t('organizationSettings.description') }}</p>
<div class="organization-title-line"> <div class="organization-title-line">
<button <v-btn variant="text" :ripple="false"
v-if="organization" v-if="organization"
class="organization-logo-button" class="organization-logo-button"
type="button" type="button"
@@ -267,7 +267,7 @@
:src="organization.logoUrl" :src="organization.logoUrl"
size="lg" size="lg"
/> />
</button> </v-btn>
<v-form <v-form
v-if="organization && isEditingName" v-if="organization && isEditingName"
class="title-edit-form" class="title-edit-form"
@@ -282,7 +282,7 @@
maxlength="256" maxlength="256"
variant="outlined" variant="outlined"
/> />
<button <v-btn variant="text" :ripple="false"
class="icon-action" class="icon-action"
type="submit" type="submit"
:disabled="organizationStore.isSaving" :disabled="organizationStore.isSaving"
@@ -290,8 +290,8 @@
:title="t('organizationSettings.saveName')" :title="t('organizationSettings.saveName')"
> >
<v-icon :icon="mdiCheck" /> <v-icon :icon="mdiCheck" />
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="icon-action secondary" class="icon-action secondary"
type="button" type="button"
:disabled="organizationStore.isSaving" :disabled="organizationStore.isSaving"
@@ -300,14 +300,14 @@
@click="cancelEditingName" @click="cancelEditingName"
> >
<v-icon :icon="mdiClose" /> <v-icon :icon="mdiClose" />
</button> </v-btn>
</v-form> </v-form>
<div <div
v-else v-else
class="title-row" class="title-row"
> >
<h1>{{ organization?.name ?? t('organizationSettings.title') }}</h1> <h1>{{ organization?.name ?? t('organizationSettings.title') }}</h1>
<button <v-btn variant="text" :ripple="false"
v-if="organization && canManageSettings" v-if="organization && canManageSettings"
class="icon-action secondary" class="icon-action secondary"
type="button" type="button"
@@ -316,7 +316,7 @@
@click="startEditingName" @click="startEditingName"
> >
<v-icon :icon="mdiPencilOutline" /> <v-icon :icon="mdiPencilOutline" />
</button> </v-btn>
</div> </div>
</div> </div>
<div class="hero-status"> <div class="hero-status">
@@ -358,7 +358,7 @@
class="settings-tabs" class="settings-tabs"
aria-label="Organization settings sections" aria-label="Organization settings sections"
> >
<button <v-btn variant="text" :ripple="false"
v-for="section in visibleSections" v-for="section in visibleSections"
:key="section.key" :key="section.key"
class="settings-tab" class="settings-tab"
@@ -368,7 +368,7 @@
> >
<v-icon :icon="section.icon" /> <v-icon :icon="section.icon" />
<span>{{ t(`organizationSettings.sections.${section.key}.title`) }}</span> <span>{{ t(`organizationSettings.sections.${section.key}.title`) }}</span>
</button> </v-btn>
</nav> </nav>
<div <div
@@ -419,13 +419,13 @@
hide-details hide-details
/> />
<div class="form-actions"> <div class="form-actions">
<button <v-btn variant="text" :ripple="false"
class="primary-action" class="primary-action"
type="submit" type="submit"
:disabled="organizationStore.isAddingMember" :disabled="organizationStore.isAddingMember"
> >
{{ organizationStore.isAddingMember ? t('organizationSettings.addingMember') : t('organizationSettings.addMember') }} {{ organizationStore.isAddingMember ? t('organizationSettings.addingMember') : t('organizationSettings.addMember') }}
</button> </v-btn>
</div> </div>
</v-form> </v-form>
<div <div
@@ -561,7 +561,7 @@
.settings-hero h1, .settings-hero h1,
.title-edit-form input { .title-edit-form input {
@apply min-w-0 text-3xl font-black md:text-4xl; @apply min-w-0 text-3xl font-black md:text-4xl;
color: #172033; color: var(--app-color-on-surface);
} }
.settings-hero p, .settings-hero p,
@@ -570,7 +570,7 @@
.placeholder-panel span, .placeholder-panel span,
.empty-state { .empty-state {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.organization-title-line { .organization-title-line {
@@ -579,11 +579,11 @@
.organization-logo-button { .organization-logo-button {
@apply inline-flex size-14 flex-shrink-0 items-center justify-center rounded-[0.75rem] border bg-white transition-colors md:size-16; @apply inline-flex size-14 flex-shrink-0 items-center justify-center rounded-[0.75rem] border bg-white transition-colors md:size-16;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
} }
.organization-logo-button:hover:not(:disabled) { .organization-logo-button:hover:not(:disabled) {
border-color: #0f766e; border-color: var(--app-color-on-tertiary);
box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12); box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12);
} }
@@ -601,24 +601,24 @@
} }
.title-edit-form input:focus { .title-edit-form input:focus {
border-color: #0f766e; border-color: var(--app-color-on-tertiary);
box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12); box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12);
} }
.icon-action { .icon-action {
@apply inline-flex size-9 flex-shrink-0 items-center justify-center rounded-[0.5rem] transition-colors; @apply inline-flex size-9 flex-shrink-0 items-center justify-center rounded-[0.5rem] transition-colors;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.icon-action.secondary { .icon-action.secondary {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.icon-action:hover:not(:disabled) { .icon-action:hover:not(:disabled) {
background: #0f766e; background: var(--app-color-on-tertiary);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.icon-action:disabled { .icon-action:disabled {
@@ -635,22 +635,22 @@
.settings-tabs { .settings-tabs {
@apply flex flex-wrap gap-2 border-b pb-3; @apply flex flex-wrap gap-2 border-b pb-3;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.settings-tab { .settings-tab {
@apply inline-flex h-10 items-center gap-2 rounded-[0.75rem] px-3 text-sm font-semibold transition-colors; @apply inline-flex h-10 items-center gap-2 rounded-[0.75rem] px-3 text-sm font-semibold transition-colors;
color: #526178; color: var(--app-text-muted);
} }
.settings-tab:hover { .settings-tab:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.settings-tab-active { .settings-tab-active {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.settings-tab :deep(.v-icon) { .settings-tab :deep(.v-icon) {
@@ -667,13 +667,13 @@
.section-heading h2 { .section-heading h2 {
@apply text-2xl font-black; @apply text-2xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.content-card { .content-card {
@apply flex flex-col gap-4 rounded-[0.75rem] border p-5; @apply flex flex-col gap-4 rounded-[0.75rem] border p-5;
background: rgba(255, 255, 255, 0.94); background: var(--app-surface-glass);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.table-list { .table-list {
@@ -682,7 +682,7 @@
.table-row { .table-row {
@apply flex items-center justify-between gap-4 rounded-[0.75rem] px-4 py-3; @apply flex items-center justify-between gap-4 rounded-[0.75rem] px-4 py-3;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
} }
.table-row { .table-row {
@@ -694,7 +694,7 @@
} }
.table-row-button:hover { .table-row-button:hover {
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
} }
.table-row div { .table-row div {
@@ -704,7 +704,7 @@
.table-row strong, .table-row strong,
.placeholder-panel strong { .placeholder-panel strong {
@apply font-semibold; @apply font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.table-row small { .table-row small {
@@ -715,18 +715,18 @@
.placeholder-panel, .placeholder-panel,
.empty-state { .empty-state {
@apply rounded-[0.75rem] px-4 py-4; @apply rounded-[0.75rem] px-4 py-4;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
} }
.settings-form { .settings-form {
@apply flex flex-col gap-4 rounded-[0.75rem] p-4; @apply flex flex-col gap-4 rounded-[0.75rem] p-4;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
} }
.usage-plan span, .usage-plan span,
.usage-row-heading span { .usage-row-heading span {
@apply text-sm; @apply text-sm;
color: #526178; color: var(--app-text-muted);
} }
.field-error { .field-error {
@@ -734,7 +734,7 @@
} }
.field-success { .field-success {
color: #0f766e !important; color: var(--app-color-on-tertiary) !important;
} }
.invite-form { .invite-form {
@@ -743,7 +743,7 @@
.settings-form label { .settings-form label {
@apply flex min-w-0 flex-col gap-2 text-sm font-semibold; @apply flex min-w-0 flex-col gap-2 text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.settings-form input, .settings-form input,
@@ -751,12 +751,12 @@
@apply h-11 w-full rounded-[0.5rem] border px-3 text-sm outline-none transition-colors; @apply h-11 w-full rounded-[0.5rem] border px-3 text-sm outline-none transition-colors;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.14); border-color: rgba(23, 32, 51, 0.14);
color: #172033; color: var(--app-color-on-surface);
} }
.settings-form input:focus, .settings-form input:focus,
.settings-form select:focus { .settings-form select:focus {
border-color: #0f766e; border-color: var(--app-color-on-tertiary);
box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12); box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12);
} }
@@ -766,12 +766,12 @@
.primary-action { .primary-action {
@apply inline-flex h-11 items-center justify-center rounded-[0.5rem] px-4 text-sm font-bold transition-colors; @apply inline-flex h-11 items-center justify-center rounded-[0.5rem] px-4 text-sm font-bold transition-colors;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.primary-action:hover:not(:disabled) { .primary-action:hover:not(:disabled) {
background: #0f766e; background: var(--app-color-on-tertiary);
} }
.primary-action:disabled { .primary-action:disabled {
@@ -789,7 +789,7 @@
.settings-alert.success { .settings-alert.success {
background: rgba(15, 118, 110, 0.12); background: rgba(15, 118, 110, 0.12);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.placeholder-panel { .placeholder-panel {
@@ -802,13 +802,13 @@
.tier-form { .tier-form {
@apply grid gap-3 rounded-[0.75rem] p-4 md:grid-cols-[minmax(0,1fr)_auto] md:items-end; @apply grid gap-3 rounded-[0.75rem] p-4 md:grid-cols-[minmax(0,1fr)_auto] md:items-end;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
} }
.usage-plan, .usage-plan,
.usage-row { .usage-row {
@apply rounded-[0.75rem] p-4; @apply rounded-[0.75rem] p-4;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
} }
.usage-plan { .usage-plan {
@@ -825,12 +825,12 @@
.usage-meter { .usage-meter {
@apply h-2 overflow-hidden rounded-full; @apply h-2 overflow-hidden rounded-full;
background: rgba(23, 32, 51, 0.1); background: var(--app-control-active);
} }
.usage-meter span { .usage-meter span {
@apply block h-full rounded-full; @apply block h-full rounded-full;
background: #0f766e; background: var(--app-color-on-tertiary);
} }
</style> </style>

View File

@@ -315,27 +315,26 @@
</header> </header>
<section class="release-shell"> <section class="release-shell">
<nav <v-tabs
:model-value="activeTab"
class="release-tabs" class="release-tabs"
aria-label="Release communications sections" aria-label="Release communications sections"
density="compact"
@update:model-value="setTab"
> >
<button <v-tab
class="release-tab" class="release-tab"
:class="{ 'release-tab-active': activeTab === 'git-log' }" value="git-log"
type="button"
@click="setTab('git-log')"
> >
{{ t('releaseCommunications.commits.gitLogTab') }} {{ t('releaseCommunications.commits.gitLogTab') }}
</button> </v-tab>
<button <v-tab
class="release-tab" class="release-tab"
:class="{ 'release-tab-active': activeTab === 'release-notes' }" value="release-notes"
type="button"
@click="setTab('release-notes')"
> >
{{ t('releaseCommunications.commits.releaseNotesTab') }} {{ t('releaseCommunications.commits.releaseNotesTab') }}
</button> </v-tab>
</nav> </v-tabs>
<section class="release-content"> <section class="release-content">
<template v-if="activeTab === 'git-log'"> <template v-if="activeTab === 'git-log'">
@@ -570,17 +569,17 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.22em]; @apply text-xs font-bold uppercase tracking-[0.22em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.page-header h1 { .page-header h1 {
@apply mt-2 text-3xl font-black md:text-4xl; @apply mt-2 text-3xl font-black md:text-4xl;
color: #172033; color: var(--app-color-on-surface);
} }
.page-header p { .page-header p {
@apply mt-2 max-w-3xl text-sm leading-6; @apply mt-2 max-w-3xl text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.release-shell { .release-shell {
@@ -596,36 +595,14 @@
} }
.release-tabs { .release-tabs {
display: flex; border-bottom: 1px solid var(--app-control-active);
flex-wrap: wrap;
gap: 8px;
border-bottom: 1px solid rgba(23, 32, 51, 0.1);
padding-bottom: 12px;
} }
.release-tab { .release-tab {
display: inline-flex; min-width: 0;
height: 40px; color: var(--app-text-muted);
align-items: center;
gap: 8px;
border: 0;
border-radius: 0.75rem;
background: transparent;
padding: 0 12px;
color: #526178;
font-size: 0.875rem; font-size: 0.875rem;
font-weight: 600; font-weight: 600;
transition: background 0.15s ease, color 0.15s ease;
}
.release-tab:hover {
background: rgba(23, 32, 51, 0.06);
color: #172033;
}
.release-tab-active {
background: #172033;
color: #fffaf2;
} }
.updates-panel, .updates-panel,
@@ -665,7 +642,7 @@
.localized-fields h3, .localized-fields h3,
.selected-commits-list h3 { .selected-commits-list h3 {
margin: 0; margin: 0;
color: #172033; color: var(--app-color-on-surface);
font-size: 1rem; font-size: 1rem;
font-weight: 800; font-weight: 800;
} }
@@ -711,33 +688,6 @@
gap: 8px; gap: 8px;
} }
.release-note-field :deep(.v-field__input) {
min-height: 40px;
align-items: center;
padding-top: 0;
padding-bottom: 0;
}
.release-note-field :deep(input) {
height: 40px;
line-height: 40px;
}
.release-note-field :deep(input::placeholder),
.release-note-textarea :deep(textarea::placeholder) {
line-height: inherit;
}
.release-note-textarea :deep(.v-field__input) {
align-items: flex-start;
padding-top: 10px;
padding-bottom: 10px;
}
.release-note-textarea :deep(textarea) {
line-height: 1.45;
}
.update-row { .update-row {
display: grid; display: grid;
width: 100%; width: 100%;
@@ -746,15 +696,22 @@
border-bottom: 1px solid #e2e8f0; border-bottom: 1px solid #e2e8f0;
background: transparent; background: transparent;
padding: 10px 0; padding: 10px 0;
color: inherit;
cursor: pointer;
font: inherit;
text-align: left; text-align: left;
} }
.update-row:hover {
background: var(--app-control-hover);
}
.update-row:last-child { .update-row:last-child {
border-bottom: 0; border-bottom: 0;
} }
.update-row strong { .update-row strong {
color: #172033; color: var(--app-color-on-surface);
font-size: 1rem; font-size: 1rem;
font-weight: 800; font-weight: 800;
line-height: 1.3; line-height: 1.3;
@@ -853,7 +810,7 @@
.commit-subject { .commit-subject {
display: grid; display: grid;
gap: 4px; gap: 4px;
color: #172033; color: var(--app-color-on-surface);
font-size: 0.92rem; font-size: 0.92rem;
line-height: 1.35; line-height: 1.35;
} }
@@ -891,7 +848,7 @@
.dialog-header h2 { .dialog-header h2 {
margin: 0; margin: 0;
color: #172033; color: var(--app-color-on-surface);
font-size: 1.35rem; font-size: 1.35rem;
font-weight: 900; font-weight: 900;
} }

View File

@@ -114,17 +114,17 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.22em]; @apply text-xs font-bold uppercase tracking-[0.22em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.page-header h1 { .page-header h1 {
@apply mt-2 text-3xl font-black md:text-4xl; @apply mt-2 text-3xl font-black md:text-4xl;
color: #172033; color: var(--app-color-on-surface);
} }
.page-header p { .page-header p {
@apply mt-2 max-w-3xl text-sm leading-6; @apply mt-2 max-w-3xl text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.updates-list { .updates-list {
@@ -155,7 +155,7 @@
margin: 0; margin: 0;
font-size: 1.1rem; font-size: 1.1rem;
font-weight: 800; font-weight: 800;
color: #172033; color: var(--app-color-on-surface);
} }
.release-description { .release-description {

View File

@@ -50,17 +50,17 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.header h1 { .header h1 {
@apply mt-2 text-4xl font-black; @apply mt-2 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.header p { .header p {
@apply mt-3 max-w-2xl text-sm leading-6; @apply mt-3 max-w-2xl text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.queue-list { .queue-list {
@@ -70,26 +70,26 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 text-sm font-medium; @apply rounded-[1.25rem] border p-4 text-sm font-medium;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.queue-row { .queue-row {
@apply flex flex-col justify-between gap-4 rounded-[1.5rem] border p-5 lg:flex-row lg:items-center; @apply flex flex-col justify-between gap-4 rounded-[1.5rem] border p-5 lg:flex-row lg:items-center;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.queue-row strong { .queue-row strong {
@apply block text-xl font-black; @apply block text-xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.queue-row span, .queue-row span,
.queue-meta span, .queue-meta span,
.queue-meta small { .queue-meta small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.queue-meta { .queue-meta {

View File

@@ -48,12 +48,12 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.page-header h1 { .page-header h1 {
@apply mt-2 text-4xl font-black; @apply mt-2 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.page-header p, .page-header p,
@@ -61,13 +61,13 @@
.placeholder-block span, .placeholder-block span,
.placeholder-block small { .placeholder-block small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.panel { .panel {
@apply flex flex-col gap-5 rounded-[1.75rem] border p-5; @apply flex flex-col gap-5 rounded-[1.75rem] border p-5;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.panel-heading { .panel-heading {
@@ -76,7 +76,7 @@
.panel-heading strong, .panel-heading strong,
.placeholder-block strong { .placeholder-block strong {
color: #172033; color: var(--app-color-on-surface);
} }
.panel-heading strong { .panel-heading strong {
@@ -85,8 +85,8 @@
.placeholder-block { .placeholder-block {
@apply flex flex-col gap-2 rounded-[1.25rem] border p-4; @apply flex flex-col gap-2 rounded-[1.25rem] border p-4;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.placeholder-block strong { .placeholder-block strong {

View File

@@ -56,7 +56,7 @@
.settings-nav { .settings-nav {
@apply flex h-fit flex-col gap-2 rounded-[1.75rem] border p-4; @apply flex h-fit flex-col gap-2 rounded-[1.75rem] border p-4;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.settings-nav-header { .settings-nav-header {
@@ -65,27 +65,27 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.settings-nav-header h1 { .settings-nav-header h1 {
@apply mt-2 text-2xl font-black; @apply mt-2 text-2xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.settings-link { .settings-link {
@apply rounded-[1rem] px-4 py-3 text-sm font-semibold no-underline transition; @apply rounded-[1rem] px-4 py-3 text-sm font-semibold no-underline transition;
color: #526178; color: var(--app-text-muted);
} }
.settings-link:hover { .settings-link:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.settings-link.router-link-active { .settings-link.router-link-active {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.settings-content { .settings-content {

View File

@@ -188,13 +188,13 @@
</div> </div>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="button" type="button"
@click="isPortraitDialogOpen = true" @click="isPortraitDialogOpen = true"
> >
{{ t('userSettings.updatePortrait') }} {{ t('userSettings.updatePortrait') }}
</button> </v-btn>
</div> </div>
<div class="panel"> <div class="panel">
@@ -271,13 +271,13 @@
</div> </div>
<div class="form-actions"> <div class="form-actions">
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="submit" type="submit"
:disabled="!canSave" :disabled="!canSave"
> >
{{ userProfileStore.isUpdating ? t('common.saving') : t('userSettings.saveDetails') }} {{ userProfileStore.isUpdating ? t('common.saving') : t('userSettings.saveDetails') }}
</button> </v-btn>
</div> </div>
</v-form> </v-form>
</div> </div>
@@ -318,7 +318,7 @@
</div> </div>
<div class="calendar-feed-actions"> <div class="calendar-feed-actions">
<button <v-btn variant="text" :ripple="false"
v-if="!userProfileStore.calendarExportFeed?.isEnabled" v-if="!userProfileStore.calendarExportFeed?.isEnabled"
class="primary-button" class="primary-button"
type="button" type="button"
@@ -326,33 +326,33 @@
@click="enableCalendarFeed" @click="enableCalendarFeed"
> >
{{ t('userSettings.calendarFeed.enable') }} {{ t('userSettings.calendarFeed.enable') }}
</button> </v-btn>
<template v-else> <template v-else>
<button <v-btn variant="text" :ripple="false"
class="secondary-button" class="secondary-button"
type="button" type="button"
:disabled="!calendarFeedUrl" :disabled="!calendarFeedUrl"
@click="copyCalendarFeedUrl" @click="copyCalendarFeedUrl"
> >
{{ t('userSettings.calendarFeed.copy') }} {{ t('userSettings.calendarFeed.copy') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="secondary-button" class="secondary-button"
type="button" type="button"
:disabled="userProfileStore.isUpdatingCalendarFeed" :disabled="userProfileStore.isUpdatingCalendarFeed"
@click="regenerateCalendarFeed" @click="regenerateCalendarFeed"
> >
{{ t('userSettings.calendarFeed.regenerate') }} {{ t('userSettings.calendarFeed.regenerate') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="danger-button" class="danger-button"
type="button" type="button"
:disabled="userProfileStore.isUpdatingCalendarFeed" :disabled="userProfileStore.isUpdatingCalendarFeed"
@click="revokeCalendarFeed" @click="revokeCalendarFeed"
> >
{{ t('userSettings.calendarFeed.revoke') }} {{ t('userSettings.calendarFeed.revoke') }}
</button> </v-btn>
</template> </template>
</div> </div>
</div> </div>
@@ -377,12 +377,12 @@
.eyebrow { .eyebrow {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.page-header h1 { .page-header h1 {
@apply mt-2 text-4xl font-black; @apply mt-2 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.page-header p, .page-header p,
@@ -390,13 +390,13 @@
.hero-identity span, .hero-identity span,
.hero-identity small { .hero-identity small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.panel { .panel {
@apply flex flex-col gap-5 rounded-[1.75rem] border p-5; @apply flex flex-col gap-5 rounded-[1.75rem] border p-5;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.hero-panel { .hero-panel {
@@ -409,7 +409,7 @@
.hero-identity strong, .hero-identity strong,
.panel-heading strong { .panel-heading strong {
color: #172033; color: var(--app-color-on-surface);
} }
.hero-identity strong { .hero-identity strong {
@@ -438,14 +438,14 @@
.field span { .field span {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field input { .field input {
@apply rounded-[1rem] border px-4 py-3 text-sm; @apply rounded-[1rem] border px-4 py-3 text-sm;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.field input:disabled { .field input:disabled {
@@ -460,19 +460,19 @@
@apply rounded-[1rem] border px-4 py-3 text-sm font-semibold; @apply rounded-[1rem] border px-4 py-3 text-sm font-semibold;
background: rgba(15, 118, 110, 0.08); background: rgba(15, 118, 110, 0.08);
border-color: rgba(15, 118, 110, 0.18); border-color: rgba(15, 118, 110, 0.18);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.page-message.error { .page-message.error {
background: rgba(185, 28, 28, 0.08); background: rgba(185, 28, 28, 0.08);
border-color: rgba(185, 28, 28, 0.16); border-color: rgba(185, 28, 28, 0.16);
color: #b91c1c; color: var(--app-danger-muted);
} }
.primary-button { .primary-button {
@apply inline-flex items-center justify-center gap-2 rounded-full px-5 py-3 text-sm font-bold transition; @apply inline-flex items-center justify-center gap-2 rounded-full px-5 py-3 text-sm font-bold transition;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.secondary-button, .secondary-button,
@@ -481,13 +481,13 @@
} }
.secondary-button { .secondary-button {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.danger-button { .danger-button {
background: rgba(185, 28, 28, 0.08); background: rgba(185, 28, 28, 0.08);
color: #b91c1c; color: var(--app-danger-muted);
} }
.primary-button:disabled, .primary-button:disabled,
@@ -499,20 +499,20 @@
.calendar-feed-box { .calendar-feed-box {
@apply flex flex-col gap-2 rounded-[1rem] border p-4; @apply flex flex-col gap-2 rounded-[1rem] border p-4;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.calendar-feed-box span, .calendar-feed-box span,
.calendar-feed-empty { .calendar-feed-empty {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.calendar-feed-box code { .calendar-feed-box code {
@apply overflow-x-auto rounded-[0.75rem] px-3 py-2 text-sm; @apply overflow-x-auto rounded-[0.75rem] px-3 py-2 text-sm;
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.calendar-feed-actions { .calendar-feed-actions {

View File

@@ -148,7 +148,7 @@
<span>{{ labels.description }}</span> <span>{{ labels.description }}</span>
</div> </div>
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
class="secondary-button" class="secondary-button"
:disabled="disabled" :disabled="disabled"
@@ -156,7 +156,7 @@
> >
<v-icon :icon="mdiPlus" /> <v-icon :icon="mdiPlus" />
<span>{{ labels.addStep }}</span> <span>{{ labels.addStep }}</span>
</button> </v-btn>
</div> </div>
<div <div
@@ -182,30 +182,30 @@
</div> </div>
<div class="approval-step-actions"> <div class="approval-step-actions">
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
:aria-label="labels.moveUp" :aria-label="labels.moveUp"
:disabled="disabled || index === 0" :disabled="disabled || index === 0"
@click="moveStep(index, -1)" @click="moveStep(index, -1)"
> >
<v-icon :icon="mdiArrowUp" /> <v-icon :icon="mdiArrowUp" />
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
:aria-label="labels.moveDown" :aria-label="labels.moveDown"
:disabled="disabled || index === modelValue.length - 1" :disabled="disabled || index === modelValue.length - 1"
@click="moveStep(index, 1)" @click="moveStep(index, 1)"
> >
<v-icon :icon="mdiArrowDown" /> <v-icon :icon="mdiArrowDown" />
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
:aria-label="labels.removeStep" :aria-label="labels.removeStep"
:disabled="disabled" :disabled="disabled"
@click="removeStep(index)" @click="removeStep(index)"
> >
<v-icon :icon="mdiDeleteOutline" /> <v-icon :icon="mdiDeleteOutline" />
</button> </v-btn>
</div> </div>
</div> </div>
@@ -321,8 +321,8 @@
.approval-editor-header { .approval-editor-header {
@apply flex flex-col gap-3 rounded-[1rem] border px-4 py-4 sm:flex-row sm:items-center sm:justify-between; @apply flex flex-col gap-3 rounded-[1rem] border px-4 py-4 sm:flex-row sm:items-center sm:justify-between;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.approval-editor-header div, .approval-editor-header div,
@@ -332,14 +332,14 @@
.approval-editor-header strong, .approval-editor-header strong,
.approval-step-heading strong { .approval-step-heading strong {
color: #172033; color: var(--app-color-on-surface);
} }
.approval-editor-header span, .approval-editor-header span,
.approval-empty, .approval-empty,
.approval-step-heading small { .approval-step-heading small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.approval-step-list { .approval-step-list {
@@ -349,8 +349,8 @@
.approval-empty, .approval-empty,
.approval-step-card { .approval-step-card {
@apply rounded-[1rem] border px-4 py-4; @apply rounded-[1rem] border px-4 py-4;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.approval-step-card { .approval-step-card {
@@ -367,8 +367,8 @@
.approval-step-actions button { .approval-step-actions button {
@apply inline-flex h-9 w-9 items-center justify-center rounded-full; @apply inline-flex h-9 w-9 items-center justify-center rounded-full;
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.approval-step-actions button:disabled { .approval-step-actions button:disabled {
@@ -382,8 +382,8 @@
.secondary-button { .secondary-button {
@apply inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 text-sm font-semibold; @apply inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 text-sm font-semibold;
background: rgba(23, 32, 51, 0.08); background: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
} }
.secondary-button:disabled { .secondary-button:disabled {
@@ -397,25 +397,25 @@
.field span { .field span {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field input, .field input,
.field select { .field select {
@apply rounded-[1rem] border px-4 py-3 text-sm; @apply rounded-[1rem] border px-4 py-3 text-sm;
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
outline: none; outline: none;
} }
.field-error { .field-error {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #b91c1c; color: var(--app-danger-muted);
} }
.field-help { .field-help {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
</style> </style>

View File

@@ -274,51 +274,51 @@
> >
<div class="calendar-toolbar"> <div class="calendar-toolbar">
<div class="calendar-nav"> <div class="calendar-nav">
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
@click="shiftPeriod(-1)" @click="shiftPeriod(-1)"
> >
<v-icon :icon="mdiChevronLeft" /> <v-icon :icon="mdiChevronLeft" />
</button> </v-btn>
<div class="calendar-period">{{ periodLabel }}</div> <div class="calendar-period">{{ periodLabel }}</div>
<button <v-btn variant="text" :ripple="false"
class="icon-button" class="icon-button"
type="button" type="button"
@click="shiftPeriod(1)" @click="shiftPeriod(1)"
> >
<v-icon :icon="mdiChevronRight" /> <v-icon :icon="mdiChevronRight" />
</button> </v-btn>
</div> </div>
<div class="calendar-controls"> <div class="calendar-controls">
<button <v-btn variant="text" :ripple="false"
class="text-button" class="text-button"
type="button" type="button"
@click="jumpToToday" @click="jumpToToday"
> >
{{ t('today') }} {{ t('today') }}
</button> </v-btn>
<div class="view-toggle"> <div class="view-toggle">
<button <v-btn variant="text" :ripple="false"
class="toggle-button" class="toggle-button"
:class="{ 'toggle-button-active': viewMode === 'month' }" :class="{ 'toggle-button-active': viewMode === 'month' }"
type="button" type="button"
@click="setView('month')" @click="setView('month')"
> >
{{ t('dashboard.month') }} {{ t('dashboard.month') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="toggle-button" class="toggle-button"
:class="{ 'toggle-button-active': viewMode === 'week' }" :class="{ 'toggle-button-active': viewMode === 'week' }"
type="button" type="button"
@click="setView('week')" @click="setView('week')"
> >
{{ t('dashboard.week') }} {{ t('dashboard.week') }}
</button> </v-btn>
</div> </div>
</div> </div>
</div> </div>
@@ -396,19 +396,19 @@
.page-message { .page-message {
@apply rounded-[1.25rem] border p-4 text-sm font-medium; @apply rounded-[1.25rem] border p-4 text-sm font-medium;
background: rgba(255, 255, 255, 0.88); background: rgba(255, 255, 255, 0.88);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #526178; color: var(--app-text-muted);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
.calendar-card { .calendar-card {
@apply rounded-[1.75rem] border p-4 md:p-5; @apply rounded-[1.75rem] border p-4 md:p-5;
background: rgba(255, 255, 255, 0.94); background: var(--app-surface-glass);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.calendar-toolbar { .calendar-toolbar {
@@ -426,7 +426,7 @@
.calendar-period { .calendar-period {
@apply min-w-0 px-2 text-base font-bold md:text-lg; @apply min-w-0 px-2 text-base font-bold md:text-lg;
color: #172033; color: var(--app-color-on-surface);
} }
.icon-button, .icon-button,
@@ -434,8 +434,8 @@
.toggle-button { .toggle-button {
@apply inline-flex items-center justify-center rounded-full border px-3 py-2 text-sm font-semibold transition; @apply inline-flex items-center justify-center rounded-full border px-3 py-2 text-sm font-semibold transition;
background: #f8fafc; background: #f8fafc;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
} }
.icon-button { .icon-button {
@@ -451,7 +451,7 @@
.view-toggle { .view-toggle {
@apply inline-flex rounded-full border p-1; @apply inline-flex rounded-full border p-1;
background: #f8fafc; background: #f8fafc;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.toggle-button { .toggle-button {
@@ -459,7 +459,7 @@
} }
.toggle-button-active { .toggle-button-active {
background: #172033; background: var(--app-color-on-surface);
color: #ffffff; color: #ffffff;
} }
@@ -474,13 +474,13 @@
.weekday-label { .weekday-label {
@apply px-2 text-xs font-bold uppercase tracking-[0.16em]; @apply px-2 text-xs font-bold uppercase tracking-[0.16em];
color: #526178; color: var(--app-text-muted);
} }
.calendar-day { .calendar-day {
@apply min-h-[8.5rem] rounded-[1.25rem] border p-3; @apply min-h-[8.5rem] rounded-[1.25rem] border p-3;
background: linear-gradient(180deg, rgba(255, 253, 248, 0.8) 0%, rgba(255, 255, 255, 0.96) 100%); background: linear-gradient(180deg, rgba(255, 253, 248, 0.8) 0%, rgba(255, 255, 255, 0.96) 100%);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.calendar-day-week { .calendar-day-week {
@@ -498,7 +498,7 @@
.day-number { .day-number {
@apply mb-3 text-sm font-bold; @apply mb-3 text-sm font-bold;
color: #172033; color: var(--app-color-on-surface);
} }
.day-entries { .day-entries {
@@ -515,23 +515,23 @@
.calendar-entry strong { .calendar-entry strong {
@apply text-sm font-bold; @apply text-sm font-bold;
color: #172033; color: var(--app-color-on-surface);
} }
.calendar-entry span { .calendar-entry span {
@apply text-xs leading-5; @apply text-xs leading-5;
color: #526178; color: var(--app-text-muted);
} }
.entry-time { .entry-time {
@apply text-[0.7rem] font-bold uppercase tracking-[0.12em]; @apply text-[0.7rem] font-bold uppercase tracking-[0.12em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.entry-more, .entry-more,
.day-empty { .day-empty {
@apply px-1 text-xs font-semibold; @apply px-1 text-xs font-semibold;
color: #526178; color: var(--app-text-muted);
} }
.calendar-entry.production { .calendar-entry.production {

View File

@@ -224,7 +224,7 @@
<div class="panel-kicker">{{ t('overview.workspacesKicker') }}</div> <div class="panel-kicker">{{ t('overview.workspacesKicker') }}</div>
<div class="panel-title">{{ t('overview.workspaceRollup') }}</div> <div class="panel-title">{{ t('overview.workspaceRollup') }}</div>
<div class="workspace-stack"> <div class="workspace-stack">
<button <v-btn variant="text" :ripple="false"
v-for="workspace in workspaceStats" v-for="workspace in workspaceStats"
:key="workspace.id" :key="workspace.id"
class="workspace-row" class="workspace-row"
@@ -240,7 +240,7 @@
<small>{{ workspace.upcomingCount }} {{ t('overview.labels.upcoming') }}</small> <small>{{ workspace.upcomingCount }} {{ t('overview.labels.upcoming') }}</small>
<small>{{ workspace.blockingCount }} {{ t('overview.labels.blocked') }}</small> <small>{{ workspace.blockingCount }} {{ t('overview.labels.blocked') }}</small>
</div> </div>
</button> </v-btn>
</div> </div>
</article> </article>
@@ -324,7 +324,7 @@
.page-header h1 { .page-header h1 {
@apply mt-2 text-4xl font-black; @apply mt-2 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.page-header p, .page-header p,
@@ -333,13 +333,13 @@
.workspace-row span, .workspace-row span,
.empty-state { .empty-state {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.eyebrow, .eyebrow,
.panel-kicker { .panel-kicker {
@apply text-xs font-bold uppercase tracking-[0.24em]; @apply text-xs font-bold uppercase tracking-[0.24em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.stats-grid { .stats-grid {
@@ -354,8 +354,8 @@
.panel { .panel {
@apply rounded-[1.75rem] border p-5; @apply rounded-[1.75rem] border p-5;
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.panel { .panel {
@@ -365,7 +365,7 @@
.panel-title, .panel-title,
.workspace-row strong, .workspace-row strong,
.list-row strong { .list-row strong {
color: #172033; color: var(--app-color-on-surface);
} }
.panel-title { .panel-title {
@@ -374,7 +374,7 @@
.stat-card strong { .stat-card strong {
@apply mt-3 block text-4xl font-black; @apply mt-3 block text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.workspace-stack { .workspace-stack {
@@ -384,8 +384,8 @@
.workspace-row, .workspace-row,
.list-row { .list-row {
@apply flex items-start justify-between gap-4 rounded-[1.1rem] border p-4 text-left no-underline; @apply flex items-start justify-between gap-4 rounded-[1.1rem] border p-4 text-left no-underline;
background: #fffaf2; background: var(--app-color-on-primary);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.workspace-row.alert, .workspace-row.alert,
@@ -401,17 +401,17 @@
.workspace-meta small, .workspace-meta small,
.list-row em { .list-row em {
@apply text-sm font-semibold not-italic; @apply text-sm font-semibold not-italic;
color: #172033; color: var(--app-color-on-surface);
} }
.page-message, .page-message,
.empty-state { .empty-state {
@apply rounded-[1.25rem] border p-4 text-sm font-medium; @apply rounded-[1.25rem] border p-4 text-sm font-medium;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.page-message.error { .page-message.error {
color: #b91c1c; color: var(--app-danger-muted);
} }
</style> </style>

View File

@@ -113,21 +113,21 @@
/> />
<div class="panel-actions field-wide"> <div class="panel-actions field-wide">
<button <v-btn variant="text" :ripple="false"
class="secondary" class="secondary"
type="button" type="button"
:disabled="workspaceStore.isCreating" :disabled="workspaceStore.isCreating"
@click="cancel" @click="cancel"
> >
{{ t('common.cancel') }} {{ t('common.cancel') }}
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
class="primary" class="primary"
type="submit" type="submit"
:disabled="workspaceStore.isCreating" :disabled="workspaceStore.isCreating"
> >
{{ workspaceStore.isCreating ? t('common.creating') : t('workspaceCreate.createAction') }} {{ workspaceStore.isCreating ? t('common.creating') : t('workspaceCreate.createAction') }}
</button> </v-btn>
</div> </div>
</v-form> </v-form>
</article> </article>
@@ -143,7 +143,7 @@
.hero-copy, .hero-copy,
.create-card { .create-card {
@apply rounded-[1.75rem] border; @apply rounded-[1.75rem] border;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(255, 255, 255, 0.92); background: rgba(255, 255, 255, 0.92);
} }
@@ -151,7 +151,7 @@
@apply p-6 md:p-8; @apply p-6 md:p-8;
background: background:
radial-gradient(circle at top left, rgba(255, 138, 61, 0.16), transparent 38%), radial-gradient(circle at top left, rgba(255, 138, 61, 0.16), transparent 38%),
linear-gradient(135deg, rgba(255, 255, 255, 0.98), rgba(255, 247, 237, 0.92)); linear-gradient(135deg, var(--app-surface-raised), rgba(255, 247, 237, 0.92));
} }
.eyebrow { .eyebrow {
@@ -161,14 +161,14 @@
.hero-copy h1 { .hero-copy h1 {
@apply mt-3 text-4xl font-black; @apply mt-3 text-4xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.hero-copy p, .hero-copy p,
.card-header span, .card-header span,
.field small { .field small {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.create-card { .create-card {
@@ -176,7 +176,7 @@
} }
.card-header strong { .card-header strong {
color: #172033; color: var(--app-color-on-surface);
} }
.card-header { .card-header {
@@ -201,15 +201,15 @@
.field span { .field span {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field input, .field input,
.field select { .field select {
@apply rounded-[1rem] border px-4 py-3 text-sm; @apply rounded-[1rem] border px-4 py-3 text-sm;
background: #fffdf8; background: var(--app-color-surface);
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
outline: none; outline: none;
} }
@@ -223,12 +223,12 @@
} }
.primary { .primary {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.secondary { .secondary {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
</style> </style>

View File

@@ -417,7 +417,7 @@
class="tab-strip" class="tab-strip"
aria-label="Workspace settings sections" aria-label="Workspace settings sections"
> >
<button <v-btn variant="text" :ripple="false"
v-for="tab in settingsTabs" v-for="tab in settingsTabs"
:key="tab.key" :key="tab.key"
type="button" type="button"
@@ -427,7 +427,7 @@
> >
<v-icon :icon="tab.icon" /> <v-icon :icon="tab.icon" />
<span>{{ tab.label }}</span> <span>{{ tab.label }}</span>
</button> </v-btn>
</nav> </nav>
<div class="tab-content"> <div class="tab-content">
@@ -486,14 +486,14 @@
{{ logoStatus }} {{ logoStatus }}
</small> </small>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="secondary-button" class="secondary-button"
type="button" type="button"
:disabled="workspaceStore.isUploadingLogo" :disabled="workspaceStore.isUploadingLogo"
@click="isLogoDialogOpen = true" @click="isLogoDialogOpen = true"
> >
{{ workspaceStore.isUploadingLogo ? t('common.saving') : t('workspaceSettings.logo.changeAction') }} {{ workspaceStore.isUploadingLogo ? t('common.saving') : t('workspaceSettings.logo.changeAction') }}
</button> </v-btn>
</div> </div>
<v-text-field <v-text-field
@@ -512,13 +512,13 @@
/> />
</label> </label>
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="submit" type="submit"
:disabled="workspaceStore.isUpdating || !isSettingsDirty" :disabled="workspaceStore.isUpdating || !isSettingsDirty"
> >
{{ workspaceStore.isUpdating ? t('common.saving') : t('workspaceSettings.general.saveAction') }} {{ workspaceStore.isUpdating ? t('common.saving') : t('workspaceSettings.general.saveAction') }}
</button> </v-btn>
</v-form> </v-form>
</article> </article>
@@ -558,12 +558,12 @@
hide-details hide-details
/> />
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="submit" type="submit"
> >
{{ workspaceStore.isInviting ? t('common.creating') : t('workspaceSettings.sendInvite') }} {{ workspaceStore.isInviting ? t('common.creating') : t('workspaceSettings.sendInvite') }}
</button> </v-btn>
</v-form> </v-form>
</article> </article>
@@ -733,14 +733,14 @@
</span> </span>
</div> </div>
<button <v-btn variant="text" :ripple="false"
class="primary-button" class="primary-button"
type="button" type="button"
:disabled="workspaceStore.isUpdating || !isSettingsDirty" :disabled="workspaceStore.isUpdating || !isSettingsDirty"
@click="submitWorkspaceSettings" @click="submitWorkspaceSettings"
> >
{{ workspaceStore.isUpdating ? t('common.saving') : t('workspaceSettings.approvals.saveAction') }} {{ workspaceStore.isUpdating ? t('common.saving') : t('workspaceSettings.approvals.saveAction') }}
</button> </v-btn>
</div> </div>
</article> </article>
@@ -857,8 +857,8 @@
.settings-card { .settings-card {
@apply flex flex-col gap-5 rounded-[0.75rem] border p-5; @apply flex flex-col gap-5 rounded-[0.75rem] border p-5;
background: rgba(255, 255, 255, 0.94); background: var(--app-surface-glass);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.section-copy { .section-copy {
@@ -867,22 +867,22 @@
.tab-strip { .tab-strip {
@apply flex flex-wrap gap-2 border-b pb-3; @apply flex flex-wrap gap-2 border-b pb-3;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.tab-button { .tab-button {
@apply inline-flex h-10 items-center gap-2 rounded-[0.75rem] px-3 text-sm font-semibold transition-colors; @apply inline-flex h-10 items-center gap-2 rounded-[0.75rem] px-3 text-sm font-semibold transition-colors;
color: #526178; color: var(--app-text-muted);
} }
.tab-button:hover { .tab-button:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.tab-button-active { .tab-button-active {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.tab-button :deep(.v-icon) { .tab-button :deep(.v-icon) {
@@ -895,7 +895,7 @@
.tab-heading h2 { .tab-heading h2 {
@apply text-2xl font-black; @apply text-2xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.section-kicker { .section-kicker {
@@ -910,7 +910,7 @@
.connector-status, .connector-status,
.workflow-rule strong, .workflow-rule strong,
.workflow-step-copy strong { .workflow-step-copy strong {
color: #172033; color: var(--app-color-on-surface);
} }
.section-copy h1 { .section-copy h1 {
@@ -927,13 +927,13 @@
.workflow-rule span, .workflow-rule span,
.workflow-step-copy span { .workflow-step-copy span {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #526178; color: var(--app-text-muted);
} }
.logo-picker-card { .logo-picker-card {
@apply flex flex-col gap-4 rounded-[0.75rem] border p-4 sm:flex-row sm:items-center; @apply flex flex-col gap-4 rounded-[0.75rem] border p-4 sm:flex-row sm:items-center;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.logo-picker-copy { .logo-picker-copy {
@@ -941,7 +941,7 @@
} }
.logo-picker-copy strong { .logo-picker-copy strong {
color: #172033; color: var(--app-color-on-surface);
} }
.logo-picker-copy small, .logo-picker-copy small,
@@ -951,11 +951,11 @@
} }
.field-error { .field-error {
color: #b91c1c; color: var(--app-danger-muted);
} }
.field-success { .field-success {
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.form-stack { .form-stack {
@@ -968,43 +968,43 @@
.field span { .field span {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.field input, .field input,
.field select { .field select {
@apply h-11 rounded-[0.5rem] border px-3 text-sm outline-none transition-colors; @apply h-11 rounded-[0.5rem] border px-3 text-sm outline-none transition-colors;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
} }
.field input:focus, .field input:focus,
.field select:focus { .field select:focus {
border-color: #0f766e; border-color: var(--app-color-on-tertiary);
box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12); box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12);
} }
.primary-button { .primary-button {
@apply inline-flex h-11 items-center justify-center rounded-[0.5rem] px-4 text-sm font-bold transition-colors; @apply inline-flex h-11 items-center justify-center rounded-[0.5rem] px-4 text-sm font-bold transition-colors;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.secondary-button { .secondary-button {
@apply inline-flex h-11 items-center justify-center rounded-[0.5rem] border px-4 text-sm font-bold transition-colors; @apply inline-flex h-11 items-center justify-center rounded-[0.5rem] border px-4 text-sm font-bold transition-colors;
background: #ffffff; background: #ffffff;
border-color: rgba(23, 32, 51, 0.14); border-color: rgba(23, 32, 51, 0.14);
color: #172033; color: var(--app-color-on-surface);
} }
.primary-button:hover:not(:disabled) { .primary-button:hover:not(:disabled) {
background: #0f766e; background: var(--app-color-on-tertiary);
} }
.secondary-button:hover:not(:disabled) { .secondary-button:hover:not(:disabled) {
border-color: #0f766e; border-color: var(--app-color-on-tertiary);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.primary-button:disabled, .primary-button:disabled,
@@ -1027,8 +1027,8 @@
.workflow-toggle, .workflow-toggle,
.workflow-step { .workflow-step {
@apply rounded-[0.75rem] border px-4 py-4; @apply rounded-[0.75rem] border px-4 py-4;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.invite-row { .invite-row {
@@ -1064,7 +1064,7 @@
.workflow-step-icon { .workflow-step-icon {
@apply inline-flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-[0.75rem]; @apply inline-flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-[0.75rem];
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.connector-status { .connector-status {
@@ -1074,11 +1074,11 @@
.connector-link { .connector-link {
@apply inline-flex h-11 w-fit items-center gap-3 rounded-[0.5rem] px-4 text-sm font-bold no-underline transition; @apply inline-flex h-11 w-fit items-center gap-3 rounded-[0.5rem] px-4 text-sm font-bold no-underline transition;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.connector-link:hover { .connector-link:hover {
background: #0f766e; background: var(--app-color-on-tertiary);
} }
</style> </style>

View File

@@ -216,21 +216,25 @@
<div class="side-menu-items side-menu-right"> <div class="side-menu-items side-menu-right">
<template v-if="!authStore.isAuthenticated"> <template v-if="!authStore.isAuthenticated">
<router-link to="/login"> <v-btn
<button class="menu-item-action"> to="/login"
<v-icon :icon="mdiLogin" /> class="menu-item-action"
<span class="label">{{ t('nav.signIn') }}</span> variant="text"
</button> :ripple="false"
</router-link> >
<v-icon :icon="mdiLogin" />
<span class="label">{{ t('nav.signIn') }}</span>
</v-btn>
</template> </template>
<div <div
v-if="contentViewActions.length" v-if="contentViewActions.length"
class="view-selector" class="view-selector"
> >
<button <v-btn
class="menu-item-action view-selector-button" class="menu-item-action view-selector-button"
type="button" variant="text"
:ripple="false"
@click="isContentViewMenuOpen = !isContentViewMenuOpen" @click="isContentViewMenuOpen = !isContentViewMenuOpen"
> >
<v-icon :icon="activeContentViewAction.icon" /> <v-icon :icon="activeContentViewAction.icon" />
@@ -239,28 +243,25 @@
class="selector-chevron" class="selector-chevron"
:icon="mdiChevronDown" :icon="mdiChevronDown"
/> />
</button> </v-btn>
<div <div
v-if="isContentViewMenuOpen" v-if="isContentViewMenuOpen"
class="view-selector-menu" class="view-selector-menu"
> >
<router-link <v-btn
v-for="action in contentViewActions" v-for="action in contentViewActions"
:key="action.key" :key="action.key"
:to="action.route" :to="action.route"
class="menu-action-link" class="view-selector-option menu-action-link"
:class="{ 'view-selector-option-active': action.active }"
variant="text"
:ripple="false"
@click="isContentViewMenuOpen = false" @click="isContentViewMenuOpen = false"
> >
<button <v-icon :icon="action.icon" />
class="view-selector-option" <span>{{ action.label }}</span>
:class="{ 'view-selector-option-active': action.active }" </v-btn>
type="button"
>
<v-icon :icon="action.icon" />
<span>{{ action.label }}</span>
</button>
</router-link>
</div> </div>
</div> </div>
@@ -268,19 +269,21 @@
v-for="action in appBarActions" v-for="action in appBarActions"
:key="action.key" :key="action.key"
> >
<button <v-btn
v-if="action.disabled" v-if="action.disabled"
class="menu-item-action" class="menu-item-action"
type="button" variant="text"
:ripple="false"
disabled disabled
> >
<v-icon :icon="action.icon" /> <v-icon :icon="action.icon" />
<span class="label">{{ action.label }}</span> <span class="label">{{ action.label }}</span>
</button> </v-btn>
<button <v-btn
v-else-if="action.handler" v-else-if="action.handler"
class="menu-item-action" class="menu-item-action"
type="button" variant="text"
:ripple="false"
:disabled="action.loading" :disabled="action.loading"
@click="action.handler" @click="action.handler"
> >
@@ -295,17 +298,17 @@
:icon="action.icon" :icon="action.icon"
/> />
<span class="label">{{ action.label }}</span> <span class="label">{{ action.label }}</span>
</button> </v-btn>
<router-link <v-btn
v-else v-else
:to="action.route" :to="action.route"
class="menu-action-link" class="menu-item-action menu-action-link"
variant="text"
:ripple="false"
> >
<button class="menu-item-action"> <v-icon :icon="action.icon" />
<v-icon :icon="action.icon" /> <span class="label">{{ action.label }}</span>
<span class="label">{{ action.label }}</span> </v-btn>
</button>
</router-link>
</template> </template>
</div> </div>
</div> </div>
@@ -318,7 +321,7 @@
@apply sticky top-0 z-20 flex flex-col gap-4 px-5 py-4 md:flex-row md:items-center md:justify-between; @apply sticky top-0 z-20 flex flex-col gap-4 px-5 py-4 md:flex-row md:items-center md:justify-between;
background: rgba(255, 250, 242, 0.82); background: rgba(255, 250, 242, 0.82);
backdrop-filter: blur(18px); backdrop-filter: blur(18px);
border-bottom: 1px solid rgba(23, 32, 51, 0.08); border-bottom: 1px solid var(--app-border-subtle);
isolation: isolate; isolation: isolate;
} }
@@ -353,8 +356,8 @@
.view-selector-menu { .view-selector-menu {
@apply absolute right-0 top-[calc(100%+0.5rem)] z-30 flex min-w-52 flex-col gap-1 rounded-[1rem] border p-2 shadow-xl; @apply absolute right-0 top-[calc(100%+0.5rem)] z-30 flex min-w-52 flex-col gap-1 rounded-[1rem] border p-2 shadow-xl;
background: #ffffff; background: var(--app-surface-raised);
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-border-subtle);
} }
.label { .label {
@@ -362,15 +365,16 @@
} }
.menu-item-action { .menu-item-action {
@apply flex h-11 items-center gap-3 rounded-full px-4 transition-colors; @apply flex h-11 items-center justify-start gap-3 rounded-full px-4 normal-case transition-colors;
background: rgba(255, 255, 255, 0.8); background: rgba(255, 255, 255, 0.8);
color: #172033; color: var(--app-color-on-surface);
border: 1px solid rgba(23, 32, 51, 0.06); border: 1px solid var(--app-border-muted);
letter-spacing: 0;
} }
.menu-item-action:hover { .menu-item-action:hover {
background: #172033; background: var(--app-color-primary);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.menu-item-action:disabled { .menu-item-action:disabled {
@@ -380,21 +384,27 @@
.menu-item-action:disabled:hover { .menu-item-action:disabled:hover {
background: rgba(255, 255, 255, 0.8); background: rgba(255, 255, 255, 0.8);
color: #172033; color: var(--app-color-on-surface);
} }
.view-selector-option { .view-selector-option {
@apply flex min-h-11 w-full items-center gap-3 rounded-[0.75rem] px-3 text-left text-sm font-semibold transition; @apply flex h-auto min-h-11 w-full items-center justify-start gap-3 rounded-[0.75rem] px-3 text-left text-sm font-semibold normal-case transition;
color: #172033; color: var(--app-color-on-surface);
letter-spacing: 0;
} }
.view-selector-option:hover, .view-selector-option:hover,
.view-selector-option-active { .view-selector-option-active {
background: #172033; background: var(--app-color-primary);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.menu-item-action i { .menu-item-action :deep(.v-btn__content),
.view-selector-option :deep(.v-btn__content) {
@apply flex min-w-0 items-center justify-start gap-3;
}
.menu-item-action :deep(.v-icon) {
@apply text-xl; @apply text-xl;
} }

View File

@@ -356,15 +356,17 @@
class="sidebar-search-group" class="sidebar-search-group"
> >
<strong>Campaigns</strong> <strong>Campaigns</strong>
<button <v-btn
v-for="result in campaignResults" v-for="result in campaignResults"
:key="`campaign-${result.id}`" :key="`campaign-${result.id}`"
class="sidebar-search-result" class="sidebar-search-result"
variant="text"
:ripple="false"
@click="openSearchResult(result)" @click="openSearchResult(result)"
> >
<span>{{ result.label }}</span> <span>{{ result.label }}</span>
<small>{{ result.description }}</small> <small>{{ result.description }}</small>
</button> </v-btn>
</div> </div>
<div <div
@@ -372,15 +374,17 @@
class="sidebar-search-group" class="sidebar-search-group"
> >
<strong>Content items</strong> <strong>Content items</strong>
<button <v-btn
v-for="result in contentResults" v-for="result in contentResults"
:key="`content-${result.id}`" :key="`content-${result.id}`"
class="sidebar-search-result" class="sidebar-search-result"
variant="text"
:ripple="false"
@click="openSearchResult(result)" @click="openSearchResult(result)"
> >
<span>{{ result.label }}</span> <span>{{ result.label }}</span>
<small>{{ result.description }}</small> <small>{{ result.description }}</small>
</button> </v-btn>
</div> </div>
<div <div
@@ -396,9 +400,10 @@
ref="notificationsRef" ref="notificationsRef"
class="sidebar-notifications-wrap" class="sidebar-notifications-wrap"
> >
<button <v-btn
class="sidebar-link sidebar-utility-link" class="sidebar-link sidebar-control sidebar-utility-link"
type="button" variant="text"
:ripple="false"
@click.stop="toggleNotifications" @click.stop="toggleNotifications"
> >
<span class="sidebar-link-main"> <span class="sidebar-link-main">
@@ -418,7 +423,7 @@
{{ t('notifications.title') }} {{ t('notifications.title') }}
</span> </span>
</span> </span>
</button> </v-btn>
<div <div
v-if="isExpanded && isNotificationsOpen" v-if="isExpanded && isNotificationsOpen"
@@ -443,17 +448,19 @@
{{ notificationsStore.error }} {{ notificationsStore.error }}
</div> </div>
<button <v-btn
v-for="notification in notificationsStore.recentItems" v-for="notification in notificationsStore.recentItems"
:key="notification.id" :key="notification.id"
class="sidebar-notification-row" class="sidebar-notification-row"
:class="{ 'sidebar-notification-row-unread': !notification.readAt }" :class="{ 'sidebar-notification-row-unread': !notification.readAt }"
variant="text"
:ripple="false"
@click="openNotification(notification)" @click="openNotification(notification)"
> >
<strong>{{ formatNotificationTitle(notification) }}</strong> <strong>{{ formatNotificationTitle(notification) }}</strong>
<span>{{ notification.message }}</span> <span>{{ notification.message }}</span>
<small>{{ formatNotificationDate(notification.createdAt) }}</small> <small>{{ formatNotificationDate(notification.createdAt) }}</small>
</button> </v-btn>
<div <div
v-if="!notificationsStore.isLoading && !notificationsStore.recentItems.length" v-if="!notificationsStore.isLoading && !notificationsStore.recentItems.length"
@@ -466,12 +473,14 @@
</div> </div>
<div class="sidebar-section sidebar-primary-links"> <div class="sidebar-section sidebar-primary-links">
<router-link <v-btn
v-for="link in visiblePrimaryLinks" v-for="link in visiblePrimaryLinks"
:key="link.to" :key="link.to"
:to="link.to" :to="link.to"
class="sidebar-link" class="sidebar-link sidebar-control"
active-class="sidebar-link-active" active-class="sidebar-link-active sidebar-control-active"
variant="text"
:ripple="false"
:title="!isExpanded ? t(link.labelKey) : null" :title="!isExpanded ? t(link.labelKey) : null"
> >
<span class="sidebar-link-icon-wrap"> <span class="sidebar-link-icon-wrap">
@@ -495,15 +504,17 @@
> >
{{ t(link.labelKey) }} {{ t(link.labelKey) }}
</span> </span>
</router-link> </v-btn>
</div> </div>
<div class="sidebar-section"> <div class="sidebar-section">
<div class="sidebar-section-header"> <div class="sidebar-section-header">
<router-link <v-btn
to="/app/content" to="/app/content"
class="sidebar-link sidebar-link-section" class="sidebar-link sidebar-control sidebar-link-section"
active-class="sidebar-link-active" active-class="sidebar-link-active sidebar-control-active"
variant="text"
:ripple="false"
:title="!isExpanded ? t('nav.content') : null" :title="!isExpanded ? t('nav.content') : null"
> >
<span class="sidebar-link-main"> <span class="sidebar-link-main">
@@ -515,25 +526,29 @@
{{ t('nav.content') }} {{ t('nav.content') }}
</span> </span>
</span> </span>
</router-link> </v-btn>
<router-link <v-btn
v-if="isExpanded" v-if="isExpanded"
:to="{ name: 'content-item-create' }" :to="{ name: 'content-item-create' }"
class="sidebar-section-action" class="sidebar-section-action sidebar-icon-button"
variant="text"
:ripple="false"
:title="t('contentItems.newItem')" :title="t('contentItems.newItem')"
> >
<v-icon :icon="mdiPlus" /> <v-icon :icon="mdiPlus" />
</router-link> </v-btn>
</div> </div>
</div> </div>
<div class="sidebar-section"> <div class="sidebar-section">
<div class="sidebar-section-header"> <div class="sidebar-section-header">
<router-link <v-btn
to="/app/campaigns" to="/app/campaigns"
class="sidebar-link sidebar-link-section" class="sidebar-link sidebar-control sidebar-link-section"
active-class="sidebar-link-active" active-class="sidebar-link-active sidebar-control-active"
variant="text"
:ripple="false"
:title="!isExpanded ? t('nav.campaigns') : null" :title="!isExpanded ? t('nav.campaigns') : null"
@click="toggleSection('campaigns')" @click="toggleSection('campaigns')"
> >
@@ -552,16 +567,18 @@
:class="{ 'sidebar-chevron-open': openSections.campaigns }" :class="{ 'sidebar-chevron-open': openSections.campaigns }"
/> />
</span> </span>
</router-link> </v-btn>
<router-link <v-btn
v-if="isExpanded" v-if="isExpanded"
to="/app/campaigns?create=true" to="/app/campaigns?create=true"
class="sidebar-section-action" class="sidebar-section-action sidebar-icon-button"
variant="text"
:ripple="false"
:title="t('campaigns.createTitle')" :title="t('campaigns.createTitle')"
> >
<v-icon :icon="mdiPlus" /> <v-icon :icon="mdiPlus" />
</router-link> </v-btn>
</div> </div>
<div <div
@@ -597,10 +614,12 @@
<div class="sidebar-section"> <div class="sidebar-section">
<div class="sidebar-section-header"> <div class="sidebar-section-header">
<router-link <v-btn
to="/app/channels" to="/app/channels"
class="sidebar-link sidebar-link-section" class="sidebar-link sidebar-control sidebar-link-section"
active-class="sidebar-link-active" active-class="sidebar-link-active sidebar-control-active"
variant="text"
:ripple="false"
:title="!isExpanded ? t('nav.channels') : null" :title="!isExpanded ? t('nav.channels') : null"
@click="toggleSection('channels')" @click="toggleSection('channels')"
> >
@@ -619,16 +638,18 @@
:class="{ 'sidebar-chevron-open': openSections.channels }" :class="{ 'sidebar-chevron-open': openSections.channels }"
/> />
</span> </span>
</router-link> </v-btn>
<router-link <v-btn
v-if="isExpanded" v-if="isExpanded"
to="/app/channels?create=true" to="/app/channels?create=true"
class="sidebar-section-action" class="sidebar-section-action sidebar-icon-button"
variant="text"
:ripple="false"
:title="t('channels.createTitle')" :title="t('channels.createTitle')"
> >
<v-icon :icon="mdiPlus" /> <v-icon :icon="mdiPlus" />
</router-link> </v-btn>
</div> </div>
<div <div
@@ -668,12 +689,14 @@
v-if="authStore.isAuthenticated && visibleBottomLinks.length" v-if="authStore.isAuthenticated && visibleBottomLinks.length"
class="sidebar-section sidebar-bottom-links" class="sidebar-section sidebar-bottom-links"
> >
<router-link <v-btn
v-for="link in visibleBottomLinks" v-for="link in visibleBottomLinks"
:key="link.to" :key="link.to"
:to="link.to" :to="link.to"
class="sidebar-link" class="sidebar-link sidebar-control"
active-class="sidebar-link-active" active-class="sidebar-link-active sidebar-control-active"
variant="text"
:ripple="false"
:title="!isExpanded ? t(link.labelKey) : null" :title="!isExpanded ? t(link.labelKey) : null"
> >
<span class="sidebar-link-icon-wrap"> <span class="sidebar-link-icon-wrap">
@@ -691,7 +714,7 @@
> >
{{ t(link.labelKey) }} {{ t(link.labelKey) }}
</span> </span>
</router-link> </v-btn>
</div> </div>
<SidebarUserMenu <SidebarUserMenu
@@ -705,7 +728,7 @@
@reference "@/assets/main.css"; @reference "@/assets/main.css";
.app-sidebar { .app-sidebar {
@apply flex h-full w-[19rem] flex-shrink-0 flex-col px-4 pt-4 transition-[width,padding] duration-200; @apply flex h-full w-[19rem] flex-shrink-0 flex-col px-4 pt-4 transition-[width,padding] duration-200;
border-right: 1px solid rgba(23, 32, 51, 0.08); border-right: 1px solid var(--app-border-subtle);
} }
.app-sidebar-scroll { .app-sidebar-scroll {
@@ -714,7 +737,7 @@
.brand-block { .brand-block {
@apply flex items-center gap-3 pb-4; @apply flex items-center gap-3 pb-4;
border-bottom: 1px solid rgba(23, 32, 51, 0.08); border-bottom: 1px solid var(--app-border-subtle);
} }
.brand-link { .brand-link {
@@ -744,7 +767,7 @@
.brand-name { .brand-name {
@apply min-w-0 text-lg font-black uppercase tracking-[0.18em]; @apply min-w-0 text-lg font-black uppercase tracking-[0.18em];
color: rgb(var(--v-theme-primary)); color: var(--app-color-primary);
line-height: 2.75rem; line-height: 2.75rem;
} }
@@ -777,25 +800,25 @@
.sidebar-search { .sidebar-search {
@apply flex h-11 items-center gap-3 rounded-[1.1rem] border px-4 transition-colors; @apply flex h-11 items-center gap-3 rounded-[1.1rem] border px-4 transition-colors;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
border-color: rgba(23, 32, 51, 0.06); border-color: var(--app-border-muted);
color: #526178; color: var(--app-text-muted);
} }
.sidebar-search-open, .sidebar-search-open,
.sidebar-search:focus-within { .sidebar-search:focus-within {
background: rgba(255, 255, 255, 0.96); background: var(--app-color-control-focus);
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-border-subtle);
} }
.sidebar-search-icon { .sidebar-search-icon {
@apply h-5 w-5 flex-shrink-0 text-xl; @apply h-5 w-5 flex-shrink-0 text-xl;
color: #526178; color: var(--app-text-muted);
} }
.sidebar-search-input { .sidebar-search-input {
@apply min-w-0 flex-1 border-0 bg-transparent p-0 text-sm; @apply min-w-0 flex-1 border-0 bg-transparent p-0 text-sm;
color: #172033; color: var(--app-color-on-surface);
outline: none; outline: none;
} }
@@ -804,14 +827,14 @@
} }
.sidebar-search-input::placeholder { .sidebar-search-input::placeholder {
color: #7a8799; color: var(--app-text-subtle);
} }
.sidebar-floating-panel { .sidebar-floating-panel {
@apply absolute left-0 right-0 top-[calc(100%+0.6rem)] z-40 flex flex-col gap-3 rounded-[1.25rem] border p-3; @apply absolute left-0 right-0 top-[calc(100%+0.6rem)] z-40 flex flex-col gap-3 rounded-[1.25rem] border p-3;
background: rgba(255, 255, 255, 0.98); background: var(--app-surface-raised);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.12); box-shadow: var(--app-shadow-popover);
} }
.sidebar-search-panel-collapsed { .sidebar-search-panel-collapsed {
@@ -828,22 +851,27 @@
.sidebar-search-group strong { .sidebar-search-group strong {
@apply px-2 text-xs font-black uppercase tracking-[0.18em]; @apply px-2 text-xs font-black uppercase tracking-[0.18em];
color: #5d6b82; color: var(--app-text-muted);
} }
.sidebar-search-result { .sidebar-search-result {
@apply flex flex-col gap-1 rounded-[0.95rem] px-3 py-3 text-left transition-colors; @apply flex h-auto min-h-0 flex-col items-stretch gap-1 rounded-[0.95rem] px-3 py-3 text-left normal-case transition-colors;
color: #172033; color: var(--app-color-on-surface);
letter-spacing: 0;
} }
.sidebar-search-result:hover { .sidebar-search-result:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
}
.sidebar-search-result :deep(.v-btn__content) {
@apply flex min-w-0 flex-col items-start gap-1 whitespace-normal;
} }
.sidebar-search-result small, .sidebar-search-result small,
.sidebar-search-empty { .sidebar-search-empty {
@apply text-xs leading-5; @apply text-xs leading-5;
color: #526178; color: var(--app-text-muted);
} }
.sidebar-search-empty { .sidebar-search-empty {
@@ -865,7 +893,7 @@
.sidebar-notification-badge { .sidebar-notification-badge {
@apply absolute -right-2 -top-2 flex h-5 min-w-[1.25rem] items-center justify-center rounded-full px-1 text-[10px] font-black; @apply absolute -right-2 -top-2 flex h-5 min-w-[1.25rem] items-center justify-center rounded-full px-1 text-[10px] font-black;
background: #ef4444; background: #ef4444;
color: #fffaf2; color: var(--app-color-on-primary);
} }
.sidebar-notifications-panel { .sidebar-notifications-panel {
@@ -878,7 +906,7 @@
.sidebar-notifications-header strong { .sidebar-notifications-header strong {
@apply text-sm font-black; @apply text-sm font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.sidebar-notifications-header span, .sidebar-notifications-header span,
@@ -886,7 +914,7 @@
.sidebar-notification-row span, .sidebar-notification-row span,
.sidebar-notification-row small { .sidebar-notification-row small {
@apply text-xs leading-5; @apply text-xs leading-5;
color: #526178; color: var(--app-text-muted);
} }
.sidebar-notifications-empty { .sidebar-notifications-empty {
@@ -894,20 +922,25 @@
} }
.sidebar-notification-row { .sidebar-notification-row {
@apply flex flex-col gap-1 rounded-[0.9rem] px-3 py-3 text-left transition-colors; @apply flex h-auto min-h-0 flex-col items-stretch gap-1 rounded-[0.9rem] px-3 py-3 text-left normal-case transition-colors;
letter-spacing: 0;
} }
.sidebar-notification-row:hover { .sidebar-notification-row:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
}
.sidebar-notification-row :deep(.v-btn__content) {
@apply flex min-w-0 flex-col items-start gap-1 whitespace-normal;
} }
.sidebar-notification-row-unread { .sidebar-notification-row-unread {
background: rgba(15, 118, 110, 0.08); background: color-mix(in srgb, var(--app-color-highlight) 14%, transparent);
} }
.sidebar-notification-row strong { .sidebar-notification-row strong {
@apply text-sm font-semibold; @apply text-sm font-semibold;
color: #172033; color: var(--app-color-on-surface);
} }
.sidebar-section { .sidebar-section {
@@ -923,18 +956,21 @@
} }
.sidebar-link { .sidebar-link {
@apply flex min-w-0 items-center gap-3 rounded-[1.1rem] px-4 py-3 text-sm font-semibold no-underline transition-colors; @apply flex h-auto min-h-11 min-w-0 items-center gap-3 rounded-[1.1rem] px-4 py-3 text-sm font-semibold no-underline normal-case transition-colors;
color: #44516a; color: #44516a;
background: transparent;
letter-spacing: 0;
justify-content: flex-start;
} }
.sidebar-link:hover { .sidebar-link:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.sidebar-link-active { .sidebar-link-active {
background: linear-gradient(135deg, rgba(255, 138, 61, 0.14), rgba(239, 68, 68, 0.1)); background: linear-gradient(135deg, rgba(255, 138, 61, 0.14), rgba(239, 68, 68, 0.1));
color: #172033; color: var(--app-color-on-surface);
box-shadow: inset 0 0 0 1px rgba(255, 138, 61, 0.2); box-shadow: inset 0 0 0 1px rgba(255, 138, 61, 0.2);
} }
@@ -951,13 +987,14 @@
} }
.sidebar-section-action { .sidebar-section-action {
@apply ml-auto flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-[1rem] transition-colors no-underline; @apply ml-auto flex h-11 min-w-0 w-11 flex-shrink-0 items-center justify-center rounded-[1rem] normal-case transition-colors no-underline;
color: #526178; color: var(--app-text-muted);
letter-spacing: 0;
} }
.sidebar-section-action:hover { .sidebar-section-action:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.sidebar-chevron { .sidebar-chevron {
@@ -974,19 +1011,28 @@
@apply h-5 w-5 flex-shrink-0 text-xl; @apply h-5 w-5 flex-shrink-0 text-xl;
} }
.sidebar-link :deep(.v-btn__content),
.sidebar-section-action :deep(.v-btn__content) {
@apply flex min-w-0 items-center justify-start gap-3;
}
.sidebar-section-action :deep(.v-btn__content) {
@apply justify-center;
}
.sidebar-sublist { .sidebar-sublist {
@apply flex flex-col gap-1 pl-4; @apply flex flex-col gap-1 pl-4;
} }
.sidebar-sublink { .sidebar-sublink {
@apply flex flex-col rounded-[1rem] px-4 py-3 text-sm no-underline transition-colors; @apply flex flex-col rounded-[1rem] px-4 py-3 text-sm no-underline transition-colors;
color: #526178; color: var(--app-text-muted);
} }
.sidebar-sublink:hover, .sidebar-sublink:hover,
.sidebar-sublink-active { .sidebar-sublink-active {
background: rgba(23, 32, 51, 0.05); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.sidebar-sublink strong { .sidebar-sublink strong {
@@ -996,7 +1042,7 @@
.sidebar-sublink small, .sidebar-sublink small,
.sidebar-empty { .sidebar-empty {
@apply text-xs; @apply text-xs;
color: #7a8799; color: var(--app-text-subtle);
} }
.app-sidebar-collapsed { .app-sidebar-collapsed {
@@ -1020,7 +1066,7 @@
} }
.app-sidebar-collapsed .sidebar-search:hover { .app-sidebar-collapsed .sidebar-search:hover {
background: rgba(23, 32, 51, 0.07); background: var(--app-control-active);
} }
.app-sidebar-collapsed .sidebar-search-panel-input { .app-sidebar-collapsed .sidebar-search-panel-input {

View File

@@ -90,9 +90,10 @@
class="sidebar-workspace sidebar-workspace-bottom" class="sidebar-workspace sidebar-workspace-bottom"
:class="{ 'sidebar-workspace-collapsed': !isExpanded }" :class="{ 'sidebar-workspace-collapsed': !isExpanded }"
> >
<button <v-btn
class="sidebar-workspace-trigger" class="sidebar-workspace-trigger"
type="button" variant="text"
:ripple="false"
:title="!isExpanded ? userProfileStore.alias : null" :title="!isExpanded ? userProfileStore.alias : null"
@click.stop="toggleUserMenu" @click.stop="toggleUserMenu"
> >
@@ -113,46 +114,50 @@
class="sidebar-workspace-icon" class="sidebar-workspace-icon"
:class="{ 'sidebar-workspace-icon-open': isUserMenuOpen }" :class="{ 'sidebar-workspace-icon-open': isUserMenuOpen }"
/> />
</button> </v-btn>
<div <div
v-if="isUserMenuOpen" v-if="isUserMenuOpen"
class="sidebar-workspace-menu" class="sidebar-workspace-menu sidebar-menu-surface"
> >
<button <v-btn
class="sidebar-workspace-option" class="sidebar-workspace-option sidebar-menu-option"
type="button" variant="text"
:ripple="false"
@click="openMyFeedback" @click="openMyFeedback"
> >
<v-icon :icon="mdiBugOutline" /> <v-icon :icon="mdiBugOutline" />
<span>{{ t('nav.myFeedback') }}</span> <span>{{ t('nav.myFeedback') }}</span>
</button> </v-btn>
<div class="sidebar-workspace-separator" /> <div class="sidebar-workspace-separator sidebar-menu-separator" />
<button <v-btn
class="sidebar-workspace-option" class="sidebar-workspace-option sidebar-menu-option"
type="button" variant="text"
:ripple="false"
@click="openProfile" @click="openProfile"
> >
<v-icon :icon="mdiAccountCircleOutline" /> <v-icon :icon="mdiAccountCircleOutline" />
<span>{{ t('nav.profile') }}</span> <span>{{ t('nav.profile') }}</span>
</button> </v-btn>
<button <v-btn
class="sidebar-workspace-option" class="sidebar-workspace-option sidebar-menu-option"
type="button" variant="text"
:ripple="false"
@click="toggleLanguage" @click="toggleLanguage"
> >
<v-icon :icon="mdiTranslate" /> <v-icon :icon="mdiTranslate" />
<span>{{ t('nav.language') }}</span> <span>{{ t('nav.language') }}</span>
</button> </v-btn>
<div class="sidebar-workspace-separator" /> <div class="sidebar-workspace-separator sidebar-menu-separator" />
<button <v-btn
class="sidebar-workspace-option sidebar-workspace-option-danger" class="sidebar-workspace-option sidebar-menu-option sidebar-workspace-option-danger sidebar-menu-option-danger"
type="button" variant="text"
:ripple="false"
@click="handleLogout" @click="handleLogout"
> >
<v-icon :icon="mdiLogout" /> <v-icon :icon="mdiLogout" />
<span>{{ t('nav.signOut') }}</span> <span>{{ t('nav.signOut') }}</span>
</button> </v-btn>
</div> </div>
</div> </div>
</template> </template>
@@ -165,26 +170,31 @@
.sidebar-workspace-bottom { .sidebar-workspace-bottom {
@apply py-4; @apply py-4;
border-top: 1px solid rgba(23, 32, 51, 0.08); border-top: 1px solid var(--app-border-subtle);
} }
.sidebar-workspace-trigger { .sidebar-workspace-trigger {
@apply flex w-full items-center gap-3 rounded-[1.1rem] px-4 py-3 text-left transition-colors; @apply flex h-auto min-h-11 w-full items-center justify-start gap-3 rounded-[1.1rem] px-4 py-3 text-left text-sm font-semibold normal-case transition-colors;
background: rgba(23, 32, 51, 0.04); background: transparent;
color: #172033; color: var(--app-color-on-surface);
letter-spacing: 0;
} }
.sidebar-workspace-trigger:hover { .sidebar-workspace-trigger:hover {
background: rgba(23, 32, 51, 0.07); background: var(--app-control-hover);
}
.sidebar-workspace-trigger :deep(.v-btn__content) {
@apply flex min-w-0 flex-1 items-center justify-start gap-3;
} }
.sidebar-workspace-label { .sidebar-workspace-label {
@apply flex-1 truncate text-sm font-semibold; @apply flex-1 truncate;
} }
.sidebar-workspace-icon { .sidebar-workspace-icon {
@apply text-base transition-transform; @apply text-base transition-transform;
color: #5d6b82; color: var(--app-text-muted);
} }
.sidebar-workspace-icon-open { .sidebar-workspace-icon-open {
@@ -192,12 +202,9 @@
} }
.sidebar-workspace-menu { .sidebar-workspace-menu {
@apply absolute bottom-[calc(100%+0.5rem)] left-0 right-0 z-30 flex flex-col gap-1 rounded-[1.25rem] border p-2; @apply absolute bottom-[calc(100%+0.5rem)] left-0 right-0;
isolation: isolate; isolation: isolate;
background: #fffdf8;
background-clip: padding-box; background-clip: padding-box;
border-color: rgba(23, 32, 51, 0.08);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.12);
} }
.sidebar-workspace-collapsed { .sidebar-workspace-collapsed {
@@ -208,35 +215,25 @@
@apply h-11 w-11 justify-center rounded-[1rem] p-0; @apply h-11 w-11 justify-center rounded-[1rem] p-0;
} }
.sidebar-workspace-collapsed .sidebar-workspace-trigger :deep(.v-btn__content) {
@apply flex-none justify-center;
}
.sidebar-workspace-collapsed .sidebar-workspace-menu { .sidebar-workspace-collapsed .sidebar-workspace-menu {
@apply left-[calc(100%+0.75rem)] right-auto w-56; @apply left-[calc(100%+0.75rem)] right-auto w-56;
bottom: 1rem; bottom: 1rem;
} }
.sidebar-workspace-option { .sidebar-workspace-option {
@apply flex items-center gap-3 rounded-[0.95rem] px-4 py-3 text-left text-sm font-semibold transition-colors; @apply h-auto min-h-11 normal-case;
color: #172033; letter-spacing: 0;
} }
.sidebar-workspace-option .v-icon { .sidebar-workspace-option :deep(.v-btn__content) {
@apply flex min-w-0 items-center justify-start gap-3;
}
.sidebar-workspace-option :deep(.v-icon) {
@apply text-base; @apply text-base;
color: #5d6b82;
}
.sidebar-workspace-option:hover {
background: rgba(23, 32, 51, 0.05);
}
.sidebar-workspace-separator {
@apply my-1;
border-top: 1px solid rgba(23, 32, 51, 0.08);
}
.sidebar-workspace-option-danger {
color: #b91c1c;
}
.sidebar-workspace-option-danger .v-icon {
color: #b91c1c;
} }
</style> </style>

View File

@@ -161,9 +161,11 @@
ref="workspaceMenuRef" ref="workspaceMenuRef"
class="user-menu-wrap" class="user-menu-wrap"
> >
<button <v-btn
class="menu-item-action workspace-trigger" class="menu-item-action workspace-trigger"
:class="{ 'workspace-trigger-static': !canOpenWorkspaceMenu }" :class="{ 'workspace-trigger-static': !canOpenWorkspaceMenu }"
variant="text"
:ripple="false"
@click.stop="toggleWorkspaceMenu" @click.stop="toggleWorkspaceMenu"
> >
<AppAvatar <AppAvatar
@@ -178,17 +180,18 @@
class="user-trigger-icon" class="user-trigger-icon"
:class="{ 'user-trigger-icon-open': isWorkspaceMenuOpen }" :class="{ 'user-trigger-icon-open': isWorkspaceMenuOpen }"
/> />
</button> </v-btn>
<div <div
v-if="isWorkspaceMenuOpen" v-if="isWorkspaceMenuOpen"
class="user-menu" class="user-menu"
> >
<button <v-btn
v-if="canSelectAllWorkspaces" v-if="canSelectAllWorkspaces"
class="user-menu-item all-workspaces-item" class="user-menu-item all-workspaces-item"
:class="{ 'user-menu-item-active': workspaceStore.isAllWorkspacesSelected }" :class="{ 'user-menu-item-active': workspaceStore.isAllWorkspacesSelected }"
type="button" variant="text"
:ripple="false"
@click="chooseAllWorkspaces" @click="chooseAllWorkspaces"
> >
<AppAvatar <AppAvatar
@@ -199,7 +202,7 @@
<span>{{ t('workspaceSelector.allWorkspaces') }}</span> <span>{{ t('workspaceSelector.allWorkspaces') }}</span>
<small>{{ t('workspaceSelector.allWorkspacesDescription') }}</small> <small>{{ t('workspaceSelector.allWorkspacesDescription') }}</small>
</span> </span>
</button> </v-btn>
<div <div
v-for="workspace in visibleWorkspaces" v-for="workspace in visibleWorkspaces"
@@ -210,9 +213,10 @@
'workspace-menu-row-muted': workspaceStore.isAllWorkspacesSelected && !workspaceStore.isWorkspaceVisible(workspace.id), 'workspace-menu-row-muted': workspaceStore.isAllWorkspacesSelected && !workspaceStore.isWorkspaceVisible(workspace.id),
}" }"
> >
<button <v-btn
class="user-menu-item workspace-menu-select" class="user-menu-item workspace-menu-select"
type="button" variant="text"
:ripple="false"
@click="chooseWorkspace(workspace.id)" @click="chooseWorkspace(workspace.id)"
> >
<AppAvatar <AppAvatar
@@ -224,47 +228,51 @@
<span>{{ workspace.name }}</span> <span>{{ workspace.name }}</span>
<small>{{ workspace.timeZone }}</small> <small>{{ workspace.timeZone }}</small>
</span> </span>
</button> </v-btn>
<button <v-btn
v-if="canSelectAllWorkspaces" v-if="canSelectAllWorkspaces"
class="workspace-visibility-button" class="workspace-visibility-button"
type="button" variant="text"
:ripple="false"
:aria-label="workspaceStore.isWorkspaceVisible(workspace.id) ? t('workspaceSelector.hideWorkspace') : t('workspaceSelector.showWorkspace')" :aria-label="workspaceStore.isWorkspaceVisible(workspace.id) ? t('workspaceSelector.hideWorkspace') : t('workspaceSelector.showWorkspace')"
@click.stop="toggleWorkspaceVisibility(workspace.id)" @click.stop="toggleWorkspaceVisibility(workspace.id)"
> >
<v-icon :icon="workspaceStore.isWorkspaceVisible(workspace.id) ? mdiEyeOutline : mdiEyeOffOutline" /> <v-icon :icon="workspaceStore.isWorkspaceVisible(workspace.id) ? mdiEyeOutline : mdiEyeOffOutline" />
</button> </v-btn>
<button <v-btn
v-if="canManageWorkspaces" v-if="canManageWorkspaces"
class="workspace-settings-button" class="workspace-settings-button"
type="button" variant="text"
:ripple="false"
:aria-label="t('workspaceSelector.workspaceSettings')" :aria-label="t('workspaceSelector.workspaceSettings')"
@click="openWorkspaceSettings(workspace.id)" @click="openWorkspaceSettings(workspace.id)"
> >
<v-icon :icon="mdiCogOutline" /> <v-icon :icon="mdiCogOutline" />
</button> </v-btn>
</div> </div>
<button <v-btn
v-if="canManageWorkspaces" v-if="canManageWorkspaces"
class="user-menu-item user-menu-item-create" class="user-menu-item user-menu-item-create"
type="button" variant="text"
:ripple="false"
@click="openCreateWorkspace" @click="openCreateWorkspace"
> >
<span>{{ t('workspaceSelector.createAction') }}</span> <span>{{ t('workspaceSelector.createAction') }}</span>
<v-icon :icon="mdiPlus" /> <v-icon :icon="mdiPlus" />
</button> </v-btn>
<div <div
v-if="activeOrganization" v-if="activeOrganization"
class="organization-switcher" class="organization-switcher"
> >
<div class="organization-current-row"> <div class="organization-current-row">
<button <v-btn
class="user-menu-item organization-current" class="user-menu-item organization-current"
type="button" variant="text"
:ripple="false"
@click="openOrganizationSettings(activeOrganization.id)" @click="openOrganizationSettings(activeOrganization.id)"
> >
<AppAvatar <AppAvatar
@@ -280,29 +288,31 @@
:icon="mdiCogOutline" :icon="mdiCogOutline"
class="organization-action-icon" class="organization-action-icon"
/> />
</button> </v-btn>
</div> </div>
<button <v-btn
v-if="canSwitchOrganizations" v-if="canSwitchOrganizations"
class="organization-swap-button" class="organization-swap-button"
type="button" variant="text"
:ripple="false"
:aria-expanded="isOrganizationListOpen" :aria-expanded="isOrganizationListOpen"
@click="toggleOrganizationList" @click="toggleOrganizationList"
> >
<span>Change organization</span> <span>Change organization</span>
<v-icon :icon="mdiSwapHorizontal" /> <v-icon :icon="mdiSwapHorizontal" />
</button> </v-btn>
<div <div
v-if="isOrganizationListOpen" v-if="isOrganizationListOpen"
class="organization-options" class="organization-options"
> >
<button <v-btn
v-for="organization in switchableOrganizations" v-for="organization in switchableOrganizations"
:key="organization.id" :key="organization.id"
class="user-menu-item organization-option" class="user-menu-item organization-option"
type="button" variant="text"
:ripple="false"
@click="chooseOrganization(organization.id)" @click="chooseOrganization(organization.id)"
> >
<AppAvatar <AppAvatar
@@ -314,7 +324,7 @@
<span>{{ organization.name }}</span> <span>{{ organization.name }}</span>
<small>{{ t('workspaceSelector.organizationLabel') }}</small> <small>{{ t('workspaceSelector.organizationLabel') }}</small>
</span> </span>
</button> </v-btn>
</div> </div>
</div> </div>
</div> </div>
@@ -328,15 +338,20 @@
} }
.menu-item-action { .menu-item-action {
@apply flex h-11 items-center gap-3 rounded-full px-4 transition-colors; @apply flex h-11 items-center justify-start gap-3 rounded-full px-4 normal-case transition-colors;
background: rgba(255, 255, 255, 0.8); background: rgba(255, 255, 255, 0.8);
color: #172033; color: var(--app-color-on-surface);
border: 1px solid rgba(23, 32, 51, 0.06); border: 1px solid var(--app-border-muted);
letter-spacing: 0;
} }
.menu-item-action:hover { .menu-item-action:hover {
background: #172033; background: var(--app-color-primary);
color: #fffaf2; color: var(--app-color-on-primary);
}
.menu-item-action :deep(.v-btn__content) {
@apply flex min-w-0 items-center justify-start gap-3;
} }
.user-menu-wrap { .user-menu-wrap {
@@ -369,21 +384,22 @@
width: max(100%, 17rem); width: max(100%, 17rem);
max-width: min(24rem, calc(100vw - 2rem)); max-width: min(24rem, calc(100vw - 2rem));
isolation: isolate; isolation: isolate;
background: #fffdf8; background: var(--app-surface-raised);
background-clip: padding-box; background-clip: padding-box;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.12); box-shadow: var(--app-shadow-popover);
z-index: 40; z-index: 40;
} }
.user-menu-item { .user-menu-item {
@apply flex items-center gap-3 rounded-[0.9rem] px-3 py-3 text-left text-sm font-semibold transition-colors; @apply flex h-auto min-h-11 items-center justify-start gap-3 rounded-[0.9rem] px-3 py-3 text-left text-sm font-semibold normal-case transition-colors;
color: #172033; color: var(--app-color-on-surface);
letter-spacing: 0;
} }
.user-menu-item:hover, .user-menu-item:hover,
.workspace-menu-row:hover { .workspace-menu-row:hover {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
} }
.user-menu-item-active { .user-menu-item-active {
@@ -393,7 +409,7 @@
.workspace-menu-row { .workspace-menu-row {
@apply flex min-w-0 items-center rounded-[0.9rem] transition-colors; @apply flex min-w-0 items-center rounded-[0.9rem] transition-colors;
color: #172033; color: var(--app-color-on-surface);
} }
.workspace-menu-row-muted { .workspace-menu-row-muted {
@@ -402,8 +418,8 @@
.all-workspaces-item { .all-workspaces-item {
@apply mb-1 border; @apply mb-1 border;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
background: rgba(23, 32, 51, 0.03); background: var(--app-control-subtle);
} }
.workspace-menu-select { .workspace-menu-select {
@@ -415,19 +431,21 @@
} }
.workspace-settings-button { .workspace-settings-button {
@apply mr-2 flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-colors; @apply mr-2 flex h-8 min-w-0 w-8 flex-shrink-0 items-center justify-center rounded-full normal-case transition-colors;
color: #526178; color: var(--app-text-muted);
letter-spacing: 0;
} }
.workspace-visibility-button { .workspace-visibility-button {
@apply flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-colors; @apply flex h-8 min-w-0 w-8 flex-shrink-0 items-center justify-center rounded-full normal-case transition-colors;
color: #526178; color: var(--app-text-muted);
letter-spacing: 0;
} }
.workspace-visibility-button:hover, .workspace-visibility-button:hover,
.workspace-settings-button:hover { .workspace-settings-button:hover {
background: rgba(23, 32, 51, 0.1); background: var(--app-control-active);
color: #172033; color: var(--app-color-on-surface);
} }
.workspace-visibility-button :deep(.v-icon), .workspace-visibility-button :deep(.v-icon),
@@ -446,17 +464,17 @@
.user-menu-item-copy small { .user-menu-item-copy small {
@apply text-xs font-medium; @apply text-xs font-medium;
color: #526178; color: var(--app-text-muted);
} }
.user-menu-item-create { .user-menu-item-create {
@apply justify-between border border-dashed; @apply justify-between border border-dashed;
border-color: rgba(23, 32, 51, 0.12); border-color: var(--app-border-subtle);
} }
.organization-switcher { .organization-switcher {
@apply mt-2 flex flex-col gap-1 border-t pt-2; @apply mt-2 flex flex-col gap-1 border-t pt-2;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.organization-current-row { .organization-current-row {
@@ -465,31 +483,46 @@
.organization-current { .organization-current {
@apply w-full min-w-0 border; @apply w-full min-w-0 border;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.organization-current:hover { .organization-current:hover {
background: rgba(23, 32, 51, 0.07); background: var(--app-control-active);
} }
.organization-action-icon { .organization-action-icon {
@apply flex-shrink-0 text-base; @apply flex-shrink-0 text-base;
color: #526178; color: var(--app-text-muted);
} }
.organization-swap-button { .organization-swap-button {
@apply flex w-full items-center justify-between gap-3 rounded-[0.9rem] border px-3 py-2.5 text-sm font-semibold transition-colors; @apply flex h-auto min-h-11 w-full items-center justify-between gap-3 rounded-[0.9rem] border px-3 py-2.5 text-sm font-semibold normal-case transition-colors;
background: rgba(23, 32, 51, 0.04); background: var(--app-control-subtle);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
color: #172033; color: var(--app-color-on-surface);
letter-spacing: 0;
} }
.organization-swap-button:hover { .organization-swap-button:hover {
background: rgba(23, 32, 51, 0.08); background: var(--app-control-active);
} }
.organization-options { .organization-options {
@apply flex flex-col gap-1; @apply flex flex-col gap-1;
} }
.user-menu-item :deep(.v-btn__content),
.organization-swap-button :deep(.v-btn__content) {
@apply flex min-w-0 items-center justify-start gap-3;
}
.organization-swap-button :deep(.v-btn__content) {
@apply w-full justify-between;
}
.workspace-visibility-button :deep(.v-btn__content),
.workspace-settings-button :deep(.v-btn__content) {
@apply justify-center;
}
</style> </style>

View File

@@ -2,12 +2,7 @@ import { createApp } from 'vue';
import App from './App.vue'; import App from './App.vue';
import router from '@/router/router.js'; import router from '@/router/router.js';
import { createPinia } from 'pinia'; import { createPinia } from 'pinia';
import './assets/main.css'; import './assets/styles.css';
import 'vuetify/styles';
import { createVuetify } from 'vuetify';
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';
import vueGoogleOauth from 'vue3-google-login'; import vueGoogleOauth from 'vue3-google-login';
import { useAuthStore } from '@/features/auth/stores/authStore.js'; import { useAuthStore } from '@/features/auth/stores/authStore.js';
import { useUserProfileStore } from '@/features/user-profile/stores/userProfileStore.js'; import { useUserProfileStore } from '@/features/user-profile/stores/userProfileStore.js';
@@ -24,23 +19,9 @@ import { useChannelsStore } from '@/features/channels/stores/channelsStore.js';
import { i18n } from '@/plugins/i18n.js'; import { i18n } from '@/plugins/i18n.js';
import config from '@/config.js'; import config from '@/config.js';
import { createHead } from '@vueuse/head'; import { createHead } from '@vueuse/head';
import { socializeTheme } from '@/plugins/theme.js'; import { createSocializeVuetify } from '@/plugins/vuetify.js';
const vuetify = createVuetify({ const vuetify = createSocializeVuetify();
components,
directives,
icons: {
defaultSet: 'mdi',
aliases,
sets: { mdi },
},
theme: {
defaultTheme: 'socializeLight',
themes: {
socializeLight: socializeTheme,
},
},
});
const pinia = createPinia(); const pinia = createPinia();
const head = createHead(); const head = createHead();

View File

@@ -0,0 +1,47 @@
import { createVuetify } from 'vuetify';
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';
import { socializeTheme } from '@/plugins/theme.js';
export function createSocializeVuetify() {
return createVuetify({
components,
directives,
defaults: {
VBtn: {
rounded: 'lg',
style: 'letter-spacing: 0; text-transform: none;',
},
VCard: {
rounded: 'lg',
},
VTextField: {
color: 'primary',
density: 'comfortable',
variant: 'outlined',
},
VTextarea: {
color: 'primary',
density: 'comfortable',
variant: 'outlined',
},
VSelect: {
color: 'primary',
density: 'comfortable',
variant: 'outlined',
},
},
icons: {
defaultSet: 'mdi',
aliases,
sets: { mdi },
},
theme: {
defaultTheme: 'socializeLight',
themes: {
socializeLight: socializeTheme,
},
},
});
}

View File

@@ -31,13 +31,13 @@
@focusin="openProductMenu" @focusin="openProductMenu"
@focusout="scheduleProductMenuClose" @focusout="scheduleProductMenuClose"
> >
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
:aria-expanded="isProductMenuOpen" :aria-expanded="isProductMenuOpen"
aria-haspopup="true" aria-haspopup="true"
> >
{{ t('public.nav.product') }} {{ t('public.nav.product') }}
</button> </v-btn>
<div <div
class="site-product-panel" class="site-product-panel"
:class="{ open: isProductMenuOpen }" :class="{ open: isProductMenuOpen }"
@@ -73,14 +73,14 @@
@focusin="openResourcesMenu" @focusin="openResourcesMenu"
@focusout="scheduleResourcesMenuClose" @focusout="scheduleResourcesMenuClose"
> >
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
:aria-expanded="isResourcesMenuOpen" :aria-expanded="isResourcesMenuOpen"
aria-haspopup="true" aria-haspopup="true"
@click="toggleResourcesMenu" @click="toggleResourcesMenu"
> >
{{ t('public.nav.resources') }} {{ t('public.nav.resources') }}
</button> </v-btn>
<div <div
class="site-nav-menu" class="site-nav-menu"
:class="{ open: isResourcesMenuOpen }" :class="{ open: isResourcesMenuOpen }"
@@ -105,20 +105,20 @@
class="site-language-toggle" class="site-language-toggle"
:aria-label="t('public.nav.language')" :aria-label="t('public.nav.language')"
> >
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
:class="{ active: currentLocale === 'en' }" :class="{ active: currentLocale === 'en' }"
@click="setLocale('en')" @click="setLocale('en')"
> >
En En
</button> </v-btn>
<button <v-btn variant="text" :ripple="false"
type="button" type="button"
:class="{ active: currentLocale === 'fr' }" :class="{ active: currentLocale === 'fr' }"
@click="setLocale('fr')" @click="setLocale('fr')"
> >
Fr Fr
</button> </v-btn>
</div> </div>
<router-link <router-link
@@ -267,7 +267,7 @@
@apply sticky top-0 z-30 w-full; @apply sticky top-0 z-30 w-full;
background: rgba(255, 250, 242, 0.9); background: rgba(255, 250, 242, 0.9);
backdrop-filter: blur(18px); backdrop-filter: blur(18px);
border-bottom: 1px solid rgba(23, 32, 51, 0.08); border-bottom: 1px solid var(--app-border-subtle);
} }
.site-menu-inner { .site-menu-inner {
@@ -317,8 +317,8 @@
.site-nav a:hover, .site-nav a:hover,
.site-nav-group:hover > button { .site-nav-group:hover > button {
background: rgba(23, 32, 51, 0.06); background: var(--app-control-hover);
color: #172033; color: var(--app-color-on-surface);
} }
.site-nav-group { .site-nav-group {
@@ -332,9 +332,9 @@
.site-nav-menu { .site-nav-menu {
@apply invisible absolute left-0 top-[calc(100%+0.5rem)] flex min-w-36 flex-col gap-1 rounded-[1rem] border p-2 opacity-0 transition-opacity; @apply invisible absolute left-0 top-[calc(100%+0.5rem)] flex min-w-36 flex-col gap-1 rounded-[1rem] border p-2 opacity-0 transition-opacity;
background: rgba(255, 255, 255, 0.98); background: var(--app-surface-raised);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.12); box-shadow: 0 18px 40px var(--app-border-subtle);
} }
.site-nav-group:hover .site-nav-menu, .site-nav-group:hover .site-nav-menu,
@@ -349,8 +349,8 @@
.site-product-panel { .site-product-panel {
@apply invisible absolute left-1/2 top-full grid w-[min(56rem,calc(100vw-2rem))] -translate-x-1/2 grid-cols-3 gap-2 rounded-[1.25rem] border p-3 opacity-0 transition-opacity; @apply invisible absolute left-1/2 top-full grid w-[min(56rem,calc(100vw-2rem))] -translate-x-1/2 grid-cols-3 gap-2 rounded-[1.25rem] border p-3 opacity-0 transition-opacity;
background: rgba(255, 255, 255, 0.98); background: var(--app-surface-raised);
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 24px 60px rgba(23, 32, 51, 0.14); box-shadow: 0 24px 60px rgba(23, 32, 51, 0.14);
} }
@@ -371,7 +371,7 @@
.site-product-icon { .site-product-icon {
@apply flex h-10 w-10 items-center justify-center rounded-[0.75rem]; @apply flex h-10 w-10 items-center justify-center rounded-[0.75rem];
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.site-product-icon svg { .site-product-icon svg {
@@ -381,7 +381,7 @@
.site-product-link strong { .site-product-link strong {
@apply block text-sm font-black leading-5; @apply block text-sm font-black leading-5;
color: #172033; color: var(--app-color-on-surface);
} }
.site-product-link small { .site-product-link small {
@@ -392,7 +392,7 @@
.site-language-toggle { .site-language-toggle {
@apply flex items-center rounded-full border p-1; @apply flex items-center rounded-full border p-1;
background: rgba(255, 255, 255, 0.64); background: rgba(255, 255, 255, 0.64);
border-color: rgba(23, 32, 51, 0.1); border-color: var(--app-control-active);
} }
.site-language-toggle button { .site-language-toggle button {
@@ -401,22 +401,22 @@
} }
.site-language-toggle button:hover { .site-language-toggle button:hover {
color: #172033; color: var(--app-color-on-surface);
} }
.site-language-toggle button.active { .site-language-toggle button.active {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.site-login { .site-login {
@apply flex h-10 min-w-[7.75rem] items-center justify-center rounded-full px-4 text-sm font-bold no-underline transition-colors; @apply flex h-10 min-w-[7.75rem] items-center justify-center rounded-full px-4 text-sm font-bold no-underline transition-colors;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.site-login:hover { .site-login:hover {
background: #0f766e; background: var(--app-color-on-tertiary);
} }
@media (max-width: 420px) { @media (max-width: 420px) {

View File

@@ -40,8 +40,8 @@
.public-page-panel { .public-page-panel {
@apply rounded-[2rem] p-6 md:p-10; @apply rounded-[2rem] p-6 md:p-10;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid rgba(23, 32, 51, 0.08); border: 1px solid var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.eyebrow { .eyebrow {
@@ -51,7 +51,7 @@
h1 { h1 {
@apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl; @apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl;
color: #172033; color: var(--app-color-on-surface);
} }
p { p {

View File

@@ -40,8 +40,8 @@
.public-page-panel { .public-page-panel {
@apply rounded-[2rem] p-6 md:p-10; @apply rounded-[2rem] p-6 md:p-10;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid rgba(23, 32, 51, 0.08); border: 1px solid var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.eyebrow { .eyebrow {
@@ -51,7 +51,7 @@
h1 { h1 {
@apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl; @apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl;
color: #172033; color: var(--app-color-on-surface);
} }
p { p {

View File

@@ -71,7 +71,7 @@
</div> </div>
<div class="hero-actions"> <div class="hero-actions">
<router-link to="/register"> <router-link to="/register">
<button class="primary">{{ t('public.landing.hero.primaryAction') }}</button> <v-btn variant="text" :ripple="false" class="primary">{{ t('public.landing.hero.primaryAction') }}</v-btn>
</router-link> </router-link>
</div> </div>
<span class="cta-note">{{ t('public.landing.hero.ctaNote') }}</span> <span class="cta-note">{{ t('public.landing.hero.ctaNote') }}</span>
@@ -145,7 +145,7 @@
<p>{{ t('public.landing.finalCta.description') }}</p> <p>{{ t('public.landing.finalCta.description') }}</p>
</div> </div>
<router-link to="/register"> <router-link to="/register">
<button class="primary">{{ t('public.landing.hero.primaryAction') }}</button> <v-btn variant="text" :ripple="false" class="primary">{{ t('public.landing.hero.primaryAction') }}</v-btn>
</router-link> </router-link>
</section> </section>
@@ -165,8 +165,8 @@
.hero-card { .hero-card {
@apply grid gap-8 overflow-hidden rounded-[2rem] p-6 md:grid-cols-[1fr_0.88fr] md:p-10; @apply grid gap-8 overflow-hidden rounded-[2rem] p-6 md:grid-cols-[1fr_0.88fr] md:p-10;
background: linear-gradient(145deg, #172033 0%, #25324b 65%, #314766 100%); background: linear-gradient(145deg, var(--app-color-on-surface) 0%, #25324b 65%, #314766 100%);
color: #fffaf2; color: var(--app-color-on-primary);
box-shadow: 0 30px 80px rgba(23, 32, 51, 0.18); box-shadow: 0 30px 80px rgba(23, 32, 51, 0.18);
} }
@@ -231,13 +231,13 @@
.preview-bar { .preview-bar {
@apply flex items-center justify-between gap-3 rounded-[1rem] bg-white/90 px-4 py-3; @apply flex items-center justify-between gap-3 rounded-[1rem] bg-white/90 px-4 py-3;
color: #172033; color: var(--app-color-on-surface);
} }
.preview-bar span, .preview-bar span,
.approval-card span { .approval-card span {
@apply text-xs font-black uppercase tracking-[0.18em]; @apply text-xs font-black uppercase tracking-[0.18em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.preview-bar strong { .preview-bar strong {
@@ -252,7 +252,7 @@
.preview-row { .preview-row {
@apply flex items-center justify-between gap-4 rounded-[1rem] bg-white/90 p-4; @apply flex items-center justify-between gap-4 rounded-[1rem] bg-white/90 p-4;
color: #172033; color: var(--app-color-on-surface);
} }
.preview-row strong { .preview-row strong {
@@ -267,12 +267,12 @@
.preview-row em { .preview-row em {
@apply rounded-full px-3 py-1 text-xs font-black not-italic; @apply rounded-full px-3 py-1 text-xs font-black not-italic;
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.approval-card { .approval-card {
@apply rounded-[1rem] bg-white/95 p-5; @apply rounded-[1rem] bg-white/95 p-5;
color: #172033; color: var(--app-color-on-surface);
} }
.approval-card strong { .approval-card strong {
@@ -286,34 +286,34 @@
.pillar-card { .pillar-card {
@apply rounded-[1.5rem] p-6; @apply rounded-[1.5rem] p-6;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid rgba(23, 32, 51, 0.08); border: 1px solid var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.pillar-card p { .pillar-card p {
@apply mt-3 text-lg font-semibold leading-7; @apply mt-3 text-lg font-semibold leading-7;
color: #172033; color: var(--app-color-on-surface);
} }
.focus-card { .focus-card {
@apply grid gap-6 rounded-[1.75rem] p-6 md:grid-cols-[1fr_1.1fr] md:p-8; @apply grid gap-6 rounded-[1.75rem] p-6 md:grid-cols-[1fr_1.1fr] md:p-8;
background: linear-gradient(135deg, rgba(255, 138, 61, 0.12), rgba(52, 211, 153, 0.1)); background: linear-gradient(135deg, rgba(255, 138, 61, 0.12), rgba(52, 211, 153, 0.1));
border: 1px solid rgba(23, 32, 51, 0.08); border: 1px solid var(--app-border-subtle);
} }
.focus-card h2 { .focus-card h2 {
@apply mt-3 text-2xl font-black leading-tight md:text-3xl; @apply mt-3 text-2xl font-black leading-tight md:text-3xl;
color: #172033; color: var(--app-color-on-surface);
} }
.inline-cta { .inline-cta {
@apply mt-5 inline-flex h-11 items-center rounded-full px-5 text-sm font-black no-underline transition-colors; @apply mt-5 inline-flex h-11 items-center rounded-full px-5 text-sm font-black no-underline transition-colors;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.inline-cta:hover { .inline-cta:hover {
background: #0f766e; background: var(--app-color-on-tertiary);
} }
.focus-metrics { .focus-metrics {
@@ -322,12 +322,12 @@
.focus-metrics div { .focus-metrics div {
@apply rounded-[1.25rem] bg-white/70 p-5; @apply rounded-[1.25rem] bg-white/70 p-5;
border: 1px solid rgba(23, 32, 51, 0.06); border: 1px solid var(--app-control-hover);
} }
.focus-metrics strong { .focus-metrics strong {
@apply block text-sm font-black uppercase tracking-[0.18em]; @apply block text-sm font-black uppercase tracking-[0.18em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.focus-metrics span { .focus-metrics span {
@@ -337,8 +337,8 @@
.final-cta { .final-cta {
@apply flex flex-col gap-6 rounded-[2rem] p-6 md:flex-row md:items-center md:justify-between md:p-10; @apply flex flex-col gap-6 rounded-[2rem] p-6 md:flex-row md:items-center md:justify-between md:p-10;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
box-shadow: 0 30px 80px rgba(23, 32, 51, 0.18); box-shadow: 0 30px 80px rgba(23, 32, 51, 0.18);
} }

View File

@@ -108,8 +108,8 @@
.public-page-panel { .public-page-panel {
@apply rounded-[2rem] p-6 md:p-10; @apply rounded-[2rem] p-6 md:p-10;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid rgba(23, 32, 51, 0.08); border: 1px solid var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.eyebrow { .eyebrow {
@@ -119,7 +119,7 @@
h1 { h1 {
@apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl; @apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl;
color: #172033; color: var(--app-color-on-surface);
} }
p { p {
@@ -133,13 +133,13 @@
.pricing-tier { .pricing-tier {
@apply relative flex min-h-[42rem] flex-col gap-6 rounded-[1.5rem] border bg-white/85 p-5; @apply relative flex min-h-[42rem] flex-col gap-6 rounded-[1.5rem] border bg-white/85 p-5;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.pricing-tier.featured { .pricing-tier.featured {
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
border-color: rgba(255, 178, 107, 0.44); border-color: rgba(255, 178, 107, 0.44);
box-shadow: 0 28px 70px rgba(23, 32, 51, 0.2); box-shadow: 0 28px 70px rgba(23, 32, 51, 0.2);
} }
@@ -147,16 +147,16 @@
.tier-badge { .tier-badge {
@apply mb-4 inline-flex w-fit rounded-full px-3 py-1 text-xs font-black uppercase tracking-[0.16em]; @apply mb-4 inline-flex w-fit rounded-full px-3 py-1 text-xs font-black uppercase tracking-[0.16em];
background: #ffb26b; background: #ffb26b;
color: #172033; color: var(--app-color-on-surface);
} }
.tier-top h2 { .tier-top h2 {
@apply text-2xl font-black; @apply text-2xl font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.featured .tier-top h2 { .featured .tier-top h2 {
color: #fffaf2; color: var(--app-color-on-primary);
} }
.tier-top p { .tier-top p {
@@ -176,11 +176,11 @@
.tier-price strong { .tier-price strong {
@apply text-4xl font-black leading-none; @apply text-4xl font-black leading-none;
color: #172033; color: var(--app-color-on-surface);
} }
.featured .tier-price strong { .featured .tier-price strong {
color: #fffaf2; color: var(--app-color-on-primary);
} }
.tier-price span { .tier-price span {
@@ -190,21 +190,21 @@
.tier-action { .tier-action {
@apply flex h-11 items-center justify-center rounded-full px-5 text-sm font-black no-underline transition-colors; @apply flex h-11 items-center justify-center rounded-full px-5 text-sm font-black no-underline transition-colors;
background: #172033; background: var(--app-color-on-surface);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.tier-action:hover { .tier-action:hover {
background: #0f766e; background: var(--app-color-on-tertiary);
} }
.featured .tier-action { .featured .tier-action {
background: #ffb26b; background: #ffb26b;
color: #172033; color: var(--app-color-on-surface);
} }
.featured .tier-action:hover { .featured .tier-action:hover {
background: #fffaf2; background: var(--app-color-on-primary);
} }
.tier-section { .tier-section {
@@ -213,7 +213,7 @@
.tier-section h3 { .tier-section h3 {
@apply text-xs font-black uppercase tracking-[0.18em]; @apply text-xs font-black uppercase tracking-[0.18em];
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.featured .tier-section h3 { .featured .tier-section h3 {
@@ -226,13 +226,13 @@
.tier-section li { .tier-section li {
@apply text-sm leading-6; @apply text-sm leading-6;
color: #172033; color: var(--app-color-on-surface);
} }
.tier-section li::before { .tier-section li::before {
content: "✓"; content: "✓";
@apply mr-2 font-black; @apply mr-2 font-black;
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.featured .tier-section li::before { .featured .tier-section li::before {
@@ -241,7 +241,7 @@
.limits { .limits {
@apply mt-auto border-t pt-5; @apply mt-auto border-t pt-5;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
} }
.featured .limits { .featured .limits {

View File

@@ -99,15 +99,15 @@
.feature-hero { .feature-hero {
@apply rounded-[2rem] p-6 md:p-10; @apply rounded-[2rem] p-6 md:p-10;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid rgba(23, 32, 51, 0.08); border: 1px solid var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.feature-icon, .feature-icon,
.related-icon { .related-icon {
@apply flex h-12 w-12 items-center justify-center rounded-[0.9rem]; @apply flex h-12 w-12 items-center justify-center rounded-[0.9rem];
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.feature-icon svg, .feature-icon svg,
@@ -123,7 +123,7 @@
h1 { h1 {
@apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl; @apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl;
color: #172033; color: var(--app-color-on-surface);
} }
p { p {
@@ -137,13 +137,13 @@
.related-card { .related-card {
@apply rounded-[1.25rem] border bg-white/80 p-5; @apply rounded-[1.25rem] border bg-white/80 p-5;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.05); box-shadow: 0 18px 40px rgba(23, 32, 51, 0.05);
} }
.feature-detail-panel { .feature-detail-panel {
@apply rounded-[1.5rem] border bg-white/80 p-5 md:p-7; @apply rounded-[1.5rem] border bg-white/80 p-5 md:p-7;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.05); box-shadow: 0 18px 40px rgba(23, 32, 51, 0.05);
} }
@@ -162,13 +162,13 @@
.feature-detail-panel li span { .feature-detail-panel li span {
@apply flex h-8 w-8 items-center justify-center rounded-full text-sm font-black; @apply flex h-8 w-8 items-center justify-center rounded-full text-sm font-black;
background: #0f766e; background: var(--app-color-on-tertiary);
color: #fffaf2; color: var(--app-color-on-primary);
} }
.feature-detail-panel li strong { .feature-detail-panel li strong {
@apply pt-1 text-base font-semibold leading-7; @apply pt-1 text-base font-semibold leading-7;
color: #172033; color: var(--app-color-on-surface);
} }
.related-features { .related-features {
@@ -177,7 +177,7 @@
.related-features h2 { .related-features h2 {
@apply mt-3 max-w-3xl text-2xl font-black leading-tight md:text-3xl; @apply mt-3 max-w-3xl text-2xl font-black leading-tight md:text-3xl;
color: #172033; color: var(--app-color-on-surface);
} }
.related-card { .related-card {
@@ -191,7 +191,7 @@
.related-card strong { .related-card strong {
@apply text-base font-black; @apply text-base font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.related-card span:last-child { .related-card span:last-child {

View File

@@ -68,8 +68,8 @@
.public-page-panel { .public-page-panel {
@apply rounded-[2rem] p-6 md:p-10; @apply rounded-[2rem] p-6 md:p-10;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid rgba(23, 32, 51, 0.08); border: 1px solid var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06); box-shadow: 0 18px 40px var(--app-control-hover);
} }
.eyebrow { .eyebrow {
@@ -79,7 +79,7 @@
h1 { h1 {
@apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl; @apply mt-4 max-w-4xl text-4xl font-black leading-tight md:text-6xl;
color: #172033; color: var(--app-color-on-surface);
} }
p { p {
@@ -93,7 +93,7 @@
.product-features h2 { .product-features h2 {
@apply mt-3 max-w-3xl text-2xl font-black leading-tight md:text-3xl; @apply mt-3 max-w-3xl text-2xl font-black leading-tight md:text-3xl;
color: #172033; color: var(--app-color-on-surface);
} }
.feature-grid { .feature-grid {
@@ -102,7 +102,7 @@
.feature-card { .feature-card {
@apply flex min-h-48 flex-col gap-3 rounded-[1.25rem] border bg-white/80 p-5 no-underline transition-colors; @apply flex min-h-48 flex-col gap-3 rounded-[1.25rem] border bg-white/80 p-5 no-underline transition-colors;
border-color: rgba(23, 32, 51, 0.08); border-color: var(--app-border-subtle);
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.05); box-shadow: 0 18px 40px rgba(23, 32, 51, 0.05);
} }
@@ -114,7 +114,7 @@
.feature-icon { .feature-icon {
@apply flex h-11 w-11 items-center justify-center rounded-[0.85rem]; @apply flex h-11 w-11 items-center justify-center rounded-[0.85rem];
background: rgba(15, 118, 110, 0.1); background: rgba(15, 118, 110, 0.1);
color: #0f766e; color: var(--app-color-on-tertiary);
} }
.feature-icon svg { .feature-icon svg {
@@ -124,7 +124,7 @@
.feature-card strong { .feature-card strong {
@apply text-base font-black; @apply text-base font-black;
color: #172033; color: var(--app-color-on-surface);
} }
.feature-card span:last-child { .feature-card span:last-child {

View File

@@ -64,6 +64,9 @@ export default defineConfig(({ isSsrBuild }) => ({
} }
} }
}, },
ssr: {
noExternal: ['vuetify'],
},
resolve: { resolve: {
alias: { alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)) '@': fileURLToPath(new URL('./src', import.meta.url))