/*
   Shared site CSS for both DME surfaces.

   HARD RULE (CLAUDE.md § "Theming", decision 36): no hardcoded colours. Every colour below is a
   Bootstrap / AdminLTE theme token (var(--bs-*), var(--lte-*)) or one of the two brand tokens the
   server writes into <head> (var(--dme-primary), var(--dme-accent)). That is what makes dark mode —
   and re-branding — automatic for pages added in later phases instead of a per-page retrofit.
*/

html,
body {
    height: 100%;
}

/* Blazor's built-in validation and error markers, restated in theme tokens. */
.valid.modified:not([type="checkbox"]) {
    outline: 1px solid var(--bs-success);
}

.invalid {
    outline: 1px solid var(--bs-danger);
}

.validation-message {
    color: var(--bs-danger);
}

.blazor-error-boundary {
    padding: 1rem;
    color: var(--bs-danger-text-emphasis);
    background-color: var(--bs-danger-bg-subtle);
    border: 1px solid var(--bs-danger-border-subtle);
    border-radius: var(--bs-border-radius);
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* The unhandled-error bar Blazor toggles at the bottom of the page. */
#blazor-error-ui {
    display: none;
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 1080;
    padding: 0.75rem 1.25rem;
    box-shadow: var(--bs-box-shadow);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    float: inline-end;
}

/* ==========================================================================================
   Brand token overlay (CLAUDE.md § "Branding", decision 43)

   --dme-primary / --dme-accent and their derived RGB triplets are emitted server-side by
   BrandTokens from IBrandProvider. This block is the ONLY place they are mapped onto Bootstrap
   and AdminLTE variables, and it maps them onto identity touchpoints only: links, primary
   buttons, focus rings, the active sidebar item and the brand marks.

   Deliberately NOT branded: success, danger, warning and info. A brand must never be able to
   make an error stop looking like an error.

   On brand-coloured *text* in the dark theme. Brand fills use the brand colour identically in
   both themes, as CLAUDE.md requires. Text cannot: the raw primary against a dark background
   falls below 4.5:1, so the dark theme swaps in a tint of the same colour, computed server-side
   in BrandDefinition. Bootstrap makes exactly the same accommodation for its own link colour.
   ========================================================================================== */

:root {
    --bs-primary: var(--dme-primary);
    --bs-primary-rgb: var(--dme-primary-rgb);

    --bs-link-color: var(--dme-primary);
    --bs-link-color-rgb: var(--dme-primary-rgb);
    --bs-link-hover-color-rgb: var(--dme-primary-hover-rgb);

    --bs-focus-ring-color: rgba(var(--dme-primary-rgb), 0.25);
}

[data-bs-theme="dark"] {
    --bs-link-color-rgb: var(--dme-primary-dark-text-rgb);
    --bs-link-hover-color-rgb: var(--dme-primary-dark-text-hover-rgb);

    --bs-focus-ring-color: rgba(var(--dme-primary-dark-text-rgb), 0.3);
}

/*
   Primary SUBTLE surfaces (Phase 7 prompt 03a): an order's "Accepted" / "In fulfillment" status pill
   and the order stepper's current step are drawn with Bootstrap's theme-aware subtle classes
   (bg-primary-subtle, text-primary-emphasis, border-primary-subtle). Bootstrap compiles those three
   variables to its own blue, so without this they would be the one primary-coloured mark on the page
   that is not the brand. The fill is a light wash of the brand in both themes; the text is the darker
   hover shade in light and the tint in dark — the same text accommodation as links.
*/
:root {
    --bs-primary-bg-subtle: rgba(var(--dme-primary-rgb), 0.12);
    --bs-primary-border-subtle: rgba(var(--dme-primary-rgb), 0.35);
    --bs-primary-text-emphasis: rgb(var(--dme-primary-hover-rgb));
}

[data-bs-theme="dark"] {
    --bs-primary-bg-subtle: rgba(var(--dme-primary-rgb), 0.25);
    --bs-primary-border-subtle: rgba(var(--dme-primary-dark-text-rgb), 0.45);
    --bs-primary-text-emphasis: rgb(var(--dme-primary-dark-text-rgb));
}

/*
   Bootstrap 5.3 compiles .btn-primary's colours into the rule itself rather than reading
   --bs-primary, so overriding the theme colour alone would leave primary buttons untouched.
   The hover/active shade is darker in both themes, which keeps the white button text above
   7:1 rather than trading contrast for a lighter hover.
*/
.btn-primary {
    --bs-btn-bg: var(--dme-primary);
    --bs-btn-border-color: var(--dme-primary);
    --bs-btn-hover-bg: rgb(var(--dme-primary-hover-rgb));
    --bs-btn-hover-border-color: rgb(var(--dme-primary-hover-rgb));
    --bs-btn-active-bg: rgb(var(--dme-primary-hover-rgb));
    --bs-btn-active-border-color: rgb(var(--dme-primary-hover-rgb));
    --bs-btn-disabled-bg: var(--dme-primary);
    --bs-btn-disabled-border-color: var(--dme-primary);
    --bs-btn-focus-shadow-rgb: var(--dme-primary-rgb);
}

/*
   The outline variant is brand-coloured *text* on the page background, so the dark theme uses the
   tint for the resting state. Its hover fills with the brand colour and Bootstrap's own white
   text, which is above 5:1 in both themes.
*/
.btn-outline-primary {
    --bs-btn-color: rgb(var(--dme-primary-rgb));
    --bs-btn-border-color: var(--dme-primary);
    --bs-btn-hover-bg: var(--dme-primary);
    --bs-btn-hover-border-color: var(--dme-primary);
    --bs-btn-active-bg: rgb(var(--dme-primary-hover-rgb));
    --bs-btn-active-border-color: rgb(var(--dme-primary-hover-rgb));
    --bs-btn-disabled-color: rgb(var(--dme-primary-rgb));
    --bs-btn-disabled-border-color: var(--dme-primary);
    --bs-btn-focus-shadow-rgb: var(--dme-primary-rgb);
}

[data-bs-theme="dark"] .btn-outline-primary {
    --bs-btn-color: rgb(var(--dme-primary-dark-text-rgb));
    --bs-btn-border-color: rgb(var(--dme-primary-dark-text-rgb));
    --bs-btn-disabled-color: rgb(var(--dme-primary-dark-text-rgb));
}

/*
   The active sidebar item. AdminLTE re-declares these two variables under [data-bs-theme=dark]
   with a more specific selector, so the dark rule has to be restated rather than inherited.
*/
.app-sidebar {
    --lte-sidebar-menu-active-bg: var(--dme-primary);
    --lte-sidebar-menu-active-color: var(--bs-white);
}

[data-bs-theme="dark"] .app-sidebar {
    --lte-sidebar-menu-active-bg: var(--dme-primary);
    --lte-sidebar-menu-active-color: var(--bs-white);
}

/* The accent's single job: the rule under the navbar. One line, both themes, no text on it. */
.app-header {
    border-bottom: 2px solid var(--dme-accent);
}

/* ==========================================================================================
   Brand marks in the sidebar
   ========================================================================================== */

/*
   The brand row grows to fit a wordmark logo rather than clipping it to AdminLTE's default
   3.5rem, and shrinks back to that when only the square mark is showing.
*/
.sidebar-brand {
    height: auto;
    min-height: 3.5rem;
    padding-block: 0.5rem;
}

.sidebar-brand .brand-link {
    justify-content: center;
    max-width: 100%;
}

.dme-brand-logo {
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 4.5rem;
}

/*
   Both logos are in the markup and CSS picks one, because a first-time visitor's theme is decided
   in the browser by prefers-color-scheme and the server cannot know which logo is right.
*/
.dme-brand-logo-dark {
    display: none;
}

[data-bs-theme="dark"] .dme-brand-logo-light {
    display: none;
}

[data-bs-theme="dark"] .dme-brand-logo-dark {
    display: block;
}

.dme-brand-mark {
    display: none;
    width: 2.25rem;
    height: 2.25rem;
}

.dme-brand-mark-icon {
    width: auto;
    height: auto;
    font-size: 1.75rem;
    line-height: 1;
}

/*
   The collapsed mini bar shows the square mark instead of the wordmark. The swap is unconditional
   because the body carries sidebar-without-hover: the collapsed bar never widens on hover, so the
   wordmark has nowhere to go (CLAUDE.md § "Shell classes and sidebar behaviour"). An earlier
   :not(:hover) qualifier here matched AdminLTE's expand-on-hover default and must not come back
   while that default is off — it would paint the full wordmark inside a 4.6rem bar.
*/
.sidebar-mini.sidebar-collapse .app-sidebar .dme-brand-logo {
    display: none;
}

.sidebar-mini.sidebar-collapse .app-sidebar .dme-brand-mark {
    display: block;
}

/* AdminLTE's brand mark: keep the icon optically aligned with the brand text. */
.sidebar-brand .brand-image {
    font-size: 1.25rem;
    line-height: 1;
}

/* ==========================================================================================
   Responsive helpers

   CLAUDE.md § "Responsive shell": every page is mobile-friendly, and content that cannot shrink
   scrolls inside its own container rather than widening the page. For tables use Bootstrap's own
   .table-responsive; .dme-scroll-x is the equivalent for anything else that has a hard minimum
   width — a wide diagram, a preformatted block, a barcode scan log.
   ========================================================================================== */

.dme-scroll-x {
    overflow-x: auto;
    max-width: 100%;
    -webkit-overflow-scrolling: touch;
}

/*
   Deliberately no `overflow-x: hidden` on the wrapper. It would look like a fix for a page that
   scrolls sideways, but on this layout it is a bug factory: a single hidden axis makes the other
   axis compute to `auto`, which turns the wrapper into a scroll container and breaks the sticky
   sidebar `layout-fixed` depends on. Overflow at 375px is a defect in the content, and the smoke
   test is where it gets caught.
*/

/* Give focused headings a visible ring instead of the browser default outline suppression. */
h1:focus-visible {
    outline: 2px solid var(--bs-focus-ring-color);
    outline-offset: 2px;
}
