
/* ---------- COLORS ---------- */
:root {
    --primary: #1b3a1e;
    --secondary: #2e7d32;
    --accent: #d4af37;
    --light: #dddddd;
    --success: #91ff00;
    --transparent: rgba(221,221,221,0);

    --log-ERROR: #77052b;
    --log-WARNING: #913b01;
    --log-ALERT: #38086e;
    --log-INFO: #8cb6dd;
    --log-DEBUG: #102836;
    --log-UNIT: #03373785;
    --log-default-color: #4242426c;
    --heatmap-empty-cell: #c1c5cb;

    --light-accent: rgba(38,59,71,0.3);
    --bg: #dddddd;
    --big-bg: linear-gradient(130deg, var(--light), rgba(255,255,255,0.7));
    --content-bg: #ffffff;
    --text: #222;
    --surface: #f2f2f2;
    --antique: rgba(38,59,71,0.5);
    --light-antique: rgba(64, 84, 95, 0.5);
    --highlight: rgba(27,58,30,0.5);
    --link-highlight: rgba(0, 49, 44, 0.7);
    --outset: rgba(109, 62, 0, 0.5);
    --info-color: rgba(2, 73, 66, 0.7);
    --info-shadow: rgba(3,255,230,0.1);
    --debug-color: rgba(131, 143, 150, 0.8);
    --debug-shadow: rgba(38,59,71,0.1);
    --warning-color: rgba(34, 20, 1, 0.6);
    --warning-shadow: rgba(255,145,3,0.2);
    --alert-color: rgba(68, 68, 2, 0.8);
    --alert-shadow: rgba(246,247,117,0.2);
    --error-color: rgba(102, 2, 2, 0.7);
    --error-shadow: rgba(255,8,8,0.1);
    --grad-error: linear-gradient(130deg, rgba(236,80,40,0.6), rgba(224,93,32,0.3));
    --grad-warning: linear-gradient(130deg, rgba(236,144,40,0.6), rgba(202,146,42,0.3));
    --grad-ready: linear-gradient(130deg, rgba(29,141,1,0.6), rgba(53,184,140,0.3));
    --grad-deny: linear-gradient(130deg, rgba(122,0,30,0.6), rgba(180,62,7,0.3));
    --tint: linear-gradient(130deg, rgba(150,150,150,0.7), rgba(221,221,221,0.7));
    --sidebar-link-bg: linear-gradient(to right, rgba(150,150,150,0.28), rgba(150,150,150,0));
    --sidebar-link-bg-hover: linear-gradient(to right, rgba(150,150,150,0.48), rgba(150,150,150,0));
    --nav-bg: linear-gradient(130deg, rgba(255,255,255,0.6), var(--light));
    --p-bg: linear-gradient(130deg, rgba(255,8,8,0.2), rgba(0,0,0,0));
    --q-bg: linear-gradient(130deg, rgba(0,0,0,0.3), rgba(0,0,0,0));
    --r-bg: linear-gradient(130deg, rgba(255,8,8,0.6), rgba(255,8,8,0.3));
    --s-bg: linear-gradient(130deg, #cfcfcf, #ffffff);
    --t-bg: linear-gradient(130deg, rgba(46,125,50,0.18), rgba(150,150,150,0.12));
    --t-bg-x: linear-gradient(130deg, rgba(46,125,50,0.1), rgba(150,150,150,0.08));
    --u-bg: linear-gradient(130deg, rgba(255,145,3,0.6), rgba(255,145,3,0.3));
    --v-bg: linear-gradient(130deg, rgba(150,150,150,0.4), rgba(150,150,150,0.1));
    --w-bg: linear-gradient(130deg, var(--light), white);
    /* Was rgba(0,0,0,0.3) in the upper-left corner - noticeably darker than the
       rest of the surface (var(--light)), which dulled contrast for text sitting
       near that corner (e.g. the modal). Whitened so the surface reads evenly. */
    --x-bg: linear-gradient(130deg, rgba(255,255,255,0.95), var(--light));
    --y-bg: linear-gradient(130deg, var(--light), rgba(0,0,0,0.08));
    --z-bg: linear-gradient(130deg, var(--light), rgba(255,255,255,0.8));
    --grad-success: linear-gradient(130deg, #b7f764, #7ba83f);
    --grad-blue: linear-gradient(130deg, #b3cddb, #6b93aa);
    --ready-color: rgba(29,141,1,0.9);
}

.dark {
    --heatmap-empty-cell: #e5e7eb;
    --light-accent: rgba(221,221,221,0.3);
    --bg: #1f2031;
    --big-bg: linear-gradient(130deg, var(--primary), rgb(0,0,0));
    --content-bg: #40434e2f;
    --text: #dddddd;
    --surface: rgba(255,255,255,0.03);
    --antique: rgba(150,150,150,0.5);
    --light-antique: rgba(175, 175, 175, 0.5);
    --highlight: rgba(46,125,50,0.5);
    --link-highlight: rgba(3,255,230,0.7);
    --outset: rgba(255,145,3,0.5);
    --info-color: rgba(3,255,230,0.7);
    --info-shadow: rgba(3,255,230,0.1);
    --debug-color: rgba(38,59,71,0.8);
    --debug-shadow: rgba(38,59,71,0.1);
    --warning-color: rgba(255,145,3,0.7);
    --warning-shadow: rgba(255,145,3,0.1);
    --alert-color: rgba(246,247,117,0.7);
    --alert-shadow: rgba(246,247,117,0.1);
    --error-color: rgba(255, 87, 87, 0.7);
    --error-shadow: rgba(255,8,8,0.1);
    --grad-error: linear-gradient(130deg, rgba(236,80,40,0.6), rgba(224,93,32,0.3));
    --grad-warning: linear-gradient(130deg, rgba(236,144,40,0.6), rgba(202,146,42,0.3));
    --grad-ready: linear-gradient(130deg, rgba(29,141,1,0.6), rgba(53,184,140,0.3));
    --grad-deny: linear-gradient(130deg, rgba(255,0,64,0.6), rgba(255,115,0,0.5));
    /* Surface tokens (tint/nav/w/x/y/z-bg) used to lean on --primary (navy) or a
       vivid blue (rgba(60,104,225,...)) as their dark stop. That's fine for the
       page's outer backdrop (--big-bg still uses --primary), but on the content
       surfaces text actually sits on - cards, panels, the modal - it read as an
       overload of blue/purple. Swapped those stops for --content-bg (the neutral
       dark grey already used for card backgrounds) or plain dark greys instead. */
    --tint: linear-gradient(130deg, rgba(160,160,170,0.35), rgba(70,70,78,0.5));
    --sidebar-link-bg: linear-gradient(to right, rgba(255,255,255,0.14), rgba(255,255,255,0));
    --sidebar-link-bg-hover: linear-gradient(to right, rgba(255,255,255,0.24), rgba(255,255,255,0));
    --nav-bg: linear-gradient(130deg, rgba(0,0,0,0.7), var(--content-bg));
    --p-bg: linear-gradient(130deg, rgba(255,8,8,0.2), rgba(255,8,8,0.1));
    --q-bg: linear-gradient(130deg, rgba(0,0,0,0.7), rgba(0,0,0,0.3));
    --r-bg: linear-gradient(130deg, rgba(255,8,8,0.3), rgba(255,8,8,0.1));
    --s-bg: linear-gradient(130deg, #25283d, #40434e);
    --t-bg: linear-gradient(130deg, rgba(46,125,50,0.15), rgba(150,150,150,0.1));
    --t-bg-x: linear-gradient(130deg, rgba(46,125,50,0.08), rgba(150,150,150,0.05));
    --u-bg: linear-gradient(130deg, rgba(255,145,3,0.3), rgba(255,145,3,0.1));
    --v-bg: linear-gradient(130deg, rgba(3,255,230,0.3), rgba(3,255,230,0.1));
    --w-bg: linear-gradient(130deg, var(--content-bg), rgba(0,0,0,0.8));
    --x-bg: linear-gradient(130deg, rgba(0,0,0,0.7), var(--content-bg));
    --y-bg: linear-gradient(130deg, rgba(0,0,0,0.7), #33363d);
    --z-bg: linear-gradient(130deg, rgba(150,150,150,0.15), var(--content-bg));
    --grad-success: linear-gradient(130deg, #3f6e00, #254100);
    --grad-blue: linear-gradient(130deg, #516977, #263b47);
}

body {
    margin: 0;
    padding: 0;
    background: var(--big-bg);
    color: var(--text);
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

body.no-scroll {
    overflow: hidden;
}

#pageLoader {
    position: fixed;
    top: 0;
    left: 0;
    height: 3px;
    width: 0%;
    background: #6e40c9;
    z-index: 300;
    transition: width 0.3s ease-out, opacity 0.4s ease;
}

#pageLoader.loading {
    opacity: 1;
}

#pageLoader.done {
    opacity: 0;
}

/* General pulsating ring animation using scale */
.pulse-ring {
  transform-origin: center;
  animation: pulse 3s infinite ease-in-out;
}

/* Different durations and delays for dramatic effect */
.ring1 { animation-duration: 3s; animation-delay: 0s; }
.ring2 { animation-duration: 4s; animation-delay: 0.5s; }
.ring3 { animation-duration: 2.5s; animation-delay: 0.8s; }
.ring4 { animation-duration: 5s; animation-delay: 0.2s; }

/* Pulse keyframes using transform scale */
@keyframes pulse {
  0% { transform: scale(1); stroke-opacity: 0.6; }
  50% { transform: scale(1.3); stroke-opacity: 0.3; }
  100% { transform: scale(1); stroke-opacity: 0.6; }
}

hr {
    border-top: 2px solid var(--accent);
    margin: 0 auto 20px auto;
}

nav {
    position: sticky;
    top: 0;
    width: 100%;
    background: var(--nav-bg);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    border-bottom: 1px solid rgba(255,255,255,0.1);
    padding: 5px;
    display: flex;
    justify-content: space-between;
    align-items: right;
    z-index: 140;
}

.body-content {
    margin-bottom: 50px;
}

.dashboard-body {
    margin-bottom: 50px;
    padding: 10px;
    /* Overridden to the sidebar's actual width via the #adminSidebar ~ .dashboard-body
       rules below, on admin/ pages only - stays 0 here for dashboard/'s sidebar-less
       pages, so anything sizing itself off the viewport (e.g. .activity-column) can
       account for the space the sidebar actually takes instead of assuming 100vw. */
    --sidebar-offset: 0px;
}

.footer-bar {
    position: fixed;
    bottom: 0;
    width: 100%;
    background: var(--x-bg);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    border-bottom: 1px solid rgba(255,255,255,0.1);
    padding: 5px;
    display: flex;
    justify-content: space-between;
    align-items: right;
    z-index: 140;
}

/* Left and Right Containers */
.nav-left, .nav-right {
    display: flex;
    align-items: center;
    gap: 10px;
}

.nav-center {
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    font-size: 18px;
    font-weight: 600;
}

#lightbox-overlay {
    position: fixed;
    inset: 0;
    display: none;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    z-index: 500;
    backdrop-filter: blur(10px);
    background: var(--x-bg);
    opacity: 0;
    transition: opacity .35s ease;
}

#lightbox-overlay.show {
    display: flex;
    opacity: 1;
}

.lightbox-close {
    position: absolute;
    top: 15px;
    right: 20px;
    color: var(--text);
    font-size: 40px;
    cursor: pointer;
    transition: opacity .2s ease;
}

.lightbox-close:hover {
    opacity: .6;
}

/* Fade + zoom animation */
#lightbox-image {
    max-width: 90vw;
    max-height: 70vh;
    border-radius: 10px;

    opacity: 0;
    transform: scale(0.95);
    transition: transform .35s ease, opacity .35s ease;
}

#lightbox-overlay.show #lightbox-image {
    opacity: 1;
    transform: scale(1);
}

#lightbox-caption {
    color: var(--text);
    margin-top: 15px;
    text-align: center;
    font-size: 1rem;
    max-width: 80vw;
}

.lightbox-prev,
.lightbox-next {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(0,0,0,0.2);
    border: none;
    color: rgba(223, 223, 223, 0.3);
    font-size: 20px;
    cursor: pointer;
    padding: 8px 12px;
    border-radius: 6px;
    z-index: 20;
    transition: background .2s ease;
}

/* Positions */
.lightbox-prev {
    left: 10px;
}
.lightbox-next {
    right: 10px;
}

.lightbox-prev:hover,
.lightbox-next:hover {
    background: rgba(0,0,0,0.5);
}

@media (max-width: 768px) {
    .lightbox-prev,
    .lightbox-next {
        display: none;
    }
}

/* Thumbnails wrapper */
#lightbox-thumbs-wrapper {
    width: 90vw;
    margin-top: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

/* Thumbnails container */
#lightbox-thumbs {
    overflow-x: auto;
    white-space: nowrap;

    display: flex;
    gap: 10px;
    padding: 10px;
    scroll-behavior: smooth;

    max-width: 80vw;
}

/* Single thumbnail */
.lightbox-thumb {
    width: 70px;
    height: 70px;
    object-fit: cover;
    object-position: center;
    border-radius: 6px;
    cursor: pointer;
    opacity: 0.6;
    transition: opacity .2s, transform .2s;
}

/* Active thumbnail highlight */
.lightbox-thumb.active {
    opacity: 1;
    outline: 2px solid var(--dark);
    transform: scale(1.1);
}

#lightbox-thumbs::-webkit-scrollbar {
    height: 8px;
}

#lightbox-thumbs::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 5px;
}

#lightbox-thumbs::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.4);
    border-radius: 5px;
}

#lightbox-thumbs {
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.4) rgba(255,255,255,0.15);
}

.icon-btn {
    border-radius: 5px;
    position: relative;
    font-size: 22px;
    align-items: center;
    padding: 5px;
    color: var(--text);
    cursor: pointer;
    display: flex;
    justify-content: center;
    gap: 5px;
    border-radius: 5px;
    background: var(--bg);
    z-index: 1;
    transition: transform 0.2s ease, background 0.25s ease;
    min-width: 0;
}

.admin-icon-btn {
    background: var(--info-shadow);
    color: var(--link-highlight);
}

.icon-btn > i {
    flex-shrink: 0;
}

/* Same reasoning as .act-btn-view span - min-width:0 overrides the flex item
   default of min-width:auto so the label can shrink below its content width and
   ellipsis instead of wrapping onto a second line when the row runs out of room. */
.icon-btn span {
    font-size: 15px;
    margin: 0 5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Gradient border wrapper */
.icon-btn::before {
    content: "";
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    background: var(--tint);
    -webkit-mask:
        linear-gradient(#dddddd 0 0) content-box,
        linear-gradient(#dddddd 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    pointer-events: none;
    z-index: -1;
}

.icon-btn:hover {
    background: var(--tint);
}

.theme-toggler {
    position: fixed;
    right: 10px;
    top: 10px;
    width: 35px;
    height: 35px;
    border: solid var(--transparent) 1px;
}

.info-block {
    margin: 5px 0;
    color: var(--alert-color);
}

.success-block {
    margin: 5px 0;
    color: var(--info-color);
}

.warning-block {
    margin: 5px 0;
    color: var(--warning-color);
}

.error-block {
    padding: 5px 10px;
    margin: 5px 0 20px 0;
    color: var(--error-color);
    background: var(--error-shadow);
    border-radius: 5px;
}

.hamburger-menu {
    position: fixed;
    top: 0;
    left: 0;
    width: 300px;
    height: 100vh;
    background: var(--w-bg);
    backdrop-filter: blur(8px);
    box-shadow: 5px 0 25px rgba(0,0,0,0.25);
    padding: 10px;
    z-index: 300;
    transform: translateX(-100%);
    transition: transform 0.3s ease;
}

.hamburger-menu.open {
    transform: translateX(0);
}

.hamburger-menu ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.hamburger-menu li {
    margin-bottom: 5px;
}

.hamburger-menu a {
    display: block;
    padding: 10px;
    border-radius: 5px;
    color: inherit;
    text-decoration: none;
}

.hamburger-menu a:hover {
    background: rgba(255,255,255,0.08);
}

.resource-link {
  text-decoration: none;
  color: var(--info-color);
}

.resource-link:hover {
  /* --highlight is tuned for decorative use (borders, underlines) and fails
     contrast as text color, especially in dark mode (~1.8:1). --link-highlight
     is the token already used for text in this role (.admin-link). */
  color: var(--link-highlight);
}

/* KYC document links (inspectReseller.php's View panel) - own class rather than
   .resource-link since that one's shared site-wide by plain text/nav links that
   don't pair an icon with truncatable text. */
.kyc-doc-link {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    padding: 5px 10px;
    border-radius: 5px;
    text-decoration: none;
    color: var(--info-color);
    /* Yellow-toned (--alert-*), not the teal --info-shadow used by .list-block -
       kept visually distinct so these don't read as the same component. */
    background: linear-gradient(130deg, var(--alert-shadow), transparent);
}

.kyc-doc-link:hover {
    /* --link-highlight is barely distinguishable from --info-color in light
       mode, and identical to it in dark mode, so text alone can't carry the
       hover state - --text always reads as a clear, theme-correct shift (near-
       black on light, near-white on dark) against the teal/cyan resting color.
       Background stays the same --alert-shadow tone used at rest (identical
       value in both themes, so it can't blow out in dark mode) - the fade to
       transparent just fills in solid instead of tapering off, which alone
       reads clearly as "hovered". */
    color: var(--text);
    background: var(--alert-shadow);
}

.kyc-doc-link i {
    flex-shrink: 0;
}

.kyc-doc-link span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.envt-link, .more-dropdown .widget-link, .hamburger-menu .envt-link {
    display: block;
    text-align: left;
    text-decoration: none;
    color: var(--text);
    padding: 10px;
    margin-bottom: 5px;
    border-radius: 5px;
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    transition: background 0.2s ease, color 0.2s ease;
    line-height: 1;
}

.admin-link {
    color: var(--link-highlight);
}

.envt-link:hover,
.more-dropdown .widget-link:hover{
    background: var(--tint);
    color: var(--light-antique);
}

.widgets-row {
    position: fixed;
    top: 44px;
    left: 0;
    width: 100%;
    height: 45px;
    display: flex;
    justify-content: flex-start;
    gap: 5px;
    padding: 0;
    background: var(--z-bg);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    border-top: 1px solid rgba(255,255,255,0.1);
    border-bottom-left-radius: 15px;
    border-bottom-right-radius: 15px;
    z-index: 160;
}

.widgets-row-placeholder {
    height: 50px;
}

.widget {
    position: relative;
    background: transparent;
    border-radius: 0;
    padding: 5px;
    cursor: pointer;
    font-weight: 500;
    color: var(--text);
    transition: color 0.2s ease;
    text-align: center;
}

.widget:hover {
    color: var(--primary);
}

/* Active tab underline */
.widget.active::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--highlight);
    border-radius: 2px 2px 0 0;
}

.widget-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    text-decoration: none;
    color: var(--text);
    padding: 5px 10px;
    border-radius: 5px;
    transition: background 0.2s ease, color 0.2s ease;
    line-height: 1;
}

.widget-link i {
    font-size: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: middle;
}

.widget-link span {
    font-size: 15px;
    white-space: nowrap;
}

/* nav-script.js's overflow logic (updateOverflowWidgets) measures each .widget's natural
   offsetWidth to decide what moves into the "More" dropdown - if a label is allowed to wrap
   onto a second line first, that measurement no longer reflects the widget's real single-line
   width, so items wrap in place instead of overflowing cleanly. Nowrap keeps that measurement
   honest; .widget itself must not shrink below its content's width either, or the browser
   would wrap/clip it before the row is ever detected as overflowing. */
.widget {
    flex-shrink: 0;
}

.widget-link:hover {
    background: var(--tint);
    color: var(--light-antique);
}

.more-menu {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 5px;
    border-radius: 5px;
    background: var(--bg);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    border: 1px solid rgba(255,255,255,0.1);
    transition: background 0.2s ease, color 0.2s ease;
    z-index: 260;
}

.more-menu:hover {
    background: var(--tint);
    color: var(--text);
}

.more-menu i {
    font-size: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.more-dropdown {
    display: none;
    /* Positioned by nav-script.js, which portals this element to <body>. It must
       NOT stay nested in .more-menu / .widgets-row - both set backdrop-filter and
       so each becomes a "backdrop root", which would starve this element's own
       backdrop-filter (it would sample the thin nav bar, not the page behind it).
       As a direct child of <body> its backdrop root is the page, so the glass works. */
    position: fixed;
    border-bottom-left-radius: 5px;
    border-bottom-right-radius: 5px;
    /* Glassmorphism: a translucent tint (not the opaque --w-bg) is what lets the
       backdrop-filter actually frost the page behind it, so the menu reads as its
       own surface and its items stay legible instead of competing with the
       content underneath. Blur + saturate = the frosted-glass look. */
    background: rgba(255, 255, 255, 0.6);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    backdrop-filter: blur(16px) saturate(160%);
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-top: solid var(--highlight) 1px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.28);
    flex-direction: column;
    min-width: 250px;
    padding: 10px 10px 5px 10px;
    z-index: 240;
}

.dark .more-dropdown {
    background: rgba(31, 32, 49, 0.62);
    border-color: rgba(255, 255, 255, 0.14);
}

.more-dropdown.open {
    display: flex;
}

/* ---------- ADMIN SIDEBAR (Lists) ---------- */
.admin-sidebar {
    position: fixed;
    top: 89px;
    /* Pulled up 30px so its top edge tucks behind .widgets-row (z-index below it,
       see below) instead of butting flush against it - flush left the widgets-row's
       own border-bottom-left-radius exposing a small curved gap of page background
       at the sidebar's top-left corner, which read as unfinished/unplanned. */
    margin-top: -30px;
    left: 0;
    width: 220px;
    height: calc(100vh - 59px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--z-bg);
    backdrop-filter: blur(5px);
    border-right: 1px solid rgba(255,255,255,0.1);
    box-shadow: 5px 0 15px rgba(0,0,0,0.1);
    transition: width 0.2s ease;
    /* Below .widgets-row's z-index (160), so the widgets-row's rounded corner
       renders on top of the sidebar's flat top edge instead of beside it. */
    z-index: 150;
}

.sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 45px 10px 10px;
    white-space: nowrap;
    overflow: hidden;
    flex-shrink: 0;
}

.sidebar-title {
    font-weight: 600;
    font-size: 15px;
    color: var(--text);
}

.sidebar-toggle {
    flex-shrink: 0;
    padding: 0;
    font-size: 20px;
    background: transparent;
    border: none;
}

.sidebar-toggle:hover {
    background: transparent;
    transform: scale(1.08);
}

/* The scrollable middle section - deliberately no background of its own, so the
   gradient (--z-bg) shows through from .admin-sidebar as one continuous surface
   rather than looking like a separate panel floating inside the sidebar. */
.sidebar-links {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    /* .sidebar-links is a <nav> element, and the global `nav { justify-content:
       space-between }` rule (for the top header bar) otherwise leaks in here
       unopposed, since this rule never declared justify-content of its own -
       that's what was stretching/rebalancing the gaps between rows, and why it
       shifted every time a sub-level's height changed. */
    justify-content: flex-start;
    gap: 5px;
    padding: 5px;
    /* Scrollbar stays invisible until the sidebar itself is hovered - see the
       .admin-sidebar:hover overrides below. */
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
}

.sidebar-links::-webkit-scrollbar {
    width: 6px;
}

.sidebar-links::-webkit-scrollbar-thumb {
    background: transparent;
    border-radius: 3px;
}

.admin-sidebar:hover .sidebar-links {
    scrollbar-color: rgba(150,150,150,0.45) transparent;
}

.admin-sidebar:hover .sidebar-links::-webkit-scrollbar-thumb {
    background: rgba(150,150,150,0.45);
}

/* Both plain rows and group wrappers must refuse to shrink - otherwise, as flex
   children of .sidebar-links, the browser squeezes every row shorter to keep
   everything fitting rather than ever letting the container overflow, which is
   what was making rows visibly shrink whenever a sub-level expanded. Refusing to
   shrink forces genuine overflow, so .sidebar-links scrolls instead. */
.sidebar-group {
    flex-shrink: 0;
}

.sidebar-link {
    flex-shrink: 0;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 5px;
    margin: 0 3px;
    border: 1px solid transparent;
    border-radius: 5px;
    text-decoration: none;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    background: var(--sidebar-link-bg);
    transition: background 0.2s ease, color 0.2s ease;
}

.sidebar-link:hover {
    background: var(--sidebar-link-bg-hover);
}

/* Active: kept a plain, near-white surface rather than tinted, framed by a thin
   left-to-right gradient border (transparent border-color reveals the border-box
   layer beneath the padding-box fill - the standard dual-background gradient-
   border technique, since `border-image`/`border-color` alone can't do gradients). */
.sidebar-link.active,
.sidebar-link.active:hover {
    background:
        linear-gradient(var(--content-bg), var(--content-bg)) padding-box,
        linear-gradient(to right, var(--highlight), transparent) border-box;
    color: var(--text);
    font-weight: 600;
}

/* Deliberately unstyled - the link's own background already carries the visual
   weight, so the icon doesn't need its own chip/circle on top of it. */
.sidebar-link i {
    font-size: 16px;
    flex-shrink: 0;
    width: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Wraps a distinct product's links in a bordered, tinted, collapsible card - unlike every other sidebar entry (ungated, or grouped only by an invisible clearance check with no visual boundary) - used for Omukristu-PIS so it can never be mistaken for more Elemental links. color-mix() keeps the accent theme-aware (var(--highlight) already flips between the light and dark palettes) without a second set of light/dark overrides. */
.sidebar-collapsible-section {
    flex-shrink: 0;
    margin: 4px 3px 10px;
    border: 1px solid color-mix(in srgb, var(--highlight) 55%, transparent);
    border-radius: 8px;
    overflow: hidden;
    background: color-mix(in srgb, var(--highlight) 8%, transparent);
}

/* --accent is the site's one gold/yellow constant (not theme-split like --highlight, same #d4af37 in light and dark), which is what makes the header read as "yellow-ish" rather than the card's own purple/navy --highlight tint - the border-bottom is the divider separating it from the links below. */
.sidebar-section-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px;
    border: none;
    border-bottom: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
    background: color-mix(in srgb, var(--accent) 22%, transparent);
    color: var(--text);
    cursor: pointer;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
}

.sidebar-section-toggle:hover {
    background: color-mix(in srgb, var(--accent) 32%, transparent);
}

.sidebar-section-toggle i {
    font-size: 13px;
    flex-shrink: 0;
}

.sidebar-section-caret {
    margin-left: auto;
    transition: transform 0.2s ease;
}

.sidebar-collapsible-section.expanded .sidebar-section-caret {
    transform: rotate(180deg);
}

.sidebar-section-body {
    display: none;
    flex-direction: column;
    gap: 4px;
    padding: 8px 6px;
}

.sidebar-collapsible-section.expanded .sidebar-section-body {
    display: flex;
}

/* Only overrides margin, not background - .sidebar-link's own background/hover/active rules must keep applying unmodified here (a same-specificity "background: transparent" placed after .sidebar-link:hover/.active in the cascade previously won on ties and silently killed both effects for every link in this card). Margin still needs zeroing so links sit flush against the card's own padding instead of carrying .sidebar-link's default horizontal margin on top of it. */
.sidebar-section-body .sidebar-link {
    margin: 0;
}

.sidebar-label {
    font-size: 15px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-parent {
    padding-right: 4px;
}

.sidebar-caret-btn {
    margin-left: auto;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: none;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
    transition: background 0.2s ease, transform 0.2s ease;
}

.sidebar-caret-btn:hover {
    background: var(--tint);
}

/* Stays a plain grey regardless of the parent link's active/hover color -
   it's a disclosure control, not part of the link's own emphasis. */
.sidebar-caret-btn i {
    color: var(--light-antique);
    font-size: 14px;
}

.sidebar-group.expanded .sidebar-caret-btn {
    transform: rotate(180deg);
}

.sidebar-sublist {
    display: none;
    flex-direction: column;
    gap: 1px;
    padding: 0 0 2px 10px;
}

.sidebar-group.expanded .sidebar-sublist {
    display: flex;
}

/* No background of their own - the bottom divider is the only separation
   between sub-items, so the sublist reads as one plain, uniform list. */
.sidebar-sublink {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 5px;
    padding: 5px;
    border: 1px solid transparent;
    text-decoration: none;
    color: var(--text);
    font-size: 14px;
    white-space: nowrap;
    background: transparent;
    transition: color 0.2s ease;
}

/* Semi-transparent divider between sub-items - skipped on the last one so the
   group doesn't end on a trailing line. */
.sidebar-sublink:not(:last-child) {
    border-bottom-color: rgba(150,150,150,0.25);
}

.sidebar-sublink:hover {
    color: var(--light-antique);
}

.sidebar-sublink.active,
.sidebar-sublink.active:hover {
    background:
        linear-gradient(var(--content-bg), var(--content-bg)) padding-box,
        linear-gradient(to right, var(--highlight), transparent) border-box;
    color: var(--text);
    font-weight: 600;
    border-radius: 8px;
    border-bottom-color: transparent;
}

.sidebar-count {
    flex-shrink: 0;
    min-width: 20px;
    padding: 1px 7px;
    border-radius: 1px;
    background: var(--surface);
    color: var(--text);
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    /* Same push-right technique .sidebar-caret-btn uses - works whether the
       badge sits in a plain .sidebar-link (no justify-content of its own) or
       a .sidebar-sublink (already space-between'd, where auto margin is a
       no-op) - so one rule covers both. */
    margin-left: auto;
}

/* A plain sidebar-count is neutral (e.g. a static Paid/Unpaid split); this
   variant is for counts that mean "needs your attention" - a pending queue,
   not just a tally - so it's meant to actually stand out in the list. */
.sidebar-count-attention {
    background: var(--accent);
    color: #1b3a1e;
}

/* Pinned to the bottom regardless of how many links are above it - a sibling of
   the scrollable .sidebar-links, not a child of it. */
.sidebar-footer {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 10px;
    flex-shrink: 0;
    border-top: 1px solid rgba(255,255,255,0.1);
    overflow: hidden;
}

.sidebar-avatar {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--v-bg);
    color: var(--text);
    font-size: 13px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sidebar-username {
    font-size: 14px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Collapsed: icons only */
body.sidebar-collapsed .admin-sidebar {
    width: 60px;
}

body.sidebar-collapsed .sidebar-title,
body.sidebar-collapsed .sidebar-label,
body.sidebar-collapsed .sidebar-caret-btn,
body.sidebar-collapsed .sidebar-sublist,
body.sidebar-collapsed .sidebar-count,
body.sidebar-collapsed .sidebar-section-label,
body.sidebar-collapsed .sidebar-section-caret {
    display: none;
}

body.sidebar-collapsed .sidebar-header,
body.sidebar-collapsed .sidebar-link,
body.sidebar-collapsed .sidebar-footer,
body.sidebar-collapsed .sidebar-section-toggle {
    justify-content: center;
}

/* Icon-only mode: the header bar has nothing left to show (label/caret hidden) and nothing to click, so it's dropped entirely rather than left as a dead, non-functional yellow strip. What's left is a plain always-open icon list, framed top and bottom by the same accent color the header used, with its own icons tinted that accent so it still reads as a distinct group from the Elemental icons above/below it - not via background (that property is already owned by .sidebar-link's own hover/active states; overriding it here at this higher specificity would silently cancel both, the same bug already fixed once on the expanded-card body). */
body.sidebar-collapsed .sidebar-collapsible-section {
    border: none;
    background: transparent;
    margin: 0;
}

body.sidebar-collapsed .sidebar-section-toggle {
    display: none;
}

body.sidebar-collapsed .sidebar-section-body {
    display: flex !important;
    padding: 4px 0;
    border-top: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
    border-bottom: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
}

/* .sidebar-section-body .sidebar-link's margin:0 (set for the expanded card, where the card's own lateral padding already insets it) leaves nothing to inset these icons in collapsed mode, where the section body has no lateral padding of its own - restoring the same 0 3px every other icon-only .sidebar-link carries keeps this row the same width as its neighbors instead of reading as wider. */
body.sidebar-collapsed .sidebar-section-body .sidebar-link {
    margin: 0 3px;
}

/* Pure --accent (#d4af37) reads fine on this card's dark backdrop but is too pale against a light theme background - blending in the theme's own --text color (already tuned for contrast against that theme's background, light or dark) keeps this legible in both instead of just the one it happened to be designed against. */
body.sidebar-collapsed .sidebar-section-body .sidebar-link i {
    color: color-mix(in srgb, var(--accent) 65%, var(--text) 35%);
}

/* Scoped via the sibling selector (not the shared .dashboard-body rule itself,
   which sentry/ and dashboard/ also use without a sidebar) so only admin/ pages
   - the only ones that render #adminSidebar - get the offset. */
#adminSidebar ~ .dashboard-body {
    margin-left: 220px;
    transition: margin-left 0.2s ease;
    --sidebar-offset: 220px;
}

body.sidebar-collapsed #adminSidebar ~ .dashboard-body {
    margin-left: 60px;
    --sidebar-offset: 60px;
}

/* Below the breakpoint already used everywhere else for icon+label collapse
   (d-none d-lg-*), force icon-only and hide the manual toggle, rather than
   adding a second, JS-driven mobile behavior on top of the existing convention. */
@media (max-width: 991px) {
    .admin-sidebar {
        width: 60px !important;
    }

    .sidebar-title,
    .sidebar-label,
    .sidebar-caret-btn,
    .sidebar-sublist,
    .sidebar-count,
    .sidebar-section-label,
    .sidebar-section-caret {
        display: none;
    }

    .sidebar-header,
    .sidebar-link,
    .sidebar-footer,
    .sidebar-section-toggle {
        justify-content: center;
    }

    .sidebar-collapsible-section {
        border: none;
        background: transparent;
        margin: 0;
    }

    .sidebar-section-toggle {
        display: none;
    }

    .sidebar-section-body {
        display: flex !important;
        padding: 4px 0;
        border-top: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
        border-bottom: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
    }

    .sidebar-section-body .sidebar-link {
        margin: 0 3px;
    }

    .sidebar-section-body .sidebar-link i {
        color: color-mix(in srgb, var(--accent) 65%, var(--text) 35%);
    }

    .sidebar-toggle {
        display: none;
    }

    #adminSidebar ~ .dashboard-body {
        margin-left: 60px !important;
        --sidebar-offset: 60px;
    }
}

/* ---------- PAGE LAYOUT ---------- */
.page {
    flex: 1;
    display: flex;
    height: calc(100vh - 60px);
}

.left,
.right {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* LEFT PANEL (IMAGE) */
.left {
    background: var(--x-bg);
    padding: 30px;
}

.left img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* RIGHT PANEL (FORM) */
.right {
    padding: 10px;
}

.form-box {
    width: 100%;
    max-width: 450px;
    background: var(--surface);
    padding: 15px;
    border-radius: 15px;
    box-shadow: 0px 5px 25px rgba(0,0,0,0.1);
    backdrop-filter: blur(5px);
}

.form-box h1 {
    margin-top: 0;
    font-weight: 500;
    text-align: center;
}

/* Inputs */
.input-group {
    margin-bottom: 15px;
}

.input-group label {
    display: block;
    margin-bottom: 6px;
    font-size: 14px;
}

.input-group input {
    width: 100%;
    padding: 5px 10px;
    font-size: 15px;
    border-radius: 5px;
    border: 1px solid rgba(0,0,0,0.15);
    background: #dddddd;
    outline: none;
}

input[type="file"] {
    padding: 5px;
}

input[type="file"]::file-selector-button,
input[type="file"]::-webkit-file-upload-button {
    padding: 5px 10px;
    background: var(--tint);
    border-radius: 3px;
    border: none;
    color: var(--text);
    margin-right: 10px;
}

.user-btn-success, .user-btn-blue {
    padding: 5px 10px;
    border: none;
    border-radius: 5px;
    background: var(--grad-blue);
    color: var(--text);
    font-size: 15px;
    cursor: pointer;
    text-decoration: none;
}

.user-btn-success {
    background: var(--grad-success);
}

button:hover,
.user-btn-success:hover,
.user-btn-blue:hover {
    background: var(--y-bg);
}

/* Responsive */
@media (max-width: 992px) {
    .page {
        flex-direction: column;
        height: auto;
    }

    .left {
        padding: 20px;
    }

    .left img {
        width: 60%;
    }
}

.off-canvas {
    position: fixed;
    top: 0;
    right: -400px;
    width: 400px;
    max-width: 90vw;
    height: 100%;
    background: var(--x-bg);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    z-index: 320;
    display: flex;
    flex-direction: column;
    transition: right 0.3s ease;
}

/* Show off-canvas */
.off-canvas.active {
    right: 0;
}

/* Off-canvas header */
.off-canvas-header, .activity-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 5px;
    margin-bottom: 5px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
}

.off-canvas-heading, .activity-heading {
    font-size: 18px;
    font-weight: 600;
    margin: 0;
}

.off-canvas-body {
    padding: 15px;
    overflow-y: auto;
    flex: 1;
}

.off-canvas-list {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.off-canvas-list-link {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 5px;
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    font-size: 13px;
    border-left: 3px solid transparent;
    transition: background 0.15s ease, box-shadow 0.15s ease;
}

.off-canvas-list-link:hover {
    background: var(--tint);
    box-shadow: inset 0 0 0 1px var(--antique);
}

.off-canvas-list-link > i {
    flex-shrink: 0;
    margin-top: 1px;
    padding-right: 10px;
    border-right: 1px solid var(--antique);
    align-self: stretch;
    display: flex;
    align-items: flex-start;
}

/* min-width:0 overrides the flex item default of min-width:auto, which would
   otherwise stop .off-canvas-list-title from ever shrinking below its content
   width and ellipsizing - same reasoning as .icon-btn span elsewhere. */
.off-canvas-list-link > span {
    min-width: 0;
    flex: 1 1 auto;
}

/* Ticket cards only - other notification types are a single plain-text line
   with no separate title, so they just use the bare <span> above. */
.off-canvas-list-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.off-canvas-list-title {
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.off-canvas-list-preview {
    font-size: 12px;
}

/* Tone = what kind of thing happened (something granted/succeeded, something
   revoked/cancelled, a heads-up that isn't good or bad, a plain fact) - a
   semi-transparent version of the same tone color as the background, a solid
   version as the left border and the icon, so the card reads at a glance
   without needing to read the text first. Reuses the same ready/deny/warning
   color families as the site's .action-ready/.action-deny/.action-warning
   buttons, not a separate palette. */
.off-canvas-tone-ready {
    background: rgba(29,141,1,0.12);
    border-left-color: rgb(29,141,1);
}
.off-canvas-tone-ready > i {
    color: rgb(29,141,1);
}

.off-canvas-tone-deny {
    background: rgba(180,62,7,0.14);
    border-left-color: rgb(180,62,7);
}
.off-canvas-tone-deny > i {
    color: rgb(180,62,7);
}

.off-canvas-tone-warning {
    background: rgba(236,144,40,0.14);
    border-left-color: rgb(236,144,40);
}
.off-canvas-tone-warning > i {
    color: rgb(236,144,40);
}

.off-canvas-tone-info {
    background: rgba(2,73,66,0.14);
    border-left-color: rgb(2,73,66);
}
.off-canvas-tone-info > i {
    color: rgb(2,73,66);
}

/* Same red as .fs-chat-badge (assets/js/fieldSupportSession's unread chat badge)
   for the same "needs your attention" reason, but a normal flex sibling here
   (not an absolutely-positioned corner dot) - .icon-btn's own align-items:center
   centers it against the icon/label without any extra positioning, and since it
   never depends on the label's own d-none-at-small-screens visibility, the count
   stays visible next to the icon even when "Info. Center" itself is hidden.
   Selector is .icon-btn .off-canvas-badge (not just .off-canvas-badge) because
   the generic .icon-btn span rule (margin: 0 5px, font-size: 15px, meant for the
   button's text label) outranks a single-class selector on specificity and was
   overriding both this badge's margin and font-size otherwise. */
.icon-btn .off-canvas-badge {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 20px;
    min-width: 20px;
    padding: 0 6px;
    margin: 0;
    border-radius: 1px;
    background: #ef4444;
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
}

/* Close button */
.off-canvas-close, .close-activity {
    background: transparent;
    border: none;
    font-size: 1.5rem;
    cursor: pointer;
}

/* Backdrop */
.off-canvas-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(27,58,30,0.5);
    backdrop-filter: blur(5px);
    z-index: 300;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.off-canvas-backdrop.active {
    opacity: 1;
    pointer-events: auto;
}

/* Error Pages */
.error-card {
    position: absolute;
    text-align: center;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.error-title {
    color: var(--outset);
    font-weight: 600;
    position: relative;
    display: inline-block;
    padding-bottom: 10px;
}

.error-title::after {
    content: "";
    position: absolute;
    left: 50%; 
    bottom: 0;
    transform: translateX(-50%);
    width: 200%;
    height: 2px;
    background: var(--secondary);
    border-radius: 3px;
    opacity: 0.8;
}

.error-meta {
    color: var(--antique);
    margin-top: 10px;
}

/* Register */
/* ---- Header Row ---- */
.register-header,
.log-search-container {
    background: var(--v-bg);
    backdrop-filter: blur(5px);
    padding: 10px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 5px;
    border-radius: 10px;
}

.header-search {
    flex: 1;
    min-width: 180px;
}

.header-search input,
.log-search-container input,
.account-form input,
.account-form textarea,
.account-form select,
.form-field {
    padding: 5px 10px;
    font-size: 15px;
    border-radius: 5px;
    color: var(--text);
    border: solid var(--light-accent) 1px;
    background: var(--transparent);
}

.log-search-container input,
.account-form input,
.account-form textarea,
.account-form select,
.form-field {
    width: 100%;
}


.header-search input:active,
.header-search input:focus,
.log-search-container input:active,
.log-search-container input:focus,
.account-form input:active,
.account-form input:focus,
.account-form textarea:active,
.account-form textarea:focus,
.account-form select:active,
.account-form select:focus,
.form-field:focus {
    background: var(--transparent);
    color: var(--text);
    outline: none;
    border-color: var(--light-accent);
}

.header-search input::placeholder,
.log-search-container input::placeholder,
.account-form input::placeholder,
.account-form textarea::placeholder,
.form-field::placeholder {
    color: var(--antique) !important;
    opacity: 0.7;
}

.account-form select option,
select.form-field option {
    background-color: var(--bg);
    color: var(--text);
}

input[type="color"].form-field {
    padding: 5px;
    height: 35px;
}

.filter-field-wrap {
    position: relative;
}

.filter-field-wrap .form-field {
    padding-right: 32px;
}

.filter-clear-icon {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--antique);
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease;
}

.filter-clear-icon.visible {
    opacity: 1;
    pointer-events: auto;
}

.filter-clear-icon:hover {
    color: var(--text);
}

.form-field:disabled {
    background: var(--surface);
    color: var(--light-antique);
    border-color: var(--light-accent);
    opacity: 0.6;
    cursor: not-allowed;
}

.field-label {
    font-size: 14px;
    color: var(--text);
    opacity: 0.7;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.header-buttons button {
    white-space: nowrap;
}


.cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 15px;
}

/* Fixed at 3 columns rather than auto-fit(minmax(260px,1fr)) - auto-fit packs
   in as many 260px+ columns as the row has room for (4 on a typical wide
   screen), which squeezes each card's own action-button row into wrapping.
   Capping the column count directly (with explicit step-downs, not another
   auto-fit) is what actually guarantees "at most 3 per row". */
.cards-grid-3 {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 15px;
}

@media (max-width: 1200px) {
    .cards-grid-3 {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 768px) {
    .cards-grid-3 {
        grid-template-columns: 1fr;
    }
}

/* Grid rows already stretch every card to the tallest one in the row (grid default
   align-items: stretch). space-between here would spread the gap evenly across
   every direct child (name, "Clearances" title, each badge, the divider, the
   button row) rather than bunching the content at the top - margin-top: auto on
   just the last child (the status/action row) is what actually pins only that
   row to the shared bottom edge, leaving everything above it bunched together. */
.cards-grid-3 .record-item {
    display: flex;
    flex-direction: column;
}

.cards-grid-3 .record-item > :last-child {
    margin-top: auto;
}

.log-tail {
    background: var(--content-bg);
    color: var(--text);
    border: solid var(--bg) 1px;
    border-radius: 5px;
    padding: 10px 12px;
    margin: 0 0 15px;
    font-size: 12px;
    line-height: 1.5;
    white-space: pre;
    overflow-x: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(128,128,128,0.35) transparent;
}

.log-tail::-webkit-scrollbar {
    height: 6px;
}

.log-tail::-webkit-scrollbar-track {
    background: transparent;
}

.log-tail::-webkit-scrollbar-thumb {
    background: rgba(128,128,128,0.35);
    border-radius: 3px;
}

.log-tail::-webkit-scrollbar-thumb:hover {
    background: rgba(128,128,128,0.55);
}

.record-card,
.important-card,
.form-card {
    background: var(--s-bg);
    border-radius: 5px;
    padding: 10px;
    border: solid var(--bg) 1px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.06);
    transition: 0.2s ease;
}

.form-card {
    background: var(--surface);
    border: solid var(--info-shadow) 1px;
}

.description-card {
    border-radius: 10px;
    padding: 10px;
    border: solid var(--bg) 1px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.06);
    transition: 0.2s ease;

    /* Layered gradients using the existing variables */
    background:
        var(--r-bg),
        var(--z-bg),
        var(--y-bg);
    background-size: 400% 400%;
    background-repeat: no-repeat;
    animation: violentGradient 5s linear infinite;
}

@keyframes violentGradient {
    0%   { background-position: 0% 0%, 100% 0%, 0% 100%, 100% 100%; }
    25%  { background-position: 100% 50%, 0% 50%, 100% 0%, 0% 100%; }
    50%  { background-position: 50% 100%, 50% 0%, 0% 50%, 100% 0%; }
    75%  { background-position: 0% 50%, 100% 50%, 50% 100%, 0% 0%; }
    100% { background-position: 0% 0%, 100% 0%, 0% 100%, 100% 100%; }
}

.description-card p {
    margin: 5px 0;
    color: var(--text);
    line-height: 1.5;
}

.account-form {
    height: 100%;
}

.account-image-wrapper {
    position: relative;
    width: 100%;
    overflow: hidden;
}

.account-full-image {
    width: 100%;
    height: auto;
    max-height: 237px;
    object-fit: cover;
    border-radius: 5px;
}

.account-floating-action {
    position: absolute;
    bottom: 0;
    right: 0;
}

.important-card {
    background: var(--p-bg);
    border: solid var(--error-shadow) 1px;
}

.record-card:hover,
.form-card:hover,
.important-card:hover {
    background: var(--v-bg);
    box-shadow: 0 3px 10px rgba(0,0,0,0.1);
}

.important-card:hover .important {
    color: var(--info-color);
}

.content-card {
    border-radius: 15px;
}

.content-card h6 {
    color: var(--info-color);
}

.content-card .important {
    color: var(--error-color);
}

.card-header-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.avatar {
    width: 35px;
    height: 35px;
    background: var(--v-bg);
    color: var(--text);
    font-size: 20px;
    font-weight: bold;
    border-radius: 2px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.name-section {
    flex: 1;
    display: flex;
    align-items: center;
    min-height: 35px;
}

.name-section span {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    text-decoration: none;
    line-height: 1.2;
    display: block;
    word-break: break-word;
}

.info-label {
    font-size: 15px;
    color: var(--light-antique);
}

.info-value {
    font-size: 15px;
    color: var(--text);
    padding: 2px 0;
    font-weight: 400;
}

.info-value.bordered {
    border-bottom: 1px solid var(--antique);
    padding-bottom: 5px;
}

.divider {
    border: none;
    height: 1px;
    background: var(--antique);
    margin: 5px 0;
}

.stat-border-card {
    border: 1px solid var(--antique);
    border-radius: 5px;
    padding: 10px;
}

/* Scoped override, not a change to .flex-grow-1 itself (a shared Bootstrap utility
   used unconstrained everywhere else) - the category rows below sit inside this
   wrapper, and without min-width: 0 here it grows to fit their unshrunk content and
   drags the whole card wider instead of letting the rows themselves ellipsize. */
.stat-border-card .flex-grow-1 {
    min-width: 0;
}

/* Header title / category labels ellipsize on overflow rather than wrapping to a
   second line; the count/value on the other side of each row stays intact on one
   line instead of shrinking to make room. */
.stat-border-card .d-flex.justify-content-between > span:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.stat-border-card .d-flex.justify-content-between > span:last-child {
    flex-shrink: 0;
    white-space: nowrap;
}

/* Scoped override, not a change to .act-btn-view/.action-link themselves - those are
   shared by many unrelated buttons across the admin panel that rely on the centered
   icon+text layout. Compound selector (not just .sentry-media-link) so this wins on
   specificity rather than depending on source order relative to .act-btn-view below. */
.act-btn-view.sentry-media-link {
    justify-content: flex-start;
    text-decoration: none;
    width: 100%;
    overflow: hidden;
}

.sentry-media-link span {
    overflow: hidden;
    white-space: nowrap;
}

/* Upload-state chips (assets/js/sentry-post-media.js) - state is conveyed by text color
   alone, not an appended check/x glyph. Color cascades to the icon too via currentColor. */
.sentry-media-chip {
    display: flex;
    align-items: center;
    gap: 5px;
}

.sentry-media-chip-done {
    color: var(--info-color);
}

.sentry-media-chip-error {
    color: var(--error-color);
}

.mini-bars {
    align-items: flex-end;
    gap: 3px;
    width: 36px;
    height: 48px;
    flex-shrink: 0;
}

.mini-bars .bar {
    flex: 1;
    min-height: 2px;
    border-radius: 2px 2px 0 0;
}

.card-actions {
    display: flex;
    justify-content: flex-end;
    gap: 5px;
}

.act-btn-snap,
.act-btn-archive,
.act-btn-view,
.act-btn-delete {
    background: var(--v-bg);
    border: none;
    padding: 5px 10px;
    border-radius: 5px;
    color: var(--text);
    cursor: pointer;
    font-size: 15px;
}

.act-btn-snap {
    background: var(--t-bg);
}

.act-btn-archive {
    background: var(--u-bg);
}

.act-btn-view {
    background: var(--v-bg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
}

.act-btn-view:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.act-btn-view i {
    font-size: 20px;
    flex-shrink: 0;
}

/* Label text shouldn't wrap onto a second line inside the button when a row runs
   out of room (e.g. invoiceInfo.php's action bar) - min-width:0 overrides the flex
   item default of min-width:auto so the span can actually shrink below its content
   width, and ellipsis reads as "truncated" rather than the two-line wrap it fell
   back to otherwise. */
.act-btn-view span {
    margin-left: 5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Card action-button rows (accounts.php etc.) can hold up to 3 full icon+label
   buttons, but .cards-grid lets a card be as narrow as 260px - a plain nowrap
   d-flex there just overflows the card. Wrapping, right-aligned so it reads as
   one right-justified block whether it takes one row or two. */
.record-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
    row-gap: 5px;
}

.act-btn-fetch {
    justify-content: space-between;
}

.asset-card-cell {
    border-radius: 10px;
    border: 1px solid var(--antique);
}

.act-btn-delete {
    background: var(--r-bg);
}

.action-orange {
    background: var(--u-bg);
}

.action-green {
    background: var(--grad-success);
}

.action-red {
    background: var(--r-bg);
}

.action-blue {
    background: var(--grad-blue);
}

.action-ready {
    background: var(--grad-ready);
}

.action-link {
    background: var(--tint);
}

.action-error {
    background: var(--grad-error);
}

.action-warning {
    background: var(--grad-warning);
}

.action-deny {
    background: var(--grad-deny);
}

.status-text-ready {
    color: var(--ready-color);
}

.status-text-warning {
    color: var(--warning-color);
}

.status-text-deny {
    color: var(--error-color);
}

.act-status-view {
    display: flex;
    height: 33px;
    align-items: center;
    justify-content: center;
    border: none;
    padding: 5px;
    border-radius: 5px;
    color: var(--text);
    font-size: 22px;
}

/* .act-status-view is a block-level flex container everywhere else because its parent's
   own flex layout (a list row, an icon-only badge) already shrink-wraps it - used standalone
   (e.g. a status word in a detail panel) it stretches to the full block width instead,
   leaving a short word lost in the middle of a wide bar. .status-pill overrides it to a
   proper compact, content-sized pill. */
.act-status-view.status-pill {
    display: inline-flex;
    width: auto;
    height: auto;
    padding: 6px 14px;
    font-size: 13px;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.act-label-view {
    display: inline-flex;
    height: 33px;
    align-items: center;
    justify-content: center;
    border: none;
    padding: 5px 10px;
    border-radius: 5px;
    color: var(--text);
    background: var(--info-shadow);
}

.pagination-container {
    border-top: solid var(--antique) 1px;
    padding-top: 10px;
}
.pagination {
    display: flex;
    gap: 5px;
    padding: 0;
}

.page-item {
    list-style: none;
}

.page-link {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 35px;
    min-width: 35px;
    padding: 5px 10px;
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    background: var(--tint);
    border: 1px solid var(--light-accent);
    border-radius: 5px;
    text-decoration: none;
    transition: 0.2s ease;
}

.page-link:hover {
    background: rgba(46,125,50,0.1);
    border-color: var(--light-accent);
}

.no-action, .no-action:hover {
    color: rgba(0,0,0,0);
    cursor: default;
}

.page-item.active .page-link {
    background: var(--v-bg);
    color: var(--text);
    border-color: var(--v-bg);
}

.page-item:first-child .page-link,
.page-item:last-child .page-link {
    padding: 5px 5px;
    font-weight: 700;
}

@media (max-width: 480px) {
    .pagination {
        gap: 3px;
    }

    .page-link {
        min-width: 28px;
        padding: 5px 10px;
        font-size: 13px;
    }
}

@media (max-width: 360px) {
    /* hide some middle numbers if too small */
    .page-item:not(.active):not(:first-child):not(:last-child) {
        display: none;
    }
}

/* INTEGRATIONS */
/* DASHBOARD WRAPPER */
.dashboard-wrapper {
    display: flex;
    gap: 15px;
    flex-wrap: wrap;
}

/* When activity panel opens */
.dashboard-wrapper.activity-open {
    flex-wrap: nowrap; /* keep left + right columns in one row */
}

.cards-area {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    flex: 1 1 100%;
}

/* Standard cards: 3 per row */
.cards-area .record-card {
    flex: 1 1 calc(33.333% - 10px);
    min-width: 250px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 200px;
}

/* Stacked cards - inside left column. Width is "100% of this flex container
   (already narrowed by the sidebar's margin-left offset on .dashboard-body)
   minus however wide .activity-column actually is" - deriving both from the
   same --detail-panel-width/--sidebar-offset formula (see .activity-column
   below) guarantees the two never overlap, on any sidebar state and at any
   panel width the user has dragged it to. No extra buffer subtracted here -
   .dashboard-body/.content's own right padding is already baked into this
   "100%", and .activity-column is fixed to the true viewport edge ignoring
   that padding entirely, so it alone produces a gap matching the one on the
   list's left (same padding, same width) with nothing further added. */
.dashboard-wrapper.activity-open .cards-area.stacked-cards {
    flex-direction: column;
    flex: 0 0 auto;
    width: calc(100% - var(--detail-panel-width, calc((100vw - var(--sidebar-offset, 0px)) * 0.64)));
    max-width: calc(100% - var(--detail-panel-width, calc((100vw - var(--sidebar-offset, 0px)) * 0.64)));
}

/* Same collapse-to-make-room-for-the-side-panel behavior as .cards-area, but
   for a plain vertical row list (.record-item/.list-block) rather than a
   .record-card grid - row-direction + wrap would break a list's natural
   top-to-bottom flow, so this stays column-direction in both states. */
.list-column {
    display: flex;
    flex-direction: column;
    flex: 1 1 100%;
}

.dashboard-wrapper.activity-open .list-column.stacked-cards {
    flex: 0 0 auto;
    width: calc(100% - var(--detail-panel-width, calc((100vw - var(--sidebar-offset, 0px)) * 0.64)));
    max-width: calc(100% - var(--detail-panel-width, calc((100vw - var(--sidebar-offset, 0px)) * 0.64)));
}

@media (max-width: 992px) {
    .list-column.stacked-cards {
        flex: 1 1 100%;
        width: 100%;
        max-width: 100%;
    }
}

/* Default width is 64% of the space actually left after the admin sidebar's
   offset (not raw 100vw, which - on admin/ pages - overshoots left into the
   list-column it's supposed to leave room for). --detail-panel-width is set
   inline by detail-panel.js while the user drags the resize handle, and
   persisted via localStorage - once set, it wins over this default on every
   page. min/max-width still clamp it either way, so a width dragged on a wide
   screen can never force it past the current viewport's available space. */
.activity-column {
    width: var(--detail-panel-width, calc((100vw - var(--sidebar-offset, 0px)) * 0.64));
    min-width: 320px;
    max-width: calc(100vw - var(--sidebar-offset, 0px) - 280px);
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 110px;
    right: 0;
    height: calc(100vh - 110px);
    z-index: 180;
    background: var(--x-bg);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    border-radius: 0;
    border-top-left-radius: 15px;
    transition: right 0.3s ease-in-out;

}

/* Drag handle - injected by detail-panel.js as the first child of every
   .activity-column, rather than hand-added to each of the ~14 pages using
   this pattern. .activity-column already establishes its own containing
   block (position: fixed), so this positions relative to it with no extra
   wrapper needed. */
.detail-resize-handle {
    position: absolute;
    top: 0;
    left: -2px;
    width: 4px;
    height: 100%;
    cursor: col-resize;
    z-index: 5;
    background: transparent;
    touch-action: none;
}

/* Same subtle grey tone already used for .sidebar-links' hover-only scrollbar
   thumb, at a lower opacity - a thin, barely-there affordance rather than a
   solid bar. */
.detail-resize-handle:hover,
.detail-resize-handle.resizing {
    background: rgba(150,150,150,0.3);
}

@media (max-width: 992px) {
    .detail-resize-handle {
        display: none;
    }
}

/* admin/'s nav+widgets-row stack is 89px tall, not dashboard/'s 110px - same
   panel, just a shorter header to sit under. */
@media (min-width: 992px) {
    .dashboard-body .activity-column {
        top: 89px;
        height: calc(100vh - 89px);
    }
}

.activity-wrapper,
#activityContent  {
    flex: 1;
    background: var(--big-bg);
    border-top-left-radius: 5px;
    padding: 5px;
    padding-bottom: 1rem;
    height: 100%;
    min-height: 500px;
    position: relative;
    overflow-y: auto;
}

.activity-wrapper {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}

.activity-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--transparent);
    flex-shrink: 0;
    border-bottom: 1px solid #cccccc27;
    padding: 5px;
}

.activity-content {
    flex: 1;
    overflow-y: auto;
    padding: 5px;
}

.activity-content::-webkit-scrollbar {
    width: 10px;
}

.activity-content::-webkit-scrollbar-track {
    background: rgba(221,221,221,0);
    border-radius: 0;
}

.activity-content::-webkit-scrollbar-thumb {
    background-color: var(--antique);
    border-radius: 5px;
    border: 2px solid rgba(0,0,0,0);
}

.activity-content::-webkit-scrollbar-thumb:hover {
    background-color: darken(var(--antique), 10%);
}

@media (max-width: 992px) {
    .dashboard-wrapper {
        flex-direction: column;
    }
    .cards-area.stacked-cards {
        flex: 1 1 100%;
        width: 100%;
        max-width: 100%;
    }

    .activity-column {
        position: fixed;
        top: 0;
        left: 0;
        right: 10px;
        width: 100vw;
        max-width: 100vw;
        height: 100vh;
        z-index: 340;
        padding: 10px;
    }

    .activity-wrapper {
        height: auto;
        min-height: auto;
        border-radius: 10px;
    }
}


.logs-view {
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--x-bg);
    border-radius: 5px;
    overflow: hidden;
}

.logs-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 5px 10px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    background: rgba(0,0,0,0.15);
}

.logs-title {
    font-weight: bold;
}

.logs-meta {
    opacity: 0.7;
}

.logs-list {
    flex: 1;
    overflow-y: auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
}

.logs-list::-webkit-scrollbar {
    width: 5px;
}

.logs-list::-webkit-scrollbar-track {
    background: transparent;
}

.logs-list::-webkit-scrollbar-thumb {
    background-color: rgba(255,255,255,0.3);
    border-radius: 10px;
}

.logs-list {
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.3) transparent;
}

.log-row {
    display: grid;
    grid-template-columns: 150px 80px 120px 1fr;
    gap: 5px;
    padding: 5px 10px;
    border-bottom: 1px solid rgba(255,255,255,0.05);
    align-items: center;
}

.log-row:hover {
    background: rgba(255,255,255,0.04);
}

.log-ts {
    opacity: 0.75;
}

.log-source {
    opacity: 0.85;
}

.log-message {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ERROR {
    color: var(--error-color);
    background: linear-gradient(130deg, var(--error-shadow), transparent);
    padding: 2px 5px;
    border-radius: 2px;
}

.ALERT {
    color: var(--alert-color);
    background: linear-gradient(130deg, var(--alert-shadow), transparent);
    padding: 2px 5px;
    border-radius: 2px;
}

.WARNING {
    color: var(--warning-color);
    background: linear-gradient(130deg, var(--warning-shadow), transparent);
    padding: 2px 5px;
    border-radius: 2px;
}

.INFO {
    color: var(--info-color);
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    padding: 2px 5px;
    border-radius: 2px;
}

.DEBUG {
    color: var(--antique);
    background: linear-gradient(130deg, var(--debug-shadow), transparent);
    padding: 2px 5px;
    border-radius: 2px;
}

.UNIT {
    color: var(--text);
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    padding: 2px 5px;
    border-radius: 2px;
}

.config-panel {
    position: fixed;
    top: 110px;
    height: calc(100vh - 110px);
    background: var(--x-bg);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    border-top-left-radius: 15px;
    overflow: hidden;
}

.config-scroll {
    height: 100%;
    overflow-y: auto;
    padding: 10px 10px 50px 10px;
    margin: 0;
}

.config-scroll::-webkit-scrollbar {
    width: 10px;
}

.config-scroll::-webkit-scrollbar-track {
    background: rgba(221, 221, 221, 0.3);
    border-radius: 5px;
}

.config-scroll::-webkit-scrollbar-thumb {
    background-color: var(--antique);
    border-radius: 5px;
    border: 2px solid rgba(0,0,0,0);
}

.config-scroll::-webkit-scrollbar-thumb:hover {
    background-color: var(--antique-dark, #444);
}

@media (max-width: 991px) {

    .config-panel {
        position: fixed;
        right: -100%;
        top: 110px;
        width: 100%;
        height: calc(100vh - 110px);
        z-index: 180;
        background: var(--x-bg);
        backdrop-filter: blur(5px);
        box-shadow: -5px 0 15px rgba(0,0,0,0.2);
        border-radius: 0;
        border-top-left-radius: 15px;
        transition: right 0.3s ease-in-out;
    }

    .config-panel.show,
    .activity-column.show {
        right: 0;
    }

    .config-fab {
        position: fixed;
        right: 5px;
        bottom: 47px;
        z-index: 260;

        display: flex;
        align-items: center;
        justify-content: center;

        /* Animated gradient base */
        background: linear-gradient(130deg,
            var(--link-highlight),
            var(--outset),
            var(--error-color),
            var(--link-highlight)
        );
        background-size: 300% 300%;
        border-radius: 5px;
        border-bottom-right-radius: 0;
        font-weight: 600;

        /* Glow */
        box-shadow:
            0 0 10px rgba(0,0,0,0.25),
            0 0 18px rgba(0, 200, 255, 0.35),
            0 0 35px rgba(0, 200, 255, 0.2);

        border: 0 solid rgba(255,255,255,0.15);

        cursor: pointer;

        animation: gradientMove 6s ease infinite, pulseGlow 2.5s ease-in-out infinite;
        transition: transform 0.2s ease, box-shadow 0.2s ease;
    }

    /* Hover = POP */
    .config-fab:hover {
        transform: translateY(-2px) scale(1.05);
        box-shadow:
            0 0 12px rgba(0,0,0,0.3),
            0 0 25px rgba(0, 255, 255, 0.6),
            0 0 55px rgba(0, 255, 255, 0.35);
    }

    /* Moving gradient */
    @keyframes gradientMove {
        0% {
            background-position: 0% 50%;
        }
        50% {
            background-position: 100% 50%;
        }
        100% {
            background-position: 0% 50%;
        }
    }

    /* Soft breathing glow */
    @keyframes pulseGlow {
        0%, 100% {
            filter: brightness(1);
        }
        50% {
            filter: brightness(1.15);
        }
    }

    .config-scroll {
        scrollbar-width: none;
        -ms-overflow-style: none;
    }

    .config-scroll::-webkit-scrollbar {
        width: 0;
        height: 0;
        display: none;
    }
}

.record-item-card {
    background: var(--z-bg);
    border-radius: 5px;
    padding: 10px;
    margin-bottom: 10px;
}

.resolve-block, .list-block, .list-btns-block {
    display: flex;               
    align-items: center;
    justify-content: space-between; 
    background-color: var(--error-shadow);   
    border: solid 1px var(--error-color);   
    border-radius: 5px;
    padding: 5px;
    color: var(--error-color);              
    gap: 5px;    
    margin-bottom: 5px;               
}

.list-block {
    background: linear-gradient(130deg, var(--info-shadow), var(--debug-shadow));  
    border: none;  
    padding: 5px; 
}

.list-btns-block {
    background: transparent;  
    border: none;  
    padding: 0; 
}

.list-block:hover {
    background: linear-gradient(130deg, var(--debug-color), var(--debug-shadow));   
}

.list-block .list-body {
    flex-grow: 1;
    display: flex;
    align-items: center;
    color: var(--link-highlight);
    flex-shrink: 1;
    min-width: 0;
}

/* Dashboard stats - plain content like the rest of this page (Quick Actions' own .title-c
   headings, no separate boxed/backgrounded panel per section - see main.php, which uses
   .title-c directly instead of a dedicated header here). Each .stats-category is one
   category (e.g. "Portals") with its total on the far right, then breakdown metric rows
   below - each row washed in its status color across the full width (reusing
   .INFO/.WARNING/.DEBUG/.ERROR for that tint+text color) with the value in a count badge on
   the far right. Neither .stats-category nor .stats-metric-row/.stats-count-badge carry
   their own horizontal padding - nothing but the shared container edge (#panelContainer) sets
   the right inset, so a category's total and its own metrics' counts land at the exact same
   x-position with nothing to knock them out of alignment. */
.stats-view {
    display: flex;
    flex-direction: column;
    margin-bottom: 10px;
}

.stats-category {
    margin-bottom: 8px;
}

.stats-category-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 4px;
    border-bottom: solid 1px var(--antique);
}

.stats-metric-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0 4px 8px;
    border-radius: 3px;
    margin: 2px 0;
}

.stats-count-badge {
    padding: 0;
    margin: 0;
    font-weight: bold;
    color: inherit;
}

.list-body i {
    font-size: 20px;
    color: var(--error-color);
}

.list-body.name-indicator {
    /* Block, not flex - text-overflow: ellipsis has no effect on a flex container's
       own text, since that text is laid out as an anonymous flex item the ellipsis
       properties below don't reach; a plain block lets them apply directly. */
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 1;
    min-width: 0; 
    padding-left: 5px;
}

.indicator-badge {
    color: var(--text);
    font-size: 15px;
    background: linear-gradient(130deg, transparent, var(--warning-shadow));
    height: 30px;
    margin-right: 5px;
    padding: 5px 10px;
    border-radius: 2px;
    border: inset var(--antique) 1px;
}

.list-details {
    display: flex;
    flex-grow: 1;
    gap: 5;
}

.text-block {
    flex-grow: 1;
    display: flex;
    align-items: center;
    color: var(--text);
    /* No left margin - .text-block sits alongside .config-title, .list-block
       rows, and .dashboard-wrapper as a sibling in the same padded container
       in every page that uses it; none of those carry a matching offset, so
       a left margin here only ever reads as the New/Add button (or the
       icon+count pairing elsewhere) being indented relative to everything
       around it, never as an intentional alignment. */
    margin: 0 0 5px 0;
}

/* The filter input sharing this row with a New/Add button (portals.php,
   invoices.php, etc.) is wrapped by records-filter.js in a .filter-field-wrap
   (to host the clear icon) - that wrap, not the <input> itself, is the actual
   flex item here, and it defaults to flex-grow: 0, sized to its content
   rather than the remaining row width. The input's own `width: 100%` is
   applied against that undersized wrapper, so it never had a chance to fill
   what's actually left in the row. */
.text-block .filter-field-wrap {
    flex: 1 1 auto;
    min-width: 0;
}

.text-block i {
    font-size: 20px;
}

.text-block-title {
    /* Block, not flex - text-overflow: ellipsis doesn't reach a flex container's own
       text (see .list-body.name-indicator above); this is plain text content, so a
       block keeps the ellipsis working while .text-block's own align-items: center
       still centers it as a flex item in the row. */
    flex-grow: 1;
    font-weight: bold;
    background: var(--info-shadow);
    padding: 5px 10px;
    border-radius: 5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.id-span {
    background: var(--t-bg);
    font-weight: bold;
    padding: 5px 10px;
    border-radius: 5px;
    margin-right: 5px;
    margin-left: -5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 1;
    min-width: 0;
    max-width: 45%;
}

/* .id-span's own background above would otherwise win over .action-ready/
   .action-warning at equal specificity, just from coming later in this file -
   settlementInfo.php uses these to show a settlement's status directly in the
   id-span instead of a static label. */
.id-span.action-ready {
    background: var(--grad-ready);
}

.id-span.action-warning {
    background: var(--grad-warning);
}

.id-span.action-deny {
    background: var(--grad-deny);
}

.resolve-block .message {
    flex-grow: 1; 
    margin-left: 5px;               
}

.resolve-block .resolve-btn {
    background: var(--u-bg);  
    color: var(--text);
    border: none;
    padding: 5px 10px;
    border: solid var(--error-shadow) 1px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 15px;
    transition: background-color 0.2s;
}

.resolve-block .resolve-btn:hover {
    background: var(--z-bg);
    border: solid var(--antique) 1px;
}

.resolve-feed {
    height: calc(100vh - 180px);
    overflow-y: auto;
    overflow-x: hidden;
    padding: 5px;
    border: solid var(--antique) 1px;
    border-radius: 5px;
    margin: 10px 0;
    background: var(--surface);
    font-size: 15px;
    scroll-behavior: smooth;

    scrollbar-width: thin;
    scrollbar-color: #888 rgba(255,255,255,0.2);
}

.resolve-feed ::-webkit-scrollbar {
    width: 10px;
}

.resolve-feed ::-webkit-scrollbar-track {
    background: rgba(255,255,255,0.2);
    border-radius: 3px;
}

.resolve-feed ::-webkit-scrollbar-thumb {
    background-color: #888;
    border-radius: 3px;
    border: 1px solid rgba(255,255,255,0.2);
}

.resolve-feed ::-webkit-scrollbar-thumb:hover {
    background-color: #555;
}

.resolve-feed-title {
    background: var(--tint);
    color: var(--alert-color);
    padding: 0px 5px;
    margin: 0 0 5px 0;
    border-left: solid var(--alert-color) 2px;
    font-weight: bold;
}

.resolve-feed-line {
    background: linear-gradient(130deg, var(--alert-shadow), transparent);
    color: var(--text);
    font-family: monospace;
    font-size: 14px;
    padding: 0px 5px;
    margin: 0 0 3px 0;
    border-left: solid var(--warning-color) 2px;
}

.resolve-feed-line:hover {
    background: var(--u-bg);
}

.config-title {
    background: linear-gradient(130deg, var(--alert-shadow), transparent);
    color: var(--text);
    font-weight: bold;
    border-radius: 5px;
    padding: 5px 10px;
    margin: 0 0 5px 0;
}

.config-section-title {
    background: var(--bg);
    border-radius: 5px;
    color: var(--text);
    padding: 5px 10px;
    margin: 0 0 5px 0;
}

.config-card {
    background: var(--z-bg);
    padding: 10px 10px 5px 10px;
    border-radius: 5px;
    margin-bottom: 10px;
}

.config-form-card {
    background: var(--x-bg);
    border: solid var(--surface) 1px;
    padding: 10px 10px 5px 10px;
    border-radius: 10px;
    margin-bottom: 10px;
}

.no-config {
    color: var(--antique);
}

.config-node {
    position: relative;
    align-items: center;
    padding: 5px;
    color: var(--text);
    cursor: pointer;
    display: flex;
    justify-content: left;
    gap: 5px;
    border-radius: 2px;
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    margin-bottom: 5px;
    z-index: 1;
    transition: transform 0.2s ease, background 0.25s ease;
}


.config-node-btn {
    background: var(--error-shadow);
    color: var(--error-color);
    padding: 5px;
    width: 30px;
    height: 30px;
    border: inset var(--error-color) 1px;
    border-radius: 2px;
}

.config-node-btn:hover {
    background: var(--error-color);
    color: var(--text);
    padding: 5px;
    border: solid var(--error-color) 1px;
    border-radius: 2px;
}

.config-node span {
    margin: 0 5px;
}

.config-node span.indicator-badge {
    margin: 0;
}

.config-node .index-label {
    margin: 0;
    color: var(--light-antique);
    background: var(--tint);
    padding: 5px;
    border-radius: 2px;
    border: solid transparent 1px;
}

.config-node:hover {
    background: var(--tint);
}

.config-node:hover .index-label{
    background: var(--info-shadow);
    color: var(--text);
   
    border: solid var(--antique) 1px;
}

@media (max-width: 500px) {
    .props-actions {
        display: grid !important;
        grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
        gap: 0.5rem;
    }
}

.contact-c {
    background: linear-gradient(130deg, var(--alert-shadow), transparent);
    margin: 0 0 5px 0;
    padding: 2px 5px;
    border-radius: 5px;
}

.title-c {
    background: linear-gradient(130deg, var(--error-shadow), transparent);
    margin: 0 0 5px 0;
    padding: 2px 5px;
    border-radius: 5px;
}

.block-c {
    margin: 0;
    font-size: 14px;
}

.block-c-sub {
    margin: 0 0 5px 0;
    font-size: 12px;
    color: var(--warning-color);
}

.view-title {
    background: var(--t-bg-x);
    font-weight: bold;
    padding: 5px 10px;
    border-radius: 5px;
    margin: 5px 0;
}

.view-sub {
    color: var(--light-antique);
    font-weight: bold;
    margin-bottom: 10px;
}

.stats-wrapper {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.stats-row {
    display: flex;
    gap: 5px;
}

.stats-attribute {
    width: 150px;
    background: var(--alert-shadow);
    padding: 5px 10px;
    border-radius: 5px;
    box-sizing: border-box;
}

.stats-value {
    flex: 1;
    background: linear-gradient(130deg, var(--alert-shadow), transparent);
    padding: 5px 10px;
    border-radius: 5px;
    box-sizing: border-box;
}

.config-img {
    width: 100%;
    object-fit: cover;
    border-radius: 5px;
    margin-bottom: 5px;
}

.ajax-modal {
    position: fixed;
    inset: 0;
    z-index: 1050;
    display: none;  
}

.ajax-modal.active {
    display: flex;
    align-items: center;
    justify-content: center;
}

.ajax-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(27,58,30,0.5);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
}

.ajax-modal-dialog {
    position: relative;
    background: var(--x-bg);
    width: 98vw;
    height: 97vh;
    border-radius: 15px;

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

@media (max-width: 991px) {
    .ajax-modal-dialog {
        width: 95vw;
        height: 88vh;
        border-radius: 10px;
    }
}

.ajax-modal-header {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px;
    border-bottom: 1px solid var(--antique);
}

.ajax-modal-tools {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 5px 10px 0 10px;
    border-bottom: 1px solid var(--info-shadow);
}

.ajax-modal-body {
    flex: 1;
    padding: 5px 10px;
    overflow: auto;
    overscroll-behavior: contain;
}

.ajax-modal-body::-webkit-scrollbar {
    width: 10px;
}

.ajax-modal-body::-webkit-scrollbar-track {
    background: rgba(221,221,221,0);
}

.ajax-modal-body::-webkit-scrollbar-thumb {
    background-color: var(--antique);
    border-radius: 5px;
    border: 2px solid rgba(0,0,0,0);
}

/* Small screens – hide scrollbar but keep scroll */
@media (max-width: 991px) {
    .ajax-modal-body {
        -ms-overflow-style: none;  /* IE / Edge */
        scrollbar-width: none;     /* Firefox */
    }

    .ajax-modal-body::-webkit-scrollbar {
        display: none;             /* Chrome / Safari */
    }
}

.ajax-modal-close {
    border: none;
}

.code-viewer {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
    font-size: 15px;
    line-height: 1.45;
    border-radius: 5px;
    display: inline-block;
    max-width: none; 
}

.code-table {
    border-collapse: collapse;
    width: max-content;
}

.code-table td {
    vertical-align: middle;
}

.code-line-number {
    width: 1%;
    padding: 0 10px;
    text-align: right;
    color: var(--light-antique);
    background: var(--debug-shadow);
    border-right: 1px solid var(--debug-color);
    user-select: none;
}

.code-line {
    padding: 0;
}

.code-line pre {
    margin: 0;
    padding: 0 12px;
    white-space: pre;
}

.code-table tr:hover {
    background: var(--info-shadow);
}

.js-form .row.align-items-stretch {
    align-items: stretch;
}

.js-form .col-lg-7,
.js-form .col-lg-5 {
    display: flex;
    flex-direction: column;
}

.wysiwyg-wrapper {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    min-height: 250px;
}

.wysiwyg-toolbar {
    position: sticky;
    top: 0;
    z-index: 20;
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.5rem;
    margin-bottom: 0.5rem;
    background: var(--bg);
    border-radius: 5px;
}

.wysiwyg-btn {
    border: none;
    padding: 0 5px;
    width: 30px;
    height: 30px;
    border-radius: 2px;
}

.wysiwyg-select {
    border: none;
    border-right: solid var(--surface) 3px;
    padding: 0 5px;
    height: 30px;
    background: var(--surface);
    color: var(--text);
    border-radius: 5px;
}

select.wysiwyg-select option {
    background-color: var(--bg);
    color: var(--text);
} 

.wysiwyg-color {
    border: none;
    height: 20px;
    width: 26px;
    padding: 0;
    background: none;
    border-radius: 3px;
    cursor: pointer;
}

/* Text Color and Highlight Color otherwise look identical at a glance (both a bare
   <input type=color> swatch) - the icon makes which-is-which obvious without hovering
   for the title tooltip. */
.wysiwyg-color-group {
    display: flex;
    align-items: center;
    gap: 5px;
    height: 30px;
    padding: 0 6px 0 8px;
    background: var(--surface);
    border-radius: 5px;
    cursor: pointer;
}

.wysiwyg-color-group i {
    font-size: 18px;
    color: var(--text);
}

.wysiwyg-editor {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0.5rem;
    border: 1px solid var(--info-shadow);
    border-radius: 5px;
    background-color: var(--debug-shadow);
    margin-bottom: 8px;
}

.wysiwyg-editor:empty:before {
    content: attr(placeholder);
    color: var(--antique);
    pointer-events: none;
    display: block;
}
blockquote {
    border-left: 4px solid var(--warning-shadow);
    padding-left: 12px;
    margin: 10px 0;
    color: var(--info);
    font-style: italic;
}

.editor-code-block {
    background: var(--info-shadow);
    color: var(--text);
    padding: 5px 10px;
    border-radius: 5px;
    overflow-x: auto;
    font-family: monospace;
    font-size: 14px;
    line-height: 1.5;
}

.editor-code-block code {
    white-space: pre-wrap;
}

.editor-table {
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
    margin: 1rem 0;
    border: 1px solid var(--info-shadow);
    border-radius: 5px;
    overflow: hidden;
}


/* Editor Table Cells */
.editor-table th,
.editor-table td {
    padding: 0.75rem 1rem;
    border: 1px solid var(--alert-shadow);
    text-align: left;
    vertical-align: middle;
    font-size: 0.95rem;
    line-height: 1.5;
}

/* Table Headers */
.editor-table th {
    font-weight: 600;
    background: var(--info-shadow);
    color: var(--info);
}

/* Zebra Stripes */
.editor-table tbody tr:nth-child(even) {
    background: transparent;
}

/* Hover Effect */
.editor-table tbody tr:hover {
    background: var(--debug-shadow);
}

/* Editable Feel */
.editor-table td:focus,
.editor-table th:focus {
    outline: 2px solid #3b82f6;
    outline-offset: -2px;
}

/* Responsive Tables */
.editor-table-wrapper {
    width: 100%;
    overflow-x: auto;
    margin: 1rem 0;
}

.editor-table.no-borders th,
.editor-table.no-borders td {
    border: none;
}

/* Shared mini modal - a small, self-contained overlay appended straight to <body>, so it
   works regardless of where it's triggered from (a WYSIWYG toolbar, a destructive-action
   button) without hijacking the shared #ajaxModal (e.g. the New Invoice form) it might be
   nested inside. Used for the WYSIWYG toolbar's table/link/image/code prompts and for the
   "Are you sure?" confirmation on delete/cancel/reject-style buttons. */
.mini-modal {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: none;
    align-items: center;
    justify-content: center;
}

.mini-modal.active {
    display: flex;
}

.mini-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(27,58,30,0.5);
    backdrop-filter: blur(5px);
}

.mini-modal-dialog {
    position: relative;
    background: var(--content-bg);
    width: 320px;
    max-width: 90vw;
    border-radius: 10px;
    padding: 16px;
}

.mini-modal-title {
    font-weight: bold;
    margin-bottom: 12px;
}

.mini-modal-message {
    font-size: 14px;
    line-height: 1.5;
}

.mini-modal-check {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}

.mini-modal-check .form-check-input {
    /* Bootstrap gives .form-check-input a top margin meant for its own stacked
       .form-check layout - reset it here so flex actually centers it against the label. */
    margin: 0;
}

.mini-modal-check .form-check-label {
    margin-bottom: 0;
}

.mini-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 14px;
}

.image-picker {
    position: relative;
    cursor: pointer;
}

/* Upload-state label for promo cover/theme pickers (assets/js/promo-media.js) - same
   color convention as .sentry-media-chip, overlaid at the bottom of the image preview. */
.promo-media-status {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 4px 8px;
    font-size: 0.75rem;
    color: #fff;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 0 0 5px 5px;
}

.promo-media-status-done {
    background: var(--info-color);
}

.promo-media-status-error {
    background: var(--error-color);
}

.image-preview {
    width: 100%;
    max-height: 250px;
    object-fit: cover;
    border-radius: 5px;
    transition: opacity 0.2s ease-in-out;
}

.image-picker:hover .image-preview {
    opacity: 0.85;
}

.image-preview-card {
    border-radius: 5px;
    background: var(--z-bg);
    padding: 10px;
    margin-bottom: 5px;
}

.image-preview-card .image-preview {
    border-radius: 0;
}

.image-cards, .image-cards-existing {
    background: var(--info-shadow);
    padding: 10px;
    border-radius: 5px;
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 5px;
    margin-bottom: 10px;
}

@media (max-width: 992px) {
    .image-cards, .image-cards-existing {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (max-width: 576px) {
    .image-cards, .image-cards-existing {
        grid-template-columns: repeat(2, 1fr);
    }
}

.image-cards-existing {
    background: var(--z-bg);
}

.image-card {
    position: relative;
    border-radius: 3px;
    overflow: hidden;
    background: #111;
}

.image-card img {
    width: 100%;
    height: 150px;
    object-fit: cover;
    display: block;
}

.image-card .remove {
    position: absolute;
    top: 5px;
    right: 5px;
    width: 25px;
    height: 25px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 1px;
    background: rgba(27,58,30,0.7);
    color: #fff;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    transition: background 0.15s ease, transform 0.1s ease;
}

.image-card .delete-image {
    position: absolute;
    top: 5px;
    right: 5px;
    width: 25px;
    height: 25px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 1px;
    background: var(--r-bg);
    color: #fff;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    transition: background 0.15s ease, transform 0.1s ease;
}

.image-card .remove:hover,
.delete-image:hover {
    background: var(--grad-deny);
}

.multi-select-dropdown {
    position: relative;
    border: 1px solid var(--info-shadow);
    border-radius: 5px;
    cursor: pointer;
    user-select: none;
    margin-bottom: 10px;
}

.multi-select-display {
    padding: 0.5rem;
    min-height: 38px;
}

.multi-select-list {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    border: 1px solid var(--info-shadow);
    border-radius: 5px;
    background: var(--z-bg);
    backdrop-filter: blur(10px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    max-height: 200px;
    overflow-y: auto;
    display: none;
    z-index: 100;
    flex-direction: column;
    padding: 0.25rem;
}

.multi-select-list input[type="text"] {
    margin: 0 0 10px 0;
    width: 100%;
    padding: 5px 10px;
}

.multi-select-item {
    display: flex;
    align-items: center;
    padding: 5px 10px;
}

/* Multi-select custom checkboxes */
.multi-select-item {
    display: flex;
    align-items: center;
    position: relative;
    padding: 5px 10px;
    cursor: pointer;
    user-select: none;
    border-radius: 4px;
    transition: background 0.2s;
}

.multi-select-item:hover {
    background-color: rgba(0, 123, 255, 0.1);
}

/* Hide default checkbox */
.multi-select-item input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    cursor: pointer;
    height: 0;
    width: 0;
}

/* Create custom checkbox */
.multi-select-item span {
    position: relative;
    padding-left: 25px;
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Checkbox square */
.multi-select-item span::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 18px;
    border: 1px solid #007bff;
    border-radius: 3px;
    background-color: #fff;
    transition: all 0.2s;
}

/* Checkmark */
.multi-select-item input:checked + span::after {
    content: "";
    position: absolute;
    left: 5px;
    top: 9px;
    width: 5px;
    height: 10px;
    border: solid #007bff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg) translateY(-50%);
}

/* Small shadow for checkbox */
.multi-select-item span::before {
    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

.multi-select-dropdown.disabled {
    pointer-events: none;
    opacity: 0.6;
}


/* Modal Safety */
.modal .image-preview {
    max-height: 200px;
}

.form-info,
.form-success,
.form-forbidden,
.form-error {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border-radius: 5px;
    margin-bottom: 10px;
}

.form-info i,
.form-success i,
.form-forbidden i,
.form-error i {
    font-size: 20px;
    flex-shrink: 0;
}

.form-info {
    background: linear-gradient(130deg, var(--debug-color), transparent);
    color: var(--info-color);
}

.form-success {
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    color: var(--info-color);
}

.form-forbidden {
    background: linear-gradient(130deg, var(--warning-shadow), transparent);
    color: var(--warning-color);
}

.form-error {
    background: linear-gradient(130deg, var(--error-shadow), transparent);
    color: var(--error-color);
}

.formMessage {
    /* .form-info/.form-success/.form-error/.form-forbidden default to a
       centered row, meant for a short "icon + one line" alert. This variant
       (renderAjaxListMessage()) holds a title followed by a <ul> of items,
       so it needs to stack instead. */
    flex-direction: column;
    align-items: flex-start;
}

.formMessage ul {
    margin: 4px 0 0;
    padding-left: 20px;
}

.form-message {
    padding: 5px 10px;
    border-radius: 5px;
    background: var(--info-shadow);
}

.contact-popup {
    position: fixed;
    bottom: 40px;
    left: 10px;
    padding: 15px;
    border-radius: 30px;
    border-bottom-left-radius: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(20px) scale(0.95);
    transition: opacity 0.25s ease, transform 0.25s ease;
    z-index: 9999;
}

.contact-popup.active {
    opacity: 1;
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    backdrop-filter: blur(5px);
    box-shadow: -5px 0 15px rgba(0,0,0,0.2);
    pointer-events: auto;
    transform: translateY(0) scale(1);
}

.contact-btn {
    position: relative;
    display: flex;
    align-items: center;
    background: transparent;
    border: none;
    padding: 0;
    cursor: pointer;
}

.contact-btn .icon-circle {
    position: relative;
    z-index: 2;
    width: 45px;
    height: 45px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    color: var(--text);
    background:
        var(--w-bg) padding-box,
        linear-gradient(130deg, var(--text), var(--accent)) border-box;
    border: 1px solid transparent;
    box-shadow: 0 10px 20px rgba(27,58,30,0.5);
}

.contact-btn .label {
    position: relative;
    z-index: 1;
    width: calc(100vw - 100px);
    padding: 10px 15px 10px 20px;
    margin-left: -10px;
    font-weight: 500;
    color: var(--text);
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    border-radius: 20px;
    border: 1px solid transparent;
    background:
        var(--w-bg) padding-box,
        linear-gradient(130deg, var(--accent), var(--transparent)) border-box;
}

.contact-btn:hover {
    background: none;
}

.contact-btn:hover .icon-circle {
    transform: scale(1.05);
}

.contact-btn:hover .label {
    background:
        var(--w-bg) padding-box,
        linear-gradient(130deg, var(--secondary), var(--transparent)) border-box;
}

@media (min-width: 992px) {
    .contact-btn .label {
        width: 350px;
    }
}

.comment-row {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    padding: 10px;
    border-radius: 5px;
    margin: 5px 0;
}

.comment-range-container {
    display: flex;
    flex: 0 0 300px;
    gap: 0.5rem;
}

.comment-range-container .comment-field {
    display: flex;
    flex-direction: column;
    flex: 1;
}

.comment-text {
    flex: 1;
    display: flex;
    flex-direction: column;
}

@media (max-width: 600px) {
    .comment-row {
        flex-direction: column;
    }

    .comment-range-container {
        flex: 1 1 auto;
        gap: 0.5rem;
    }

    .comment-text {
        width: 100%;
    }
}

.teacher-row {
    background: linear-gradient(130deg, var(--info-shadow), transparent);
    padding: 10px;
    border-radius: 5px;
    margin: 5px 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
    width: 100%;
}

.teacher-range-container {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    width: 100%;
}

.teacher-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.teacher-field:first-child {
    flex: 0 0 150px;
}

.teacher-field.teacher-text,
.teacher-field:nth-child(3) {
    flex: 1 1 auto;
    min-width: 120px;
}

@media (max-width: 500px) {
    .teacher-range-container {
        flex-wrap: wrap;
    }
    .teacher-field:first-child,
    .teacher-field.teacher-text {
        flex: 0 0 auto;
        width: calc(50% - 3px);
    }
    .teacher-field:nth-child(3) {
        flex: 0 0 100%;
    }
}

.form-accordion {
    background: var(--z-bg);
    border-radius: 5px;
    margin-bottom: 10px;
    overflow: hidden;
}

.form-accordion-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 5px;
    cursor: pointer;
    user-select: none;
}

.form-accordion-icon {
    font-size: 22px;
    transition: transform 0.2s ease;
}

.form-accordion-content {
    border-top: 1px solid var(--antique);
    display: none;
}

.form-accordion.open .form-accordion-content {
    display: block;
}

.form-accordion.open .form-accordion-icon {
    transform: rotate(45deg);
}

.class-row {
    display: flex;
    align-items: center;
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    border-bottom: 1px solid var(--antique);
}

.class-row .detailsBtn {
    margin-left: auto;
}

.class-left {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.class-left .form-check-input {
    margin-top: 0;
}

.class-row:last-child {
    border-bottom: none;
}

.class-row:hover {
    background: rgba(0,0,0,0.03);
}

.record-header {
    display: flex;
    align-items: center;
    gap: 5px;
}

.record-title {
    color: var(--text);
    flex: 1;
    font-weight: bold;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.record-field {
    width: 100px;
    flex-shrink: 0;
}

.filter-text-block {
    display: flex;
    gap: 5px;
    align-items: center;
}

/* records-filter.js wraps the actual <input class="filter-input"> in a
   .filter-field-wrap (to host the clear icon) - that wrap, not the input
   itself, is the real flex child of .filter-text-block, so it's what needs
   flex: 1 to fill the row. Same root cause as .text-block's New/Add button
   row above. */
.filter-text-block .filter-field-wrap {
    flex: 1;
    min-width: 0;
}

.filter-text-block .filter-input {
    width: 100%;
}

.filter-text-block .items-per-page {
    width: 100px;
    flex-shrink: 0;
}

.heatmap-row {
    display: flex;
    align-items: stretch;
    gap: 10;
    width: 100%;
    background: var(--surface);
    border-radius: 5px;
}

.heatmap-wrapper {
    max-width: 880px;
    flex: 0 0 auto;
    overflow-x: auto;
    overflow-y: hidden;
    display: flex;
}

.heatmap-sidepanel {
    flex: 1 1 auto;
    background: var(--surface);
    border-radius: 5px;
    padding: 10px;
    min-width: 0;
    display: flex;
}

.heatmap-sidepanel > div {
    width: 100%;
}

.heatmap-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 14px;
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    color: var(--text);
}

.legend-swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    flex: 0 0 auto;
}

.heatmap-container {
    position: relative;
    display: inline-block;
    padding: 10px;
    height: 100%;
}

.heatmap-svg {
    display: block;
}

.heatmap-day {
    cursor: pointer;
}

.heatmap-tooltip {
    position: fixed;
    pointer-events: none;
    background: var(--content-bg);
    color: var(--text);
    padding: 5px 10px;
    border-radius: 5px;
    font-size: 15px;
    line-height: 1.4;
    min-width: 120px;
    white-space: nowrap;
    display: none;
    z-index: 1000;
    box-shadow: 0 4px 10px rgba(0,0,0,0.35);
}

.heatmap-tooltip .row {
    display: flex;
    justify-content: space-between;
    gap: 5px;
}

.heatmap-tooltip .row span:last-child {
    opacity: 0.85;
}

@media (max-width: 500px) {
    .heatmap-sidepanel {
        display: none;
    }

    .heatmap-wrapper {
        max-width: 100%;
    }
}

.heatmap-wrapper {
    scrollbar-width: thin; /* Firefox */
    scrollbar-color: rgba(255,255,255,0.35) transparent;
}

.heatmap-wrapper::-webkit-scrollbar {
    height: 10px;
}

.heatmap-wrapper::-webkit-scrollbar-track {
    background: transparent;
}

.heatmap-wrapper::-webkit-scrollbar-thumb {
    background-color: rgba(255,255,255,0.35);
    border-radius: 10px;
}

.heatmap-wrapper::-webkit-scrollbar-thumb:hover {
    background-color: rgba(255,255,255,0.55);
}

.js-btn-loading {
    pointer-events: none;
    opacity: 0.7;
}

.js-btn-spinner {
    width: 1em;
    height: 1em;
    font-size: 22px;
    border: 2px solid var(--antique);
    border-top-color: var(--text);
    border-radius: 50%;
    display: inline-block;
    animation: spin .6s linear infinite;
    vertical-align: middle;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}
.record-card-header {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.record-line {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.2rem;
    border-bottom: 1px solid var(--antique);
}
.record-line:last-child {
    border-bottom: none;
}
.record-line .form-check-input {
    margin-top: 0;
}
.record-line-text {
    min-width: 0;
    flex: 1 1 auto;
}
.status-label.ph-circle-fill {
    font-size: 0.55rem;
    flex-shrink: 0;
}