/* ═══════════════════════════════════════════════════════════════════
   WerkWyse site CSS — small overrides on top of the compiled theme
   (css/werkwyse-bootstrap.css). Loaded after the theme and vendor CSS.
   ═══════════════════════════════════════════════════════════════════ */

/* Column-aligned digits everywhere (tables, totals, rates) */
body {
    font-variant-numeric: tabular-nums;
}

/* Tab hover: fill the full border box instead of Bootstrap's default
   transparent bottom, which looked broken against the tab content */
.nav-tabs {
    --bs-nav-tabs-link-hover-border-color: var(--bs-border-color) var(--bs-border-color) var(--bs-border-color);
}

.min-w-100px {
    min-width: 100px;
}

/* #42 filter offcanvas: the header joins the topbar row-1 band (61px) so
   its bottom border continues row 1's — stock Bootstrap 1rem-padding
   header is 57px, leaving the two lines 4px apart (KHR report). */
.offcanvas-header {
    min-height: 61px;
}

/* #47 dashboard: Chart.js needs an explicit-height wrapper for
   responsive resizing (maintainAspectRatio: false in werkwyse-ui.js). */
.chart-wrap {
    position: relative;
    height: 280px;
}

/* #48: cap long flush lists (the unused-activities card) at chart height. */
.list-scroll {
    max-height: 280px;
    overflow-y: auto;
}

/* Dashboard grid rhythm (demo feedback 2026-08-01): the grid ROWS own
   the vertical spacing (g-4 mb-4 gutters) — cards inside row columns
   carry NO bottom margin. The c-card component's baked-in mb-4 can't be
   attribute-patched (cotton drops extra attrs — the #51 gotcha), so
   it's suppressed here: card mb-4 + row gutter doubled the gap (48px
   next to the rhythm's 24px). !important: Bootstrap's .mb-4 utility
   carries it. */
.dashboard-grid .row > [class*="col"] > .card {
    margin-bottom: 0 !important;
}

/* Completion banner progress track (demo feedback 2026-08-01): the
   theme's card bg == secondary-bg in BOTH modes, so the stock track
   (var(--bs-secondary-bg)) was invisible on the card. The palette's
   secondary stone at 35% alpha reads as a neutral rail in both modes —
   darker on the light card, lighter on the dark one — without a second
   "data" color fighting the teal fill (Firdaus-approved mock). */
.dashboard-grid .progress {
    background-color: rgba(120, 113, 108, 0.35);
}

/* ═══════════════════════════════════════════════════════════════════
   GLOBAL HTMX PROGRESS BAR (#htmx-progress)
   Thin top-of-page bar (YouTube/NProgress style) shown during HTMX
   requests. Created and driven by js/werkwyse-ui.js
   (htmx:beforeRequest → trickle, htmx:afterRequest → complete + fade),
   with a ~120ms delay-to-show so fast swaps stay flicker-free.
   Port of urus-web's mechanism (urus.css / urus-ui.js).

   Orange (not brand teal): contrasts with both the teal accents and
   the neutral chrome in either mode.
   ═══════════════════════════════════════════════════════════════════ */
#htmx-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 0;
    height: 3px;
    background: var(--bs-orange, #fd7e14);
    box-shadow: 0 0 8px var(--bs-orange, #fd7e14);
    z-index: 9999;
    opacity: 0;
    pointer-events: none;
    transition: width 0.2s ease;
}
#htmx-progress.htmx-progress-active {
    opacity: 1;
}
#htmx-progress.htmx-progress-done {
    opacity: 0;
    transition: width 0.2s ease, opacity 0.3s ease 0.1s;
}

/* ═══════════════════════════════════════════════════════════════════
   SHELL (#26) — urus layout port: viewport-locked app shell with a
   240px sectioned sidebar; #id_main is the only content scroll region.
   Rule blocks ported from urus-web's urus.css; all colors via
   var(--bs-*) theme tokens (no new tokens). Drawer/backdrop/active-sync
   behavior lives in js/werkwyse-ui.js.
   ═══════════════════════════════════════════════════════════════════ */
:root {
    --sidebar-width: 240px;
}

.werkwyse-sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    background: var(--bs-secondary-bg);
    border-right: 1px solid var(--bs-border-color);
    transition: margin-left 0.3s ease, transform 0.3s ease;
}

.werkwyse-content-wrapper {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Content scroll region — the page itself never scrolls */
#id_main {
    flex: 1;
    overflow-y: auto;
}

/* #37 item 5 (urus parity): wider horizontal padding around the content
   cards than Bootstrap's 0.75rem container default */
#id_main .container-xxl {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
}

/* #31 toasts/flashes: the channel box lives outside #id_main, so the card
   inset rule doesn't reach it — align it explicitly. Alerts drop their
   default bottom margin (the content region's pt-4 below already provides
   the gap); stacked alerts keep a 1rem gap between themselves. */
#alert-container {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
}
#alert-container .alert {
    margin-bottom: 0;
}
#alert-container .alert + .alert {
    margin-top: 1rem;
}

/* Mobile (< 992px): sidebar becomes a fixed drawer over a backdrop.
   100dvh accounts for the mobile browser URL bar so the pinned
   utilities bar doesn't clip; 100vh fallback for older engines. */
@media (max-width: 991.98px) {
    .werkwyse-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        height: 100vh;
        height: 100dvh;
        z-index: 1040;
        transform: translateX(-100%);
    }
    .werkwyse-sidebar.show {
        transform: translateX(0);
    }
    #sidebar-backdrop {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.5);
        z-index: 1035;
        display: none;
    }
    #sidebar-backdrop.show {
        display: block;
    }
}

/* ═══════════════════════════════════════════════════════════════════
   TOPBAR (#27) — two-row bar ported from urus.css.
   Row 1: hamburger + page title (61px, matches the sidebar brand band)
   Row 2: hoisted contextual tabs (nav-underline, 3px active)
   ═══════════════════════════════════════════════════════════════════ */
#topbar {
    background: var(--bs-secondary-bg);
    flex-shrink: 0;
}
#topbar-row1 {
    display: flex;
    align-items: center;
    min-height: 61px;
    border-bottom: 1px solid var(--bs-border-color);
    padding: 0 1.5rem; /* #37 item 5: match the wider content padding */
    gap: 0.5rem;
}
#topbar-row1 > #topbar-title {
    min-width: 0; /* allow flex truncation — text-truncate needs this */
}

/* #40 (Bootstrap-breadcrumb amendment): the row-1 crumb rides the
   breadcrumb component. The divider is the docs' SVG chevron via the
   component's own CSS var — the #6c757d fill reads on both themes (an
   SVG fill can't follow --bs-breadcrumb-divider-color). Bootstrap
   mutes the ACTIVE item — the inverse of our muted-prefix grammar — so
   it is set back to body color; the h1 inside it must not inflate to
   UA heading styles. */
#topbar-title {
    --bs-breadcrumb-divider: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='%236c757d'/%3E%3C/svg%3E");
}
#topbar-title .breadcrumb-item.active {
    color: var(--bs-body-color);
}
.topbar-crumb-current {
    font: inherit;
    margin: 0;
}

/* Bootstrap ships no min-width utility — the crumb's truncation chain
   (nav → ol → active li) pins it explicitly (utilities convention:
   !important). */
.min-w-0 {
    min-width: 0 !important;
}
#topbar-row2 {
    padding: 0 1.5rem; /* #37 item 5: match the wider content padding */
}

/* nav-underline: primary = selected (matches the sidebar convention) */
.nav-underline {
    --bs-nav-underline-link-active-color: var(--bs-link-color);
}
.nav-underline .nav-link {
    color: var(--bs-body-color);
    padding: 0.75rem 1rem;
}
.nav-underline .nav-link:hover:not(.active) {
    background: var(--bs-tertiary-bg);
    border-bottom-color: var(--bs-border-color);
}
#subnav {
    --bs-nav-underline-border-width: 3px;
    scrollbar-width: none;
}
#subnav::-webkit-scrollbar {
    display: none;
}
#subnav .nav-link.active {
    font-weight: 600;
}
/* #37 (item 4): tab label + count badge never wrap onto two lines */
#subnav .nav-link {
    white-space: nowrap;
}

/* Row-2 right-edge fade on narrow screens: hints at horizontal scroll
   when tabs overflow (mask on the nav itself; invisible when no overflow) */
@media (max-width: 767.98px) {
    #subnav {
        mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
    }
}

/* Desktop: sidebar collapses via negative margin (topbar hamburger) */
@media (min-width: 992px) {
    .werkwyse-sidebar.collapsed {
        margin-left: calc(-1 * var(--sidebar-width));
    }
}

/* Sidebar section group headers (small caps) */
.sidebar-heading {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bs-secondary-color);
    padding: 0.75rem 0.75rem 0.25rem;
    margin-top: 1rem;
    margin-bottom: 0;
}
.sidebar-heading:first-child {
    margin-top: 0;
}

/* ═══════════════════════════════════════════════════════════════════
   BRAND MARK — the wordmark is a generated inline SVG
   (_component/_brand_mark.html, scripts/build-brandmark.py from the
   vendored Dune Rise outlines): tight viewBox centers exactly, no font
   metrics; fill/stroke currentColor flips with data-bs-theme like FA.
   ═══════════════════════════════════════════════════════════════════ */
.brand-mark {
    display: block;
    margin: 0 auto;
    height: auto;
}
.brand-mark-sidebar {
    width: 12rem;
}
.brand-mark-auth {
    width: min(100%, 26rem);
}

/* Teal 61px brand band (matches urus; works in both color modes).
   #37 item 1: centered vertically AND horizontally. 2026-08-03: the
   font-based wordmark (letterspacing could never center exactly)
   became the SVG brand mark above. */
#sidebar-brand {
    min-height: 61px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--bs-primary);
    border-bottom: 1px solid var(--bs-border-color);
}

/* Primary nav — teal text + 3px left indicator when active */
#sidebar-nav .nav-link {
    color: var(--bs-body-color);
    border-left: 3px solid transparent;
    border-radius: 0;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
}
#sidebar-nav .nav-link.active {
    color: var(--bs-link-color);
    font-weight: 600;
    border-left-color: currentcolor;
}
#sidebar-nav .nav-link:hover:not(.active) {
    background: var(--bs-tertiary-bg);
}

/* Utilities bar (user, notifications placeholder, logout) — pinned bottom
   via mt-auto; the theme toggle moved to the topbar (#37 items 2+7) */
#sidebar-utilities {
    min-height: 57px;
}
#sidebar-utilities .flex-fill {
    min-width: 0; /* let text-truncate shrink the user name in the flex row */
}
#sidebar-utilities .nav-link {
    color: var(--bs-body-color);
}
#sidebar-utilities .nav-link:hover {
    background: var(--bs-tertiary-bg);
}

/* Sidebar nav scrolls internally; brand + utilities stay put */
.sidebar-nav-scroll {
    flex: 1;
    overflow-y: auto;
}

/* ═══════════════════════════════════════════════════════════════════
   GLOBAL SEARCH (#36) — topbar search input + results dropdown.
   Ported from urus-web (static/css/urus.css:919-1018); all colors via
   var(--bs-*) theme tokens, so dark mode holds by construction. The
   htmx-indicator display rules are the first in the project — the
   spinner is wired via the input's hx-indicator, so the request class
   lands on .global-search-spinner (not on the input itself).
   ═══════════════════════════════════════════════════════════════════ */

/* --- Wrapper: positions the icon, spinner, and close button over the input --- */
.global-search-wrapper {
    width: 260px;
}
#global-search-mobile.global-search-wrapper {
    width: auto; /* mobile variant grows to fill topbar row 1 (flex-grow-1) */
}

/* --- Input: padded left for icon, right for spinner --- */
.global-search-input {
    padding-left: 2.25rem !important;
    padding-right: 2rem !important;
    background-color: var(--bs-body-bg) !important;
}
/* Remove the browser-native clear (×) button on type="search" */
.global-search-input::-webkit-search-cancel-button {
    -webkit-appearance: none;
}

/* --- Magnifying glass icon (left) --- */
.global-search-icon {
    position: absolute;
    left: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bs-secondary-color);
    font-size: 0.875rem;
    pointer-events: none;
    z-index: 4;
}

/* --- HTMX spinner (right) — htmx adds .htmx-request to the hx-indicator
       target (this span) for the request's lifetime --- */
.global-search-spinner {
    position: absolute;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    z-index: 4;
}
.global-search-spinner .htmx-indicator {
    display: none;
}
.global-search-spinner.htmx-request .htmx-indicator {
    display: inline-block;
}
.global-search-spinner .spinner-border {
    width: 0.75rem;
    height: 0.75rem;
}

/* --- Mobile close button (right, after spinner position) --- */
.global-search-close {
    position: absolute;
    right: 0.25rem;
    top: 50%;
    transform: translateY(-50%);
    z-index: 4;
    background: none;
    border: none;
    padding: 0.25rem;
    color: var(--bs-secondary-color);
    line-height: 1;
    cursor: pointer;
}
.global-search-close:hover {
    color: var(--bs-body-color);
}

/* --- Results dropdown (hidden until the JS sync shows it) --- */
.global-search-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: 0.25rem;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    box-shadow: var(--bs-box-shadow-sm);
    max-height: 400px;
    overflow-y: auto;
    z-index: 1050;
    scrollbar-width: thin;
}

.global-search-group-header {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.5rem 0.75rem 0.25rem;
    color: var(--bs-secondary-color);
    border-bottom: 1px solid var(--bs-border-color-translucent);
}

.global-search-item {
    display: flex;
    flex-direction: column;
    padding: 0.5rem 0.75rem;
    text-decoration: none;
    color: var(--bs-body-color);
    border-bottom: 1px solid var(--bs-border-color-translucent);
}
.global-search-item:last-child {
    border-bottom: none;
}
.global-search-item:hover {
    background: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}

/* ═══════════════════════════════════════════════════════════════════
   CONTENT SLICE 1 (#28) — urus table hierarchy + info tip.
   Rule blocks ported from urus-web's urus.css; all colors via
   var(--bs-*) theme tokens. Applies to tables inside the elevation
   cards (base_list.html, compliance_report.html) and globally to
   thead (e.g. the calendar grid).
   ═══════════════════════════════════════════════════════════════════ */

/* Table visual hierarchy (inside cards on secondary-bg):
   thead (tertiary-bg) > group header (subtle tint) > body rows (card bg)
   Column headers don't wrap — long headers scroll via .table-responsive. */
.table > thead {
    --bs-table-bg: var(--bs-tertiary-bg);
}
.table > thead th {
    white-space: nowrap;
}

/* Group header rows — subtle tint, less prominent than thead.
   Uses emphasis-color-rgb (black in light, white in dark) for auto-adaptation.
   Bootstrap's compile-time .table-secondary doesn't adapt to dark mode
   (Bootstrap issue #39272), so we override for both modes. */
.table-secondary,
.table-light {
    --bs-table-color: var(--bs-body-color);
    --bs-table-bg: rgba(var(--bs-emphasis-color-rgb), 0.06);
    --bs-table-border-color: var(--bs-border-color);
    --bs-table-hover-color: var(--bs-body-color);
    --bs-table-hover-bg: rgba(var(--bs-emphasis-color-rgb), 0.08);
}

/* Tables in cards: horizontal breathing room for first/last cells */
.card .table th:first-child,
.card .table td:first-child {
    padding-left: 1rem;
}
.card .table th:last-child,
.card .table td:last-child {
    padding-right: 1rem;
}

/* Tables in cards: prevent double bottom border when no card-footer */
.card.overflow-hidden .table-responsive:last-child .table > :last-child > tr:last-child > * {
    border-bottom-width: 0;
}

/* Table header — sortable columns use body color, not primary */
#id_table thead a {
    color: var(--bs-body-color);
}
#id_table thead a:hover {
    color: var(--bs-body-color);
}

/* <c-info-tip> metric-definition hover icon (ⓘ) — slightly smaller than
   the label text so it reads as an adornment */
.urus-info-tip {
    cursor: help;
    font-size: 0.8em;
}

/* ═══════════════════════════════════════════════════════════════════
   MODAL DIALOGS (#32) — <dialog class="werkwyse-modal">
   Native <dialog> instead of Bootstrap Modal JS; the outer dialog is
   transparent while Bootstrap's .modal-dialog / .modal-content /
   .modal-header / etc. classes still style the inner content. The
   browser handles focus trap, Escape, and top-layer stacking.

   Bootstrap's .modal-header/.modal-body/.modal-footer read --bs-modal-*
   custom properties that are ONLY defined inside `.modal`. Since we use
   <dialog>, we redeclare the same vars here so the inner padding /
   border / radius render correctly.

   Ported wholesale from urus-web (static/css/urus.css:1063-1109), class
   renamed urus-modal → werkwyse-modal.
   ═══════════════════════════════════════════════════════════════════ */
dialog.werkwyse-modal {
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    max-width: 100vw;
    max-height: 100vh;
    margin: auto;
    overflow: visible;

    --bs-modal-zindex: 1055;
    --bs-modal-width: 500px;
    --bs-modal-padding: 1rem;
    --bs-modal-margin: 0.5rem;
    --bs-modal-color: var(--bs-body-color);
    --bs-modal-bg: var(--bs-body-bg);
    --bs-modal-border-color: var(--bs-border-color-translucent);
    --bs-modal-border-width: var(--bs-border-width);
    --bs-modal-border-radius: var(--bs-border-radius-lg);
    --bs-modal-box-shadow: var(--bs-box-shadow-sm);
    --bs-modal-inner-border-radius: calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));
    --bs-modal-header-padding-x: 1rem;
    --bs-modal-header-padding-y: 1rem;
    --bs-modal-header-padding: 1rem 1rem;
    --bs-modal-header-border-color: var(--bs-border-color);
    --bs-modal-header-border-width: var(--bs-border-width);
    --bs-modal-title-line-height: 1.5;
    --bs-modal-footer-gap: 0.5rem;
    --bs-modal-footer-bg: ;
    --bs-modal-footer-border-color: var(--bs-border-color);
    --bs-modal-footer-border-width: var(--bs-border-width);
}
dialog.werkwyse-modal::backdrop {
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(2px);
}
