diff --git a/fusion_plating/fusion_plating_shopfloor/__manifest__.py b/fusion_plating/fusion_plating_shopfloor/__manifest__.py index 03627229..240b8f05 100644 --- a/fusion_plating/fusion_plating_shopfloor/__manifest__.py +++ b/fusion_plating/fusion_plating_shopfloor/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — Shop Floor', - 'version': '19.0.2.0.0', + 'version': '19.0.3.0.0', 'category': 'Manufacturing/Plating', 'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer, ' 'first-piece inspection gates.', diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/scss/_fp_shopfloor_tokens.scss b/fusion_plating/fusion_plating_shopfloor/static/src/scss/_fp_shopfloor_tokens.scss index 6a779835..ac3709bf 100644 --- a/fusion_plating/fusion_plating_shopfloor/static/src/scss/_fp_shopfloor_tokens.scss +++ b/fusion_plating/fusion_plating_shopfloor/static/src/scss/_fp_shopfloor_tokens.scss @@ -31,32 +31,39 @@ $fp-radius-lg : 20px; $fp-radius-xl : 28px; $fp-radius-pill: 999px; -// ---------- Surfaces — depth by TINT, not by border -------------------------- -// The page gets a slightly tinted background; cards sit on a lighter -// surface. That tint difference replaces the need for card borders. -$fp-page : color-mix(in srgb, var(--bs-body-color) 2.5%, - var(--o-view-background-color, var(--bs-body-bg))); -$fp-card : var(--o-view-background-color, var(--bs-body-bg)); -$fp-card-soft : color-mix(in srgb, var(--bs-body-color) 4%, - var(--o-view-background-color, var(--bs-body-bg))); +// ---------- Surfaces — explicit values, matching Odoo kanban conventions ----- +// Odoo's own kanban uses hex values (not CSS vars) because --bs-border-color +// and --bs-body-bg drift between themes and addons. We follow the same +// approach with clear, strong contrast: tinted page, tinted column, SOLID +// WHITE card with a VISIBLE border. +// +// Dark mode: overrides are applied at the bottom of each file via +// :root[data-bs-theme="dark"], body.o_dark_mode, or @media dark-pref. +$fp-page : var(--fp-page-bg, #f3f4f6); +$fp-column : var(--fp-column-bg, #e9ebef); +$fp-card : var(--fp-card-bg, #ffffff); +$fp-card-soft : var(--fp-card-soft-bg, #f8fafc); +$fp-border : var(--fp-border-color, #d8dadd); +$fp-border-strong : var(--fp-border-strong, #b6babf); // ---------- Text tiers ------------------------------------------------------- -$fp-ink : var(--bs-body-color); -$fp-ink-soft : color-mix(in srgb, var(--bs-body-color) 70%, transparent); -$fp-ink-mute : color-mix(in srgb, var(--bs-body-color) 48%, transparent); -$fp-ink-faint : color-mix(in srgb, var(--bs-body-color) 28%, transparent); +$fp-ink : var(--fp-ink, #1f2937); +$fp-ink-soft : var(--fp-ink-soft, #4b5563); +$fp-ink-mute : var(--fp-ink-mute, #6b7280); +$fp-ink-faint : var(--fp-ink-faint, #9ca3af); -// ---------- Elevation — soft, layered, theme-safe ---------------------------- -// Shadows built on the foreground colour so they darken appropriately in -// light mode and show a subtle halo in dark mode. -$fp-elev-1 : 0 1px 2px color-mix(in srgb, var(--bs-body-color) 5%, transparent), - 0 1px 3px color-mix(in srgb, var(--bs-body-color) 7%, transparent); -$fp-elev-2 : 0 2px 4px color-mix(in srgb, var(--bs-body-color) 6%, transparent), - 0 6px 14px color-mix(in srgb, var(--bs-body-color) 9%, transparent); -$fp-elev-3 : 0 4px 8px color-mix(in srgb, var(--bs-body-color) 8%, transparent), - 0 12px 28px color-mix(in srgb, var(--bs-body-color) 12%, transparent); -$fp-elev-hover : 0 6px 12px color-mix(in srgb, var(--bs-body-color) 10%, transparent), - 0 18px 36px color-mix(in srgb, var(--bs-body-color) 14%, transparent); +// ---------- Elevation — explicit rgba shadows -------------------------------- +// Explicit rgba values (not color-mix) so they render identically across +// browsers and themes. In dark mode the shadows still work against the +// darker surfaces because they're translucent. +$fp-elev-1 : 0 1px 2px rgba(0, 0, 0, 0.06), + 0 1px 3px rgba(0, 0, 0, 0.08); +$fp-elev-2 : 0 2px 4px rgba(0, 0, 0, 0.06), + 0 6px 14px rgba(0, 0, 0, 0.10); +$fp-elev-3 : 0 4px 8px rgba(0, 0, 0, 0.10), + 0 12px 28px rgba(0, 0, 0, 0.14); +$fp-elev-hover : 0 6px 12px rgba(0, 0, 0, 0.12), + 0 18px 36px rgba(0, 0, 0, 0.16); // ---------- Semantic colour helpers (NOT gradients) -------------------------- $fp-accent : var(--o-action); // the one action colour @@ -129,3 +136,24 @@ $fp-touch-min : 48px; // larger than Apple's 44px minimum — shop floor @content; } } + + +// ============================================================================= +// Dark-mode palette overrides +// Odoo 19 flips dark mode via [data-bs-theme="dark"] on the root. +// We provide a matching-level body selector for compatibility. +// ============================================================================= +:root[data-bs-theme="dark"], +body.o_dark_mode, +.o_dark_mode { + --fp-page-bg : #13161a; + --fp-column-bg : #1a1e24; + --fp-card-bg : #22262d; + --fp-card-soft-bg : #1c2027; + --fp-border-color : #343942; + --fp-border-strong : #4a505a; + --fp-ink : #e5e7eb; + --fp-ink-soft : #c8ccd2; + --fp-ink-mute : #8a909a; + --fp-ink-faint : #5a606b; +} diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/scss/fusion_plating_shopfloor.scss b/fusion_plating/fusion_plating_shopfloor/static/src/scss/fusion_plating_shopfloor.scss index 9499e901..3d275ae4 100644 --- a/fusion_plating/fusion_plating_shopfloor/static/src/scss/fusion_plating_shopfloor.scss +++ b/fusion_plating/fusion_plating_shopfloor/static/src/scss/fusion_plating_shopfloor.scss @@ -87,7 +87,7 @@ min-width: 240px; min-height: $fp-touch-min; padding: $fp-space-2 $fp-space-4; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; color: $fp-ink; @@ -102,7 +102,7 @@ .o_fp_scan_toggle { min-height: $fp-touch-min; padding: 0 $fp-space-5; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; color: $fp-ink; @@ -117,7 +117,7 @@ @include fp-hover-only { &:hover { box-shadow: $fp-elev-2; - border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); } } &:active { transform: scale(0.97); } @@ -206,7 +206,7 @@ .o_fp_kpi { position: relative; padding: $fp-space-5; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-lg; background-color: $fp-card; box-shadow: $fp-elev-1; @@ -217,7 +217,7 @@ &:hover { transform: translateY(-2px); box-shadow: $fp-elev-2; - border-color: color-mix(in srgb, #{$fp-accent} 30%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 30%, #{$fp-border}); } } @@ -334,7 +334,7 @@ // ------------------------------------------------------------------------- .o_fp_panel { background-color: $fp-card; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-lg; box-shadow: $fp-elev-1; padding: $fp-space-5; @@ -346,7 +346,7 @@ align-items: center; margin-bottom: $fp-space-4; padding-bottom: $fp-space-3; - border-bottom: 1px solid var(--bs-border-color); + border-bottom: 1px solid #{$fp-border}; h3 { font-size: $fp-text-lg; @@ -411,7 +411,7 @@ align-items: center; gap: $fp-space-3; padding: $fp-space-3 $fp-space-4; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; min-height: 64px; @@ -423,7 +423,7 @@ @include fp-hover-only { &:hover { background-color: color-mix(in srgb, #{$fp-accent} 4%, $fp-card); - border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); box-shadow: $fp-elev-2; } } @@ -486,7 +486,7 @@ } .o_fp_tile { padding: $fp-space-4; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; cursor: pointer; @@ -499,7 +499,7 @@ &:hover { transform: translateY(-1px); background-color: color-mix(in srgb, #{$fp-accent} 4%, $fp-card); - border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); box-shadow: $fp-elev-2; } } @@ -550,7 +550,7 @@ align-items: center; gap: $fp-space-3; padding: $fp-space-3 $fp-space-4; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; min-height: 64px; @@ -569,7 +569,7 @@ &[data-state="missed_window"], &[data-state="fail"], &[data-state="on_hold"] { box-shadow: inset 4px 0 0 0 $fp-bad; background-color: fp-wash(--bs-danger, 5%); - border-color: color-mix(in srgb, #{$fp-bad} 35%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-bad} 35%, #{$fp-border}); } &[data-state="baked"], &[data-state="pass"] { box-shadow: inset 4px 0 0 0 $fp-ok; diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/scss/manager_dashboard.scss b/fusion_plating/fusion_plating_shopfloor/static/src/scss/manager_dashboard.scss index 57c89efa..febc6b52 100644 --- a/fusion_plating/fusion_plating_shopfloor/static/src/scss/manager_dashboard.scss +++ b/fusion_plating/fusion_plating_shopfloor/static/src/scss/manager_dashboard.scss @@ -84,7 +84,7 @@ padding: 0 $fp-space-4; border-radius: $fp-radius-md; font-weight: $fp-weight-semibold; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; background-color: $fp-card; color: $fp-ink; box-shadow: $fp-elev-1; @@ -94,7 +94,7 @@ @include fp-hover-only { &:hover { box-shadow: $fp-elev-2; - border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); } } &:active { transform: scale(0.97); } @@ -149,7 +149,7 @@ .o_fp_kpi { position: relative; padding: $fp-space-5; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-lg; background-color: $fp-card; box-shadow: $fp-elev-1; @@ -160,7 +160,7 @@ &:hover { transform: translateY(-2px); box-shadow: $fp-elev-2; - border-color: color-mix(in srgb, #{$fp-accent} 30%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 30%, #{$fp-border}); } } @@ -226,7 +226,7 @@ // ------------------------------------------------------------------------- .o_fp_panel { background-color: $fp-card; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-lg; box-shadow: $fp-elev-1; padding: $fp-space-5; @@ -238,7 +238,7 @@ align-items: center; margin-bottom: $fp-space-4; padding-bottom: $fp-space-3; - border-bottom: 1px solid var(--bs-border-color); + border-bottom: 1px solid #{$fp-border}; h3 { font-size: $fp-text-lg; @@ -309,7 +309,7 @@ .o_fp_mgr_card { position: relative; background-color: $fp-card; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; overflow: hidden; transition: transform $fp-dur-fast $fp-ease, @@ -318,7 +318,7 @@ @include fp-hover-only { &:hover { - border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); box-shadow: $fp-elev-2; transform: translateY(-1px); } @@ -327,7 +327,7 @@ // Priority stripe (4px) on the left — only when priority is set &[data-priority="2"] { background-color: color-mix(in srgb, #{$fp-bad} 4%, $fp-card); - border-color: color-mix(in srgb, #{$fp-bad} 35%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-bad} 35%, #{$fp-border}); &::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; @@ -376,7 +376,7 @@ align-items: center; padding: $fp-space-2 $fp-space-3; background-color: $fp-card; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-sm; font-size: $fp-text-sm; @@ -401,7 +401,7 @@ min-width: 140px; max-width: 220px; min-height: 40px; padding: 0 $fp-space-3; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-sm; background-color: $fp-card; color: $fp-ink; @@ -454,7 +454,7 @@ align-items: center; gap: $fp-space-3; padding: $fp-space-3 $fp-space-4; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; cursor: pointer; @@ -467,7 +467,7 @@ @include fp-hover-only { &:hover { background-color: color-mix(in srgb, #{$fp-accent} 4%, $fp-card); - border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); box-shadow: $fp-elev-2; } } diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss b/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss index 1fa3e6c4..3164ccb3 100644 --- a/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss +++ b/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss @@ -68,7 +68,7 @@ .o_fp_po_search_input { padding: 0 $fp-space-4 0 $fp-space-7; min-height: $fp-touch-min; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; color: $fp-ink; @@ -95,7 +95,7 @@ .o_fp_po_refresh_btn { width: $fp-touch-min; height: $fp-touch-min; display: flex; align-items: center; justify-content: center; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; color: $fp-ink; @@ -132,7 +132,7 @@ display: flex; flex-direction: column; background-color: $fp-card-soft; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-lg; box-shadow: $fp-elev-1; max-height: calc(100vh - 180px); @@ -148,7 +148,7 @@ .o_fp_po_col_header { display: flex; align-items: center; justify-content: space-between; padding: $fp-space-4; - border-bottom: 1px solid var(--bs-border-color); + border-bottom: 1px solid #{$fp-border}; background-color: $fp-card; .o_fp_po_col_name { @@ -214,7 +214,7 @@ .o_fp_po_card { position: relative; background-color: $fp-card; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; padding: $fp-space-3 $fp-space-4; margin-bottom: $fp-space-2; @@ -227,7 +227,7 @@ @include fp-hover-only { &:hover { - border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); box-shadow: $fp-elev-2; transform: translateY(-1px); } @@ -251,7 +251,7 @@ } &[data-priority="2"], &.o_fp_po_card_hot { background-color: color-mix(in srgb, #{$fp-bad} 5%, $fp-card); - border-color: color-mix(in srgb, #{$fp-bad} 35%, var(--bs-border-color)); + border-color: color-mix(in srgb, #{$fp-bad} 35%, #{$fp-border}); &::before { background-color: $fp-bad; } } &[data-priority="1"], &.o_fp_po_card_urgent { @@ -271,7 +271,7 @@ border-radius: $fp-radius-sm; object-fit: contain; background-color: $fp-card-soft; - border: 1px solid var(--bs-border-color); + border: 1px solid #{$fp-border}; padding: 2px; } .o_fp_po_card_avatar_blank {