/*
 * Project overrides on top of the Thunder AI theme.
 * Mainly dark-mode polish: our Blade pages use hard-coded light Bootstrap
 * utilities (bg-white headers, table-light heads) that must follow the theme
 * surface colour when dark mode is active.
 */
[data-bs-theme="dark"] .card-header.bg-white,
[data-bs-theme="dark"] .card-footer.bg-white,
[data-bs-theme="dark"] .modal-content .bg-white {
    background-color: var(--bs-card-bg) !important;
    color: var(--bs-body-color);
}

[data-bs-theme="dark"] .table-light,
[data-bs-theme="dark"] .table-light > th,
[data-bs-theme="dark"] thead.table-light th {
    --bs-table-bg: var(--bs-card-bg);
    --bs-table-color: var(--bs-body-color);
    color: var(--bs-body-color);
}

[data-bs-theme="dark"] .text-bg-light {
    background-color: var(--bs-card-bg) !important;
    color: var(--bs-body-color) !important;
}

/* Initials avatar in the employee table keeps its primary fill in both modes. */
.avatar.bg-primary { color: #fff !important; }

/* Auth separator: "──── text ────" with a line on each side. */
.text-divider {
    display: flex;
    align-items: center;
    text-align: center;
    gap: 1rem;
}
.text-divider::before,
.text-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background-color: rgba(128, 128, 128, .4);
}

/* Plan-limit upgrade notice (Employees page) — soft branded tint rather
   than a stock warning-yellow alert, since this is a "nudge to upgrade"
   notice, not an error. */
.upgrade-notice-card {
    background: linear-gradient(135deg, color-mix(in srgb, var(--bs-primary) 8%, transparent), color-mix(in srgb, var(--bs-primary) 3%, transparent));
    border: 1px solid color-mix(in srgb, var(--bs-primary) 18%, transparent) !important;
}
.upgrade-notice-icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--bs-primary) 15%, transparent);
    color: var(--bs-primary);
    font-size: 1.15rem;
}
@media (max-width: 575.98px) {
    .upgrade-notice-card .card-body { text-align: center; justify-content: center; }
    .upgrade-notice-card .btn { width: 100%; }
}

/* ==========================================================================
   Premium design-system layer
   --------------------------------------------------------------------------
   Everything below is a pure visual pass on top of the existing Thunder AI
   theme + Bootstrap. Nothing here changes markup structure, routes, or
   behaviour — every admin page extends admin.layouts.app and pulls in
   Bootstrap utility classes, so token + component refinements made once
   here reach all ~40 screens automatically. Kept in `!important`-light,
   additive rules that respect whichever `--bs-primary` skin is active
   (see common.js theme-color switcher) rather than hardcoding a new brand
   colour.
   ========================================================================== */

:root {
    /* Neutral scale — calmer, less saturated than Bootstrap's stock greys,
       closer to the Linear/Vercel/Stripe "cool slate" family. */
    --surface-0: #ffffff;
    --surface-1: #f8f9fb;
    --surface-2: #f1f3f6;
    --border-subtle: #e7e9ee;
    --border-default: #dde1e8;
    --text-strong: #14161a;
    --text-default: #3c4149;
    --text-muted: #6b7280;

    /* Elevation — soft, layered shadows instead of Bootstrap's harsh default. */
    --shadow-xs: 0 1px 2px rgba(16, 24, 40, .04);
    --shadow-sm: 0 1px 3px rgba(16, 24, 40, .06), 0 1px 2px rgba(16, 24, 40, .04);
    --shadow-md: 0 4px 12px rgba(16, 24, 40, .08), 0 2px 4px rgba(16, 24, 40, .04);
    --shadow-lg: 0 12px 32px rgba(16, 24, 40, .12), 0 4px 8px rgba(16, 24, 40, .04);

    /* Motion — fast and consistent, never sluggish. */
    --ease-out: cubic-bezier(.16, 1, .3, 1);
    --dur-fast: 120ms;
    --dur-base: 180ms;
}

[data-bs-theme="dark"] {
    --surface-0: var(--bs-body-bg);
    --surface-1: color-mix(in srgb, var(--bs-body-bg) 92%, white 8%);
    --surface-2: color-mix(in srgb, var(--bs-body-bg) 85%, white 15%);
    --border-subtle: color-mix(in srgb, var(--bs-body-color) 12%, transparent);
    --border-default: color-mix(in srgb, var(--bs-body-color) 18%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}

/* -- Typography ------------------------------------------------------- */

/* No font-family here on purpose. The theme sets it from the `font-*` class on
   <body> (styles.css: body.font-opensans etc.), and its Open Sans webfont is
   already pulled in by styles.css's own @import chain. An 'Inter' declaration
   used to sit here and quietly won, so every page rendered in Inter while the
   markup claimed Open Sans. */
body {
    color: var(--text-default);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-strong);
}

.page-name { letter-spacing: -0.01em; }

small, .small { letter-spacing: 0; }

.text-muted { color: var(--text-muted) !important; }

/* -- Focus & accessibility -------------------------------------------- */

a, button, .btn, .form-control, .form-select, .form-check-input,
.dropdown-toggle, .nav-link, [tabindex] {
    outline-color: var(--bs-primary);
}
a:focus-visible, button:focus-visible, .btn:focus-visible,
.form-control:focus-visible, .form-select:focus-visible,
.nav-link:focus-visible, [tabindex]:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
    border-radius: 4px;
}

/* -- Buttons ------------------------------------------------------------ */

.btn {
    font-weight: 600;
    letter-spacing: 0;
    transition: transform var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out),
                filter var(--dur-fast) var(--ease-out);
}
.btn:hover { filter: brightness(1.04); }
.btn:active { transform: scale(0.97); }
.btn-primary, .btn-success, .btn-danger {
    box-shadow: var(--shadow-xs);
}
.btn-primary:hover, .btn-success:hover, .btn-danger:hover {
    box-shadow: var(--shadow-sm);
}
.btn.disabled, .btn:disabled { transform: none; filter: none; }

/* -- Cards ---------------------------------------------------------------
   Existing pages already use `border-0 shadow-sm` liberally (Plan Limits,
   Billing, Organization Profile) — refine what that resolves to instead of
   changing every blade file's classes. */

.card {
    border-color: var(--border-subtle);
    box-shadow: var(--shadow-sm) !important;
    transition: box-shadow var(--dur-base) var(--ease-out);
}
.card.shadow-sm { box-shadow: var(--shadow-sm) !important; }
a.card:hover, .card[role="button"]:hover, .card-hover:hover {
    box-shadow: var(--shadow-md) !important;
    transform: translateY(-1px);
}

/* -- Badges & alerts — soft "tinted" style instead of solid saturated
   fills, the pattern used by Linear/Stripe/GitHub for status pills. ---- */

.badge {
    font-weight: 600;
    letter-spacing: .01em;
    padding: .4em .7em;
}
.badge.text-bg-primary { background-color: color-mix(in srgb, var(--bs-primary) 14%, transparent) !important; color: var(--bs-primary) !important; }
.badge.text-bg-success { background-color: color-mix(in srgb, var(--bs-success) 14%, transparent) !important; color: var(--bs-success) !important; }
.badge.text-bg-warning { background-color: color-mix(in srgb, var(--bs-warning) 22%, transparent) !important; color: #8a5a00 !important; }
.badge.text-bg-danger  { background-color: color-mix(in srgb, var(--bs-danger) 14%, transparent) !important; color: var(--bs-danger) !important; }
.badge.text-bg-secondary { background-color: var(--surface-2) !important; color: var(--text-muted) !important; }

.alert {
    border: 1px solid transparent;
    box-shadow: var(--shadow-xs);
}

/* -- Tables --------------------------------------------------------------
   Applies to every admin list page (Employees, Departments, Attendance,
   Plan Limits, etc.) since they all reuse `.table`. */

.table > thead {
    background: var(--surface-1);
}
.table > thead th {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-default);
    padding-top: .85rem;
    padding-bottom: .85rem;
}
.table > tbody > tr {
    transition: background-color var(--dur-fast) var(--ease-out);
}
.table-hover > tbody > tr:hover > * {
    background-color: var(--surface-1);
}
.table > :not(caption) > * > * { padding-top: .75rem; padding-bottom: .75rem; }

/* Clickable table rows (e.g. Organizations list) — `.cursor-pointer` was
   referenced in markup but never actually defined, so rows never showed a
   pointer cursor despite being clickable via onclick navigation. */
.cursor-pointer { cursor: pointer; }
.cursor-pointer:hover .fw-semibold { color: var(--bs-primary); }

/* -- Forms ------------------------------------------------------------ */

.form-control, .form-select {
    transition: border-color var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
}
.form-control:focus, .form-select:focus {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--bs-primary) 18%, transparent);
}
.form-control.is-invalid:focus, .form-select.is-invalid:focus {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--bs-danger) 18%, transparent);
}
.form-label { font-weight: 600; font-size: .875rem; color: var(--text-default); }
.form-text { color: var(--text-muted); }

/* -- Dropdown menus ------------------------------------------------------ */

.dropdown-menu {
    border-color: var(--border-subtle);
    box-shadow: var(--shadow-lg) !important;
    animation: dropdown-in var(--dur-base) var(--ease-out);
}
@keyframes dropdown-in {
    /* Opacity-only: Popper already controls this element's `transform` for
       positioning, so animating transform here fights it and causes a
       visible jerk/snap right as the animation finishes. */
    from { opacity: 0; }
    to   { opacity: 1; }
}
.dropdown-item {
    transition: background-color var(--dur-fast) var(--ease-out);
    border-radius: .5rem;
}

/* -- Modals ------------------------------------------------------------ */

.modal-content { box-shadow: var(--shadow-lg); border: none; }
.modal.fade .modal-dialog { transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out); }

/* -- Sidebar -------------------------------------------------------------
   The sidebar is the theme's, verbatim. Its appearance — 245px wide, 24px/20px
   padding, `nav-title` groups with the rotating +/× toggle, plain-text links on
   tree connectors, primary-coloured hover/active — comes entirely from
   styles.css and responsive.css. Nothing here restyles it.

   Two rounds of drift had to be undone to get back to that: an override block
   in this file (270px, connectors off, gradient pill links) and, less visibly,
   direct edits to the vendored `styles.css` itself, which had rewritten
   `.nav-sidebar .nav .nav-link` into a padded pill with a filled active state.
   If the sidebar ever stops matching the reference again, diff
   `public/theme/css/styles.css` against the template before looking here. */

/* The theme's stock width, named so the header rule below can derive from it. */
:root {
    --sidebar-width: 245px;
}

/* The header's logo column ends exactly on the sidebar's outer edge, so the
   divider under it continues the sidebar/content boundary — the same alignment
   the template gets from its hardcoded 221px logo column. The 24px is the
   header container's own `px-md-4` padding, which the sidebar doesn't have.
   (Layout only: this sets no colour, type or spacing inside the header.) */
.header .logo .brand-link {
    width: calc(var(--sidebar-width) - 24px);
    box-sizing: border-box;
}

/* Keyboard focus ring — an accessibility addition, not a restyle. */
.left-sidebar .nav-link:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

/* Off-canvas anchoring, tablet/iPad and below.
   ---------------------------------------------------------------------------
   The theme pins the slide-in panel to the viewport at a hardcoded
   `top: 136px` (its own header + breadcrumbs), and 104px under 768px. Punch
   Axis's header is not that height — and it grows by another row whenever the
   Super Admin impersonation banner is showing — so those constants would leave
   the panel overlapping the breadcrumbs on some screens and floating below them
   on others.

   Anchoring to .content-wrapper instead lands it flush under whatever is above
   it, on every device and with the banner up or down. Everything else about the
   panel — the -250px resting position, 245px/280px widths, 24px padding, the
   overlay and its fade — is still the theme's. */
@media (max-width: 991.98px) {
    .content-wrapper {
        position: relative;
    }

    .left-sidebar {
        position: absolute;
        top: 0;
    }
}

/* -- Header / profile dropdown ------------------------------------------ */

.header { box-shadow: var(--shadow-xs); }

/* Organization section in header */
.header .logo .border-start {
    border-left: 2px solid var(--border-subtle) !important;
    padding-left: 1.2rem !important;
    margin-left: 0.75rem !important;
    transition: all var(--dur-base) var(--ease-out);
}

.header .logo .border-start:hover {
    border-left-color: var(--bs-primary) !important;
}

.header .logo .border-start span {
    font-weight: 500;
    color: var(--text-default);
    transition: color var(--dur-base) var(--ease-out);
}

.header .logo .border-start:hover span {
    color: var(--bs-primary);
}

.header .logo .border-start img {
    transition: box-shadow var(--dur-base) var(--ease-out);
}

.header .logo .border-start:hover img {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--bs-primary) 15%, transparent);
}

.profile-dropdown img { transition: box-shadow var(--dur-fast) var(--ease-out); }
.profile-dropdown:hover img { box-shadow: 0 0 0 3px color-mix(in srgb, var(--bs-primary) 20%, transparent); }

/* -- Billing: "Available upgrade" cards --------------------------------- */

.upgrade-option-card {
    border-color: var(--border-subtle);
    transition: box-shadow var(--dur-base) var(--ease-out),
                border-color var(--dur-base) var(--ease-out),
                transform var(--dur-base) var(--ease-out);
}
.upgrade-option-card:hover {
    border-color: color-mix(in srgb, var(--bs-primary) 35%, var(--border-subtle));
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}
.upgrade-option-icon {
    width: 44px;
    height: 44px;
    font-size: 1.1rem;
    color: var(--bs-primary);
    background: color-mix(in srgb, var(--bs-primary) 12%, transparent);
}

/* -- Layout: fixed header/sidebar, content-area scrolls independently ----
   Header, the impersonation banner, and the breadcrumbs bar stay put;
   only .content-area scrolls. The sidebar gets its own independent
   scroll too (sticky within the remaining height) so a long nav list
   doesn't push the page around.

   Desktop only (>=992px) — mobile's sidebar is a separate off-canvas
   overlay (see responsive.css, position:fixed there already), which is
   already independent of page scroll and is left untouched here. */

html, body {
    height: 100%;
}

body {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

#header,
.impersonation-banner,
.page-breadcrumbs {
    flex-shrink: 0;
}

.content-wrapper {
    flex: 1 1 auto;
    min-height: 0; /* let this flex item shrink below its content size so overflow can actually kick in */
    overflow: hidden;
}

.content-area {
    height: 100%;
    overflow-y: auto;
}

/* No desktop rule for .left-sidebar here on purpose. It used to be pinned with
   `position: sticky; height: 100%`, which is the theme's job to decide — and the
   theme's own `position: relative; overflow-y: auto` already gives the same
   result inside this shell, because the sidebar is a stretched flex child of
   .content-wrapper and so fills it and scrolls its own overflow. */

/* -- Skeleton loader primitive --------------------------------------------
   Reusable shimmer block: <div class="skeleton" style="width:120px;height:1rem"></div>
   Not yet wired into every async fetch — dropped in here so it's available
   to adopt page-by-page without another CSS pass. */

.skeleton {
    display: block;
    border-radius: .4rem;
    background: linear-gradient(90deg, var(--surface-1) 25%, var(--surface-2) 37%, var(--surface-1) 63%);
    background-size: 400% 100%;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
@keyframes skeleton-shimmer {
    0%   { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* -- Empty states ----------------------------------------------------------
   Utility classes for a consistent "nothing here yet" layout: icon circle +
   message + CTA. Opt-in per page (see admin.plan-limits.index for a usage
   note) — not auto-applied so existing empty-state markup isn't touched
   sight-unseen. */

.empty-state { text-align: center; padding: 3rem 1.5rem; }
.empty-state-icon {
    width: 56px; height: 56px; margin: 0 auto 1rem;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-1);
    color: var(--text-muted);
    font-size: 1.5rem;
}
.empty-state-title { font-weight: 700; color: var(--text-strong); margin-bottom: .25rem; }
.empty-state-body { color: var(--text-muted); max-width: 32rem; margin: 0 auto 1.25rem; }

/* -- Monthly Attendance Matrix -------------------------------------------
   Every employee × every day of the month. Sticky employee column so it
   stays visible while scrolling horizontally through a full month. Kept
   to plain table markup (no per-cell JS) since a large roster × 31 days
   is already hundreds of cells — anything heavier per cell would hurt
   render performance. */

.attendance-matrix-wrapper {
    overflow-x: auto;
    border-top: 1px solid var(--border-subtle);
}
.attendance-matrix {
    border-collapse: separate;
    border-spacing: 0;
    font-size: .8rem;
    width: max-content;
}
.attendance-matrix th,
.attendance-matrix td {
    padding: .45rem .4rem;
    text-align: center;
    white-space: nowrap;
    border-bottom: 1px solid var(--border-subtle);
}
.attendance-matrix thead th {
    background: var(--surface-1);
    font-weight: 600;
    color: var(--text-muted);
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    position: sticky;
    top: 0;
    z-index: 1;
}
.attendance-matrix .att-emp-col {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--surface-0);
    text-align: left;
    min-width: 180px;
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    box-shadow: 1px 0 0 var(--border-subtle);
}
.attendance-matrix thead .att-emp-col {
    z-index: 3;
    background: var(--surface-1);
}
.attendance-matrix .att-day-col { min-width: 38px; }
.attendance-matrix .att-summary-col { min-width: 64px; }
.attendance-matrix .att-today { background: color-mix(in srgb, var(--bs-primary) 8%, transparent); }
.attendance-matrix .att-weekend:not(.att-today) { background: var(--surface-1); }
.attendance-matrix tbody tr:hover td:not(.att-emp-col) { background: var(--surface-1); }
.attendance-matrix tbody tr:hover td.att-emp-col { background: var(--surface-1); }

/* Collapsed weekend block: consecutive Sat/Sun day-columns merge into one
   cell (colspan across the run's dates, rowspan down every employee row)
   with a centered vertical "Weekend" label, instead of repeating the word
   in every row × every weekend column. */
.attendance-matrix .att-weekend-block {
    background: var(--surface-1);
    border-left: 1px dashed var(--border-subtle);
    border-right: 1px dashed var(--border-subtle);
    vertical-align: middle;
}
.attendance-matrix tbody tr:hover td.att-weekend-block { background: var(--surface-1); }
.att-weekend-label {
    writing-mode: sideways-lr;
    text-orientation: mixed;
    display: inline-block;
    color: var(--text-muted);
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    white-space: nowrap;
}

.att-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 26px;
    height: 22px;
    padding: 0 .25rem;
    border-radius: .4rem;
    font-size: .66rem;
    font-weight: 700;
}
/* Status badge tints. These pairs (base colour + mix percentage) are mirrored
   in AttendanceMatrixService::STATUS_META, which flattens them to concrete hex
   for the PDF and Excel exports — neither can run color-mix(). Change one and
   change the other, or a download stops matching the screen. */
.att-present { background: color-mix(in srgb, var(--bs-success) 18%, transparent); color: var(--bs-success); }
.att-late { background: color-mix(in srgb, var(--bs-warning) 26%, transparent); color: #8a5a00; }
.att-halfday { background: color-mix(in srgb, #0dcaf0 22%, transparent); color: #087990; }
.att-working { background: color-mix(in srgb, var(--bs-primary) 18%, transparent); color: var(--bs-primary); }
.att-pending-review { background: color-mix(in srgb, var(--bs-danger) 26%, transparent); color: var(--bs-danger); }
.att-leave { background: color-mix(in srgb, #6f42c1 18%, transparent); color: #6f42c1; }
.att-holiday { background: color-mix(in srgb, var(--bs-primary) 16%, transparent); color: var(--bs-primary); }
.att-absent { background: color-mix(in srgb, var(--bs-danger) 16%, transparent); color: var(--bs-danger); }
.att-shortfall { background: color-mix(in srgb, var(--bs-warning) 18%, transparent); color: #8a5a00; }
/* ─────────────────────────────────────────────────────────────────────────────
 * Template component styles
 *
 * The theme styles list tables through per-<th> utility classes
 * (`py-2 fw-medium small text-uppercase`, repeated on every heading in the HTML
 * reference). Encoding it once here means a column added later cannot come out
 * in the wrong style, and our Blade tables stay free of presentational noise.
 * ───────────────────────────────────────────────────────────────────────────── */
.content-area .table > thead > tr > th,
.modal .table > thead > tr > th {
    padding-top: .5rem;
    padding-bottom: .5rem;
    font-size: .8125rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--text-muted, var(--bs-secondary-color));
    white-space: nowrap;
}

/* Row actions: borderless icon buttons that sit quietly until hovered, so the
 * page's primary action stays the only thing competing for attention. */
.table .btn-link {
    color: var(--bs-secondary-color);
    text-decoration: none;
    line-height: 1;
}
.table .btn-link:hover { color: var(--bs-primary); }
.table .btn-link.text-danger:hover { color: var(--bs-danger) !important; }
.table .btn-link:disabled { opacity: .4; }
.table .btn-link .bi { font-size: 1rem; vertical-align: middle; }

/* Filter panel above a list (the template's `border-bg` block). Its background
 * is the theme's border colour, which is the intended subtle tint. */
.border-bg { background: var(--bs-border-color); }

/* DataTables' own controls, aligned with the theme's form controls rather than
 * the plugin's stock look. */
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    padding: .35rem .75rem;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
}
.dataTables_wrapper .dataTables_filter input:focus,
.dataTables_wrapper .dataTables_length select:focus {
    outline: 0;
    border-color: var(--bs-primary);
}
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter { color: var(--bs-secondary-color); font-size: .875rem; }

/* Cards holding a full-bleed table: the table's own borders provide the
 * separation, so the header sheds its bottom rule. */
.card > .card-header + .table-responsive > .table > thead > tr > th { border-top: 0; }

/* Grouped list rows (the attendance log's day headers and their column
 * headings). They live inside <tbody>, so they can't inherit the <thead> rule
 * above — and they were previously Bootstrap's `table-light`, which needed its
 * own dark-mode patch and never matched the theme's own tables. */
.table > tbody > tr.table-group-row > td {
    background: var(--bs-tertiary-bg);
    border-top: 1px solid var(--bs-border-color);
    /* The group row spans every column, so its content aligns to the table's
       own left edge — flush with the rows below it, never inheriting a
       centred alignment from a surrounding utility class. */
    text-align: left;
}
.table > tbody > tr.table-group-row:hover > td { background: var(--bs-secondary-bg); }

.table > tbody > tr.table-subhead-row > th {
    padding-top: .5rem;
    padding-bottom: .5rem;
    font-size: .8125rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--text-muted, var(--bs-secondary-color));
    white-space: nowrap;
    background: transparent;
}

/* ==========================================================================
   Work timer — the employee dashboard's live "remaining working time".
   --------------------------------------------------------------------------
   Deliberately quiet: one large tabular figure and a line of explanation. It
   owns a column of the dashboard's Today card — it is the only thing on that
   screen that moves, and the reason most people open it — with the punch
   times and status beside it in the same block, since app-ui.js refreshes all
   of them from the one poll that card owns.
   ========================================================================== */

/* The ring: an SVG circle whose stroke is dashed at exactly its own
   circumference, so shifting the dash offset sweeps the arc. The face is
   layered over it rather than placed inside the SVG — real text reflows and
   inherits theme colours, where <text> in an SVG does neither. */
.work-ring {
    position: relative;
    width: 6.25rem;
    height: 6.25rem;
    margin: 0 auto;
}
/* On the Today card the ring gets a column to itself, so it is drawn large
   enough to read across a room rather than at the size of an inline figure. */
.work-ring--lg {
    width: 8.5rem;
    height: 8.5rem;
}
.work-ring--lg .work-timer-value { font-size: 1.4rem; }
.work-ring--lg .work-timer-seconds { font-size: .78rem; }

.work-ring svg {
    width: 100%;
    height: 100%;
    /* Start the arc at 12 o'clock instead of 3. */
    transform: rotate(-90deg);
}
.work-ring circle {
    fill: none;
    stroke-width: 8;
    stroke-linecap: round;
}
.work-ring-track { stroke: var(--bs-secondary-bg); }
.work-ring-bar {
    /* Painted in whichever `text-*` tone the state carries, so the arc, the
       figure inside it and the state dot below always agree. */
    stroke: currentColor;
    transition: stroke-dashoffset var(--dur-base) var(--ease-out);
}

.work-ring-face {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1.1;
}

.work-timer-value {
    font-size: 1.05rem;
    font-weight: 700;
    /* Tabular figures so a ticking countdown doesn't shuffle its own width
       once a second — the single most distracting thing a live number can do. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

/* The seconds, kept small and muted: they prove the figure is live without
   pulling the eye away from the hours and minutes that actually matter. */
.work-timer-seconds {
    font-size: .7rem;
    font-weight: 600;
    color: var(--text-muted, var(--bs-secondary-color));
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    min-height: .85rem;
}

/* The status dot next to the heading. Only the running state animates, and
   only gently; a paused or finished timer has nothing to report. */
.work-timer-dot {
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background: var(--bs-secondary-color);
    flex: 0 0 auto;
}
.work-timer--running .work-timer-dot { background: var(--bs-primary); animation: work-timer-pulse 2s var(--ease-out) infinite; }
.work-timer--paused .work-timer-dot { background: var(--bs-warning); }
.work-timer--complete .work-timer-dot { background: var(--bs-success); }
.work-timer--closed .work-timer-dot,
.work-timer--pending_review .work-timer-dot { background: var(--bs-danger); }

@keyframes work-timer-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .35; }
}

/* Respect a reduced-motion preference: the dot still colours the state, it
   just stops moving. */
@media (prefers-reduced-motion: reduce) {
    .work-timer--running .work-timer-dot { animation: none; }
    .work-ring-bar { transition: none; }
}

/* ==========================================================================
   Employee profile images
   --------------------------------------------------------------------------
   Two pieces: `.app-avatar` (the <x-ui.avatar> component, used on every
   surface that shows a face) and `.profile-image-field` (the uploader in the
   Add/Edit Employee forms). Both size themselves from an inline width/height
   so one rule serves a 28px table avatar and a 96px profile header alike.
   ========================================================================== */

.app-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    overflow: hidden;
    border-radius: 50%;
    font-weight: 600;
    line-height: 1;
    /* The photo is a square JPEG, so a circular mask is all that's needed —
       but a name-initials fallback still has to be centred in the same disc. */
    background: var(--bs-primary);
    color: #fff;
    user-select: none;
}

.app-avatar img {
    width: 100%;
    height: 100%;
    /* `cover` rather than `contain`: the stored file is already centre-cropped
       square, and cover keeps a non-square legacy file from letterboxing. */
    object-fit: cover;
    display: block;
}

.app-avatar--light-blue { background: var(--bs-light-blue, #dbeafe); color: #14161a; }
.app-avatar--light-purple { background: var(--bs-light-purple, #ede9fe); color: #14161a; }

/* -- The uploader in the Add / Edit Employee forms --------------------- */

.profile-image-field {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

/* Sits behind the avatar preview so a photo that hasn't loaded (or an empty
   slot) still reads as a deliberate frame rather than a gap. */
.profile-image-preview {
    border: 2px solid var(--border-subtle, var(--bs-border-color));
    background: var(--surface-2, #f1f3f6);
}

.profile-image-actions {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    min-width: 12rem;
    flex: 1 1 14rem;
}

/* The real <input type="file"> stays in the layout (so validation styling and
   keyboard focus behave normally) but compact, next to the preview. */
.profile-image-field input[type="file"] {
    font-size: .85rem;
}

.profile-image-hint {
    font-size: .78rem;
    color: var(--text-muted, var(--bs-secondary-color));
}

/* "Remove photo" is only meaningful once there is one; JS toggles this. */
.profile-image-remove[hidden] { display: none !important; }

/* ==========================================================================
   Employee Profile page
   --------------------------------------------------------------------------
   Support for the profile components in resources/views/components/profile/,
   which reproduce the Thunder AI "Employee Profile" screen. The look itself
   comes from the vendored theme (`.border-bg`, `.image-input`, `.bg-light-*`,
   `.nav-pills`, timeline.css); only the few things the kit assumes but never
   actually ships live here.
   ========================================================================== */

/* A flex child will not shrink below its content by default, so a long email
   in a profile field or timeline entry pushes the row wider than its column
   instead of truncating. Both components rely on this. */
.profile-field,
.timeline-item .min-w-0 {
    min-width: 0;
}

.profile-field > p {
    /* Long values (an email, a designation) wrap rather than overflow the
       card they sit in — these cards are narrow at lg and below. */
    overflow-wrap: anywhere;
}

/* The framed avatar in the profile header. The theme's `.image-input` only
   handles background-image sizing, because the kit puts a CSS background
   there; ours holds a real <img> (or the initials disc), so it needs to be a
   box of its own. */
.image-input:has(> .app-avatar) {
    line-height: 0;
}

/* The tab strip's decorative connector hangs below the bar; without this the
   strip's own stacking context can clip it on some browsers. */
.nav-pills + .tab-content,
.border-bg > .nav-pills {
    position: relative;
}

/* Timeline entries carry a card of their own on wide screens; keep the gap
   from doubling up with the list's own bottom padding on the last one. */
.timeline-item:last-child {
    padding-bottom: 1em;
}

/* The tinted pill badges the template uses for roles and statuses read as
   washed-out on dark. Lift the text so it keeps its contrast. */
[data-bs-theme="dark"] .badge.bg-opacity-25 {
    --bs-bg-opacity: 0.28;
}

/* ==========================================================================
   Attendance Log
   --------------------------------------------------------------------------
   The month-at-a-time listing: a toolbar carrying the month picker, a row of
   stat tiles, and one collapsible row per calendar day.

   Naming note — everything here is `.att-toolbar` / `.att-month-*` /
   `.att-day-*` / `.att-stat*` / `.att-help*`. The Monthly Attendance Matrix
   further up already owns the bare `.att-present`, `.att-late`, `.att-absent`
   … tints and they are NOT scoped to `.attendance-matrix`, so nothing below
   may use those names. The two sets are also deliberately independent: the
   matrix's badges grade one employee on one day and must keep matching
   AttendanceMatrixService::STATUS_META for the PDF/Excel exports, whereas
   these grade a whole day across the roster and reach no export at all.
   ========================================================================== */

/* -- Toolbar ------------------------------------------------------------ */

.att-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    padding: 1.25rem 1.5rem;
    border-bottom: 1px solid var(--border-subtle);
}

/* Three tracks so the month picker sits optically centred rather than
   wherever the title's length happens to leave it. */
@media (min-width: 1200px) {
    .att-toolbar {
        display: grid;
        grid-template-columns: 1fr auto 1fr;
    }
    .att-toolbar-actions { justify-self: end; }
}

.att-toolbar-title { margin-right: auto; }

.att-toolbar-actions {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin-bottom: 0;
}

.att-status-select {
    min-width: 11.5rem;
    border-radius: .6rem;
}

.att-export-btn {
    white-space: nowrap;
    border-radius: .6rem;
}

/* -- Month navigation ----------------------------------------------------
   Shared: <x-ui.month-picker> renders this on the Attendance Log toolbar and
   in the dashboard's Monthly Attendance card header. The `--sm` modifier is
   for the latter, where it sits in a row of small buttons. */

.att-month-nav {
    display: flex;
    align-items: center;
    gap: .4rem;
}

.att-month-nav--sm .att-month-arrow {
    width: 1.95rem;
    height: 1.95rem;
    font-size: .8rem;
}
.att-month-nav--sm .att-month-btn {
    min-width: 10.5rem;
    padding: .3rem .65rem;
    font-size: .8125rem;
}

.att-month-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.35rem;
    height: 2.35rem;
    border-radius: .6rem;
    border: 1px solid var(--border-default);
    background: var(--surface-0);
    color: var(--text-default);
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                color var(--dur-fast) var(--ease-out);
}
.att-month-arrow:hover {
    background: var(--surface-1);
    border-color: color-mix(in srgb, var(--bs-primary) 35%, var(--border-default));
    color: var(--bs-primary);
}
/* Kept in the layout rather than removed, so the picker doesn't shift
   sideways on the last month of history. */
.att-month-arrow.is-disabled {
    opacity: .35;
    pointer-events: none;
}

.att-month-btn {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
    min-width: 13rem;
    padding: .5rem .85rem;
    border-radius: .6rem;
    border: 1px solid var(--border-default);
    background: var(--surface-0);
    color: var(--text-strong);
    font-weight: 600;
    transition: border-color var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
}
.att-month-btn:hover,
.att-month-btn[aria-expanded="true"] {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--bs-primary) 14%, transparent);
}
.att-month-btn-icon { color: var(--bs-primary); }
.att-month-btn-label { flex: 1 1 auto; text-align: left; }
.att-month-btn-caret {
    font-size: .75rem;
    color: var(--text-muted);
    transition: transform var(--dur-fast) var(--ease-out);
}
.att-month-btn[aria-expanded="true"] .att-month-btn-caret { transform: rotate(180deg); }

/* -- Month dropdown ----------------------------------------------------- */

.att-month-menu {
    width: 20rem;
    max-width: calc(100vw - 2rem);
    padding: .75rem;
    border-radius: .9rem;
}

.att-month-search {
    position: relative;
    margin-bottom: .6rem;
}
.att-month-search .form-control {
    padding-right: 2.2rem;
    border-radius: .6rem;
}
/* The magnifier is decorative — the input is already labelled — so it sits
   behind pointer events rather than stealing clicks meant for the field. */
.att-month-search .bi-search {
    position: absolute;
    top: 50%;
    right: .75rem;
    transform: translateY(-50%);
    color: var(--text-muted);
    font-size: .85rem;
    pointer-events: none;
}

.att-month-heading {
    margin: .25rem .25rem .35rem;
    font-size: .78rem;
    font-weight: 700;
    color: var(--text-strong);
}

.att-month-list {
    max-height: 17rem;
    overflow-y: auto;
}

.att-month-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .5rem .55rem;
    border-radius: .5rem;
    text-decoration: none;
    color: var(--text-default);
    font-size: .875rem;
    transition: background-color var(--dur-fast) var(--ease-out);
}
.att-month-option:hover { background: var(--surface-1); color: var(--text-strong); }
.att-month-option.is-selected {
    background: color-mix(in srgb, var(--bs-primary) 10%, transparent);
    color: var(--bs-primary);
    font-weight: 600;
}
/* The JS filter toggles `hidden`; these are flex items, so the attribute
   needs help to win. */
.att-month-option[hidden],
.att-month-all[hidden],
.att-month-empty[hidden] { display: none !important; }

.att-month-option-label { white-space: nowrap; }

.att-month-tag {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .75rem;
    font-weight: 600;
    white-space: nowrap;
}
.att-month-tag .bi { font-size: .6rem; }
.att-month-tag--current { color: var(--bs-primary); }
.att-month-tag--done { color: var(--bs-success); }

.att-month-empty {
    margin: 0;
    padding: .75rem .55rem;
    font-size: .82rem;
    color: var(--text-muted);
}

.att-month-all {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    width: 100%;
    margin-top: .5rem;
    padding: .55rem;
    border: 0;
    border-top: 1px solid var(--border-subtle);
    border-radius: 0 0 .5rem .5rem;
    background: transparent;
    color: var(--bs-primary);
    font-size: .82rem;
    font-weight: 600;
}
.att-month-all:hover { background: var(--surface-1); }

/* Why the list stops where it does. Sits below "View all months" so it reads
   as the end of the range rather than a warning about it. */
.att-month-floor {
    display: flex;
    align-items: flex-start;
    gap: .4rem;
    margin: .5rem 0 0;
    padding: .5rem .55rem 0;
    border-top: 1px solid var(--border-subtle);
    font-size: .72rem;
    line-height: 1.45;
    color: var(--text-muted);
}
.att-month-floor .bi { color: var(--bs-primary); margin-top: .1rem; }

/* -- Stat tiles ---------------------------------------------------------- */

.att-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: .85rem;
    padding: 1.25rem 1.5rem;
}

.att-stat {
    display: flex;
    align-items: flex-start;
    gap: .8rem;
    padding: 1rem;
    border-radius: .85rem;
    border: 1px solid var(--border-subtle);
    background: var(--surface-0);
}

.att-stat-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: .7rem;
    font-size: 1.05rem;
}

.att-stat-value {
    margin: 0;
    font-size: 1.45rem;
    font-weight: 700;
    line-height: 1.15;
    color: var(--text-strong);
    /* A figure that changes between months shouldn't change the tile's
       width with it. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}
.att-stat-label {
    margin: .1rem 0 0;
    font-size: .82rem;
    font-weight: 600;
    color: var(--text-default);
}
.att-stat-caption {
    margin: 0;
    font-size: .72rem;
    color: var(--text-muted);
}

/* Fixed hues rather than `--bs-primary` derivatives: this row reads as a set
   of five distinct measures, and it must keep doing so whichever skin the
   theme-colour switcher is on. */
.att-stat--emerald .att-stat-icon { background: color-mix(in srgb, #10b981 15%, transparent); color: #047857; }
.att-stat--green   .att-stat-icon { background: color-mix(in srgb, #22c55e 15%, transparent); color: #15803d; }
.att-stat--amber   .att-stat-icon { background: color-mix(in srgb, #f59e0b 18%, transparent); color: #b45309; }
.att-stat--rose    .att-stat-icon { background: color-mix(in srgb, #f43f5e 15%, transparent); color: #be123c; }
.att-stat--violet  .att-stat-icon { background: color-mix(in srgb, #8b5cf6 15%, transparent); color: #6d28d9; }

/* -- Day rows ------------------------------------------------------------ */

.att-days { border-top: 1px solid var(--border-subtle); }

.att-day { border-bottom: 1px solid var(--border-subtle); }
/* "Load More" unfolds these; the whole month is always in the DOM. */
.att-day--folded { display: none; }

/* A <button> so the row is keyboard-operable, reset back to a plain block so
   nothing of the button look survives. */
.att-day-head {
    display: grid;
    /* date · weekday · status chips (elastic) · turnout · chevron */
    grid-template-columns: 10.5rem 8rem 1fr auto auto;
    align-items: center;
    gap: .75rem;
    width: 100%;
    padding: .85rem 1.5rem;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: left;
    text-decoration: none;
    color: var(--text-default);
    transition: background-color var(--dur-fast) var(--ease-out);
}
.att-day-head:hover { background: var(--surface-1); color: var(--text-default); }
.att-day-head:focus-visible { outline-offset: -2px; }

.att-day--today > .att-day-head {
    background: color-mix(in srgb, var(--bs-primary) 5%, transparent);
    box-shadow: inset 3px 0 0 var(--bs-primary);
}

.att-day-date {
    font-weight: 700;
    color: var(--text-strong);
    white-space: nowrap;
}

.att-day-today {
    display: inline-block;
    margin-left: .4rem;
    padding: .1rem .4rem;
    border-radius: .35rem;
    background: color-mix(in srgb, var(--bs-primary) 14%, transparent);
    color: var(--bs-primary);
    font-size: .65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    vertical-align: middle;
}

.att-day-weekday {
    color: var(--text-muted);
    font-size: .875rem;
    white-space: nowrap;
}

/* Status tallies for the day — "4 Absent", "1 Half Day". Variable width by
   nature, so no min-width: the row is quiet on a day with nothing to flag. */
.att-day-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
}

.att-day-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: .3rem .65rem;
    border-radius: .5rem;
    font-size: .75rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Day-level tints. Independent of the matrix's `.att-present` family on
   purpose (see the header note): these summarise a whole day across the
   roster and feed no export, so they follow the screen design rather than
   STATUS_META. */
.att-day-badge--present    { background: color-mix(in srgb, #22c55e 16%, transparent); color: #15803d; }
.att-day-badge--late       { background: color-mix(in srgb, #f59e0b 22%, transparent); color: #b45309; }
.att-day-badge--half-day   { background: color-mix(in srgb, #f59e0b 20%, transparent); color: #b45309; }
.att-day-badge--weekly-off { background: color-mix(in srgb, #fb7185 18%, transparent); color: #c2410c; }
.att-day-badge--holiday    { background: color-mix(in srgb, #8b5cf6 16%, transparent); color: #6d28d9; }
.att-day-badge--leave      { background: color-mix(in srgb, #6f42c1 15%, transparent); color: #6f42c1; }
.att-day-badge--working    { background: color-mix(in srgb, var(--bs-primary) 15%, transparent); color: var(--bs-primary); }
.att-day-badge--pending    { background: color-mix(in srgb, #ef4444 18%, transparent); color: #b91c1c; }
.att-day-badge--absent     { background: color-mix(in srgb, #ef4444 15%, transparent); color: #b91c1c; }

.att-day-count {
    justify-self: end;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-size: .85rem;
    font-weight: 600;
    color: var(--text-default);
    white-space: nowrap;
}
.att-day-count .bi { color: var(--text-muted); }

.att-day-chevron {
    color: var(--text-muted);
    font-size: .9rem;
    transition: transform var(--dur-fast) var(--ease-out);
}
.att-day-head:not(.collapsed) .att-day-chevron { transform: rotate(90deg); }

.att-day-body {
    padding: 0 1.5rem 1rem;
    background: var(--surface-1);
}
.att-day-body .att-day-table {
    background: var(--surface-0);
    border-radius: .6rem;
    overflow: hidden;
}

.att-day-empty {
    padding: .9rem 0 .25rem;
    font-size: .85rem;
    color: var(--text-muted);
}

/* Narrow screens: the five-track grid stops being readable well before it
   stops fitting, so it becomes a wrapping stack with the chevron pinned. */
@media (max-width: 991.98px) {
    .att-day-head {
        grid-template-columns: 1fr auto;
        row-gap: .35rem;
    }
    .att-day-date { grid-column: 1; }
    .att-day-chevron { grid-row: 1; grid-column: 2; justify-self: end; }
    .att-day-weekday,
    .att-day-chips,
    .att-day-count { grid-column: 1 / -1; justify-self: start; }
    .att-day-body { padding-inline: 1rem; }
    .att-toolbar,
    .att-stats { padding-inline: 1rem; }
}

/* -- Load more + footnote ------------------------------------------------ */

.att-load-more {
    display: flex;
    justify-content: center;
    padding: .35rem 0;
    border-bottom: 1px solid var(--border-subtle);
}
.att-load-more .btn-link {
    font-weight: 600;
    font-size: .875rem;
    text-decoration: none;
}

.att-footnote {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .9rem 1.5rem;
}
.att-footnote-text {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    font-size: .8rem;
    color: var(--text-muted);
}
.att-footnote-text .bi { color: var(--bs-primary); }

/* -- "How it works" panel ------------------------------------------------ */

.att-help {
    display: grid;
    grid-template-columns: auto repeat(3, 1fr);
    gap: 1.5rem;
    padding: 1.35rem 1.5rem;
    border: 1px solid var(--border-subtle);
    border-radius: 1rem;
    background: color-mix(in srgb, var(--bs-primary) 4%, var(--surface-0));
}
@media (max-width: 991.98px) {
    .att-help { grid-template-columns: 1fr; gap: 1rem; }
}

.att-help-lead {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-weight: 700;
    color: var(--bs-primary);
    line-height: 1.25;
}
.att-help-lead .bi { font-size: 1.1rem; }

.att-help-item {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
}

.att-help-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.35rem;
    height: 2.35rem;
    border-radius: .65rem;
    font-size: .95rem;
}
.att-help-icon--green  { background: color-mix(in srgb, #22c55e 15%, transparent); color: #15803d; }
.att-help-icon--violet { background: color-mix(in srgb, #8b5cf6 15%, transparent); color: #6d28d9; }
.att-help-icon--teal   { background: color-mix(in srgb, #14b8a6 15%, transparent); color: #0f766e; }

.att-help-title {
    margin: 0 0 .15rem;
    font-size: .875rem;
    font-weight: 700;
    color: var(--text-strong);
}
.att-help-body {
    margin: 0;
    font-size: .78rem;
    line-height: 1.5;
    color: var(--text-muted);
}

/* -- Dark mode -----------------------------------------------------------
   The tints above are already translucent so they sit correctly on a dark
   surface; only the opaque chrome needs re-pointing at the theme's own
   surface variables, and the badge text needs lifting off its own tint. */

[data-bs-theme="dark"] .att-month-arrow,
[data-bs-theme="dark"] .att-month-btn,
[data-bs-theme="dark"] .att-stat {
    background: var(--bs-card-bg);
    color: var(--bs-body-color);
    border-color: var(--border-default);
}
[data-bs-theme="dark"] .att-day-body { background: color-mix(in srgb, var(--bs-body-bg) 60%, var(--bs-card-bg)); }
[data-bs-theme="dark"] .att-day-body .att-day-table { background: var(--bs-card-bg); }
[data-bs-theme="dark"] .att-help { background: color-mix(in srgb, var(--bs-primary) 8%, var(--bs-card-bg)); }
[data-bs-theme="dark"] .att-stat-value,
[data-bs-theme="dark"] .att-day-date,
[data-bs-theme="dark"] .att-help-title,
[data-bs-theme="dark"] .att-month-heading { color: var(--bs-body-color); }

[data-bs-theme="dark"] .att-day-badge--present    { background: color-mix(in srgb, #22c55e 24%, transparent); color: #86efac; }
[data-bs-theme="dark"] .att-day-badge--late,
[data-bs-theme="dark"] .att-day-badge--half-day   { background: color-mix(in srgb, #f59e0b 26%, transparent); color: #fcd34d; }
[data-bs-theme="dark"] .att-day-badge--weekly-off { background: color-mix(in srgb, #fb7185 26%, transparent); color: #fda4af; }
[data-bs-theme="dark"] .att-day-badge--holiday,
[data-bs-theme="dark"] .att-day-badge--leave      { background: color-mix(in srgb, #8b5cf6 26%, transparent); color: #c4b5fd; }
[data-bs-theme="dark"] .att-day-badge--pending,
[data-bs-theme="dark"] .att-day-badge--absent     { background: color-mix(in srgb, #ef4444 26%, transparent); color: #fca5a5; }

[data-bs-theme="dark"] .att-stat--emerald .att-stat-icon { color: #6ee7b7; }
[data-bs-theme="dark"] .att-stat--green   .att-stat-icon { color: #86efac; }
[data-bs-theme="dark"] .att-stat--amber   .att-stat-icon { color: #fcd34d; }
[data-bs-theme="dark"] .att-stat--rose    .att-stat-icon { color: #fda4af; }
[data-bs-theme="dark"] .att-stat--violet  .att-stat-icon { color: #c4b5fd; }
[data-bs-theme="dark"] .att-help-icon--green  { color: #86efac; }
[data-bs-theme="dark"] .att-help-icon--violet { color: #c4b5fd; }
[data-bs-theme="dark"] .att-help-icon--teal   { color: #5eead4; }
