/*
    The bridge between Vuexy and piRx: the palette, and the mapping of Vuexy's custom
    properties onto it. Written for the Vuexy evaluation, and it is the file that decided
    it.

    It answers the only question that decides whether Vuexy can be vendored and
    maintained in-house: does re-skinning it need its build toolchain?

    It does not. core.css is a Bootstrap 5.3 build, and 5.3 publishes its whole palette
    as CSS custom properties — 633 distinct --bs-* properties in the compiled file. So
    the template's colours can be redefined by a stylesheet that loads after it, with
    no SCSS, no gulp, no webpack, no Node 24, and nothing to re-run when a colour
    changes. The 115 scss directories and the yarn.lock can be left in the zip.

    What that buys, concretely: piRx's own palette survives. Those colours were not
    picked by eye — the chart slots were validated for lightness band, chroma floor,
    adjacent CVD separation and contrast, and the comment above them in charts.css says so.
    Adopting Vuexy's own purple would throw that away and silently regress every chart.
    Here the template keeps its shapes, spacing, shadows and components, and takes its
    colour from piRx.

    It also means the three-state theme survives intact. The mapping below is written
    ONCE, in terms of token NAMES, so when the token block switches to its dark values
    every --bs-* follows with no second mapping — light, dark and follow-the-machine all
    keep working, which is the thing two hand-maintained palettes would never do.

    ---------------------------------------------------------------------------------

    The token block below is THE definition of the palette. It began as a copy of the
    :root block in app.css, the old stylesheet, while both were loaded on different
    screens; app.css is gone, and this is the one place a piRx colour is set.
*/

/* ---- piRx tokens ---------------------------------------------------------------- */

:root {
    --bg: #f3f5f8;
    --panel: #ffffff;
    --panel-2: #eef2f6;
    --line: #dde3ea;
    --line-strong: #b9c3cf;
    --ink: #172029;
    --ink-2: #3d4b5a;
    --muted: #64748b;
    --field: #ffffff;

    --accent: #0a6fb3;
    --accent-ink: #ffffff;
    --accent-soft: rgba(10, 111, 179, 0.10);

    --ok: #1a7f37;
    --ok-bg: #e7f7ec;
    --ok-line: #9fd8b1;
    --warn: #8a5a00;
    --warn-bg: #fff6d6;
    --warn-line: #ecd07f;
    --danger: #c42f36;
    --danger-bg: #fdecec;
    --danger-line: #f2b3b6;

    --radius: 10px;
}

/* Dark follows the machine unless the person chose — a two-block arrangement, so that
   the browser resolves "system" rather than a script. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg: #0b0f14;
        --panel: #131a22;
        --panel-2: #1a232d;
        --line: #243040;
        --line-strong: #34465a;
        --ink: #e6edf3;
        --ink-2: #c3ceda;
        --muted: #8b9bb0;
        --field: #0b0f14;

        --accent: #4cc2ff;
        --accent-ink: #04202e;
        --accent-soft: rgba(76, 194, 255, 0.14);

        --ok: #3fb950;
        --ok-bg: #0f2416;
        --ok-line: #1f5c2b;
        --warn: #d29922;
        --warn-bg: #241d0d;
        --warn-line: #6b4a12;
        --danger: #f85149;
        --danger-bg: #2a1012;
        --danger-line: #7f1d1d;
    }
}

:root[data-theme="dark"] {
    --bg: #0b0f14;
    --panel: #131a22;
    --panel-2: #1a232d;
    --line: #243040;
    --line-strong: #34465a;
    --ink: #e6edf3;
    --ink-2: #c3ceda;
    --muted: #8b9bb0;
    --field: #0b0f14;

    --accent: #4cc2ff;
    --accent-ink: #04202e;
    --accent-soft: rgba(76, 194, 255, 0.14);

    --ok: #3fb950;
    --ok-bg: #0f2416;
    --ok-line: #1f5c2b;
    --warn: #d29922;
    --warn-bg: #241d0d;
    --warn-line: #6b4a12;
    --danger: #f85149;
    --danger-bg: #2a1012;
    --danger-line: #7f1d1d;
}

/* ---- Shared components, during the migration only ------------------------------
   A handful of shared components — ReportDownloads sits on six screens — still carry
   class names from the old stylesheet. Without a definition they render as unstyled
   HTML: report links that look like raw anchors rather than the three neat formats they
   are.

   Duplicating the component per design system would be worse: two copies of "which
   formats does a report come in", free to disagree about the answer. So the few class
   names they use are defined here too, in Vuexy's terms, and the component itself is
   untouched and host-agnostic.

   THIS SECTION SHOULD SHRINK TO NOTHING. Every rule in it is a shared component that has
   not been rewritten in Bootstrap's terms yet; when ReportDownloads is converted this
   goes with it. If it is growing instead, components are being written against a
   stylesheet that no longer exists, which is the thing to fix rather than to
   accommodate. */

.formats {
    display: inline-flex;
    align-items: baseline;
    gap: 0.55rem;
}

/* ---- The two typography classes, kept on purpose -------------------------------
   `.sub` and `.sku` are used 493 times across the component tree, and they are not
   layout: each is a colour and a font size, nothing else — the muted text colour at
   0.88rem and 0.8rem, which Vuexy has exact equivalents for in its own tokens. So they are defined here rather than rewritten 493 times into
   `text-body-secondary` and `small`.

   This is a deliberate exception to the "the bridge should shrink" rule above, and the
   reason it is defensible is that nothing about them is tied to the old stylesheet — a
   muted caption is a muted caption in any design system. Mapping them buys every remaining screen
   a shorter conversion, and it is reversible with one find-and-replace on the day
   somebody wants the Bootstrap names instead.

   Nothing else from the old stylesheet is mapped. These two are typography; `.card`,
   `.actions`, `.tabs` and the rest carried layout and were converted per screen, which
   is why there is nothing of them left to map. */

.sub {
    color: var(--bs-secondary-color);
    font-size: 0.88rem;
}

p.sub {
    margin: 0.25rem 0 0.9rem;
    max-width: 72ch;
}

.sku {
    color: var(--bs-secondary-color);
    font-size: 0.8rem;
}

/* The appearance switch in the navbar. theme.js owns which button is pressed and says so
   with aria-pressed, which Bootstrap's button group does not paint. Bootstrap's own
   `.active` would need a script to toggle it, and the whole point of the switch is that
   it works without one — on a statically rendered page and across a circuit reconnect. */
.theme-switch [aria-pressed="true"] {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
    color: var(--bs-primary-contrast);
}

/* The Icon component's inline SVGs. It is self-contained otherwise — stroke-only, drawn in
   currentColor, sized by width/height attributes — and the names it answers to come from
   GlobalSearch.Icon in PiRx.Pos, shared with the till and the fleet app. So it is NOT
   remapped onto Tabler: that would mean either a parallel name map or changing a signature
   three apps use, to replace an icon that already works in both design systems. Only the
   `flex: 0 0 auto` matters here, and only so an icon in a flex row is not squeezed. */
.ico {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
}

.formats a.linkish,
a.linkish {
    color: var(--bs-primary);
    font-size: 0.82rem;
    font-weight: 500;
    text-decoration: none;
}

.formats a.linkish:hover,
a.linkish:hover {
    text-decoration: underline;
}

.formats a.linkish + a.linkish {
    padding-left: 0.55rem;
    border-left: 1px solid var(--bs-border-color);
}

/* ---- The menu: the group you are in, and native scrolling ----------------------- */

/* "You are somewhere in here." Vuexy's template marks a group's row `active` from the
   server; this shell cannot, because once the page is up the row's class attribute
   belongs to menu.js (see MenuGroup) and Blazor must not write it. So the highlight is
   read off the child that IS marked — the same colour Vuexy's own rule gives the row.
   :has() is already load-bearing in core.css, so this asks nothing new of a browser. */
.menu-vertical .menu-inner > .menu-item:has(> .menu-sub > .menu-item.active) > .menu-toggle {
    background-color: var(--bs-menu-sub-active-bg);
}

/* The rail scrolls natively. vuexy-init.js hands menu.js a stand-in for PerfectScrollbar
   that adds this class instead of a thumb of its own — the library wrote scrollTop on
   every wheel notch, a hundred-pixel jump where the browser eases. What is left to say
   here is the overflow the library used to own, a scrollbar drawn thin and in the menu's
   colour, and that reaching the end of the rail does not scroll the page under it. */
.menu-inner.menu-native-scroll {
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--bs-menu-color-rgb), 0.35) transparent;
}

/* Vuexy sizes every row to the menu's full width, because with an overlay thumb the
   column never lost any to a scrollbar. Now it can, so rows fill what is there. */
.menu-vertical .menu-inner.menu-native-scroll > .menu-item,
.menu-vertical .menu-inner.menu-native-scroll > .menu-header {
    inline-size: auto;
    align-self: stretch;
}

/* ---- The mapping: Bootstrap/Vuexy reads these, piRx defines them ---------------- */
/*
    Written once, against token names. Nothing below repeats per theme.

    --bs-*-rgb has to be given as bare channel numbers rather than a colour, because
    Bootstrap composes them inside rgba(var(--bs-primary-rgb), .5) for its subtle
    backgrounds. That is the one place a hex token cannot be forwarded as-is, and the
    one place this mapping has to restate a value — kept next to its token so the two
    are changed together.
*/
:root,
:root[data-theme="dark"],
[data-bs-theme="light"],
[data-bs-theme="dark"] {
    --bs-primary: var(--accent);
    --bs-primary-rgb: 10, 111, 179;
    --bs-primary-bg-subtle: var(--accent-soft);
    --bs-primary-text-emphasis: var(--accent);
    --bs-primary-contrast: var(--accent-ink);

    --bs-success: var(--ok);
    --bs-success-rgb: 26, 127, 55;
    --bs-success-bg-subtle: var(--ok-bg);
    --bs-success-border-subtle: var(--ok-line);
    --bs-success-text-emphasis: var(--ok);

    --bs-warning: var(--warn);
    --bs-warning-rgb: 138, 90, 0;
    --bs-warning-bg-subtle: var(--warn-bg);
    --bs-warning-border-subtle: var(--warn-line);
    --bs-warning-text-emphasis: var(--warn);

    --bs-danger: var(--danger);
    --bs-danger-rgb: 196, 47, 54;
    --bs-danger-bg-subtle: var(--danger-bg);
    --bs-danger-border-subtle: var(--danger-line);
    --bs-danger-text-emphasis: var(--danger);

    --bs-secondary: var(--muted);
    --bs-secondary-color: var(--muted);
    --bs-secondary-bg: var(--panel-2);
    --bs-secondary-bg-subtle: var(--panel-2);

    --bs-body-bg: var(--bg);
    --bs-body-color: var(--ink-2);
    --bs-heading-color: var(--ink);
    --bs-emphasis-color: var(--ink);
    --bs-border-color: var(--line);

    --bs-link-color: var(--accent);
    --bs-link-hover-color: var(--accent);

    --bs-border-radius: var(--radius);

    /* The template's pages pull Public Sans from fonts.googleapis.com, which the CSP
       refuses twice over — style-src 'self' blocks the stylesheet and font-src 'self'
       blocks the file. No self-hosting needed, though: Vuexy's own stack falls through
       to "Segoe UI", which is exactly what app.css already sets, so on Windows the
       blocked font resolves to the right face by accident. Stated here so it is a
       decision rather than an accident of fallback order. */
    --bs-font-sans-serif: "Segoe UI", system-ui, -apple-system, sans-serif;

    /* Vuexy's own layer, on top of Bootstrap's. The menu and the "paper" surfaces are
       its additions and have to be pointed at the same tokens or the shell stays
       purple-grey while the content follows piRx. */
    --bs-paper-bg: var(--panel);
    --bs-card-bg: var(--panel);

    /* Vuexy defines --bs-gray-50 twice — once per theme — and app-invoice.css uses it
       for the invoice letterhead panel. Pointed at the token so the letterhead follows
       the theme from one definition instead of two. */
    --bs-gray-50: var(--panel-2);
}
