/* ============================================================
   DEC 敬拜团排班系统 — app.css
   SHARED THEME LAYER — keep this block identical across the DEC PHP apps
   (vault.dec4u.org / ticket.dec4u.org / worship.service.dec4u.org).

   A theme layer over Bootstrap 5.3, not a replacement: it re-points
   Bootstrap's own CSS variables at the house design tokens (tinted page,
   white cards, soft shadows, 14px corners, a CJK-aware 14.5px base) and then
   nudges a handful of components. Views keep using plain Bootstrap classes,
   so the markup stays maintainable while the look stays ours.

   To restyle an app, change the tokens in the two :root blocks — avoid adding
   component rules unless Bootstrap truly has no equivalent. Anything below the
   "APP-SPECIFIC" marker at the end of the file is that app's own.
   ============================================================ */

/* ---------- Design tokens (light) ---------- */
:root {
    /* Brand */
    --app-brand: #4f46e5;
    --app-brand-hover: #4338ca;
    --app-brand-active: #3730a3;
    --app-brand-soft: #eef2ff;     /* tinted background for active/selected */
    --app-brand-grad: linear-gradient(135deg, #4f46e5, #7c3aed);

    /* Surfaces: page is tinted, cards/sidebar/topbar are white */
    --app-page-bg: #f6f7fb;
    --app-surface: #ffffff;
    --app-surface-2: #f9fafc;      /* hover rows, subtle fills */

    /* Ink */
    --app-text: #1e2233;
    --app-muted: #71768a;
    --app-faint: #9aa0b3;

    /* Lines, corners, depth */
    --app-border: #e6e8ef;
    --app-border-strong: #d5d9e4;
    --app-shadow: 0 1px 2px rgba(24, 28, 50, .04), 0 4px 16px rgba(24, 28, 50, .06);
    --app-shadow-lg: 0 10px 40px rgba(24, 28, 50, .14);
    --app-radius: 14px;
    --app-radius-sm: 10px;

    --app-sidebar-w: 250px;
    --app-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
                "Microsoft YaHei", "Hiragino Sans GB", Roboto, Helvetica, Arial, sans-serif;

    /* ---- Hand these tokens to Bootstrap ---- */
    --bs-body-font-family: var(--app-font);
    --bs-body-font-size: 14.5px;
    --bs-body-line-height: 1.55;
    --bs-body-bg: var(--app-page-bg);
    --bs-body-color: var(--app-text);
    --bs-secondary-color: var(--app-muted);
    --bs-tertiary-color: var(--app-faint);
    --bs-secondary-bg: var(--app-surface-2);
    --bs-tertiary-bg: var(--app-surface-2);
    --bs-border-color: var(--app-border);
    --bs-border-color-translucent: var(--app-border);
    /* Base radius is the CONTROL radius; cards opt up to --app-radius. */
    --bs-border-radius: var(--app-radius-sm);
    --bs-border-radius-lg: var(--app-radius);
    --bs-border-radius-sm: 7px;
    --bs-link-color: var(--app-brand);
    --bs-link-hover-color: var(--app-brand-hover);
    --bs-emphasis-color: var(--app-text);

    /* Bootstrap's "primary" family = our indigo, so every bg-primary-subtle /
       text-primary-emphasis utility is on-brand without extra classes. */
    --bs-primary: var(--app-brand);
    --bs-primary-rgb: 79, 70, 229;
    --bs-primary-bg-subtle: var(--app-brand-soft);
    --bs-primary-border-subtle: #c7d2fe;
    --bs-primary-text-emphasis: #3730a3;
}

/* ---------- Design tokens (dark) ---------- */
[data-bs-theme="dark"] {
    --app-brand: #818cf8;
    --app-brand-hover: #6366f1;
    --app-brand-active: #4f46e5;
    --app-brand-soft: #1e213a;
    --app-brand-grad: linear-gradient(135deg, #6366f1, #8b5cf6);

    --app-page-bg: #0f1117;
    --app-surface: #171a23;
    --app-surface-2: #1d212c;

    --app-text: #e7e9f0;
    --app-muted: #9096a8;
    --app-faint: #6b7183;

    --app-border: #272b38;
    --app-border-strong: #333848;
    --app-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 16px rgba(0, 0, 0, .3);
    --app-shadow-lg: 0 10px 40px rgba(0, 0, 0, .5);

    --bs-primary: #818cf8;
    --bs-primary-rgb: 129, 140, 248;
    --bs-primary-bg-subtle: #1e213a;
    --bs-primary-border-subtle: #312e81;
    --bs-primary-text-emphasis: #a5b4fc;
}

body { -webkit-font-smoothing: antialiased; }

/* ---------- Cards: white, rounded, softly raised ---------- */
.card {
    --bs-card-bg: var(--app-surface);
    --bs-card-border-color: var(--app-border);
    --bs-card-border-radius: var(--app-radius);
    --bs-card-inner-border-radius: calc(var(--app-radius) - 1px);
    --bs-card-cap-bg: transparent;
    box-shadow: var(--app-shadow);
}
.card-header { padding: .85rem 1.1rem; border-bottom-color: var(--app-border); font-weight: 700; }
.card-header .ic { color: var(--app-muted); }
.card-body { padding: 1.1rem; }
/* A card that is itself a link (stat tiles) lifts on hover. */
a.card { transition: transform .14s, box-shadow .14s, border-color .14s; }
a.card:hover {
    transform: translateY(-2px);
    box-shadow: var(--app-shadow-lg);
    border-color: var(--app-border-strong);
}

/* ---------- Tables: small uppercase heads, quiet rules ---------- */
.table {
    --bs-table-bg: transparent;
    --bs-table-border-color: var(--app-border);
    --bs-table-hover-bg: var(--app-surface-2);
    font-size: 13.5px;
    margin-bottom: 0;
}
.table > thead > tr > th {
    padding: .75rem .9rem;
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--app-faint);
    background: transparent;
    border-bottom: 1px solid var(--app-border);
    white-space: nowrap;
}
.table > tbody > tr > td { padding: .7rem .9rem; border-color: var(--app-border); }
.table > tbody > tr:last-child > td { border-bottom: 0; }

/* ---------- Buttons: compact, 600 weight ---------- */
.btn {
    --bs-btn-font-size: 13.5px;
    --bs-btn-font-weight: 600;
    --bs-btn-padding-y: .5rem;
    --bs-btn-padding-x: .9rem;
    --bs-btn-border-radius: var(--app-radius-sm);
    white-space: nowrap;
}
.btn-sm { --bs-btn-font-size: 12.5px; --bs-btn-padding-y: .3rem; --bs-btn-padding-x: .6rem; }
.btn-primary {
    --bs-btn-bg: var(--app-brand);
    --bs-btn-border-color: var(--app-brand);
    --bs-btn-hover-bg: var(--app-brand-hover);
    --bs-btn-hover-border-color: var(--app-brand-hover);
    --bs-btn-active-bg: var(--app-brand-active);
    --bs-btn-active-border-color: var(--app-brand-active);
    --bs-btn-disabled-bg: var(--app-brand);
    --bs-btn-disabled-border-color: var(--app-brand);
}
/* Neutral buttons read as "surface with a hairline", not as outlines. */
.btn-outline-secondary, .btn-light {
    --bs-btn-color: var(--app-text);
    --bs-btn-bg: var(--app-surface);
    --bs-btn-border-color: var(--app-border-strong);
    --bs-btn-hover-color: var(--app-text);
    --bs-btn-hover-bg: var(--app-surface-2);
    --bs-btn-hover-border-color: var(--app-faint);
    --bs-btn-active-color: var(--app-text);
    --bs-btn-active-bg: var(--app-surface-2);
    --bs-btn-active-border-color: var(--app-faint);
}
/* Segmented controls (language switcher): quiet pills, tinted when on. */
.btn-group .btn-outline-secondary {
    --bs-btn-font-size: 12.5px;
    --bs-btn-border-color: var(--app-border);
    --bs-btn-color: var(--app-muted);
}
.btn-group .btn-outline-secondary.active {
    background: var(--app-brand-soft);
    border-color: var(--app-brand-soft);
    color: var(--app-brand);
}

/* ---------- Forms ---------- */
.form-control, .form-select {
    font-size: 14.5px;
    padding: .55rem .75rem;
    border-radius: var(--app-radius-sm);
    background-color: var(--app-surface);
    border-color: var(--app-border-strong);
    color: var(--app-text);
}
.form-control:focus, .form-select:focus {
    background-color: var(--app-surface);
    border-color: var(--app-brand);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, .14);
}
.form-control::placeholder { color: var(--app-faint); }
.form-label { font-size: 13px; font-weight: 650; margin-bottom: .3rem; }
.form-text { font-size: 12px; color: var(--app-faint); }
.form-check-input:checked { background-color: var(--app-brand); border-color: var(--app-brand); }
.form-check-input:focus { border-color: var(--app-brand); box-shadow: 0 0 0 3px rgba(79, 70, 229, .14); }
.input-group > .form-control:focus { z-index: 3; }
/* Date boxes open the picker on click anywhere (see app.js). */
input[type="date"] { cursor: pointer; }
input[type="date"]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .55; }
input[type="date"]:hover::-webkit-calendar-picker-indicator { opacity: .9; }

/* ---------- Alerts, dropdowns, lists, badges ---------- */
.alert {
    --bs-alert-border-radius: var(--app-radius-sm);
    font-weight: 500;
    box-shadow: var(--app-shadow);
}
.dropdown-menu {
    --bs-dropdown-bg: var(--app-surface);
    --bs-dropdown-border-color: var(--app-border);
    --bs-dropdown-border-radius: var(--app-radius-sm);
    box-shadow: var(--app-shadow-lg);
}
.list-group {
    --bs-list-group-bg: transparent;
    --bs-list-group-border-color: var(--app-border);
}
.badge {
    --bs-badge-padding-y: .22em;
    --bs-badge-padding-x: .6em;
    --bs-badge-font-size: 11.5px;
    --bs-badge-font-weight: 650;
    line-height: 1.4;
}

/* Sidebar links: tinted when active (not a solid block), muted at rest. */
.nav-pills {
    --bs-nav-link-padding-y: .55rem;
    --bs-nav-link-padding-x: .75rem;
    --bs-nav-pills-border-radius: var(--app-radius-sm);
}
.nav-pills .nav-link {
    color: var(--app-muted);
    font-weight: 500;
    transition: background-color .12s, color .12s;
}
.nav-pills .nav-link:hover:not(.active) { background: var(--app-surface-2); color: var(--app-text); }
.nav-pills .nav-link.active {
    background: var(--app-brand-soft);
    color: var(--app-brand);
    font-weight: 600;
}
.nav-pills .nav-link.active .ic { color: var(--app-brand); }

/* ---------- Small shared bits ---------- */
a.link { color: var(--app-brand); font-weight: 600; text-decoration: none; }
a.link:hover { text-decoration: underline; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.avatar { border-radius: 50%; object-fit: cover; }
.avatar-initials {
    display: inline-flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 600; flex: 0 0 auto;
}
.ic { flex: 0 0 auto; vertical-align: middle; }
tr.row-inactive > td { opacity: .55; }
.min-w-0 { min-width: 0; }

/* ============================================================
   APP-SPECIFIC — 敬拜团排班系统
   Everything above this marker is the shared theme layer.
   ============================================================ */

/* ---------- App shell ---------- */
.ws-sidebar {
    width: var(--app-sidebar-w);
    background: var(--app-surface);
    border-right: 1px solid var(--app-border);
    position: sticky;
    top: 0;
    height: 100vh;
}
.ws-offcanvas {
    width: var(--app-sidebar-w);
    --bs-offcanvas-bg: var(--app-surface);
    --bs-offcanvas-border-color: var(--app-border);
}
.ws-topbar {
    min-height: 60px;
    background: color-mix(in srgb, var(--app-surface) 82%, transparent);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--app-border) !important;
    position: sticky;
    top: 0;
    z-index: 1020;
}
.ws-topbar > span { font-size: 15px; font-weight: 700; }
.ws-topbar .dropdown-toggle { border-radius: 999px; padding: .25rem .7rem .25rem .3rem; }
.ws-brand-logo {
    width: 38px; height: 38px; flex: 0 0 38px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 10px;
    background: var(--app-brand-grad);
    color: #fff; font-weight: 800; font-size: 14px; letter-spacing: .5px;
}
.ws-nav-section {
    margin: 1rem 0 .25rem .75rem;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    color: var(--app-faint);
}
/* ---------- Stat tile icon chip (dashboard / PCO) ----------
   Pass the accent through --c: <div class="ws-stat-icon" style="--c:#4f46e5">. */
.ws-stat-icon {
    width: 38px; height: 38px;
    border-radius: 10px;
    display: grid; place-items: center;
    color: var(--c, var(--app-brand));
    background: color-mix(in srgb, var(--c, var(--app-brand)) 13%, transparent);
    margin-bottom: .75rem;
}
.ws-stat-val { font-size: 20px; font-weight: 780; line-height: 1.2; letter-spacing: -.02em; word-break: break-word; }
.ws-stat-label { font-size: 12.5px; color: var(--app-muted); margin-top: .3rem; }

/* ---------- Proficiency scale (新手 → 资深) ----------
   Four levels that must stay distinguishable at a glance in both themes.
   Built on Bootstrap's *-subtle / *-emphasis pairs so dark mode follows. */
.ws-lv { --ws-lv-bg: var(--bs-secondary-bg); --ws-lv-fg: var(--bs-secondary-color);
    background: var(--ws-lv-bg); color: var(--ws-lv-fg); }
.ws-lv-1 { --ws-lv-bg: var(--bs-danger-bg-subtle);  --ws-lv-fg: var(--bs-danger-text-emphasis); }
.ws-lv-2 { --ws-lv-bg: var(--bs-warning-bg-subtle); --ws-lv-fg: var(--bs-warning-text-emphasis); }
.ws-lv-3 { --ws-lv-bg: var(--bs-info-bg-subtle);    --ws-lv-fg: var(--bs-info-text-emphasis); }
.ws-lv-4 { --ws-lv-bg: var(--bs-success-bg-subtle); --ws-lv-fg: var(--bs-success-text-emphasis); }
/* Same scale applied to the inline <select> admins use on the people page. */
.ws-lv-select { min-width: 6.5rem; }
.ws-lv-select.ws-lv-1 { background-color: var(--bs-danger-bg-subtle);  color: var(--bs-danger-text-emphasis); }
.ws-lv-select.ws-lv-2 { background-color: var(--bs-warning-bg-subtle); color: var(--bs-warning-text-emphasis); }
.ws-lv-select.ws-lv-3 { background-color: var(--bs-info-bg-subtle);    color: var(--bs-info-text-emphasis); }
.ws-lv-select.ws-lv-4 { background-color: var(--bs-success-bg-subtle); color: var(--bs-success-text-emphasis); }

/* ---------- Schedule grid (dates × position seats) ----------
   A wide matrix: the position column stays put while dates scroll. */
.ws-sched { white-space: nowrap; }
.ws-sched th, .ws-sched td { vertical-align: middle; }
.ws-sched .ws-pos {
    position: sticky; left: 0; z-index: 2;
    background: var(--app-surface);
    border-right: 1px solid var(--app-border);
    white-space: normal; min-width: 8rem;
}
.ws-sched thead .ws-pos { z-index: 3; }
.ws-sched .ws-date { font-weight: 700; }
.ws-sched .ws-date small { display: block; font-weight: 400; color: var(--app-faint); }
.ws-cell-gap    { background: var(--bs-danger-bg-subtle); }
.ws-cell-except { background: var(--bs-warning-bg-subtle); }

/* The people × positions proficiency matrix scrolls the same way. */
.ws-matrix th:first-child, .ws-matrix td:first-child {
    position: sticky; left: 0; z-index: 2;
    background: var(--app-surface);
    border-right: 1px solid var(--app-border);
}
.ws-matrix thead th:first-child { z-index: 3; }

/* ---------- 服事報告 (/report) ----------
   One hue for "people on the roster": slot-1 blue for what has been served,
   a lighter step of the same blue for what is scheduled but still to come
   (an ordinal pair, validated against the card surface in both modes; dark
   mode gets its own steps rather than a flip). "Nobody" stays neutral grey.
   Colours mark bars only — numbers and labels stay in the text inks. */
:root {
    --rp-main: #2a78d6;
    --rp-plan: #86b6ef;
    --rp-zero: #b9bdc9;
    --rp-grid: #eef0f4;
    --rp-axis: var(--app-border-strong);
    --rp-bad:  #d03b3b;
}
[data-bs-theme="dark"] {
    --rp-main: #3987e5;
    --rp-plan: #184f95;
    --rp-zero: #5b6172;
    --rp-grid: #232733;
    --rp-bad:  #e66767;
}

/* Period picker */
.ws-rp-nav { padding: .35rem; gap: .25rem; }
.ws-rp-navbtn {
    width: 34px; height: 34px; padding: 0;
    display: grid; place-items: center;
    border: 0; color: var(--app-muted);
}
.ws-rp-navbtn:hover { background: var(--app-surface-2); color: var(--app-text); }
.ws-rp-navbtn.disabled { opacity: .3; }

/* KPI tiles (reuse .ws-stat-icon / -label; the dashboard's 20px value is too quiet for a headline) */
.ws-rp-val { font-size: 28px; font-weight: 780; line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.ws-rp-unit { font-size: 15px; font-weight: 600; margin-left: .2rem; letter-spacing: 0; color: var(--app-muted); }
.ws-rp-sub { font-size: 12px; color: var(--app-faint); margin-top: .35rem; }
.ws-rp-delta { font-size: 11.5px; font-weight: 600; color: var(--app-muted); white-space: nowrap; padding-top: .2rem; }
.ws-rp-headnum { font-size: 13px; font-weight: 600; color: var(--app-muted); }
.ws-rp-bad  { color: var(--rp-bad); font-weight: 600; }
.ws-rp-warn { color: var(--bs-warning-text-emphasis); font-weight: 600; }

/* Colour keys */
.ws-rp-swatch { display: inline-block; flex: 0 0 auto; width: 10px; height: 10px; border-radius: 3px; background: var(--k); }
.ws-rp-keys { display: flex; flex-wrap: wrap; gap: .3rem 1rem; font-size: 12.5px; font-weight: 500; color: var(--app-muted); }
.ws-rp-keys li { display: flex; align-items: center; gap: .4rem; }

/* People on, month by month: one column per month, each links to its month.
   Grid rows: plot / month labels / seats per month. */
.ws-rp-chart {
    display: grid; grid-template-columns: 2.4rem minmax(0, 1fr);
    column-gap: .5rem; row-gap: .4rem; margin-top: .6rem;
}
.ws-rp-yaxis { position: relative; height: 190px; }
.ws-rp-yaxis span {
    position: absolute; right: 0; transform: translateY(50%);
    font-size: 11px; line-height: 1; color: var(--app-faint); font-variant-numeric: tabular-nums;
}
.ws-rp-plot { position: relative; height: 190px; border-bottom: 1px solid var(--rp-axis); }
.ws-rp-gl { position: absolute; left: 0; right: 0; border-top: 1px solid var(--rp-grid); }
.ws-rp-cols { position: absolute; inset: 0; display: flex; }
.ws-rp-col {
    flex: 1 1 0; min-width: 0; height: 100%;
    display: flex; align-items: flex-end; justify-content: center;
    border-radius: 6px 6px 0 0; color: inherit; text-decoration: none; outline-offset: -2px;
}
.ws-rp-col:hover, .ws-rp-col:focus-visible { background: color-mix(in srgb, var(--app-text) 4%, transparent); }
.ws-rp-col.is-sel { background: color-mix(in srgb, var(--app-brand) 9%, transparent); }
.ws-rp-col:hover .ws-rp-bar { filter: brightness(1.08); }
.ws-rp-bar { width: min(24px, 60%); background: var(--k); border-radius: 4px 4px 0 0; }
.ws-rp-xrow { display: flex; }
.ws-rp-xrow span {
    flex: 1 1 0; min-width: 0; text-align: center; white-space: nowrap;
    font-size: 11px; color: var(--app-faint); font-variant-numeric: tabular-nums;
}
.ws-rp-xrow span.is-sel { color: var(--app-text); font-weight: 700; }
.ws-rp-seatrow { padding-top: .35rem; border-top: 1px dashed var(--app-border); }
.ws-rp-seatrow span { font-size: 12px; color: var(--app-muted); }
.ws-rp-rowlabel {
    align-self: end; text-align: right; white-space: nowrap;
    font-size: 11px; font-weight: 700; color: var(--app-faint); cursor: help;
}
/* Phones: every other month label, and none crowding a selected one */
@media (max-width: 575.98px) {
    .ws-rp-xrow:not(.ws-rp-seatrow) span:nth-child(even):not(.is-sel),
    .ws-rp-xrow:not(.ws-rp-seatrow) span.is-sel + span:not(.is-sel),
    .ws-rp-xrow:not(.ws-rp-seatrow) span:not(.is-sel):has(+ span.is-sel) { visibility: hidden; }
}

/* Chart tooltip (built by app.js from data-tip) — value first, label after */
.ws-rp-tip {
    position: fixed; z-index: 1080; pointer-events: none; min-width: 150px;
    padding: .55rem .7rem; border-radius: 10px;
    background: var(--app-surface); border: 1px solid var(--app-border); box-shadow: var(--app-shadow-lg);
    font-size: 12.5px;
}
.ws-rp-tip-title { font-weight: 700; margin-bottom: .3rem; }
.ws-rp-tip-row { display: flex; align-items: center; gap: .5rem; padding: .1rem 0; }
.ws-rp-tip-row i { flex: 0 0 auto; width: 12px; height: 3px; border-radius: 2px; background: var(--k); }
.ws-rp-tip-row b { min-width: 2ch; text-align: right; font-variant-numeric: tabular-nums; }
.ws-rp-tip-row span { color: var(--app-muted); }

.ws-rp-tableview summary { width: fit-content; font-size: 12.5px; color: var(--app-muted); cursor: pointer; }
.ws-rp-tnum td { font-variant-numeric: tabular-nums; }

/* Horizontal bars: how many people were on 0, 1, 2 … times (scaled to the biggest bucket) */
.ws-rp-hbars { display: grid; gap: .6rem; }
.ws-rp-hrow { display: grid; grid-template-columns: minmax(5.5em, 26%) 1fr auto; align-items: center; gap: .75rem; }
.ws-rp-hlabel { font-size: 13px; font-weight: 600; line-height: 1.3; }
.ws-rp-htrack { height: 12px; background: var(--rp-grid); border-radius: 0 4px 4px 0; }
.ws-rp-hbar { display: block; height: 100%; background: var(--k); border-radius: 0 4px 4px 0; }
.ws-rp-hval { display: flex; align-items: baseline; justify-content: flex-end; gap: .4rem; min-width: 5em; font-variant-numeric: tabular-nums; }
.ws-rp-hval b { font-size: 15px; }
.ws-rp-hval span { min-width: 4ch; text-align: right; font-size: 12px; color: var(--app-faint); }
.ws-rp-note {
    display: flex; align-items: flex-start; gap: .45rem;
    margin-top: 1rem; padding: .5rem .65rem; border-radius: 8px;
    background: var(--app-surface-2); font-size: 12.5px; color: var(--app-muted);
}
.ws-rp-note .ic { margin-top: 2px; }

/* Tables: a small bar beside the number (served + scheduled share one track) */
.ws-rp-barcol { min-width: 9rem; }
.ws-rp-ibar { display: flex; align-items: center; gap: .5rem; }
.ws-rp-itrack { display: flex; gap: 1px; flex: 0 0 6rem; height: 8px; }
.ws-rp-itrack > span { display: block; height: 100%; background: var(--k, var(--rp-main)); }
.ws-rp-itrack > span:last-child { border-radius: 0 3px 3px 0; }
.ws-rp-ibar b { font-weight: 600; min-width: 2ch; }
tr.ws-rp-idle > td { color: var(--app-muted); }
