/* Layout reset only. Typography (font-family, weight, line-height) and base
   text/background colors come from brand tokens.css, loaded earlier in the
   <head> via App.razor. tokens.css sets `html { font-family: var(--sa-font-sans); … }`
   but doesn't touch height/margin — those stay here so the app-shell can
   stretch to full viewport height. */
html, body { height: 100%; margin: 0; }
/* Always reserve the vertical scrollbar gutter so the centered layout doesn't
   shift horizontally when a section's content grows past the viewport (or a
   PreventScroll modal hides the scrollbar). No-op on macOS overlay scrollbars;
   prevents the ~15px jump on Windows/Linux classic scrollbars. */
html { scrollbar-gutter: stable; }

/* SteelAxis design tokens. Colors do real work here — workers scan the screen
   for status before they read it, so the same hex must mean the same thing
   across every list, card, badge, and print view. light-dark() flips with
   FluentDesignTheme's color-scheme so dark mode follows automatically.
   Keep this list in sync with the JS demo: workorders-list.tsx TYPE_COLORS
   and the part-piece status palette in unified-parts-table.tsx. */
:root {
    color-scheme: light dark;

    /* Piece lifecycle: PENDING → CUT → FABRICATED → WELDED → PAINTED → READY */
    --sa-status-pending: light-dark(#6b7280, #9ca3af);
    --sa-status-cut: light-dark(#2563eb, #60a5fa);
    --sa-status-fab: light-dark(#ea580c, #fb923c);
    --sa-status-welded: light-dark(#1e40af, #3b82f6);
    --sa-status-painted: light-dark(#92400e, #d97706);
    --sa-status-ready: light-dark(#16a34a, #4ade80);

    /* Work-order type: berry / blue / teal / yellow / orange / purple / green.
       The colored 4px left border on each ProcessCard reads as the WO type
       at a glance — never break this mapping. */
    --sa-wo-material-prep: light-dark(#be185d, #ec4899);
    --sa-wo-cutting: light-dark(#2563eb, #60a5fa);
    --sa-wo-machining: light-dark(#0d9488, #2dd4bf);
    --sa-wo-fabrication: light-dark(#ca8a04, #facc15);
    --sa-wo-welding: light-dark(#c2410c, #fb923c);
    --sa-wo-painting: light-dark(#7c3aed, #a78bfa);
    --sa-wo-assembly: light-dark(#16a34a, #4ade80);

    /* Palette for NestingBar segments. 10 distinguishable hues; Hash(partNumber)
       % 10 picks one. Same part = same color across web, print, and supplier
       quote — deterministic for visual continuity. Must live at :root in the
       global stylesheet (Blazor scoped CSS rewrites :root selectors). */
    --sa-palette-0: light-dark(#2563eb, #60a5fa);
    --sa-palette-1: light-dark(#16a34a, #4ade80);
    --sa-palette-2: light-dark(#ca8a04, #facc15);
    --sa-palette-3: light-dark(#7c3aed, #a78bfa);
    --sa-palette-4: light-dark(#0d9488, #2dd4bf);
    --sa-palette-5: light-dark(#be185d, #ec4899);
    --sa-palette-6: light-dark(#c2410c, #fb923c);
    --sa-palette-7: light-dark(#1e40af, #3b82f6);
    --sa-palette-8: light-dark(#92400e, #d97706);
    --sa-palette-9: light-dark(#475569, #94a3b8);
}

/* Page content lives inside this. The 80rem (1280px) cap keeps tables and
   forms readable on ultra-wides; padding stays consistent on phone widths.
   The TopBar has its own inner container with the same cap so logo and
   nav line up vertically with the body. */
.content {
    /* width:100% is load-bearing: .app-shell is a column flex, and the
       margin-inline:auto below disables flex's cross-axis stretch — without an
       explicit width the main would shrink-wrap to its content (narrow on an
       empty section, wide on a table) and re-center, sliding the whole page
       left/right between sections. A definite width caps cleanly at max-width
       and the auto margins just center it, so the layout stays put. */
    width: 100%;
    box-sizing: border-box;
    max-width: 80rem;
    margin-inline: auto;
    padding: 1.5rem;
}

/* Tighten the page gutters on phones so content isn't squeezed by 24px on
   each side. Mirrors the topbar's 640px padding step. */
@media (max-width: 640px) {
    .content { padding: 1rem; }
}

/* Blazor's <FocusOnNavigate Selector="h1" /> stamps tabindex="-1" on the page
   title and focuses it after SPA navigation so screen-readers announce the new
   page. The programmatic focus is non-interactive — suppress the browser's
   default outline ring so every page doesn't visually wear a frame. Keyboard
   focus on real interactive controls is unaffected (:focus-visible still
   applies to buttons, links, inputs). */
h1[tabindex]:focus {
    outline: none;
}

/* All dialogs are mounted as `<FluentDialog Modal="true">`. The web component
   ships a backdrop on its positioning-region part, but the default scrim is
   barely visible in dark mode and lets the page bleed through — operators
   reading the underlying list while a dialog is open misread it as "nothing
   happened on click". A flat 50% black scrim across the viewport gives the
   modal a clear focus context in both light and dark themes. */
fluent-dialog::part(positioning-region) {
    background-color: rgba(0, 0, 0, 0.5);
}

/* Cap centered modal dialogs to the viewport and let their body scroll, so a
   tall form (Add person + grant access, Create part, Receive lot) doesn't push
   its footer off-screen. Fluent only does this for its left/right drawer
   variants — centered modals are content-sized with no cap. The dialog control
   is a CSS grid (header / 1fr body / footer); capping the control + scrolling
   the body keeps header and footer pinned. `!important` per the part-override
   rule (Fluent's shadow-DOM stylesheet wins on specificity otherwise). */
fluent-dialog::part(control) {
    max-height: 92dvh !important;
    /* Never let a dialog exceed the viewport width — a wide form on a small
       screen would otherwise overflow horizontally. Per-dialog widths use
       `width: min(Npx, NNvw)`; this is the universal backstop. */
    max-width: 94vw !important;
}
fluent-dialog .fluent-dialog-body {
    overflow-y: auto;
}

/* ---- Shared dialog form layout (.sa-form-*) ----
   Wide, grouped, left-to-right form schema so dialogs read across columns
   (identity → details → …) instead of one tall scrolling column. Any dialog
   can adopt it: wrap fields in `.sa-form-group` cards inside a `.sa-form-grid`;
   pair short fields with `.sa-form-pair`; full-width rows get `.sa-form-span`.
   Collapses to a single column on narrow screens. Per-dialog width still uses
   `width: min(Npx, NNvw)` on the FluentDialog. */
.sa-form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.9rem;
    align-items: start;
}
.sa-form-grid > .sa-form-span { grid-column: 1 / -1; }
.sa-form-group {
    display: flex; flex-direction: column; gap: 0.6rem;
    padding: 0.75rem;
    border: 1px solid var(--neutral-stroke-rest);
    border-radius: 8px;
}
.sa-form-group__title {
    margin: 0;
    font-size: 0.72rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--neutral-foreground-hint);
}
/* Pair / triple a row of fields. FluentTextField / FluentNumberField render
   their label as a SEPARATE sibling (<label class="fluent-input-label"> then
   <fluent-*-field>), so a naive grid treats each field as TWO cells and the
   labels/inputs wrap out of alignment. Pin every label to grid row 1 and every
   field to row 2 so each column shows "label above its field" with no markup
   wrapping. Columns auto-place left-to-right. */
.sa-form-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0.25rem 0.6rem; align-items: end; }
.sa-form-row3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.25rem 0.6rem; align-items: end; }
.sa-form-pair > .fluent-input-label,
.sa-form-row3 > .fluent-input-label { grid-row: 1; }
.sa-form-pair > *:not(.fluent-input-label),
.sa-form-row3 > *:not(.fluent-input-label) { grid-row: 2; width: 100%; }
@media (max-width: 760px) {
    .sa-form-grid { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
    /* Single column: labels + fields fall back to natural document flow. */
    .sa-form-pair, .sa-form-row3 { display: flex; flex-direction: column; gap: 0.25rem; }
}

/* ---- Shared list table (.parts-grid) ----
   The Parts table and the Assemblies table share this chrome so the two lists
   read as one consistent surface ("separate lists, shared styling"). Lifted out
   of UnifiedPartsTable's scoped CSS so both components can use it. */
.parts-grid {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}
.parts-grid thead {
    /* Sticky header keeps the column labels visible when the page scrolls. */
    position: sticky;
    top: 0;
    background: var(--neutral-layer-1);
    z-index: 1;
}
.parts-grid th {
    text-align: left;
    padding: 8px 12px;
    font-weight: 600;
    color: var(--neutral-foreground-hint);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom: 2px solid var(--neutral-stroke-rest);
}
.parts-grid td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--neutral-stroke-rest);
    vertical-align: middle;
}
.parts-grid tr:hover:not(.parts-grid__expand) {
    background: var(--neutral-fill-stealth-hover);
}
.parts-grid tr.is-selected {
    background: color-mix(in srgb, var(--accent-fill-rest) 8%, transparent);
}
.parts-grid__expand { background: var(--neutral-layer-2); }
.parts-grid__expand:hover { background: var(--neutral-layer-2); }

/* Description column. Clamped to one line so long labels don't blow up the row
   height — full text is on the title attribute / hover. */
.parts-grid__description {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--neutral-foreground-rest);
}
.parts-grid__dwng-th { font-size: 0.7rem; }

/* Per-row progress cell. */
.parts-grid__progress {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 140px;
}
.parts-grid__progress fluent-progress { flex: 1; min-width: 80px; }
.parts-grid__progress-label {
    font-size: 0.8rem;
    color: var(--neutral-foreground-hint);
    font-variant-numeric: tabular-nums;
    min-width: 36px;
    text-align: right;
}

/* ---- On-page detail view (.detail-view) ----
   Part / assembly progress now render inline in the project workspace's main
   panel instead of a capped modal, so a tall pieces table gets full page height
   (no scroll-in-a-box). The back bar carries a "Back" button + the title; the
   shared class keeps both detail views identical. */
.detail-view {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.detail-view__bar {
    display: flex;
    align-items: center;
    gap: 12px;
}
.detail-view__title {
    margin: 0;
    font-size: 1.15rem;
}
/* Inline edit affordances on the detail screen (Save row + unsaved hint). */
.detail-view__edit-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 0.4rem;
}
.detail-view__edit-hint {
    font-size: 0.8rem;
    color: var(--accent-fill-rest);
}

/* FluentSelect dropdowns render their option list as a `<div part="listbox">`
   in the component's shadow DOM. Catalog families with lots of sizes
   (L profile has ~20 entries, IPE has ~12, …) make the listbox grow to
   ~1300px and overflow upward when Fluent flips the dropdown above the
   trigger, clipping the topmost options off the screen edge.

   `!important` is required — FluentUI's own shadow-DOM stylesheet
   declares the listbox geometry and wins on specificity otherwise. */
fluent-select::part(listbox),
fluent-combobox::part(listbox),
fluent-autocomplete::part(listbox) {
    max-height: 50vh !important;
    overflow-y: auto !important;
}
