/* ============================================================================
   KOSIS — assets/css/kosis-attendance.css
   ----------------------------------------------------------------------------
   Module 1 (SDP2): Attendance & Participation Tracking.
   Page-specific styling for pages/attendance.php. Loaded only on that page via
   the $pageExtraCss hook, AFTER the shared chain, so all --ks-* tokens and base
   components (.ks-card, .ks-input, .btn, .ks-tabs) are available.

   Status colour convention (shared by the marking selector summary chips and
   the history badges):
     present    = sage/green   (there, on time)
     late       = gold/amber   (there, but late — the chargeable case)
     left_early = teal         (there, but left)
     excused    = slate/blue   (away, allowed)
     absent     = brick/red    (away, not allowed)
   ============================================================================ */

/* ── Summary chips (counts per status for the selected event) ─────────────── */
.ks-att-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: var(--ks-space-md);
}
.ks-att-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: .35rem .7rem;
    border-radius: 999px;
    font-size: .85rem;
    border: 1px solid var(--ks-border);
    background: #fff;
    color: var(--ks-slate);
}
.ks-att-chip strong { color: var(--ks-navy); font-weight: 700; }
.ks-att-chip--present    { background: #EAF3EE; border-color: #BFD9C9; color: #2E6347; }
.ks-att-chip--late       { background: #FBF1DC; border-color: #E6CF95; color: #8A6312; }
.ks-att-chip--left_early { background: #E6F0F2; border-color: #B6D4D9; color: #2E6470; }
.ks-att-chip--excused    { background: #ECEFF6; border-color: #C5CEE0; color: #3A4A6B; }
.ks-att-chip--absent     { background: #F8E9E7; border-color: #E3BDB6; color: #9A3B2E; }
.ks-att-chip--total      { background: var(--ks-parchment, #FBF7EC); border-color: var(--ks-gold); color: var(--ks-navy); }

/* ── Marking + reporting tables (CSS grid "tables") ───────────────────────── */
.ks-att-form { margin-top: 0; }

.ks-att-table {
    width: 100%;
    border: 1px solid var(--ks-border);
    border-radius: var(--ks-radius-md, 12px);
    /* Scroll wide grids horizontally on a narrow window instead of clipping the
       right-hand action/export column (was overflow:hidden). Stacked-card mode
       on small viewports fits the container, so no scrollbar appears there. */
    overflow-x: auto;
    overflow-y: hidden;
    background: #fff;
}
.ks-att-row {
    display: grid;
    grid-template-columns: minmax(140px, 1.6fr) 150px 96px minmax(120px, 1.4fr);
    align-items: center;
    gap: 10px;
    padding: .55rem .75rem;
    border-bottom: 1px solid var(--ks-border);
}
.ks-att-row:last-child { border-bottom: 0; }
.ks-att-row--head {
    background: var(--ks-parchment, #FBF7EC);
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 700;
    color: var(--ks-muted, #6B7280);
}
.ks-att-row:not(.ks-att-row--head):nth-child(even) { background: #FCFBF7; }

.ks-att-cell { min-width: 0; }
.ks-att-cell--name { display: flex; flex-direction: column; gap: 1px; }
.ks-att-membername { font-weight: 600; color: var(--ks-navy); }
.ks-att-membervoice { font-size: .76rem; color: var(--ks-muted, #6B7280); }

.ks-att-status { width: 100%; }
.ks-att-mins   { width: 100%; }
.ks-att-mins:disabled { background: #F1F0EC; color: var(--ks-muted, #9aa1ad); cursor: not-allowed; }

/* Totals + history tables have their own column shapes. */
.ks-att-table--totals .ks-att-row {
    grid-template-columns: minmax(120px, 1.4fr) repeat(6, 1fr) 64px;
}
.ks-att-table--totals .ks-att-cell { text-align: center; }
.ks-att-table--totals .ks-att-cell--name { text-align: left; display: block; font-weight: 600; color: var(--ks-navy); }

.ks-att-table--history .ks-att-row {
    grid-template-columns: minmax(160px, 2fr) 130px 90px minmax(120px, 1.6fr);
}
.ks-att-cell--when { display: flex; flex-direction: column; gap: 1px; }
.ks-att-histwhen  { font-size: .8rem; color: var(--ks-slate); }
.ks-att-histtitle { font-weight: 600; color: var(--ks-navy); }

.ks-att-viewlink { color: var(--ks-sage); text-decoration: none; font-weight: 600; font-size: .85rem; }
.ks-att-viewlink:hover { text-decoration: underline; }
.ks-att-viewlink--export { margin-left: 8px; font-size: 1rem; color: var(--ks-navy); }

.ks-att-detailhead {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 6px;
}
.ks-att-detailhead__export { white-space: nowrap; }

.ks-att-overview__title { display: block; color: var(--ks-navy); font-size: 1.05rem; margin-bottom: 4px; }

/* ── Status badges (history view) ─────────────────────────────────────────── */
.ks-att-badge {
    display: inline-block;
    padding: .2rem .55rem;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 600;
    border: 1px solid transparent;
}
.ks-att-badge--present    { background: #EAF3EE; border-color: #BFD9C9; color: #2E6347; }
.ks-att-badge--late       { background: #FBF1DC; border-color: #E6CF95; color: #8A6312; }
.ks-att-badge--left_early { background: #E6F0F2; border-color: #B6D4D9; color: #2E6470; }
.ks-att-badge--excused    { background: #ECEFF6; border-color: #C5CEE0; color: #3A4A6B; }
.ks-att-badge--absent     { background: #F8E9E7; border-color: #E3BDB6; color: #9A3B2E; }
.ks-att-badge--none       { background: #F1F0EC; border-color: var(--ks-border); color: var(--ks-muted, #6B7280); }

/* ── Event picker ──────────────────────────────────────────────────────────── */
.ks-att-picker__form { margin: 0; }
.ks-att-picker .ks-label--xs { display: block; margin-bottom: 4px; }

/* ── Mobile: collapse the grid tables into stacked cards ──────────────────── */
@media (max-width: 720px) {
    .ks-att-row,
    .ks-att-table--totals .ks-att-row,
    .ks-att-table--history .ks-att-row {
        grid-template-columns: 1fr 1fr;
        gap: 6px 10px;
    }
    .ks-att-row--head { display: none; }                 /* headers don't fit; cells self-label below */
    .ks-att-cell--name,
    .ks-att-cell--when { grid-column: 1 / -1; }
    .ks-att-table--totals .ks-att-cell { text-align: left; }
    /* Label the totals cells on mobile so the numbers keep meaning. */
    .ks-att-table--totals .ks-att-cell:not(.ks-att-cell--name)::before {
        content: attr(data-label);
        display: inline-block;
        min-width: 84px;
        font-size: .72rem;
        text-transform: uppercase;
        letter-spacing: .03em;
        color: var(--ks-muted, #6B7280);
    }
}

/* ── Prominent event picker ───────────────────────────────────────────────── */
.ks-att-picker__lead {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: var(--ks-space-sm);
}
.ks-att-picker__icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px; height: 38px;
    border-radius: 10px;
    background: var(--ks-navy);
    color: var(--ks-gold);
}
.ks-att-picker__title { display: block; color: var(--ks-navy); font-size: 1.05rem; }
.ks-att-picker__sub { margin: 2px 0 0; font-size: .85rem; color: var(--ks-muted, #6B7280); }
.ks-att-picker__label { display: block; margin-bottom: 4px; }
.ks-att-picker__selectwrap { position: relative; }
/* A bigger, unmistakably-interactive select with a custom caret.
   Selector = body.kosis-dashboard .ks-card select.ks-att-picker__select
   (specificity 0,3,2), chosen deliberately so it OUTRANKS the inline blade
   Polls-form override `body.kosis-dashboard .ks-card .ks-input` (0,3,1): the
   picker is a .ks-input inside a .ks-card, so that Polls rule was matching it
   and repainting it with the cream auth-input look (thin border, 13px, no
   caret). !important on every property additionally guards against the leaked
   kosis-public.css `input,select,textarea` auth rule (which in the v2 SPA
   loads globally onto the dashboard). The plain select.ks-att-picker__select
   fallback selector keeps it styled on any page that isn't .kosis-dashboard
   and matches the live app, where kosis-public.css isn't loaded here at all. */
body.kosis-dashboard .ks-card select.ks-att-picker__select,
select.ks-att-picker__select {
    width: 100% !important;
    box-sizing: border-box !important;
    min-height: 0 !important;
    height: auto !important;
    font-size: 1rem !important;
    padding: .7rem 2.4rem .7rem .8rem !important;
    border: 2px solid var(--ks-gold) !important;
    border-radius: var(--ks-radius-input, 10px) !important;
    background-color: #fff !important;
    color: var(--ks-navy) !important;
    font-weight: 600 !important;
    cursor: pointer !important;
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%231F2952' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right .9rem center !important;
}
body.kosis-dashboard .ks-card select.ks-att-picker__select:focus,
select.ks-att-picker__select:focus {
    outline: none !important;
    border-color: var(--ks-gold) !important;
    box-shadow: 0 0 0 3px rgba(212,169,85,.35) !important;
}

/* ── Chosen-event summary strip ───────────────────────────────────────────── */
.ks-att-selected {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: .7rem .9rem;
    margin-bottom: var(--ks-space-md);
    background: var(--ks-parchment, #FBF7EC);
    border: 1px solid var(--ks-border);
    border-left: 4px solid var(--ks-gold);
    border-radius: var(--ks-radius-md, 12px);
}
.ks-att-selected__info { display: flex; flex-direction: column; gap: 1px; margin-right: auto; }
.ks-att-selected__title { color: var(--ks-navy); font-size: 1rem; }
.ks-att-selected__when { font-size: .82rem; color: var(--ks-slate); }
.ks-att-selected__badge {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .25rem .6rem;
    border-radius: 999px;
    border: 1px solid transparent;
}
.ks-att-selected__badge.is-past   { background: #EAF3EE; border-color: #BFD9C9; color: #2E6347; }
.ks-att-selected__badge.is-future { background: #FBF1DC; border-color: #E6CF95; color: #8A6312; }
.ks-att-selected__export { white-space: nowrap; }

/* Event-type chip on the selected-event strip. A small coloured pill (soft
   fill + matching text/border) that gives each event type an at-a-glance
   colour — the labels are the KOSIS_EVENT_TYPES set. This only colours the
   little chip; the picker box fill stays white. One soft palette per type,
   kept in the brand's warm/cool family and distinct from the status colours. */
.ks-att-typechip {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .25rem .6rem;
    border-radius: 999px;
    border: 1px solid transparent;
    white-space: nowrap;
}
.ks-att-typechip--rehearsal         { background: #EAF3EE; border-color: #BFD9C9; color: #2E6347; } /* sage */
.ks-att-typechip--concert           { background: #FBF1DC; border-color: #E6CF95; color: #8A6312; } /* gold */
.ks-att-typechip--hired_performance { background: #E6F0F2; border-color: #B6D4D9; color: #2E6470; } /* teal */
.ks-att-typechip--social            { background: #F0EAF6; border-color: #D4C2E6; color: #5B2A86; } /* violet */
.ks-att-typechip--religious_service { background: #ECEFF6; border-color: #C5CEE0; color: #3A4A6B; } /* navy-blue */
.ks-att-typechip--field_trip        { background: #EAF3EE; border-color: #BFD9C9; color: #33804A; } /* green */
.ks-att-typechip--mission_trip      { background: #FBE9D0; border-color: #E9C79A; color: #9A5B12; } /* amber */
.ks-att-typechip--other             { background: #EEF0F2; border-color: #D3D9DF; color: #48505A; } /* slate */

/* ── Future-event read-only note ──────────────────────────────────────────── */
.ks-att-futurenote {
    border-left: 4px solid #E6CF95;
}
.ks-att-futurenote strong { color: var(--ks-navy); display: block; margin-bottom: 2px; }
.ks-att-table--readonly .ks-att-row { grid-template-columns: minmax(160px, 2fr) 1fr; }
.ks-att-cell--voice { color: var(--ks-slate); }

/* ── Filter / sort / search bar ───────────────────────────────────────────── */
.ks-att-filterbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
    padding: .7rem .8rem;
    margin-bottom: var(--ks-space-sm);
    background: #fff;
    border: 1px solid var(--ks-border);
    border-radius: var(--ks-radius-md, 12px);
}
.ks-att-filterbar__group { display: flex; flex-direction: column; gap: 3px; min-width: 120px; }
.ks-att-filterbar__group--grow { flex: 1 1 160px; }
.ks-att-filterbar__group--reset { margin-left: auto; align-self: flex-end; }
.ks-att-filterbar .ks-label--xs { margin: 0; }
.ks-att-filtercount { font-size: .82rem; color: var(--ks-muted, #6B7280); margin: 0 0 var(--ks-space-sm); }

@media (max-width: 720px) {
    .ks-att-filterbar__group { min-width: 0; flex: 1 1 45%; }
    .ks-att-filterbar__group--reset { flex-basis: 100%; margin-left: 0; }
}

/* ============================================================================
   Module 2 (SDP2) — Assets & inventory. These rules live here because
   pages/assets.php reuses this stylesheet (shared .ks-att-* table/chip/
   filterbar machinery) and adds these asset-specific hooks on top.
   ============================================================================ */

/* Catalogue table: Item · Category · Owned · Out · Lost · Repl.cost · [actions] */
.ks-asset-row {
    grid-template-columns: minmax(150px, 2fr) 1fr 64px 56px 56px 90px 110px;
}
.ks-att-row--head.ks-asset-row { /* header inherits the same grid */ }

/* Ledger table: Item · Member · Status · Issued · Returned/Lost · [action] */
.ks-asset-ledrow {
    grid-template-columns: minmax(150px, 1.8fr) minmax(110px, 1.3fr) 110px 110px 120px 150px;
}

/* By-member overview: Member · Holding · Returned · Lost · Lost cost · [export] */
.ks-asset-memrow {
    grid-template-columns: minmax(130px, 1.6fr) 90px 90px 70px 110px 56px;
}
.ks-asset-memrow .ks-att-cell { text-align: center; }
.ks-asset-memrow .ks-att-cell--name { text-align: left; }

/* Action cells: lay buttons/links in a row, vertically centred. */
.ks-asset-actions,
.ks-asset-ledactions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
/* The delete/lost affordance reads as destructive (brick), as a link-button. */
.ks-asset-del {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    font: inherit;
    color: var(--ks-brick, #B85450);
    font-weight: 600;
    font-size: .85rem;
}
.ks-asset-del:hover { text-decoration: underline; }

/* Status badges (reuse the .ks-att-badge shape from the history view). */
.ks-asset-badge--issued   { background: #E6F0F2; border-color: #B6D4D9; color: #2E6470; }
.ks-asset-badge--returned { background: #EAF3EE; border-color: #BFD9C9; color: #2E6347; }
.ks-asset-badge--lost     { background: #F8E9E7; border-color: #E3BDB6; color: #9A3B2E; }

/* Issue form: a responsive row of fields ending in the Issue button. */
.ks-asset-issueform { margin: 0; }
.ks-asset-issueform__row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
}
.ks-asset-issueform__row > div { display: flex; flex-direction: column; gap: 3px; min-width: 130px; }
.ks-asset-issueform__grow { flex: 1 1 180px; }
.ks-asset-issueform__btn { min-width: 0; }
.ks-asset-issueform .ks-label--xs { margin: 0; }

@media (max-width: 760px) {
    /* Collapse the asset grids into stacked cards, like the .ks-att tables. */
    .ks-asset-row,
    .ks-asset-ledrow,
    .ks-asset-memrow {
        grid-template-columns: 1fr 1fr;
        gap: 6px 10px;
    }
    .ks-att-row--head.ks-asset-row,
    .ks-att-row--head.ks-asset-ledrow,
    .ks-att-row--head.ks-asset-memrow { display: none; }
    .ks-asset-memrow .ks-att-cell { text-align: left; }
    .ks-asset-actions,
    .ks-asset-ledactions { grid-column: 1 / -1; }
    .ks-asset-issueform__row > div { flex: 1 1 45%; min-width: 0; }
}

/* ============================================================================
   Module 2 polish — uniform field heights, searchable selects, pagination.
   ============================================================================ */

/* Uniform control heights across the issue form AND the ledger filter bar, so
   Choose item / Choose member / Issued on / Note / All statuses / Member (A–Z)
   / Search / Export all line up at the same size. We pin a shared height on the
   small inputs/selects in these two regions and let the export button match. */
.ks-asset-issueform .ks-input--sm,
.ks-asset-issueform .ks-ss__input,
.ks-att-filterbar .ks-input--sm,
.ks-att-filterbar .btn {
    height: 40px;
    box-sizing: border-box;
}
.ks-asset-issueform .ks-input--sm,
.ks-asset-issueform .ks-ss__input,
.ks-att-filterbar .ks-input--sm {
    padding-top: 0;
    padding-bottom: 0;
    line-height: 38px;
}
/* The export link-button in the filter bar: center its label in the 40px box. */
.ks-att-filterbar .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
}

/* Searchable single-select (§32). The native <select> is visually hidden but
   stays in the DOM to submit its value; the text input + floating list sit on
   top. The wrapper is positioned so the list anchors to it. */
.ks-ss { position: relative; display: block; }
.ks-ss-native {
    /* Hidden but still focusable/submittable; not display:none so validation
       messages can still anchor to it if the browser shows them. */
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0; pointer-events: none;
    margin: 0; padding: 0; border: 0;
}
.ks-ss__input { width: 100%; cursor: text; }
.ks-ss__list {
    position: absolute;
    z-index: 40;
    top: calc(100% + 2px);
    left: 0;
    right: 0;
    max-height: 240px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--ks-border);
    border-radius: var(--ks-radius-input, 10px);
    box-shadow: 0 8px 24px rgba(31, 41, 82, .12);
    padding: 4px;
}
.ks-ss__opt {
    padding: 8px 10px;
    border-radius: 8px;
    cursor: pointer;
    font-size: .9rem;
    color: var(--ks-navy);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ks-ss__opt:hover,
.ks-ss__opt.is-active { background: var(--ks-parchment, #F4EFE2); }
.ks-ss__empty { padding: 8px 10px; font-size: .85rem; color: var(--ks-muted, #6B7280); }

/* Pagination (§31). A row off the current page is hidden WITHOUT touching its
   inline display (the filter owns that), via this class. */
.ks-page-hidden { display: none !important; }

.ks-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 12px 0 2px;
}
.ks-pager__btn,
.ks-pager__num {
    border: 1px solid var(--ks-border);
    background: #fff;
    color: var(--ks-navy);
    border-radius: 8px;
    padding: 6px 10px;
    font-size: .85rem;
    font-weight: 600;
    cursor: pointer;
    line-height: 1;
}
.ks-pager__num.is-active {
    background: var(--ks-navy);
    color: #fff;
    border-color: var(--ks-navy);
}
.ks-pager__btn:disabled {
    opacity: .45;
    cursor: default;
}
.ks-pager__btn:not(:disabled):hover,
.ks-pager__num:not(.is-active):hover { background: var(--ks-parchment, #F4EFE2); }
.ks-pager__gap { color: var(--ks-muted, #6B7280); padding: 0 2px; }
.ks-pager__count {
    margin-left: auto;
    font-size: .8rem;
    color: var(--ks-muted, #6B7280);
}

/* The By-member export column now holds a real button — give it room and make
   it clearly tappable rather than a tiny glyph. */
.ks-asset-memrow {
    grid-template-columns: minmax(130px, 1.6fr) 90px 90px 70px 110px 120px;
}
.ks-asset-memexport { display: flex; align-items: center; justify-content: flex-start; }
.ks-asset-memexport__btn {
    white-space: nowrap;
    font-size: .82rem;
    padding: 6px 12px;
}

@media (max-width: 760px) {
    .ks-asset-memexport { grid-column: 1 / -1; }
    .ks-pager__count { margin-left: 0; flex-basis: 100%; }
}

/* =========================================================================
   MODULE 3 (SDP2) — Policy & rules (pages/policy.php)
   Rule cards: a header row carrying the enable checkbox + label/blurb, then a
   fields row of amount/threshold inputs. Reuses the shared .ks-card shell, the
   .ks-att-badge chips, and the .ks-att-table for the fees list.
   ========================================================================= */
.ks-pol-rule__head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
}
.ks-pol-rule__head > input[type="checkbox"] {
    width: 18px; height: 18px;
    margin-top: 2px;
    flex: 0 0 auto;
    accent-color: var(--ks-sage, #4A6F5C);
    cursor: pointer;
}
.ks-pol-rule__head strong {
    display: block;
    color: var(--ks-navy);
    font-size: .98rem;
}
.ks-pol-rule__blurb {
    display: block;
    margin-top: 2px;
    font-size: .84rem;
    color: var(--ks-muted, #6B7280);
    line-height: 1.45;
}
/* The amount/threshold inputs sit in a wrapping row below the toggle. */
.ks-pol-rule__fields {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 12px;
    padding-left: 28px;   /* align under the label, clearing the checkbox */
}
.ks-pol-rule__fields > div { min-width: 130px; }
.ks-pol-rule__check { display: flex; align-items: center; }
.ks-pol-rule__inline {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: .9rem;
    color: var(--ks-navy);
    cursor: pointer;
}
.ks-pol-rule__inline input[type="checkbox"] {
    width: 17px; height: 17px;
    accent-color: var(--ks-sage, #4A6F5C);
    cursor: pointer;
}
.ks-mt-xs { margin-top: 6px; }

/* Disabled (read-only / member view) rule cards read as muted, not broken. */
.ks-pol-rule input:disabled,
.ks-pol-rule select:disabled {
    opacity: .6;
    cursor: default;
}

/* Fees list grid: Fee | Amount | Status | actions. Mirrors the asset rows. */
.ks-pol-feerow {
    grid-template-columns: minmax(150px, 2fr) 120px 110px 130px;
}
@media (max-width: 760px) {
    .ks-pol-rule__fields { padding-left: 0; }
}

/* =========================================================================
   MODULE 4 (SDP2) — Finance & penalties (pages/finance.php)
   Choir-wide stat cards, the per-member statement table, and the expandable
   itemised charge lines. Reuses the shared .ks-card / .ks-att-table shells.
   ========================================================================= */

/* Three headline stat cards: penalties | standing fees | grand total. */
.ks-fin-totals {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
}
.ks-fin-stat {
    background: #fff;
    border: 1px solid var(--ks-border);
    border-radius: var(--ks-radius-md, 12px);
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.ks-fin-stat--grand {
    background: var(--ks-navy);
    border-color: var(--ks-navy);
}
.ks-fin-stat__label {
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ks-muted, #6B7280);
}
.ks-fin-stat--grand .ks-fin-stat__label { color: rgba(255,255,255,.75); }
.ks-fin-stat__value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--ks-navy);
    line-height: 1.1;
}
.ks-fin-stat--grand .ks-fin-stat__value { color: #fff; }
.ks-fin-stat__sub {
    font-size: .8rem;
    color: var(--ks-muted, #6B7280);
}
.ks-fin-stat--grand .ks-fin-stat__sub { color: rgba(255,255,255,.7); }

/* Standing-fee chips. */
.ks-fin-feeline { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
.ks-fin-feechip {
    display: inline-block;
    background: var(--ks-parchment, #F4EFE2);
    border: 1px solid var(--ks-border);
    border-radius: 999px;
    padding: 4px 12px;
    font-size: .85rem;
    color: var(--ks-navy);
    font-weight: 600;
}

/* Statement table grid: Member | Penalties | Standing fees | Total | actions. */
.ks-fin-row {
    grid-template-columns: minmax(150px, 2fr) 120px 130px 120px 110px;
}
.ks-fin-actions { display: flex; align-items: center; gap: 10px; justify-content: flex-start; }

/* The (i) tooltips on the header row point UPWARD, but .ks-att-table clips with
   overflow:hidden (for its rounded corners), which would hide them. Let the
   finance table — and specifically its header row — show overflow so the
   bubbles escape. The body rows still read fine; the rounded-corner clip is a
   minor cosmetic trade we accept on this table so the help bubbles work. */
.ks-fin-table { overflow: visible; }
.ks-fin-table .ks-att-row--head { overflow: visible; position: relative; z-index: 1; }

/* Same treatment for the Assets catalogue + by-member tables, whose headers
   also carry (i) help tooltips that must escape the table's rounded-corner clip. */
.ks-att-table:has(.ks-fin-info) { overflow: visible; }
.ks-att-table:has(.ks-fin-info) .ks-att-row--head { overflow: visible; position: relative; z-index: 1; }

/* The expandable detail row sits full-width beneath its summary row. */
.ks-fin-detail { grid-column: 1 / -1; padding: 0; }
.ks-fin-detail__inner {
    background: var(--ks-parchment, #F4EFE2);
    border-radius: var(--ks-radius-md, 12px);
    padding: 10px 14px;
    margin: 2px 0 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ks-fin-line {
    display: grid;
    grid-template-columns: 110px 1fr auto;
    align-items: center;
    gap: 12px;
    font-size: .88rem;
    color: var(--ks-navy);
}
.ks-fin-line__badge {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: 3px 8px;
    border-radius: 6px;
    text-align: center;
    white-space: nowrap;
}
.ks-fin-line__badge--late_arrival { background: #FBE9D0; color: #9A5B12; }
.ks-fin-line__badge--late_return  { background: #FCE3E1; color: #9A2A22; }
.ks-fin-line__badge--lost_item    { background: #E7D9F2; color: #5B2A86; }
.ks-fin-line__badge--fee          { background: #DCE7E1; color: var(--ks-sage, #4A6F5C); }
.ks-fin-line__detail { color: var(--ks-slate, #44506A); overflow: hidden; text-overflow: ellipsis; }
.ks-fin-line__amt { font-weight: 700; color: var(--ks-navy); white-space: nowrap; }
.ks-fin-line__none { margin: 2px 0; font-size: .85rem; color: var(--ks-muted, #6B7280); }
.ks-fin-line--fee .ks-fin-line__amt { color: var(--ks-sage, #4A6F5C); }

/* Prominent export banner: a gold-edged strip with a clear primary button, so
   the download is an obvious call to action rather than a quiet filter-bar link. */
.ks-fin-exportbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    background: linear-gradient(180deg, #fff, var(--ks-parchment, #F4EFE2));
    border: 1px solid var(--ks-gold, #D4A955);
    border-radius: var(--ks-radius-md, 12px);
    padding: 14px 18px;
}
.ks-fin-exportbar__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ks-fin-exportbar__text strong { color: var(--ks-navy); font-size: .98rem; }
.ks-fin-exportbar__text span { font-size: .85rem; color: var(--ks-muted, #6B7280); }
.ks-fin-exportbar__btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
    flex: 0 0 auto;
    font-weight: 700;
    box-shadow: 0 2px 8px rgba(212, 169, 85, .35);
}
.ks-fin-exportbar__btn svg { flex: 0 0 auto; }

/* Per-row "Export" pill in the member actions column. Clear and tappable, not a
   bare glyph. */
.ks-fin-rowexport {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .8rem;
    font-weight: 600;
    color: var(--ks-navy);
    border: 1px solid var(--ks-border);
    border-radius: 7px;
    padding: 4px 10px;
    background: #fff;
    text-decoration: none;
    white-space: nowrap;
}
.ks-fin-rowexport:hover {
    background: var(--ks-parchment, #F4EFE2);
    border-color: var(--ks-gold, #D4A955);
}
.ks-fin-rowexport svg { flex: 0 0 auto; }

/* The (i) information marker on column headers / totals labels. A small round
   badge that shows a styled tooltip bubble on hover AND tap. The text rides on
   a data-tip attribute (NOT the native title, which is slow and easy to miss);
   a pure-CSS ::after bubble appears on :hover, :focus, and .is-open (the last
   set by a tap handler in kosis.js §34, so it works on touch devices too). */
.ks-fin-info {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    margin-left: 4px;
    border-radius: 50%;
    background: var(--ks-navy, #1F2952);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    font-style: normal;
    line-height: 1;
    cursor: help;
    vertical-align: middle;
    user-select: none;
    -webkit-user-select: none;
}
.ks-fin-info:hover,
.ks-fin-info:focus {
    background: var(--ks-gold, #D4A955);
    color: #fff;
    outline: none;
}
/* The tooltip bubble. Hidden until hover / focus / tap-open. text-transform is
   reset to none so a header's uppercase styling doesn't shout the tip. */
.ks-fin-info::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    width: max-content;
    max-width: 260px;
    white-space: normal;
    text-align: left;
    text-transform: none;
    letter-spacing: normal;
    font-weight: 500;
    font-size: .78rem;
    line-height: 1.4;
    color: #fff;
    background: #1F2952;
    padding: 8px 10px;
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(31, 41, 82, .28);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .12s ease, transform .12s ease;
    z-index: 60;
}
/* Little arrow under the bubble. */
.ks-fin-info::before {
    content: "";
    position: absolute;
    bottom: calc(100% + 3px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    border: 5px solid transparent;
    border-top-color: #1F2952;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .12s ease, transform .12s ease;
    z-index: 60;
}
.ks-fin-info:hover::after,
.ks-fin-info:focus::after,
.ks-fin-info.is-open::after,
.ks-fin-info:hover::before,
.ks-fin-info:focus::before,
.ks-fin-info.is-open::before {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}
/* On the dark grand-total card the badge needs lighter colours to read. */
.ks-fin-stat--grand .ks-fin-info {
    background: rgba(255,255,255,.3);
    color: #fff;
}
/* Inline mention inside the intro paragraph (no tooltip, just the look). */
.ks-fin-info--inline { cursor: default; }
.ks-fin-info--inline::after,
.ks-fin-info--inline::before { display: none; }

/* Near the right edge of a table, a centered bubble can overflow the viewport.
   The .ks-fin-info--left modifier anchors the bubble to the right instead. */
.ks-fin-info--left::after { left: auto; right: -4px; transform: translateY(4px); }
.ks-fin-info--left:hover::after,
.ks-fin-info--left:focus::after,
.ks-fin-info--left.is-open::after { transform: translateY(0); }

/* Advisory note: a soft amber strip explaining why a recorded fact (e.g. a lost
   item's cost) isn't appearing as a charge because its rule is off. */
.ks-fin-advisory {
    border-left: 4px solid var(--ks-gold, #D4A955);
    background: #FFF9EE;
}
.ks-fin-advisory strong { color: #9A5B12; }

@media (max-width: 760px) {
    .ks-fin-totals { grid-template-columns: 1fr; }
    .ks-fin-line { grid-template-columns: 90px 1fr auto; gap: 8px; }
    .ks-fin-exportbar { flex-direction: column; align-items: stretch; }
    .ks-fin-exportbar__btn { justify-content: center; }
}
