/* ============================================================================
   Modibbo Girei — components
   ----------------------------------------------------------------------------
   Shared by the portal and the public site. Every class is prefixed `c-` so it
   cannot collide with the Bootstrap-4 classes still present in the views while
   the migration runs (see compat.css).

   Nothing here contains a raw colour, size or duration — only tokens. If a
   value is missing from tokens.css, add it there rather than inlining it.

   The last section reskins the three vendor libraries whose JavaScript we keep
   (toastr, sweetalert, DataTables). Their stylesheets are dropped and their
   generated DOM restyled from tokens, which is how those widgets join the
   design system without rewriting a line of the jQuery that calls them.
   ============================================================================ */

/* ============================================================================
   Buttons
   ============================================================================ */
.c-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 0 var(--space-4);
    height: 38px;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    background: var(--surface-raised);
    color: var(--text-primary);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}
.c-btn:hover { text-decoration: none; }
.c-btn:active { transform: translateY(0.5px); }
.c-btn:disabled, .c-btn[aria-disabled="true"] { opacity: 0.55; pointer-events: none; }

.c-btn--primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--text-on-accent);
}
.c-btn--primary:hover  { background: var(--accent-hover);  border-color: var(--accent-hover);  color: var(--text-on-accent); }
.c-btn--primary:active { background: var(--accent-active); border-color: var(--accent-active); }

.c-btn--secondary {
    background: var(--surface-raised);
    border-color: var(--border-default);
    color: var(--text-primary);
}
.c-btn--secondary:hover { background: var(--surface-hover); border-color: var(--border-strong); }

.c-btn--ghost { background: transparent; color: var(--text-secondary); }
.c-btn--ghost:hover { background: var(--surface-hover); color: var(--text-primary); }

.c-btn--danger {
    background: var(--status-danger-text);
    border-color: var(--status-danger-text);
    color: #fff;
}
.c-btn--danger:hover { filter: brightness(1.08); }

.c-btn--subtle {
    background: var(--accent-subtle);
    border-color: var(--accent-border);
    color: var(--accent-text);
}
.c-btn--subtle:hover { background: var(--accent-subtle); border-color: var(--accent); }

.c-btn--sm { height: 30px; padding: 0 var(--space-3); font-size: var(--fs-xs); }
.c-btn--lg { height: 46px; padding: 0 var(--space-6); font-size: var(--fs-base); }
.c-btn--block { display: flex; width: 100%; }
.c-btn--icon { width: 38px; padding: 0; }
.c-btn--icon.c-btn--sm { width: 30px; }

/* Busy state. members.js already swaps the label for a spinner icon; this
   styles the same state declaratively for anything that sets aria-busy. */
.c-btn[aria-busy="true"] { pointer-events: none; opacity: 0.7; }

/* ============================================================================
   Card
   ============================================================================ */
.c-card {
    background: var(--surface-raised);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.c-card--flat   { box-shadow: none; }
.c-card--sunken { background: var(--surface-sunken); box-shadow: none; }

.c-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--border-subtle);
}
.c-card__title {
    margin: 0;
    font-size: var(--fs-base);
    font-weight: var(--fw-semibold);
}
.c-card__subtitle { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.c-card__actions { display: flex; align-items: center; gap: var(--space-2); }
.c-card__body   { padding: var(--space-5); }
.c-card__body--flush { padding: 0; }
.c-card__footer {
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--border-subtle);
    background: var(--surface-sunken);
}

/* ============================================================================
   Table
   ============================================================================ */
.c-table-wrap {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.c-table {
    width: 100%;
    font-size: var(--fs-sm);
}
.c-table th {
    padding: var(--space-3) var(--space-4);
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--border-default);
    color: var(--text-secondary);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    white-space: nowrap;
}
.c-table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
    vertical-align: middle;
}
.c-table tbody tr:last-child td { border-bottom: 0; }
.c-table--hover tbody tr { transition: background var(--duration-fast) var(--ease-out); }
.c-table--hover tbody tr:hover { background: var(--surface-hover); }
.c-table--striped tbody tr:nth-child(even) { background: color-mix(in srgb, var(--surface-sunken) 55%, transparent); }
.c-table--compact th, .c-table--compact td { padding: var(--space-2) var(--space-3); }

/* Money and counts align on the decimal and share a digit width. */
.c-table__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Headers stay put while a long report scrolls. */
.c-table--sticky thead th { position: sticky; top: 0; z-index: var(--z-base); }

/* ============================================================================
   Forms
   ============================================================================ */
.c-field { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-4); }
.c-field__label {
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    color: var(--text-secondary);
}
.c-field__label .c-field__required { color: var(--status-danger-text); margin-left: 2px; }
.c-field__hint  { font-size: var(--fs-xs); color: var(--text-muted); }
.c-field__error { font-size: var(--fs-xs); color: var(--status-danger-text); }

.c-input, .c-select, .c-textarea {
    width: 100%;
    padding: 0 var(--space-3);
    height: 38px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--surface-raised);
    color: var(--text-primary);
    font-size: var(--fs-sm);
    transition: border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}
.c-textarea { height: auto; min-height: 110px; padding: var(--space-3); line-height: var(--lh-normal); }

.c-input::placeholder, .c-textarea::placeholder { color: var(--text-muted); }

.c-input:hover, .c-select:hover, .c-textarea:hover { border-color: var(--border-strong); }
.c-input:focus, .c-select:focus, .c-textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--ring-focus);
}
.c-input:disabled, .c-select:disabled, .c-textarea:disabled {
    background: var(--surface-sunken);
    color: var(--text-muted);
}
.c-input[aria-invalid="true"], .c-textarea[aria-invalid="true"] {
    border-color: var(--status-danger-border);
}

/* Native select arrow replaced with an inline SVG so it follows the theme.
   currentColor is not available in a data: URI, hence the two variants. */
.c-select {
    appearance: none;
    padding-right: var(--space-8);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238c8172' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-3) center;
}
/* The arrow SVG is a data: URI, which cannot read currentColor, so the stroke
   is baked in and the dark variant declared separately. Both theme signals need
   their own rule — a selector list cannot contain an @media. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .c-select {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23b3a998' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    }
}
:root[data-theme="dark"] .c-select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23b3a998' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}

.c-input-group { display: flex; align-items: stretch; }
.c-input-group .c-input { border-radius: var(--radius-md) 0 0 var(--radius-md); }
.c-input-group .c-btn   { border-radius: 0 var(--radius-md) var(--radius-md) 0; }

/* Search field with a leading icon. */
.c-search { position: relative; }
.c-search .c-input { padding-left: var(--space-10); }
.c-search__icon {
    position: absolute;
    left: var(--space-3);
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
}

.c-checkbox, .c-radio {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--fs-sm);
    cursor: pointer;
}
.c-checkbox input, .c-radio input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

.c-form-grid { display: grid; gap: 0 var(--space-4); grid-template-columns: 1fr; }
@media (min-width: 640px) {
    .c-form-grid--2 { grid-template-columns: repeat(2, 1fr); }
    .c-form-grid--3 { grid-template-columns: repeat(3, 1fr); }
}
.c-form-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    padding-top: var(--space-4);
    margin-top: var(--space-2);
    border-top: 1px solid var(--border-subtle);
}

/* ============================================================================
   Avatar
   ----------------------------------------------------------------------------
   The initials variant is what makes a member with no photo look deliberate
   rather than broken. Most members have no file on disk yet, so this is the
   common case, not the fallback.
   ============================================================================ */
.c-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    background: var(--surface-sunken);
    color: var(--text-secondary);
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    letter-spacing: 0.02em;
    overflow: hidden;
    user-select: none;
}
/* object-position, not the browser's default centre: an avatar is square but the
   photographs are upright, so something always has to go. Taking it off the
   bottom keeps the face; splitting it evenly cuts the forehead. 25% is the
   ordinary place for eyes in a head-and-shoulders photo, and it is the fallback
   for photographs whose focal point has never been set — one that HAS been set
   overrides this with an inline object-position. */
.c-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 25%; }

/* Click-the-face focal point picker, on the Photograph tab. The crosshair says
   plainly that the photograph is clickable; without it people read the image as
   a preview and never discover the control. */
#focusPicker { cursor: crosshair; display: block; }
#focusPicker[data-no-photo] { cursor: default; }
#focusMarker {
    position: absolute;
    width: 26px; height: 26px;
    margin: -13px 0 0 -13px;        /* centre the marker on the clicked point */
    border: 2px solid #fff;
    border-radius: var(--radius-full);
    box-shadow: 0 0 0 2px var(--accent), 0 1px 6px rgba(0, 0, 0, 0.45);
    pointer-events: none;           /* never swallow the next click */
    transition: left 120ms ease, top 120ms ease;
}
#focusMarker::after {
    content: '';
    position: absolute;
    inset: 9px;
    border-radius: var(--radius-full);
    background: var(--accent);
}
.c-avatar--xs { width: 24px; height: 24px; font-size: 10px; }
.c-avatar--sm { width: 32px; height: 32px; font-size: var(--fs-xs); }
.c-avatar--lg { width: 64px; height: 64px; font-size: var(--fs-lg); }
.c-avatar--xl { width: 96px; height: 96px; font-size: var(--fs-2xl); }
.c-avatar--square { border-radius: var(--radius-md); }
.c-avatar--ring { box-shadow: 0 0 0 2px var(--surface-raised), 0 0 0 4px var(--accent-border); }

/* ============================================================================
   Badges & chips
   ============================================================================ */
.c-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px var(--space-2);
    border: 1px solid transparent;
    border-radius: var(--radius-full);
    background: var(--surface-sunken);
    color: var(--text-secondary);
    font-size: var(--fs-xs);
    font-weight: var(--fw-medium);
    line-height: 1.5;
    white-space: nowrap;
}
.c-badge--success { background: var(--status-success-bg); color: var(--status-success-text); border-color: color-mix(in srgb, var(--status-success-border) 40%, transparent); }
.c-badge--danger  { background: var(--status-danger-bg);  color: var(--status-danger-text);  border-color: color-mix(in srgb, var(--status-danger-border) 40%, transparent); }
.c-badge--warning { background: var(--status-warning-bg); color: var(--status-warning-text); border-color: color-mix(in srgb, var(--status-warning-border) 40%, transparent); }
.c-badge--info    { background: var(--status-info-bg);    color: var(--status-info-text);    border-color: color-mix(in srgb, var(--status-info-border) 40%, transparent); }
.c-badge--accent  { background: var(--accent-subtle);     color: var(--accent-text);         border-color: var(--accent-border); }
.c-badge--gen     { background: var(--highlight-subtle);  color: var(--highlight-text);      border-color: color-mix(in srgb, var(--highlight) 35%, transparent); }
.c-badge--male    { color: var(--gender-male);   border-color: color-mix(in srgb, var(--gender-male) 35%, transparent); background: color-mix(in srgb, var(--gender-male) 10%, transparent); }
.c-badge--female  { color: var(--gender-female); border-color: color-mix(in srgb, var(--gender-female) 35%, transparent); background: color-mix(in srgb, var(--gender-female) 10%, transparent); }

/* A member id, a voucher — anything the user might copy or compare. */
.c-badge--id { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0; }

.c-badge__dot { width: 6px; height: 6px; border-radius: var(--radius-full); background: currentColor; flex: none; }

/* ============================================================================
   Alert
   ============================================================================ */
.c-alert {
    display: flex;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-subtle);
    border-left-width: 3px;
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
    font-size: var(--fs-sm);
}
.c-alert__title { font-weight: var(--fw-semibold); margin-bottom: var(--space-1); }
.c-alert--success { background: var(--status-success-bg); border-color: var(--status-success-border); color: var(--status-success-text); }
.c-alert--danger  { background: var(--status-danger-bg);  border-color: var(--status-danger-border);  color: var(--status-danger-text); }
.c-alert--warning { background: var(--status-warning-bg); border-color: var(--status-warning-border); color: var(--status-warning-text); }
.c-alert--info    { background: var(--status-info-bg);    border-color: var(--status-info-border);    color: var(--status-info-text); }

/* ============================================================================
   Stat tile
   ============================================================================ */
.c-stat {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4) var(--space-5);
    background: var(--surface-raised);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
}
.c-stat__label {
    font-size: var(--fs-xs);
    font-weight: var(--fw-medium);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
}
.c-stat__value {
    font-size: var(--fs-2xl);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-tight);
    font-variant-numeric: tabular-nums;
    letter-spacing: var(--tracking-tight);
}
.c-stat__meta { font-size: var(--fs-xs); color: var(--text-muted); }
.c-stat__meta--up   { color: var(--status-success-text); }
.c-stat__meta--down { color: var(--status-danger-text); }
.c-stat--accent { border-color: var(--accent-border); background: var(--accent-subtle); }
.c-stat--accent .c-stat__value { color: var(--accent-text); }

.c-stat-row {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

/* ============================================================================
   Tabs
   ============================================================================ */
.c-tabs__list {
    display: flex;
    gap: var(--space-1);
    padding: 0;
    margin: 0;
    list-style: none;
    border-bottom: 1px solid var(--border-subtle);
    overflow-x: auto;
    scrollbar-width: none;
}
.c-tabs__list::-webkit-scrollbar { display: none; }

.c-tabs__tab {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border: 0;
    border-bottom: 2px solid transparent;
    background: none;
    color: var(--text-secondary);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out);
}
.c-tabs__tab:hover { color: var(--text-primary); }
.c-tabs__tab[aria-selected="true"] {
    color: var(--accent-text);
    border-bottom-color: var(--accent);
}
.c-tabs__panel { padding-top: var(--space-5); }
.c-tabs__panel[hidden] { display: none; }

/* ============================================================================
   Breadcrumb
   ============================================================================ */
.c-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    padding: 0;
    margin: 0;
    list-style: none;
    font-size: var(--fs-sm);
}
.c-breadcrumb li { display: inline-flex; align-items: center; gap: var(--space-1); }
.c-breadcrumb li + li::before {
    content: "/";
    color: var(--text-muted);
    margin-right: var(--space-1);
}
.c-breadcrumb a { color: var(--text-secondary); text-decoration: none; }
.c-breadcrumb a:hover { color: var(--accent-text); text-decoration: underline; }
.c-breadcrumb [aria-current="page"] { color: var(--text-primary); font-weight: var(--fw-medium); }

/* ============================================================================
   Empty state
   ----------------------------------------------------------------------------
   Replaces the `colspan` "No records" rows and the blank <div>s the portal
   currently shows. A blank panel reads as a broken page; this reads as an
   answer.
   ============================================================================ */
.c-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-12) var(--space-6);
    text-align: center;
    color: var(--text-muted);
}
.c-empty__icon {
    display: grid;
    place-items: center;
    width: 48px; height: 48px;
    border-radius: var(--radius-full);
    background: var(--surface-sunken);
    color: var(--text-muted);
}
.c-empty__title { font-size: var(--fs-base); font-weight: var(--fw-semibold); color: var(--text-secondary); margin: 0; }
.c-empty__body  { font-size: var(--fs-sm); margin: 0; max-width: 42ch; }

/* ============================================================================
   Skeleton
   ============================================================================ */
.c-skeleton {
    position: relative;
    overflow: hidden;
    background: var(--surface-sunken);
    border-radius: var(--radius-sm);
}
.c-skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--surface-raised) 60%, transparent), transparent);
    animation: c-shimmer 1.4s infinite;
}
@keyframes c-shimmer {100% { transform: translateX(100%); } }
.c-skeleton--text { height: 0.85em; margin: 0.25em 0; }
.c-skeleton--title { height: 1.2em; width: 45%; }
.c-skeleton--avatar { width: 40px; height: 40px; border-radius: var(--radius-full); }

/* ============================================================================
   Modal — native <dialog>, so focus trapping and Esc are the browser's job
   rather than ours.
   ============================================================================ */
.c-modal {
    width: min(560px, calc(100vw - 2 * var(--space-4)));
    padding: 0;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-overlay);
    color: var(--text-primary);
    box-shadow: var(--shadow-xl);
}
.c-modal::backdrop { background: var(--backdrop); }
.c-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--border-subtle);
}
.c-modal__title { margin: 0; font-size: var(--fs-md); font-weight: var(--fw-semibold); }
.c-modal__body  { padding: var(--space-5); max-height: 70vh; overflow-y: auto; }
.c-modal__footer {
    display: flex; justify-content: flex-end; gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--border-subtle);
    background: var(--surface-sunken);
}
.c-modal--wide { width: min(920px, calc(100vw - 2 * var(--space-4))); }

/* ============================================================================
   Drawer — the tree's member panel, and the sidebar on small screens.
   ============================================================================ */
.c-drawer {
    position: fixed;
    top: 0; bottom: 0; right: 0;
    z-index: var(--z-drawer);
    display: flex;
    flex-direction: column;
    width: min(var(--drawer-w), 100vw);
    background: var(--surface-overlay);
    border-left: 1px solid var(--border-subtle);
    box-shadow: var(--shadow-xl);
    transform: translateX(100%);
    transition: transform var(--duration-base) var(--ease-out);
}
.c-drawer[data-open="true"] { transform: translateX(0); }
.c-drawer--left { right: auto; left: 0; border-left: 0; border-right: 1px solid var(--border-subtle); transform: translateX(-100%); }
.c-drawer--left[data-open="true"] { transform: translateX(0); }

.c-drawer__header {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--border-subtle);
}
.c-drawer__body   { flex: 1; overflow-y: auto; padding: var(--space-5); }
.c-drawer__footer { padding: var(--space-4) var(--space-5); border-top: 1px solid var(--border-subtle); }

.c-drawer-backdrop {
    position: fixed; inset: 0;
    z-index: calc(var(--z-drawer) - 1);
    background: var(--backdrop);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-out);
}
.c-drawer-backdrop[data-open="true"] { opacity: 1; pointer-events: auto; }

/* On a phone the side drawer becomes a bottom sheet — a 420px panel on a 375px
   screen is a full-screen takeover with none of the affordances. */
@media (max-width: 640px) {
    .c-drawer:not(.c-drawer--keep-side) {
        top: auto;
        left: 0; right: 0;
        width: 100%;
        height: 72vh;
        border-left: 0;
        border-top: 1px solid var(--border-subtle);
        border-radius: var(--radius-xl) var(--radius-xl) 0 0;
        transform: translateY(100%);
    }
    .c-drawer:not(.c-drawer--keep-side)[data-open="true"] { transform: translateY(0); }
    .c-drawer__handle {
        width: 36px; height: 4px;
        margin: var(--space-2) auto 0;
        border-radius: var(--radius-full);
        background: var(--border-strong);
    }
}
.c-drawer__handle { display: none; }
@media (max-width: 640px) { .c-drawer__handle { display: block; } }

/* ============================================================================
   Toast
   ============================================================================ */
.c-toast-stack {
    position: fixed;
    top: var(--space-4); right: var(--space-4);
    z-index: var(--z-toast);
    display: flex; flex-direction: column; gap: var(--space-2);
    max-width: min(380px, calc(100vw - 2 * var(--space-4)));
}
.c-toast {
    display: flex; align-items: flex-start; gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-subtle);
    border-left-width: 3px;
    border-radius: var(--radius-md);
    background: var(--surface-overlay);
    box-shadow: var(--shadow-lg);
    font-size: var(--fs-sm);
    animation: c-toast-in var(--duration-base) var(--ease-out);
}
@keyframes c-toast-in { from { opacity: 0; transform: translateX(12px); } }
.c-toast--success { border-left-color: var(--status-success-border); }
.c-toast--danger  { border-left-color: var(--status-danger-border); }
.c-toast--warning { border-left-color: var(--status-warning-border); }
.c-toast--info    { border-left-color: var(--status-info-border); }

/* ============================================================================
   Menu / dropdown / typeahead results
   ============================================================================ */
.c-menu {
    min-width: 200px;
    padding: var(--space-1);
    margin: 0;
    list-style: none;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-overlay);
    box-shadow: var(--shadow-lg);
    max-height: 380px;
    overflow-y: auto;
}
.c-menu__item {
    display: flex; align-items: center; gap: var(--space-3);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: var(--fs-sm);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}
.c-menu__item:hover,
.c-menu__item[aria-selected="true"],
.c-menu__item.is-active {
    background: var(--accent-subtle);
    color: var(--accent-text);
    text-decoration: none;
}
.c-menu__item--muted { color: var(--text-muted); cursor: default; }
.c-menu__item--muted:hover { background: none; color: var(--text-muted); }
.c-menu__divider { height: 1px; margin: var(--space-1) 0; background: var(--border-subtle); }
.c-menu__label {
    padding: var(--space-2) var(--space-3) var(--space-1);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semibold);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
}

/* ============================================================================
   Vendor reskins
   ----------------------------------------------------------------------------
   toastr, sweetalert and DataTables keep their JavaScript — it is called from
   the existing jQuery modules — but their stylesheets are dropped and their
   generated markup restyled here. This is what lets those widgets match the
   design system without touching members.js, finance.js or layout-init.js.
   ============================================================================ */

/* ---- toastr ------------------------------------------------------------- */
/* Positioning, like sweetalert's, came from the stylesheet we dropped. Without
   it the container is static and toasts render in the document flow, shoving
   the page down instead of floating over it. members.js, finance.js and
   finance-profile.js all pass positionClass 'toast-top-right'. */
#toast-container {
    position: fixed;
    z-index: var(--z-toast);
    pointer-events: none;                 /* the toasts themselves re-enable it */
}
#toast-container > * { pointer-events: auto; }

#toast-container.toast-top-right    { top: var(--space-4); right: var(--space-4); }
#toast-container.toast-top-left     { top: var(--space-4); left: var(--space-4); }
#toast-container.toast-bottom-right { bottom: var(--space-4); right: var(--space-4); }
#toast-container.toast-bottom-left  { bottom: var(--space-4); left: var(--space-4); }
#toast-container.toast-top-center   { top: var(--space-4); left: 50%; transform: translateX(-50%); }

/* A container with no recognised position class still has to float. */
#toast-container:not([class*="toast-"]) { top: var(--space-4); right: var(--space-4); }
#toast-container > div {
    display: flex; align-items: flex-start; gap: var(--space-3);
    width: auto; max-width: 380px;
    padding: var(--space-3) var(--space-4);
    margin: 0 0 var(--space-2);
    border: 1px solid var(--border-subtle);
    border-left-width: 3px;
    border-radius: var(--radius-md);
    background-image: none !important;
    background-color: var(--surface-overlay);
    box-shadow: var(--shadow-lg);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: var(--fs-sm);
    opacity: 1;
}
#toast-container > div:hover { box-shadow: var(--shadow-xl); }
#toast-container > .toast-success { border-left-color: var(--status-success-border); }
#toast-container > .toast-error   { border-left-color: var(--status-danger-border); }
#toast-container > .toast-warning { border-left-color: var(--status-warning-border); }
#toast-container > .toast-info    { border-left-color: var(--status-info-border); }
.toast-title   { font-weight: var(--fw-semibold); }
.toast-message { color: var(--text-secondary); }
.toast-close-button {
    color: var(--text-muted);
    text-shadow: none;
    opacity: 0.7;
    font-weight: var(--fw-normal);
}
.toast-close-button:hover { color: var(--text-primary); opacity: 1; }

/* ---- sweetalert (1.x — the callback API members.js/finance.js use) -------
   The LAYOUT rules here are not cosmetic. Dropping sweetalert.css also dropped
   the positioning it supplied, and the dialog fell back to position:static —
   rendering as a full-width block 668px down the document while the overlay
   dimmed the screen. It looked exactly like a hang: the page greys out and no
   dialog appears. Every delete confirmation in the portal goes through this. */
.sweet-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    background: var(--backdrop) !important;
}
.sweet-alert {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: calc(var(--z-modal) + 1);
    width: min(460px, calc(100vw - 2 * var(--space-4)));
    max-height: calc(100vh - 2 * var(--space-6));
    overflow-y: auto;
    margin: 0 !important;
    padding: var(--space-6);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-overlay) !important;
    box-shadow: var(--shadow-xl);
    font-family: var(--font-sans);
    text-align: center;
}
/* sweetalert ships markup for every mode it supports and relies on its own CSS
   to hide the parts a given call does not use. Without that, a plain confirm
   dialog also rendered an empty text input and the words "Not valid!" — both
   belong to prompt mode. Its JavaScript adds .show-input / .show when it wants
   them, so honouring those classes keeps prompt mode working. */
.sweet-alert input { display: none; }
.sweet-alert.show-input input {
    display: block;
    width: 100%;
    height: 38px;
    margin-top: var(--space-4);
    padding: 0 var(--space-3);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--surface-raised);
    color: var(--text-primary);
}
.sweet-alert .sa-input-error { display: none; }
.sweet-alert .sa-error-container { display: none; }
.sweet-alert .sa-error-container.show {
    display: block;
    margin-top: var(--space-3);
    color: var(--status-danger-text);
    font-size: var(--fs-sm);
}

.sweet-alert h2 {
    margin: 0 0 var(--space-2);
    color: var(--text-primary);
    font-size: var(--fs-lg);
    font-weight: var(--fw-semibold);
}
.sweet-alert p { color: var(--text-secondary); font-size: var(--fs-sm); }
.sweet-alert .sa-button-container { margin-top: var(--space-5); }
.sweet-alert button {
    height: 38px;
    padding: 0 var(--space-5);
    border: 1px solid transparent;
    border-radius: var(--radius-md) !important;
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    box-shadow: none !important;
}
.sweet-alert button.confirm {
    background-color: var(--accent) !important;
    color: var(--text-on-accent);
}
.sweet-alert button.confirm:hover { background-color: var(--accent-hover) !important; }
.sweet-alert button.cancel {
    background-color: var(--surface-raised) !important;
    border-color: var(--border-default);
    color: var(--text-primary);
}
.sweet-alert button.cancel:hover { background-color: var(--surface-hover) !important; }
.sweet-alert button:focus-visible { box-shadow: var(--ring-focus) !important; }

/* ---- DataTables (layout-init.js binds .myTable / .myTableSelect) --------- */
.dataTables_wrapper {
    font-size: var(--fs-sm);
    color: var(--text-secondary);
}
.dataTables_wrapper .dataTables_filter { margin-bottom: var(--space-3); }
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
    height: 34px;
    padding: 0 var(--space-3);
    margin-left: var(--space-2);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--surface-raised);
    color: var(--text-primary);
}
.dataTables_wrapper .dataTables_filter input:focus,
.dataTables_wrapper .dataTables_length select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--ring-focus);
}
.dataTables_wrapper .dataTables_info { padding-top: var(--space-3); color: var(--text-muted); font-size: var(--fs-xs); }
.dataTables_wrapper .dataTables_paginate { padding-top: var(--space-3); }
.dataTables_wrapper .dataTables_paginate .paginate_button {
    padding: var(--space-1) var(--space-3) !important;
    margin-left: var(--space-1);
    border: 1px solid transparent !important;
    border-radius: var(--radius-md) !important;
    background: none !important;
    color: var(--text-secondary) !important;
    font-size: var(--fs-sm);
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
    background: var(--surface-hover) !important;
    border-color: var(--border-default) !important;
    color: var(--text-primary) !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current {
    background: var(--accent) !important;
    border-color: var(--accent) !important;
    color: var(--text-on-accent) !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled {
    opacity: 0.4;
    pointer-events: none;
}
table.dataTable thead th { position: relative; }
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc { cursor: pointer; }
