/*
 * OMPanel overrides — loaded AFTER the template's style.css.
 *
 * The one file in the theme that is ours. `bootstrap.min.css` and `style.css` are vendored
 * and must stay byte-identical to the purchased kit, or the next template update becomes a
 * merge instead of a copy. Anything we need to change about the template's appearance goes
 * here, where it survives that update.
 */

/* ---------------------------------------------------------------------------
 * Hide the template's Theme Customizer.
 *
 * `theme-script.js` unconditionally injects a floating settings tab and an offcanvas
 * panel offering layout, colour and sidebar switches — and a "Buy Product" button. It is
 * the vendor's demo shopfront, not a feature of this platform, and it caused two visible
 * defects: the tab clipped the right edge of the viewport and overlapped the footer.
 *
 * Suppressed here rather than by editing `theme-script.js`, because that same file also
 * applies the `data-bs-theme`, `data-sidebar`, `data-topbar` and `data-layout` attributes
 * that `style.css` needs, and handles the responsive sidebar collapse. Removing the panel
 * from it means re-doing that surgery on every template update; a display rule does not.
 *
 * NOTE: the panel is still injected into the DOM, so the three `img/theme/*.svg` requests
 * it makes still 404 — files the purchased kit does not ship (see TODO T.4). Hiding it
 * fixes what a user can see; only not injecting it would stop the requests.
 * ------------------------------------------------------------------------- */
.sidebar-contact,
.sidebar-themesettings {
    display: none !important;
}

/* ---------------------------------------------------------------------------
 * Dismissible alerts: give the close button its room back.
 *
 * THE CASCADE PROBLEM — read this before "simplifying" the selector below.
 *
 * Bootstrap builds a dismissible alert out of two rules that only work as a pair:
 *
 *     .alert-dismissible            { padding-right: 3rem; }
 *     .alert-dismissible .btn-close { position: absolute; top: 0; right: 0; }
 *
 * The button is out of the flow, so NOTHING reserves space for it except that
 * padding. The template's `style.css` then says:
 *
 *     .alert { padding: 12px 16px; }
 *
 * — a SHORTHAND, so it rewrites all four sides, including the right padding
 * Bootstrap reserved. It has the same specificity as Bootstrap's rule (0,1,0)
 * and loads after it, so it wins, and every dismissible alert in the product
 * ends up with 16px of right padding and a 46px button sitting on top of the
 * last words of its own message. Measured on the forgot-password notice
 * before this rule: computed padding-right 16px, text running 25px underneath
 * the cross. It is not one screen — it is `Views/Shared/flash.php`, which is
 * every flash message on the platform, plus all four auth notices.
 *
 * `style.css` is the purchased kit and is read-only (see the file header), so
 * the override lives here.
 *
 * WHY `.alert.alert-dismissible` AND NOT `.alert-dismissible`:
 * a bare `.alert-dismissible` is (0,1,0) — an exact TIE with `style.css`'s
 * `.alert`, decided only by the fact that `ompanel.css` currently happens to be
 * listed after `ui/css/style.css` in `Ui/Config/Assets.php`. That is a load
 * order, not a guarantee; reorder the array, inline a sheet, or let a build step
 * concatenate differently and the bug comes back silently, on every alert at
 * once. Doubling the class makes it (0,2,0) and it wins on specificity alone,
 * whatever the order. That is also why this does NOT need `!important`.
 *
 * WHAT IT DELIBERATELY DOES NOT TOUCH:
 *  - Plain `.alert` (no `.alert-dismissible`) keeps `style.css`'s 12px/16px.
 *    Those are correct today; they have no absolutely-positioned button in them.
 *  - `auth.css`'s `[data-sign-in-notice].alert-dismissible` is also (0,2,0) and
 *    loads after this file, so the sign-in notice keeps its own, different fix
 *    (button put back in the flow with `position: static`, padding-right 1rem).
 *    A tie that the later sheet wins — intentionally. Do not raise the
 *    specificity here without checking that rule still applies.
 *
 * 3rem is Bootstrap's own figure and it clears the button: `style.css` gives
 * `.alert.alert-dismissible .btn-close` 1rem of padding on each side, measuring
 * 46px wide in the browser, so 48px leaves it 2px of air.
 *
 * Only `padding-right` is set — a shorthand here would re-break the top/bottom
 * 12px that the template intends.
 *
 * FOOTNOTE on the markup: the views put `ms-auto` on the `.btn-close`. It does
 * nothing at all while the button is `position: absolute` — it is a flex margin
 * on an element that is no longer a flex item. Harmless, and those view files
 * are not this file's to change.
 * ------------------------------------------------------------------------- */
.alert.alert-dismissible {
    padding-right: 3rem;
}

/* ---------------------------------------------------------------------------
 * Sortable table headers.
 *
 * The template styles its DataTables headers with the sort arrow pinned to the RIGHT
 * EDGE of the cell in amber, well away from the label. Our tables sort server-side, so
 * the header is a link rather than a DataTables-managed cell and none of that styling
 * reaches it — the arrow otherwise sits immediately after the text in grey, which is the
 * single most visible difference from the original page.
 *
 * Reproduced here rather than by adopting DataTables: the placement is presentation, and
 * copying twenty lines of CSS is cheaper than a client-side grid that cannot page a set
 * it has not downloaded.
 *
 * Both header kinds take the body colour, so a column that cannot be sorted does not read
 * as a different weight — the arrow is what signals interactivity, not the text.
 * ------------------------------------------------------------------------- */
.ompanel-table > thead th {
    color: var(--bs-body-color);
    font-weight: 500;
    position: relative;
}

.ompanel-table > thead th > a {
    color: inherit;
    display: block;
    padding-right: 1.25rem;
}

.ompanel-table > thead th > a > i {
    position: absolute;
    right: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    color: #f8a02c;
    font-size: 0.9rem;
}

/* The neutral "either direction" arrow stays muted, so the active column reads first. */
.ompanel-table > thead th > a > i.ti-arrows-sort {
    color: var(--bs-secondary-color);
}

/* ---------------------------------------------------------------------------
 * THE PANEL GROUND (21 Sep 2026).
 *
 * The owner asked for the profile screen's background everywhere: "make whole project
 * everywhere universal bg color as per i have in profile bg collor".
 *
 * ## It is the TOKEN, not the colour
 *
 * The profile screen paints `.upr-page` with `var(--purple-transparent)`, and that token is
 * theme-aware — `#F1EBF7` in light, `#311B2F` in dark. Copying the hex would have given every
 * panel a lavender ground in dark mode, which is the one way to get this visibly wrong. Using
 * the same token the profile uses means the two can never drift, and dark mode is correct
 * without a second rule.
 *
 * ## Why `body.twocol-layout` and not `body`
 *
 * The owner ticked the control panel and the tenant admin panel, and deliberately did NOT tick
 * the auth screens or the public site. This file is loaded by `app-css` AND by `auth-css`, so
 * a bare `body` rule would have repainted the sign-in door too.
 *
 * `twocol-layout` is the class both panel shells carry and nothing else does:
 *
 *     control/layouts/main.php   <body class="twocol-layout">
 *     admin/layouts/main.php     <body class="twocol-layout">
 *     Shared/layouts/auth.php    <body class="account-page signin-page …">
 *     public/layouts/main.php    <body class="d-flex flex-column … bg-body-tertiary">
 *     Shared/layouts/print.php   <body class="bg-white">
 *
 * So the selector IS the scope, checked against every layout that exists rather than assumed.
 *
 * ## What this deliberately does not touch
 *
 * Only the page ground. The theme's `--light` token is left alone, because it paints far more
 * than the background — `bg-light` utilities, `btn-outline-light` faces, assorted borders and
 * hover states, including the profile screen's own Cancel and edit buttons. Redefining it was
 * offered and declined in favour of this. Cards stay white, so content still lifts off the
 * ground the way the design intends.
 * --------------------------------------------------------------------------- */
body.twocol-layout {
    background-color: var(--purple-transparent);
}


/* ---------------------------------------------------------------------------
 * THE APPEARANCE PREFERENCES, MADE TO TAKE EFFECT  ·  todos 440 and 480
 *
 * Eight settings on the Account page — theme, accent, density, size, and the four
 * accessibility switches — were saving to `usr_preferences` and changing nothing on
 * screen. `App\Core\Support\Appearance` now puts each of them on `<html>` as an
 * attribute (and the accent as two custom properties in the `style` attribute), from
 * `Shared/layouts/html-open.php`, which every one of the five page shells calls.
 *
 * FIVE of the eight are answered in this file: `density`, `size`, `motion`, `contrast`
 * and `underline`. The other three were already half-built elsewhere and are finished
 * where they live, so a reader finds the rule beside the thing it modifies:
 *
 *   theme      `style.css` already keys off `data-bs-theme`; the shells simply never
 *              wrote it. Nothing to add here.
 *   accent     `module.css` held three literal `228, 31, 7`s that could not follow a
 *              changed accent; they now read `var(--primary-rgb)`.
 *   focus      the `:focus-visible` block in `module.css` gained an
 *              `html[data-always-show-focus]` companion on plain `:focus`.
 *
 * `motion` is answered in two places and the split is deliberate: the five
 * `@media (prefers-reduced-motion: reduce)` blocks in `module.css` and `layout.css`
 * each gained an exact `html[data-reduce-motion]` companion, and the catch-all that
 * covers everything else in the purchased theme is below.
 *
 * ## Where these rules do and do not reach
 *
 * This file is loaded by `app-css` and by `auth-css` — the control panel, the tenant
 * panel and the sign-in door. It is NOT in `public-css` or `print-css`, so a tenant's
 * public site and a printed page carry the attributes and ignore them. That is the
 * right answer for both and not an oversight: a public page is drawn for a VISITOR,
 * not for the signed-in person whose preference it would be, and a printed document is
 * drawn for paper, where a dark theme and a text-size step are actively wrong.
 *
 * ## Why `html[...]` and not a body class
 *
 * `<html>` is where `data-bs-theme` already lives, so all of this is legible in one
 * place in the inspector, and the shells write one tag instead of a tag and a class.
 * The element selector also buys a point of specificity, which is what lets every rule
 * below beat `style.css` without a single `!important` that is not already there.
 * ------------------------------------------------------------------------- */


/* ---------------------------------------------------------------------------
 * DENSITY — one number, applied to the four things that actually decide how much
 * fits on a screen.
 *
 * `comfortable` is the template exactly as drawn: the scale is 1 and every `calc()`
 * below evaluates to the literal `style.css` already used. That is deliberate — the
 * default must be a no-op, so a person who never opens the pane cannot be given a
 * screen that is subtly not the one the designer drew.
 *
 * ## What it touches, and what it refuses to
 *
 * Card padding, card spacing, table rows and the height of a form field. Those four
 * are what "density" means to somebody looking at a list: how many rows fit. It does
 * NOT touch font size — that is `size` below, and conflating the two leaves a person
 * no way to ask for small text in roomy rows — nor the sidebar, the topbar, or any of
 * the template's several hundred bespoke components.
 *
 * Scaling everything was the alternative and it is the worse product: a purchased
 * theme of fifteen thousand lines has components whose paddings are load-bearing, and
 * a blanket transform breaks them in ways nobody finds until a customer does.
 *
 * `.table tbody tr td` carries `!important` because `style.css` line 9619 does, and
 * `!important` against `!important` is decided on specificity — which this wins.
 * ------------------------------------------------------------------------- */
html[data-density] {
    --app-density: 1;
}

html[data-density="cosy"] {
    --app-density: 0.7;
}

html[data-density="compact"] {
    --app-density: 0.45;
}

html[data-density] .card .card-body {
    padding: calc(20px * var(--app-density));
}

html[data-density] .card {
    margin-bottom: calc(20px * var(--app-density));
}

html[data-density] .table tbody tr td {
    padding: calc(10px * var(--app-density)) 8px !important;
}

html[data-density] .table thead tr th {
    padding: calc(8px * var(--app-density)) 10px;
}

html[data-density] .form-control,
html[data-density] .form-select {
    padding-top: calc(0.5rem * var(--app-density));
    padding-bottom: calc(0.5rem * var(--app-density));
}


/* ---------------------------------------------------------------------------
 * TEXT SIZE — a step on the root, and the body taught to follow it.
 *
 * Two rules and not one, because this theme needs both:
 *
 *   `html`  carries the rem basis. Bootstrap's spacing, and most of what the template
 *           writes in rem, follows it. This is the half that makes the whole screen
 *           breathe rather than only the paragraphs.
 *   `body`  because `style.css` line 9302 sets `font-size: 14px` — a PIXEL value, so
 *           body text does not inherit the rem basis at all. Stepping the root alone
 *           moved the padding and left every word exactly the size it was, which is
 *           the one way to make this preference look broken while being applied.
 *
 * ## Both rules are RELATIVE, and that is the whole point
 *
 * Percentages on the root rather than pixels, so somebody who has already enlarged
 * text in their browser keeps that enlargement and has this applied on top of it.
 * Writing `18px` here would quietly overrule them — the opposite of what a setting in
 * an accessibility pane is for.
 *
 * `0.875em` on the body for the same reason once removed: it is 14/16, the template's
 * own ratio, expressed against whatever the root now is. At `m` it computes to exactly
 * the 14px the theme draws, so the default costs nothing and there is no literal to
 * keep in step with `style.css`.
 *
 * The steps are one notch either side and no more. A purchased theme has fixed-width
 * furniture in it, and a "large" that overflows the sidebar is not an accessibility
 * feature. Somebody who needs more than this has browser zoom, which scales the
 * furniture too.
 * ------------------------------------------------------------------------- */
html[data-text-size="s"] {
    font-size: 93.75%;
}

html[data-text-size="l"] {
    font-size: 112.5%;
}

html[data-text-size] body {
    font-size: 0.875em;
}


/* ---------------------------------------------------------------------------
 * REDUCE MOTION — the catch-all, beneath the five companions.
 *
 * `module.css` and `layout.css` now each carry `html[data-reduce-motion]` rules beside
 * their `@media (prefers-reduced-motion: reduce)` blocks, so the switch answers exactly
 * what the OS setting answers, component by component.
 *
 * That is five components out of a fifteen-thousand-line theme. Everything else in it
 * still slides, fades and spins for somebody who has asked the platform to stop, and
 * "the toast stopped moving" is not what a person ticking this box is asking for. So
 * this is the floor underneath those five: whatever else the theme animates, it
 * finishes instantly.
 *
 * The two halves are kept separate on purpose. The companions are a faithful mirror of
 * the media queries and stay in step with them; this is a blunt instrument and is
 * written as one, where it can be read as one.
 *
 * ## `.001ms` and not `0s`
 *
 * A duration of exactly zero stops `transitionend` from firing at all, and anything
 * waiting on that event then waits for ever — Bootstrap's collapse and offcanvas both
 * do. `.001ms` finishes instantly and still fires, which is the established answer to
 * this and not an invention here.
 * ------------------------------------------------------------------------- */
html[data-reduce-motion] *,
html[data-reduce-motion] *::before,
html[data-reduce-motion] *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
}


/* ---------------------------------------------------------------------------
 * HIGHER CONTRAST — five tokens, and deliberately nothing else.
 *
 * ## The scope is the whole design of this rule
 *
 * `style.css` is fifteen thousand lines of purchased theme with a hundred-odd colour
 * tokens. A "high contrast mode" that reskinned it would be a second theme to maintain
 * for ever, and it would be wrong in a hundred small places nobody would notice until
 * a customer did.
 *
 * So this changes the three things that actually decide whether text can be read, and
 * stops:
 *
 *   `--body-color`   #707070 on white measures about 4.9:1. That clears AA for body
 *                    text by a margin so thin that any tinted card ground drops it
 *                    below. #1F2020 — the template's OWN heading colour, not a new
 *                    value invented here — measures about 15.3:1.
 *   `--gray-500`     what the template reaches for when it wants something to recede.
 *                    Muted text is the first thing to become unreadable and the last
 *                    thing anybody tests.
 *   `--border-color` #E2E8F0 is very nearly invisible. Table rules, card edges and
 *                    input outlines are STRUCTURE: somebody who cannot see the border
 *                    of a field cannot see the field.
 *
 * Both themes are answered, because "higher contrast" in dark mode means brighter, not
 * darker, and a single set of literals would have made dark mode worse.
 *
 * `.text-muted` and `.text-secondary` are named explicitly because Bootstrap drives
 * them from `--bs-secondary-color` rather than from any of the theme's own tokens, and
 * they are where most of the product's low-contrast text actually is.
 * ------------------------------------------------------------------------- */
html[data-higher-contrast] {
    --body-color: #1F2020;
    --gray-400: #5A5B5B;
    --gray-500: #454646;
    --border-color: #94A3B8;
    --bs-secondary-color: #454646;
}

html[data-higher-contrast][data-bs-theme="dark"] {
    --body-color: #EDEFFF;
    --gray-400: #B5BBCC;
    --gray-500: #C9CEDD;
    --border-color: #5B5BA8;
    --bs-secondary-color: #C9CEDD;
}

/* `!important` for the same reason the focus ring needs it: Bootstrap and the template
   declare these utilities `!important` themselves, and nothing without it reaches them.

   `.text-default`, `.fs-12` and `small` are the template's own three ways of saying
   "this matters less", and between them they carry most of the secondary text in the
   product — timestamps, helper lines under a field, the counts beside a heading. A
   contrast setting that left those alone would have missed the text people actually
   struggle with. */
html[data-higher-contrast] .text-muted,
html[data-higher-contrast] .text-secondary,
html[data-higher-contrast] .text-default,
html[data-higher-contrast] .fs-12,
html[data-higher-contrast] small {
    color: var(--bs-secondary-color) !important;
}

/* Raising `--border-color` above reaches everything that draws its edge from the token.
   These five do not: the template and Bootstrap give each of them a border colour of
   their own, `!important` in places, and they are the edges that matter most — the line
   round a card, the rule between two rows, the outline of a field somebody is trying to
   type into. */
html[data-higher-contrast] .card,
html[data-higher-contrast] .table > :not(caption) > * > *,
html[data-higher-contrast] .form-control,
html[data-higher-contrast] .form-select,
html[data-higher-contrast] .dropdown-menu {
    border-color: var(--border-color) !important;
}


/* ---------------------------------------------------------------------------
 * UNDERLINE LINKS — and the anchors in this theme that are not links.
 *
 * `style.css` line 9321 sets `a { text-decoration: none }` for the whole product, so
 * colour is the only thing separating a link from the sentence around it — which is
 * exactly the failure this preference exists to fix, and it is invisible to anybody
 * who cannot tell the two hues apart.
 *
 * ## The exclusions are not tidiness
 *
 * This template builds buttons, menu rows, tabs and icon actions out of `<a>`. Without
 * the `:not()` chain every button on the platform grows an underline through its label
 * and every sidebar row underlines itself, which is not "links are underlined" — it is
 * a product that looks broken. The four the survey named are here, plus three more
 * found in the same sweep: `.navbar-brand`, `.page-link` and `.badge`.
 *
 * ## Why a `:not()` chain and not `!important`
 *
 * Each `:not()` contributes its argument's weight, so this selector scores (0,8,2) and
 * beats every descendant rule in the template on specificity alone. An `!important`
 * would have needed a second `!important` on each exclusion to undo it, and a pair of
 * duelling `!important`s is how a stylesheet stops being readable.
 * ------------------------------------------------------------------------- */
html[data-underline-links] a:not(.btn):not(.dropdown-item):not(.nav-link):not(.action-icon):not(.navbar-brand):not(.page-link):not(.badge) {
    text-decoration: underline;
}


/* ===========================================================================
 * THE ACCENT, MADE UNIVERSAL — HOVER, ACTIVE, FOCUS AND CHECKED INCLUDED
 * ===========================================================================
 *
 * Owner, 22 Sep 2026: *"still needs to make preference accent to follow only one
 * universal to everywhere including active hover and all — I noticed in tenant
 * modal login button hover shows another color that I selected accent from
 * preference."*
 *
 * ## The fault, exactly
 *
 * `App\Core\Support\Appearance` puts the chosen accent on `<html>` as `--primary`
 * and `--primary-rgb`, and an inline style beats every selector in `style.css`, so
 * the RESTING state of everything followed the preference. The STATES did not, and
 * the reason is one line of the purchased theme:
 *
 *     .btn-primary:hover, .btn-primary:active, … { background-color: var(--primary-hover) }
 *
 * `--primary-hover` is a SEPARATE token (`style.css:78`, a literal `#c11a06`), not a
 * function of `--primary`. Overriding `--primary` therefore left every hover, every
 * pressed button and every `.btn-check` selection painting the brand red — which is
 * precisely the modal button the owner saw. `--primary-transparent` (`:100`/`:194`)
 * and `--primary-gradient-100` (`:134`) are the same story for soft buttons, the
 * active menu row's tint and the gradient utilities.
 *
 * ## Why the derivation lives here and not in PHP
 *
 * `--primary-transparent` is a TINT TOWARDS THE PAGE, and the page is white in one
 * theme and near-black in the other. PHP does not know which theme the browser will
 * resolve `system` to, so a value computed server-side would be wrong for half the
 * people using it. `color-mix()` is evaluated by the browser, after `data-bs-theme`
 * is settled, which is the only place the question can be answered.
 *
 * `--primary-hover` is derived at 85% towards black, and `--primary-transparent` at
 * 10% towards white, because that is what the theme itself did by hand: #E41F07 →
 * #c11a06 is 0.85, 0.84, 0.86 per channel, and #E41F07 → #fce9e6 is a 10% tint.
 * MEASURED at the default accent, the derivation lands on rgb(194, 26, 6) against
 * the template's rgb(193, 26, 6) and on rgb(252, 233, 230) exactly — one step of
 * 1/255 on one channel, which is the closest a formula can come to a hand-picked
 * pair and is the no-op a default has to be.
 *
 * ## The three things this block is not
 *
 * It is NOT a `*` sweep and NOT a blanket `!important`. `style.css` is fifteen
 * thousand lines and a sweep breaks it in ways nobody can bisect later. Every rule
 * below names a component, and `!important` appears only where the VENDORED rule it
 * answers already carries one.
 *
 * It is NOT an edit to `style.css` or `bootstrap.min.css`. Those stay byte-identical
 * to the purchased kit, so the next template release is a copy and not a merge.
 *
 * It is NOT complete in the sense of "every red pixel". See THE HONEST REMAINDER at
 * the foot of the block.
 * ------------------------------------------------------------------------- */


/* ---------------------------------------------------------------------------
 * 1 · THE DERIVED TOKENS
 *
 * Four of the theme's five accent tokens, restated as functions of the one the
 * preference actually sets. This section alone fixes the reported modal button and
 * most of what follows it; the rules after it exist only for the places the theme
 * or Bootstrap wrote a literal instead of reaching for a token.
 *
 * `--app-accent` is the accent under a name no descendant redefines.
 * `[data-color=…]` blocks in `style.css` reassign `--primary` inside a subtree (the
 * role cards do exactly this), so a rule that needs THE PREFERENCE rather than THE
 * LOCAL COLOUR has to read this instead.
 * ------------------------------------------------------------------------- */
:root {
    --app-accent: var(--primary);
    --app-accent-rgb: var(--primary-rgb);

    /* Every hover, pressed and `.btn-check:checked` state in the theme. */
    --primary-hover: color-mix(in srgb, var(--primary) 85%, #000);

    /* Soft buttons, the active menu row, badges, every `-transparent` surface. */
    --primary-transparent: color-mix(in srgb, var(--primary) 10%, #fff);

    --primary-gradient-100: linear-gradient(180deg, var(--primary) 0%, color-mix(in srgb, var(--primary) 70%, #fff) 100%);
    --linear-gradient: linear-gradient(180deg, var(--primary) 0%, var(--secondary) 100%);
}

/* Dark keeps a NEUTRAL transparent surface, which is what `style.css:194` chose: a
   10% tint of the accent against black is a muddy smear at these luminances, and
   the theme's own answer — a flat near-black — reads correctly under every accent.
   Restated rather than left alone so the light value above cannot leak in. */
:root[data-bs-theme=dark] {
    --primary-transparent: #1a1d20;
}

/* A role card paints itself with `data-color`, and `primary` on that attribute
   means "the product's own accent" — so it has to be the PERSON's accent, not the
   literal `#E41F07` that `style.css:6094` assigns. The other eleven colours are
   left exactly as the theme defines them: they are a fixed palette of role hues,
   not accents. */
[data-color=primary] {
    --primary: var(--app-accent);
    --primary-rgb: var(--app-accent-rgb);
}


/* ---------------------------------------------------------------------------
 * 2 · THE TABS THE THEME WROTE AS LITERALS
 *
 * `style.css:7622-7680` builds `nav-bordered-primary` and `nav-solid-primary` out
 * of a raw `#E41F07` in every state — hover, focus and active alike — while the
 * `nav-border` variant three lines above it uses `var(--primary)` properly. There
 * is no token to point at, so each is restated at its own specificity.
 * ------------------------------------------------------------------------- */
.nav-tabs.nav-bordered-primary.nav-tabs-top .nav-item .nav-link:hover,
.nav-tabs.nav-bordered-primary.nav-tabs-top .nav-item .nav-link:focus,
.nav-tabs.nav-bordered-primary .nav-item .nav-link:hover,
.nav-tabs.nav-bordered-primary .nav-item .nav-link:focus {
    color: var(--primary);
}

.nav-tabs.nav-bordered-primary.nav-tabs-top .nav-item .nav-link.active {
    border-top-color: var(--primary);
    color: var(--primary);
}

.nav-tabs.nav-bordered-primary .nav-item .nav-link.active {
    border-bottom-color: var(--primary);
    color: var(--primary);
}

.nav-tabs.nav-solid-primary.nav-tabs-rounded li a:hover,
.nav-tabs.nav-solid-primary li a:hover {
    color: var(--primary);
}

.nav-tabs.nav-solid-primary.nav-tabs-rounded li a.active,
.nav-tabs.nav-solid-primary.nav-tabs-rounded-fill li a.active,
.nav-tabs.nav-solid-primary li a.active {
    background-color: var(--primary);
    border-color: var(--primary);
}


/* ---------------------------------------------------------------------------
 * 3 · THE RANGE SLIDER PLUGIN
 *
 * `style.css:13139-13147`, the noUiSlider skin, same literal.
 * ------------------------------------------------------------------------- */
[data-slider-color=primary] .noUi-connect,
[data-slider-color=primary] .noUi-handle {
    background: var(--primary);
}

[data-slider-color=primary][data-slider-style=border] .noUi-handle,
[data-slider-color=primary][data-slider-style=square] .noUi-handle {
    border-color: var(--primary);
}


/* ---------------------------------------------------------------------------
 * 4 · THE SHELL VARIANTS THAT PAINT THEMSELVES BRAND RED
 *
 * `style.css:238` and `:452`. These only apply when the shell is drawn with those
 * attributes, which is a layout choice rather than a preference — but if one is
 * ever turned on, a red sidebar under a teal accent is the same bug in a bigger
 * area, so they are pointed at the accent now rather than found later.
 * ------------------------------------------------------------------------- */
:root[data-sidebar=sidebar4] {
    --menu-bg: var(--primary);
}

:root[data-topbar=topbar3] {
    --topbar-bg: var(--primary);
}


/* ---------------------------------------------------------------------------
 * 5 · BOOTSTRAP'S OWN COMPONENT TOKENS
 *
 * `module.css` already points `--bs-primary`, `--bs-primary-rgb`,
 * `--bs-focus-ring-color` and `--bs-link-color-rgb` at the accent, and restates the
 * four rules where Bootstrap wrote `#86b7fe` / `rgba(13,110,253,.25)` as literals.
 *
 * What it does NOT reach is the per-component token blocks: `.btn-primary`,
 * `.nav-pills`, `.pagination`, `.progress`, `.list-group`, `.dropdown-menu` and
 * `.accordion` each declare their accent as a HEX OF THEIR OWN, so `--bs-primary`
 * never enters the calculation. The theme redraws several of these by hand and
 * hides the fault; the ones it does not redraw went blue.
 *
 * Declared as the components' own tokens rather than as property overrides, which
 * is how Bootstrap 5.3 is meant to be themed: it keeps every state the component
 * already has — disabled, focus shadow, the hover/active split — instead of
 * replacing the rules and losing them.
 * ------------------------------------------------------------------------- */
.btn-primary {
    --bs-btn-bg: var(--primary);
    --bs-btn-border-color: var(--primary);
    --bs-btn-hover-bg: var(--primary-hover);
    --bs-btn-hover-border-color: var(--primary-hover);
    --bs-btn-active-bg: var(--primary-hover);
    --bs-btn-active-border-color: var(--primary-hover);
    --bs-btn-disabled-bg: var(--primary);
    --bs-btn-disabled-border-color: var(--primary);
    --bs-btn-focus-shadow-rgb: var(--primary-rgb);
}

.btn-outline-primary {
    --bs-btn-color: var(--primary);
    --bs-btn-border-color: var(--primary);
    --bs-btn-hover-bg: var(--primary);
    --bs-btn-hover-border-color: var(--primary);
    --bs-btn-active-bg: var(--primary);
    --bs-btn-active-border-color: var(--primary);
    --bs-btn-disabled-color: var(--primary);
    --bs-btn-disabled-border-color: var(--primary);
    --bs-btn-focus-shadow-rgb: var(--primary-rgb);
}

.nav-pills {
    --bs-nav-pills-link-active-bg: var(--primary);
}

.pagination {
    --bs-pagination-color: var(--primary);
    --bs-pagination-hover-color: var(--primary-hover);
    --bs-pagination-focus-color: var(--primary-hover);
    --bs-pagination-focus-bg: var(--primary-transparent);
    --bs-pagination-focus-box-shadow: 0 0 0 .25rem rgba(var(--primary-rgb), .25);
    --bs-pagination-active-bg: var(--primary);
    --bs-pagination-active-border-color: var(--primary);
}

.progress,
.progress-stacked {
    --bs-progress-bar-bg: var(--primary);
}

.list-group {
    --bs-list-group-active-bg: var(--primary);
    --bs-list-group-active-border-color: var(--primary);
}

.dropdown-menu {
    --bs-dropdown-link-active-bg: var(--primary);
}

.accordion {
    --bs-accordion-active-color: var(--primary);
    --bs-accordion-btn-focus-border-color: var(--primary);
}


/* ---------------------------------------------------------------------------
 * 6 · CHECKBOXES, RADIOS AND SWITCHES
 *
 * `.form-check-input:checked { background-color: #0d6efd; border-color: #0d6efd }`
 * is a LITERAL in `bootstrap.min.css` with no token in front of it, and so are the
 * indeterminate checkbox and the range thumb. Restated at the specificity Bootstrap
 * used, so no `!important` is needed — this file loads after it.
 *
 * The checked SWITCH takes its track from the same `:checked` rule and is therefore
 * covered by the first selector. Its KNOB is a white circle in a data URI and stays
 * white, which is right on any accent. The FOCUS knob — the one place a COLOURED
 * circle is baked into a URL — is answered in `module.css` through `--primary-knob`,
 * assembled by `Appearance` because CSS has no `url(var(--x))`.
 * ------------------------------------------------------------------------- */
.form-check-input:checked {
    background-color: var(--primary);
    border-color: var(--primary);
}

.form-check-input[type=checkbox]:indeterminate {
    background-color: var(--primary);
    border-color: var(--primary);
}

.form-range::-webkit-slider-thumb {
    background-color: var(--primary);
}

.form-range::-moz-range-thumb {
    background-color: var(--primary);
}


/* ---------------------------------------------------------------------------
 * 7 · THE FOCUSED FIELD — WHICH IS ALREADY RIGHT, AND IS LEFT ALONE
 *
 * Stated because the obvious next rule here is a wrong one. `style.css:6665` and
 * `:7364` say, deliberately:
 *
 *     .form-control:focus, .form-check-input:focus { border-color: var(--border-color) }
 *
 * A focused field in this template KEEPS ITS NEUTRAL BORDER. Focus is shown by the
 * ring, not by recolouring the edge, and the ring is `--app-focus-color` in
 * `module.css`, which is already `var(--primary)` and already follows the accent.
 * Bootstrap's own `#86b7fe` border and blue glow are answered in `module.css` too.
 *
 * A `border-color: var(--primary)` on `:focus` was written here, measured, and
 * REMOVED: it redraws a field the designer drew on purpose, and it is not what the
 * accent preference was asked to do.
 * ------------------------------------------------------------------------- */


/* ---------------------------------------------------------------------------
 * THE HONEST REMAINDER — what is still the template's red, and why
 * ---------------------------------------------------------------------------
 *
 * 1. `style.css` ships eleven further `[data-color=…]` themes (`secondary`,
 *    `success`, `info`, `teal`, …). Those are a fixed palette of role hues, not
 *    accents, and are deliberately untouched. Only `[data-color=primary]` follows
 *    the preference, in section 1.
 *
 * 2. `.sidebar-themesettings .offcanvas-body .bg-primary { background: #E41F07
 *    !important }` (`style.css:1703`) is the vendor's demo customiser, which the top
 *    of this file hides with `display: none`. Left alone on purpose: overriding a
 *    colour inside an element nobody can see is noise in a stylesheet.
 *
 * 3. `--sw-pv-accent: 228, 31, 7` in `profile-shell.css:3120` is the accent used
 *    INSIDE the theme-preview mock on the Account page. It is pinned by design — the
 *    two preview cards have to stay comparable with each other, so the picture must
 *    not repaint when the thing it is a picture of does.
 *
 * 4. Images and icons carrying the brand colour as PIXELS — the logo above all —
 *    cannot follow an accent from CSS at all. That needs an SVG written with
 *    `currentColor`, which is a design deliverable rather than a stylesheet change.
 *
 * 5. A CHECKED SWITCH and a checked checkbox take the accent as their FILL but keep
 *    a neutral 1px edge: `style.css:6823` is `.form-check .form-check-input {
 *    border: 1px solid var(--border-color) !important }`. That is the theme's own
 *    decision and it reads the same under every accent, so the `!important` is left
 *    standing rather than answered with a second one.
 *
 * 6. A RESTING link is `var(--gray-900)` by design (`style.css:9320`) — only
 *    `a:hover` is the accent, and that one already follows the preference because
 *    the theme wrote it as `var(--primary)`. Links are not recoloured here.
 *
 * 7. `color-mix()` is required by section 1. Every engine has shipped it since 2023;
 *    a browser without it falls back to the token's declared value, which is the
 *    template's own red — degraded, not broken.
 * ------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   A TAB THAT IS DRAWN BUT NOT YET OPENABLE (23 Sep 2026).

   `data-pane-soon` marks a section the design has and the product does not.
   It stays in the strip and keeps its tooltip, so it has to LOOK inert without
   being `disabled` — a disabled button fires no pointer events, and the
   tooltip explaining it would never open.

   `cursor: default` rather than `not-allowed`: nothing is forbidden here, it
   simply is not ready, and `not-allowed` reads as a refusal.
   --------------------------------------------------------------------------- */
.up-tabs .nav-link.is-soon {
    opacity: .55;
    cursor: default;
}

.up-tabs .nav-link.is-soon:hover,
.up-tabs .nav-link.is-soon:focus {
    color: inherit;
    border-color: transparent;
    background: transparent;
}
