Design consistency audit fixes: alerts, cards, dark mode, utilities

Alert sweep (113 alerts, 79 files):
  All persistent static banners now carry alert-permanent so the
  layout's 5-second auto-dismiss cannot swallow guidance, warnings,
  or validation errors. Transient dismissible toasts left untouched.

CSS fixes (site.css):
  .card.shadow-sm      — strips rogue border from ~40 drifted cards
  .card-header.bg-white — rebinds to var(--bs-body-bg) so card
                          headers follow dark/light theme correctly
  Typography utilities  — .text-2xs (.68rem), .text-xs (.73rem)
  Token color classes   — .text-ember, .text-ok, .text-bad,
                          .text-warn, .text-cool, .bg-paper-2
  Layout utilities      — .mw-xs/sm/md/lg replace inline max-width
  Comment              — documents text-ember vs text-primary intent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 18:05:29 -04:00
parent f6d457fe0e
commit 328b195127
80 changed files with 603 additions and 561 deletions
@@ -1,4 +1,4 @@
@model PowderCoating.Application.DTOs.Scheduling.OvenSchedulerViewModel
@model PowderCoating.Application.DTOs.Scheduling.OvenSchedulerViewModel
@{
ViewData["Title"] = "Oven Scheduler";
var dateStr = Model.ScheduledDate.ToString("yyyy-MM-dd");
@@ -8,7 +8,7 @@
@section Styles {
<style>
/* ─── Layout ─────────────────────────────────────── */
/* ─── Layout ─────────────────────────────────────── */
.scheduler-layout {
display: flex;
gap: 1rem;
@@ -39,7 +39,7 @@
flex-shrink: 0;
}
/* ─── Batch cards ────────────────────────────────── */
/* ─── Batch cards ────────────────────────────────── */
.batch-card {
border-radius: 10px;
border: 2px solid transparent;
@@ -52,14 +52,14 @@
.batch-card.status-completed { border-color: #198754; opacity: .85; }
.batch-card.drag-over { border-color: #0d6efd !important; box-shadow: 0 0 12px rgba(13,110,253,.4) !important; }
/* ─── Capacity bar ───────────────────────────────── */
/* ─── Capacity bar ───────────────────────────────── */
.capacity-bar-wrap { height: 6px; border-radius: 3px; background: #e9ecef; overflow: hidden; }
.capacity-bar-fill { height: 100%; border-radius: 3px; transition: width .3s; }
.cap-ok { background: #198754; }
.cap-warn { background: #ffc107; }
.cap-over { background: #dc3545; }
/* ─── Queue items ────────────────────────────────── */
/* ─── Queue items ────────────────────────────────── */
.queue-job-card {
border-radius: 8px;
cursor: grab;
@@ -90,7 +90,7 @@
.batch-item-row:hover { background: var(--bs-secondary-bg); }
.batch-item-row.dragging { opacity: .5; }
/* ─── AI panel ───────────────────────────────────── */
/* ─── AI panel ───────────────────────────────────── */
.ai-suggestion-panel {
position: fixed;
top: 0; right: 0;
@@ -115,7 +115,7 @@
}
.ai-panel-backdrop.open { display: block; }
/* ─── Drop zone hint ─────────────────────────────── */
/* ─── Drop zone hint ─────────────────────────────── */
.drop-zone-empty {
min-height: 80px;
border: 2px dashed var(--bs-border-color);
@@ -275,7 +275,7 @@
<p class="small text-muted mb-2">
The Oven Scheduler helps you plan which jobs go into which oven on a given day.
Jobs waiting to be coated appear in the <strong>Queue</strong> on the left.
Each oven gets its own column create <strong>batches</strong> and drag jobs into them
Each oven gets its own column — create <strong>batches</strong> and drag jobs into them
to build your day's run sheet.
</p>
<p class="small text-muted mb-0">
@@ -292,8 +292,8 @@
<li class="mb-1">Use the <strong>date arrows</strong> to navigate to the day you want to schedule.</li>
<li class="mb-1">Click <strong>New Batch</strong> and pick an oven to create a batch slot.</li>
<li class="mb-1"><strong>Drag job coat items</strong> from the Queue into a batch, or drag between batches to reorder.</li>
<li class="mb-1">Set a <strong>start time</strong> on each batch and monitor the capacity bar it turns yellow at 80 % and red when over capacity.</li>
<li class="mb-1">Use the batch <strong>status buttons</strong> (Planned Loading In Progress Completed) to track real-time progress.</li>
<li class="mb-1">Set a <strong>start time</strong> on each batch and monitor the capacity bar — it turns yellow at 80 % and red when over capacity.</li>
<li class="mb-1">Use the batch <strong>status buttons</strong> (Planned → Loading → In Progress → Completed) to track real-time progress.</li>
<li class="mb-0">Drag an item back to the Queue to unschedule it.</li>
</ol>
</div>
@@ -303,23 +303,23 @@
<h6 class="fw-semibold mb-2"><i class="bi bi-gear-fill text-warning me-1"></i>Setup for best results</h6>
<ul class="small text-muted mb-0 ps-3">
<li class="mb-1">
<strong>Ovens in Equipment</strong> each oven must exist as an Equipment record
<strong>Ovens in Equipment</strong> — each oven must exist as an Equipment record
with <em>Type = Oven</em> and Status = Operational for it to appear as a column.
</li>
<li class="mb-1">
<strong>Oven capacity</strong> set a <em>capacity (sq ft)</em> on each oven so
<strong>Oven capacity</strong> — set a <em>capacity (sq ft)</em> on each oven so
the capacity bar can warn you before you overload a batch.
</li>
<li class="mb-1">
<strong>Job items with surface area</strong> enter <em>surface area (sq ft)</em>
<strong>Job items with surface area</strong> — enter <em>surface area (sq ft)</em>
on each job item so the scheduler can calculate load accurately.
</li>
<li class="mb-1">
<strong>Coat quantities</strong> job items need at least one coat defined
<strong>Coat quantities</strong> — job items need at least one coat defined
(powder color + quantity) so they appear as draggable coat rows in the Queue.
</li>
<li class="mb-0">
<strong>Due dates &amp; priorities</strong> set due dates and priorities on
<strong>Due dates &amp; priorities</strong> — set due dates and priorities on
jobs so the AI and sorting tools can recommend the most urgent work first.
</li>
</ul>
@@ -332,7 +332,7 @@
<!-- No ovens warning -->
@if (!Model.Ovens.Any())
{
<div class="alert alert-warning">
<div class="alert alert-warning alert-permanent">
<i class="bi bi-exclamation-triangle me-2"></i>
No active ovens found. Go to <a asp-controller="Equipment" asp-action="Index">Equipment</a> and add a piece of equipment with Type = "Oven".
</div>
@@ -341,7 +341,7 @@
<!-- Main layout -->
<div class="scheduler-layout">
<!-- ── JOB QUEUE (left sidebar) ───────────────── -->
<!-- ── JOB QUEUE (left sidebar) ───────────────── -->
<div class="scheduler-queue">
<div class="card shadow-sm">
<div class="card-header d-flex align-items-center py-2">
@@ -408,11 +408,11 @@
<span class="color-dot" style="background:@GetColorHex(coat.ColorName, coat.ColorCode)"></span>
}
<span class="fw-medium">@coat.CoatName</span>
<span class="text-muted ms-1"> @coat.ItemDescription</span>
<span class="text-muted ms-1">— @coat.ItemDescription</span>
</div>
<div class="text-muted" style="font-size:.75rem;">
Pass @coat.CoatPassNumber · @coat.SurfaceAreaSqFt.ToString("F1") sqft
@if (!string.IsNullOrEmpty(coat.ColorName)) { <span>· @coat.ColorName</span> }
Pass @coat.CoatPassNumber · @coat.SurfaceAreaSqFt.ToString("F1") sqft
@if (!string.IsNullOrEmpty(coat.ColorName)) { <span>· @coat.ColorName</span> }
</div>
</div>
<i class="bi bi-grip-vertical text-muted ms-1"></i>
@@ -426,7 +426,7 @@
</div>
</div>
<!-- ── OVEN COLUMNS ───────────────────────────── -->
<!-- ── OVEN COLUMNS ───────────────────────────── -->
<div class="scheduler-board">
<div class="oven-columns" id="ovenColumns">
@foreach (var oven in Model.Ovens)
@@ -447,7 +447,7 @@
</div>
<div class="small text-muted">
@(oven.MaxLoadSqFt.HasValue ? $"{oven.MaxLoadSqFt:F0} sqft max" : "No capacity set")
· @oven.CycleMinutes min cycle
· @oven.CycleMinutes min cycle
</div>
</div>
<button class="btn btn-sm btn-outline-primary ms-auto"
@@ -503,7 +503,7 @@
<!-- Error state -->
<div id="aiError" class="d-none p-4">
<div class="alert alert-danger mb-0">
<div class="alert alert-danger alert-permanent mb-0">
<i class="bi bi-exclamation-triangle me-2"></i>
<span id="aiErrorText"></span>
</div>
@@ -546,8 +546,8 @@
</ul>
@if (!Model.QueuedJobs.Any())
{
<div class="alert alert-info small">
<i class="bi bi-info-circle me-1"></i>The queue is empty no jobs need oven scheduling right now.
<div class="alert alert-info alert-permanent small">
<i class="bi bi-info-circle me-1"></i>The queue is empty — no jobs need oven scheduling right now.
</div>
}
else
@@ -561,7 +561,7 @@
@section Scripts {
<script>
// ── Info panel (always visible on load; dismiss hides for this visit only)
// ── Info panel (always visible on load; dismiss hides for this visit only) ─
document.getElementById('btnDismissInfo').addEventListener('click', function () {
document.getElementById('schedulerInfoPanel').style.display = 'none';
});