/* Project-specific overrides for the Tabler theme.
   Keep this file small — prefer Tabler's built-in classes over overrides. */

/* Self-hosted Inter variable font. Drop InterVariable.woff2 /
   InterVariable-Italic.woff2 into /static/fonts/inter/ — Tabler's default
   font stack ("Inter Var", Inter, ...) will pick this up automatically.
   If files are missing, the browser falls back to system fonts gracefully. */
@font-face {
    font-family: 'Inter Var';
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
    src: url('/fonts/inter/InterVariable-2bf3d951bf9d6109437ea0874bbf12fb.woff2') format('woff2-variations');
}
@font-face {
    font-family: 'Inter Var';
    font-weight: 100 900;
    font-style: italic;
    font-display: swap;
    src: url('/fonts/inter/InterVariable-Italic-8d1dc86da25893737b6bb8a9c64b790e.woff2') format('woff2-variations');
}

/* Sidebar collapse (toggled by #sidebarToggleBtn in topbar) — hides the
   vertical nav and lets .page-wrapper reclaim the full viewport width.
   Persisted via localStorage in scripts.js.
   Uses `margin-left` because Tabler's .page-wrapper rules set `margin-left: 15rem`
   in multiple media queries; `margin-inline-start` alone didn't beat them in LTR. */
body.sidebar-collapsed .navbar-vertical { display: none !important; }
body.sidebar-collapsed .page-wrapper {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

/* --- DataTables footer (info + pagination) --- */
/* Kill default DataTables margin/padding so info+pagination sit cleanly in the flex footer */
.dt-footer .dataTables_info { padding: 0; }
.dt-footer .dataTables_paginate { padding: 0; margin: 0; }
.dt-footer .pagination { margin: 0; }
/* Small muted page-links matching Tabler's compact button sizing */
.dt-footer .page-link {
    padding: .25rem .5rem;
    font-size: .8125rem;
}
/* Hide the whole footer row when there's nothing to page (only 1 page of results).
   DataTables still renders the bar; this keeps cards tight on small tables. */
.dt-footer:has(.paginate_button.current:only-child) .dataTables_paginate { display: none; }

/* --- Accessibility: visible focus ring for keyboard users --- */
/* Browsers show :focus-visible only for keyboard navigation, not mouse clicks,
   so interactive targets stay clean when clicked but prominent when tabbed to. */
*:focus-visible {
    outline: 2px solid var(--tblr-primary, #066fd1);
    outline-offset: 2px;
    border-radius: 2px;
}
/* Override inside form controls — BS5 already shows a box-shadow on :focus,
   the outline would duplicate. Use outline only on buttons and links. */
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible {
    outline: none;
}

/* --- Required field indicator: red asterisk after the label --- */
/* Uses :has() to detect when the immediately-following input is required.
   Falls back silently on browsers without :has() support (Chrome 105+, Safari 15.4+, Firefox 121+). */
.form-label:has(+ input[required]),
.form-label:has(+ textarea[required]),
.form-label:has(+ select[required]) {
    position: relative;
}
.form-label:has(+ input[required])::after,
.form-label:has(+ textarea[required])::after,
.form-label:has(+ select[required])::after {
    content: " *";
    color: var(--tblr-danger, #d63939);
    font-weight: 600;
}

/* --- Card header dropdowns: let menus escape the card's overflow:hidden clipping.
   Targeted via :has() so only cards that actually have a header dropdown lose the clip. */
.card:has(> .card-header .dropdown),
.card:has(> .card-header .dropend),
.card:has(> .card-header .dropstart) {
    overflow: visible;
}

/* --- Row-level dropdowns inside DataTables: same clipping pattern, but inside
   .table-responsive (which has overflow-x:auto). Open the parent card while a
   menu is shown so it isn't cut by the row container. */
.card:has(.table-responsive .dropdown-menu.show) {
    overflow: visible;
}
.card:has(.table-responsive .dropdown-menu.show) .table-responsive {
    overflow: visible;
}

/* --- Linked primary cells in list tables.
   Click the name/account/reference to open the detail page. Hover affordance
   matches Tabler's link styles; truncation + native title attribute handles
   long values on narrow viewports without breaking row height.
   Hover styling is scoped to anchor variants only — a bare .row-link <div>
   is non-interactive and must not look clickable. */
.row-link {
    max-width: 100%;
}
a.row-link:hover .fw-medium {
    color: var(--tblr-primary);
    text-decoration: underline;
}
.row-link .text-truncate {
    max-width: 28ch;
}
@media (min-width: 992px) {
    .row-link .text-truncate { max-width: 32ch; }
}

/* --- Sticky first column for tables that may overflow on narrow viewports.
   Add class="table-sticky-first" to the <table>. Keeps the primary identifier
   (name / reference) in view while the rest scrolls horizontally. */
.table-sticky-first > thead > tr > th:first-child,
.table-sticky-first > tbody > tr > td:first-child {
    position: sticky;
    left: 0;
    background-color: var(--tblr-bg-surface, #fff);
    z-index: 1;
}
.table-sticky-first > thead > tr > th:first-child {
    z-index: 2;
}
[data-bs-theme="dark"] .table-sticky-first > thead > tr > th:first-child,
[data-bs-theme="dark"] .table-sticky-first > tbody > tr > td:first-child {
    background-color: var(--tblr-bg-surface, #1a2234);
}
/* Striping must keep working under the sticky cell. */
.table-sticky-first.card-table > tbody > tr:nth-child(even) > td:first-child {
    background-color: var(--tblr-bg-surface-tertiary, rgba(0, 0, 0, .025));
}
[data-bs-theme="dark"] .table-sticky-first.card-table > tbody > tr:nth-child(even) > td:first-child {
    background-color: rgba(255, 255, 255, .03);
}

/* --- Skeleton row placeholders for server-side DataTables initial load --- */
/* Shimmer effect matches Bootstrap 5 .placeholder-glow. Rows are replaced
   automatically by DataTables on first draw. */
tr.dt-skeleton td .placeholder {
    height: 0.75rem;
    background-color: var(--tblr-bg-surface-secondary, rgba(0, 0, 0, .08));
}

/* --- Alternating row colors for card-table data tables --- */
/* Global zebra striping — applies to every Tabler .card-table so list pages
   don't each need their own .table-striped class. Uses a subtle background
   that works in both light and dark themes via the --tblr-bg-surface-tertiary var. */
.table.card-table > tbody > tr:nth-child(even) > * {
    background-color: var(--tblr-bg-surface-tertiary, rgba(0, 0, 0, .025));
}
[data-bs-theme="dark"] .table.card-table > tbody > tr:nth-child(even) > * {
    background-color: rgba(255, 255, 255, .03);
}

/* Sidebar submenu — inline expansion (BS5 collapse) inside .navbar-vertical.
   Nested nav items use the same look as top-level but slightly muted so the
   hierarchy reads clearly. */
.navbar-vertical .nav-sidebar-submenu { margin: 0; padding-left: 0; list-style: none; }
.navbar-vertical .nav-sidebar-submenu .nav-link { padding-block: .35rem; opacity: .85; }
.navbar-vertical .nav-sidebar-submenu .nav-link:hover { opacity: 1; }

/* Tabler's .nav-link-toggle class draws the chevron via ::after
   and rotates it 180° on [aria-expanded=true] — no custom rules needed. */

/* The sidebar has a small fixed set of items — suppress the browser scrollbar
   and OS-level scroll arrow buttons that Tabler's default overflow: auto causes
   when content is near the viewport boundary. */
.navbar-vertical .navbar-collapse {
    overflow: visible !important;
}
.navbar-vertical {
    overflow-y: auto;
    scrollbar-width: none;               /* Firefox */
}
.navbar-vertical::-webkit-scrollbar {    /* Chrome, Safari, Edge */
    width: 0;
    height: 0;
}

/* --- Sidebar hover + active states (dark theme) --- */

/* Hover on any top-level or submenu nav link — subtle lighter tint. */
.navbar-vertical .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.06);
    color: #fff;
}

/* Active (current page) — accented background + left border + white text. */
.navbar-vertical .nav-item.active > .nav-link,
.navbar-vertical .nav-sidebar-submenu .nav-item.active > .nav-link {
    background-color: rgba(var(--tblr-primary-rgb, 6, 111, 209), 0.15);
    color: #fff;
    border-left: 3px solid var(--tblr-primary, #066fd1);
    padding-left: calc(var(--tblr-navbar-nav-link-padding-x, .75rem) - 3px);
}

/* Submenu items — tighter left padding accounts for the active border. */
.navbar-vertical .nav-sidebar-submenu .nav-item.active > .nav-link {
    padding-left: calc(1rem - 3px);
    opacity: 1;
}

/* --- Acumatica: error message viewer inside the batch-detail modal.
     Acumatica's 422 bodies can be hundreds of lines, so we cap height and
     allow line wrapping rather than horizontal scroll. */
.acumatica-error-block {
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 320px;
    overflow: auto;
}

/* --- Acumatica: technical-details summary needs an obvious affordance.
     Default <summary> renders a tiny native marker that's easy to miss; we hide it
     and use a chevron that rotates 90deg when the accordion is open. */
.acumatica-tech-details summary {
    cursor: pointer;
    list-style: none;
}
.acumatica-tech-details summary::-webkit-details-marker {
    display: none;
}
.acumatica-tech-details summary .icon-chevron {
    transition: transform 0.15s ease;
}
.acumatica-tech-details[open] summary .icon-chevron {
    transform: rotate(90deg);
}

/* --- Acumatica: BR account chips on the error card.
     Yellow-on-yellow was overwhelming when there are dozens of unmapped accounts;
     this is a neutral chip with monospace digits and a per-chip copy button. */
.acumatica-account-chip {
    padding: 0.125rem 0.25rem 0.125rem 0.5rem;
    border: 1px solid var(--tblr-border-color, #dee2e6);
    border-radius: 0.25rem;
    background: var(--tblr-bg-surface-secondary, #f8f9fa);
    font-size: 0.8125rem;
    color: var(--tblr-body-color, #1f2937);
}

/* --- Acumatica: GL lines table can be 100+ rows; keep the header visible while scrolling. */
.acumatica-lines-table {
    max-height: 60vh;
    overflow: auto;
}
.acumatica-lines-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--tblr-bg-surface, #fff);
}
.acumatica-lines-table tfoot td {
    position: sticky;
    bottom: 0;
    z-index: 1;
    background: var(--tblr-bg-surface, #fff);
    box-shadow: inset 0 1px 0 var(--tblr-border-color, #dee2e6);
}

/* --- Readability: WCAG contrast fixes (audited 2026-06-11, 4.5:1 target).
     Dark mode: Tabler's stock primary (#066fd1) and muted gray (#6b7280) sit
     at 2.9–3.7:1 on the dark surfaces — lighten links, outline buttons and
     secondary text only there. Ghost-danger red was 2.9:1 dark / 4.46:1 on
     striped rows in light — nudged both ways. */
[data-bs-theme="dark"] {
    --tblr-link-color: #74b6f3;
    --tblr-link-hover-color: #a3cdf6;
    --tblr-secondary-color: #98a2b3;  /* .text-secondary, footer, inactive tabs */
    --tblr-muted: #98a2b3;
}
[data-bs-theme="dark"] .btn-outline-primary {
    --tblr-btn-color: #74b6f3;
    --tblr-btn-border-color: #74b6f3;
}
[data-bs-theme="dark"] .btn-ghost-danger {
    --tblr-btn-color: #f27d7d;
}
/* These take a literal gray from the vendor build, not --tblr-secondary-color,
   so the variable override above can't reach them. */
[data-bs-theme="dark"] .footer {
    color: #98a2b3;
}
[data-bs-theme="dark"] .nav-tabs .nav-link:not(.active) {
    color: #98a2b3;
}
/* Row-link hover highlight uses --tblr-primary, which is too dim on dark rows. */
[data-bs-theme="dark"] a.row-link:hover .fw-medium {
    color: #74b6f3;
}
.btn-ghost-danger {
    --tblr-btn-color: #c92a2a;  /* stock #d63939 measured 4.46:1 on striped table rows */
}

/* Amber notes (stalled batches, stale balances): Tabler's .text-warning is
   2.1:1 on light surfaces — far too faint for text that carries information.
   Readable amber pair for both themes. */
.note-warning {
    color: #9a6700;
}
[data-bs-theme="dark"] .note-warning {
    color: #f0b357;
}

/* --- Dashboard: staggered card reveal. Each card animates in slightly after
     the previous one (driven by --dash-delay), so the page builds itself
     instead of popping in at once. Respects reduced-motion. */
.dash-reveal {
    opacity: 0;
    animation: dash-reveal 0.45s ease forwards;
    animation-delay: calc(var(--dash-delay, 0) * 70ms);
}
@keyframes dash-reveal {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .dash-reveal { animation: none; opacity: 1; }
}

/* --- Dashboard: pulse dot on the verdict strip. Breathing ring while healthy,
     solid + urgent ring when something needs attention. */
.dash-pulse-dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    flex: 0 0 auto;
    position: relative;
    background: var(--tblr-secondary, #6c7a91);
}
.dash-pulse-dot::after {
    content: '';
    position: absolute;
    inset: -4px;
    border-radius: 50%;
    border: 2px solid currentColor;
    opacity: 0;
}
.dash-pulse-dot[data-tone="ok"]      { background: var(--tblr-success, #2fb344); color: var(--tblr-success, #2fb344); }
.dash-pulse-dot[data-tone="warning"] { background: var(--tblr-warning, #f59f00); color: var(--tblr-warning, #f59f00); }
.dash-pulse-dot[data-tone="danger"]  { background: var(--tblr-danger, #d63939);  color: var(--tblr-danger, #d63939); }
.dash-pulse-dot[data-tone="ok"]::after,
.dash-pulse-dot[data-tone="warning"]::after,
.dash-pulse-dot[data-tone="danger"]::after {
    animation: dash-pulse 2s ease-out infinite;
}
@keyframes dash-pulse {
    0%   { transform: scale(0.6); opacity: 0.8; }
    70%  { transform: scale(1.6); opacity: 0; }
    100% { transform: scale(1.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .dash-pulse-dot::after { animation: none !important; }
}

/* --- Dashboard: provider health pills — status-page style, one dot per provider. */
.dash-provider-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.2rem 0.6rem;
    border: 1px solid var(--tblr-border-color, #dee2e6);
    border-radius: 2rem;
    font-size: 0.8125rem;
    color: var(--tblr-body-color, #1f2937);
    background: var(--tblr-bg-surface, #fff);
}
.dash-provider-pill .dash-provider-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--tblr-success, #2fb344);
}
.dash-provider-pill.is-degraded {
    border-color: var(--tblr-danger, #d63939);
    color: var(--tblr-danger, #d63939);
}
.dash-provider-pill.is-degraded .dash-provider-dot {
    background: var(--tblr-danger, #d63939);
    animation: dash-pulse 1.2s ease-out infinite;
}

/* --- Dashboard: attention chips on the pulse strip — each is a deep link to
     the page where the problem gets fixed. */
.dash-attention-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.3rem 0.75rem;
    border-radius: 2rem;
    font-size: 0.8125rem;
    font-weight: 500;
    text-decoration: none;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.dash-attention-chip:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
    text-decoration: none;
}
.dash-attention-chip.is-warning {
    background: var(--tblr-warning-lt, #fcf0db);
    /* NOT var(--tblr-warning): that amber is 2.1:1 on the -lt background. */
    color: #9a6700;
}
[data-bs-theme="dark"] .dash-attention-chip.is-warning {
    color: #f0b357;
}
.dash-attention-chip.is-danger {
    background: var(--tblr-danger-lt, #fbebeb);
    color: var(--tblr-danger, #d63939);
}

/* --- Bill payment provider form: product/package cards collapse to a one-line
     header so a provider with many products stays scannable. Chevron points
     right when collapsed, down when expanded. Direct-child selector so a
     product's chevron is not affected by its nested package cards. */
.js-toggle-card .icon-chevron {
    transition: transform 0.15s ease;
    transform: rotate(90deg);
}
.card-collapsed > .card-header .js-toggle-card .icon-chevron {
    transform: none;
}
