/* ── Public layout ───────────────────────────────────────────────────────────
   The template's app.css applies `.navbar { position: fixed; top: 0 }` globally.
   We override it so the public header is sticky (in normal flow) instead.
   Inline style on the <nav> is the primary override; this is the safety net.
────────────────────────────────────────────────────────────────────────────── */
[data-layout="public"] body {
    padding-top: 0 !important;
    margin-top: 0 !important;
}

[data-layout="public"] header .navbar {
    position: sticky !important;
    top: 0 !important;
    z-index: 1030;
}

/* ── Auth layout ─────────────────────────────────────────────────────────────
   No body offset needed — the auth wrapper uses min-height: 100dvh directly.
────────────────────────────────────────────────────────────────────────────── */
[data-layout="auth"] body {
    padding-top: 0 !important;
    margin-top: 0 !important;
}

/* ── Legacy safety net ───────────────────────────────────────────────────────
   Any page that somehow lacks a data-layout gets no extra body padding.
   The template's own mechanism handles admin pages via [data-layout="semibox"...].
────────────────────────────────────────────────────────────────────────────── */
html:not([data-layout]) body {
    padding-top: 0;
}

/* ── Notification bell animation ──────────────────────────────────────────────
   The bell icon swings while there are unread notifications. The class is
   toggled by the unread-count poller in _AdminLayout. */
@keyframes bell-ring {
    0%   { transform: rotate(0); }
    5%   { transform: rotate(18deg); }
    10%  { transform: rotate(-16deg); }
    15%  { transform: rotate(14deg); }
    20%  { transform: rotate(-12deg); }
    25%  { transform: rotate(8deg); }
    30%  { transform: rotate(-6deg); }
    35%  { transform: rotate(3deg); }
    40%  { transform: rotate(0); }
    100% { transform: rotate(0); }
}

#notifBellBtn .bell-ring {
    display: inline-block;
    transform-origin: top center;
    animation: bell-ring 2s ease-in-out infinite;
}

/* ── Action menus / dropdowns above all panes ─────────────────────────────────
   Table "Actions" dropdowns (and any nested submenus) must render above cards,
   table panes and other components, and must not be clipped by the table
   wrapper's overflow. z-index is handled here; clipping is handled by
   dropdown-fixed-strategy.js, which positions menus with Popper's "fixed"
   strategy (anchored to the viewport) instead of toggling the wrapper's
   overflow — toggling overflow:visible on a scrolled wrapper resets its
   scrollLeft to 0, which snapped horizontally-scrolled tables (e.g. Fellowship
   Centers) back to the left the instant a dropdown opened. */
.dropdown-menu {
    z-index: 1090 !important;
}

.dropdown-menu.show,
.dropdown-menu .dropdown-menu,
.dropdown-submenu .dropdown-menu {
    z-index: 1091 !important;
}

/* ── Profile dropdown ─────────────────────────────────────────────────────────
   Portalled to <body> while open (see topbar-dropdown-portal.js) to escape the
   stacking context created by .main-topbar's own position:fixed + z-index —
   without that, no z-index on the menu itself can lift it above sibling
   elements outside the topbar (modals, offcanvas, etc). This rule keeps it on
   top of everything once it's a direct child of <body>. */
.dropdown-menu.topbar-dropdown-portal,
.dropdown-menu.topbar-dropdown-portal.show {
    z-index: 2000 !important;
}

/* ── Bootstrap switch fix ─────────────────────────────────────────────────────
   The admin theme's .form-switch rules assume a custom label-drawn switch
   (input hidden via width:0/height:0, label painted as the pill via ::after)
   but never finish styling it, while also outranking Bootstrap's own native
   switch on selector specificity. With box-sizing:border-box, a 0×0 input
   plus its 1px border renders as a barely-visible 2×2px box — "Status"
   toggles (WhatsApp/SMS Attendance settings, Permission matrix) all show this.
   Restore Bootstrap's real switch appearance everywhere in the app. */
.form-switch .form-check-input[type="checkbox"] {
    width: 2.5em !important;
    height: 1.25em !important;
    visibility: visible !important;
}

/* The same theme rule also pins any <label> inside .form-switch to a fixed
   3rem width (meant for the unfinished custom switch's pill track), which
   squeezes a real text label like "Enabled" into two wrapped lines. Let the
   label size to its actual text. */
.form-switch .form-check-label {
    width: auto !important;
    white-space: nowrap;
}

/* ── Forced Change Password modal backdrop ────────────────────────────────────
   Bootstrap's own backdrop opacity is driven by a CSS custom property
   (--dx-backdrop-opacity) that resolves to 0 in this theme rather than the
   usual 0.5, so a plain inline style.opacity set from JS gets computed away —
   only a class rule with matching/higher specificity reliably wins here. */
.modal-backdrop.force-change-password-backdrop {
    opacity: 0.85 !important;
}

/* ── Sortable table headers ───────────────────────────────────────────────────
   Headers in sortable tables get a pointer cursor and an asc/desc arrow once
   sorted. Tables/headers opted out via [data-no-sort] are unaffected. */
table:not([data-no-sort]) thead th {
    cursor: pointer;
    user-select: none;
}

table:not([data-no-sort]) thead th[data-no-sort] {
    cursor: default;
}

thead th.sort-asc::after {
    content: " \2191"; /* ↑ */
    font-size: 0.8em;
    opacity: 0.7;
}

thead th.sort-desc::after {
    content: " \2193"; /* ↓ */
    font-size: 0.8em;
    opacity: 0.7;
}

/* ── Follow-up timeline (New Members) ─────────────────────────────────────────*/
.nm-timeline {
    list-style: none;
    margin: 0;
    padding: 0 0 0 1rem;
    border-left: 2px solid var(--bs-border-color, #dee2e6);
}

.nm-timeline-item {
    position: relative;
    padding: 0 0 1rem 1rem;
}

.nm-timeline-item:last-child {
    padding-bottom: 0;
}

.nm-timeline-dot {
    position: absolute;
    left: -1.45rem;
    top: 0.2rem;
    width: 0.7rem;
    height: 0.7rem;
    border-radius: 50%;
    background: var(--bs-primary, #0d6efd);
    border: 2px solid var(--bs-body-bg, #fff);
}

/* ── Mobile responsiveness ────────────────────────────────────────────────────
   The admin template is Bootstrap-based and mostly responsive; these rules
   smooth the rough edges on phones (≤ md) without altering desktop layout. */

/* Any table that isn't already in a scroll wrapper still scrolls horizontally
   instead of breaking the page width on small screens. */
@media (max-width: 991.98px) {
    .table-card,
    .table-responsive {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

@media (max-width: 767.98px) {
    /* Tighter gutters so cards use the full width on phones. */
    .card-body { padding: 0.85rem; }
    .card-header { padding: 0.75rem 0.85rem; }

    /* Headings scale down a touch. */
    h4, .h4 { font-size: 1.15rem; }
    h5, .h5 { font-size: 1.05rem; }

    /* Card headers with a title + action button stack neatly. */
    .card-header.d-flex { flex-wrap: wrap; gap: 0.5rem; }

    /* Page heading action buttons wrap under the title. */
    .page-heading { flex-wrap: wrap; gap: 0.5rem; }

    /* Full-width primary action buttons in card headers read better on phones. */
    .card-header .btn-primary { white-space: nowrap; }

    /* Topbar brand text is dropped on phones — the icon plus the sidebar
       toggle, church switcher, bell, dark-mode toggle and avatar don't all
       fit next to a ~200px wordmark in a ~375px viewport. */
    .main-topbar .logos span { display: none; }

    /* Topbar church switcher must not force horizontal overflow. */
    #churchSwitcher { min-width: 110px !important; }
    #churchSwitchForm { max-width: 38vw; }

    /* Filter / inline-edit groups with hard-coded widths become flexible. */
    .input-group[style*="width"] { width: 100% !important; }
    input[type="date"].form-control-sm[style*="width"] { width: 100% !important; }

    /* Modals get a small margin so they never touch screen edges. */
    .modal-dialog { margin: 0.5rem; }

    /* Denser, more legible tables on phones. */
    .table { font-size: 0.85rem; }
    .table > :not(caption) > * > * { padding: 0.4rem 0.5rem; }

    /* Notification offcanvas fills the screen width on phones. */
    #notificationPanel { width: 100vw !important; }

    /* Button toolbars / action groups wrap instead of overflowing. */
    .d-flex.gap-2 > .btn,
    .btn-group { flex-wrap: wrap; }

    /* Modal footers opt into flex-nowrap for a single desktop row (e.g. the
       Add/Edit Attendance modal's Testimony/Voice Testimony + Cancel/Save
       buttons) — on phones that pushes Cancel/Save off-screen with no way to
       reach them, so let the footer wrap into two rows instead. */
    .modal-footer.flex-nowrap { flex-wrap: wrap !important; row-gap: 0.5rem; }

    /* Content area uses tighter side padding on phones. */
    .page-wrapper .container-fluid { padding-left: 0.75rem; padding-right: 0.75rem; }
}

/* Avoid the iOS "zoom on focus" by keeping form font ≥ 16px on phones. */
@media (max-width: 575.98px) {
    .form-control, .form-select { font-size: 16px; }
}

/* ── Mobile sidebar: always overlay, never push content ───────────────────────
   The vendor toggle button (main.js) is built for a desktop collapse/expand
   pattern: clicking it removes the `sidebar-hidden` body class entirely, which
   also re-enables [data-layout="semibox"]'s unconditional
   `.page-wrapper { margin-left: calc(sidebar + semibox-width) }` rule. On a
   phone that squeezes all page content into a sliver next to the drawer
   instead of the drawer overlaying on top of it.

   Fix: at mobile/tablet widths, force the content area to stay full-width
   *regardless* of `sidebar-hidden`/toggle state — the drawer's own visibility
   is controlled separately (by #main-sidebar.show, toggled by
   mobile-sidebar.js, which also intercepts the toggle button before the
   vendor handler runs). A backdrop dims the page while the drawer is open. */
@media (max-width: 991.98px) {
    [data-layout="semibox"] .page-wrapper {
        margin-left: 0 !important;
    }

    /* Drawer must render above everything, including the topbar. */
    .main-sidebar.show {
        z-index: 1060;
    }

    #mobileSidebarBackdrop {
        display: none;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 1055; /* above topbar (1003) and content, below the drawer (1060) */
    }

    #mobileSidebarBackdrop.show {
        display: block;
    }
}

/* ── Stacked responsive table (.table-stack) ──────────────────────────────────
   On phones, a wide table collapses into one card per row with label:value
   pairs (label comes from each cell's data-label), so it fits the screen
   without horizontal scrolling. */
@media (max-width: 767.98px) {
    .table-stack thead { display: none; }

    .table-stack,
    .table-stack tbody,
    .table-stack tr,
    .table-stack td {
        display: block;
        width: 100%;
    }

    .table-stack tr {
        margin-bottom: 0.75rem;
        border: 1px solid var(--bs-border-color, #dee2e6);
        border-radius: 0.5rem;
        padding: 0.25rem 0.6rem;
        background: var(--bs-body-bg, #fff);
    }

    .table-stack td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 1rem;
        border: 0 !important;
        padding: 0.4rem 0.1rem;
        text-align: right;
        white-space: normal;
        word-break: break-word;
    }

    .table-stack td::before {
        content: attr(data-label);
        font-weight: 600;
        color: var(--bs-secondary-color, #6c757d);
        text-align: left;
        flex: 0 0 40%;
    }

    /* Cells without a label (e.g. the "no records" row) span full width. */
    .table-stack td:not([data-label])::before { content: none; }
    .table-stack td:not([data-label]) { justify-content: center; }
}
