/* ============================================================================
   AtChurch.Online — Shared Component Layer
   ============================================================================

   Every pattern here was extracted from the inline <style> blocks that were
   duplicated across the 70 pages that carry one. Nothing was invented: the
   audit that produced this file found the same handful of ideas reimplemented
   with slightly different numbers each time. For example —

       .settings-card   identical copy-paste in 3 pages
       .stat-card       5 pages, radius 10px vs 12px, border #e0e0e0 vs #e2e8f0,
                        value colour #333 vs a page-local variable
       .stats-card      3 more pages — same idea, different name
       .status-badge    6 pages, each with its own private set of state colours
       .empty-state     4 pages, some with a background, some without

   This file is where those go to die. It is written entirely against the
   tokens in theme-tokens.css, so every pattern below re-skins with the theme.

   NAMING
   ------
   All classes are `ac-` prefixed. That prefix is a promise: an `ac-` class is
   theme-safe and shared. An unprefixed class in a page's <style> block is
   legacy and is a migration candidate.

   MIGRATION NOTE
   --------------
   This file is ADDITIVE. It defines new class names and touches no existing
   ones, so adding it changes nothing on screen until a page is converted.
   Pages are converted one at a time by deleting their <style> block and
   swapping their markup onto these classes — each page independently
   shippable, no big-bang rewrite.
   ============================================================================ */


/* ============================================================================
   PAGE HEADER
   ============================================================================
   Title on the left, actions on the right, rule underneath. Generalised from
   .bible-page-header, which was the most complete of the hand-rolled versions.
   Collapses to stacked on phones — several of the originals did not, and
   overflowed.
   ============================================================================ */

.ac-page-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: var(--ac-gap);
    margin-bottom: var(--ac-section-gap);
    padding-bottom: var(--ac-gap);
    border-bottom: var(--ac-border-width) solid var(--ac-border);
}

.ac-page-header__title {
    margin: 0;
    font-size: var(--ac-text-2xl);
    font-weight: var(--ac-weight-heading);
    color: var(--ac-text);
}

.ac-page-header__subtitle {
    margin: 0.25rem 0 0;
    font-size: var(--ac-text-sm);
    color: var(--ac-text-muted);
}

.ac-page-header__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

@media (max-width: 575.98px) {
    .ac-page-header {
        flex-direction: column;
        align-items: stretch;
    }

    .ac-page-header__actions {
        justify-content: stretch;
    }

    .ac-page-header__actions > * {
        flex: 1 1 auto;
    }
}


/* ============================================================================
   PANEL — the workhorse container
   ============================================================================
   Replaces .settings-card, .position-card, .help-section and the many
   ad-hoc `background:#fff; border:1px solid #e0e0e0; border-radius:10px`
   blocks. Prefer this over Bootstrap's .card on new pages: site.css applies a
   global `.card { text-align:center }` (a legacy rule from the attendance
   screens) that every page then has to fight with `text-align:left`.
   ============================================================================ */

.ac-panel {
    background: var(--ac-surface);
    border: var(--ac-border-width) solid var(--ac-border);
    border-radius: var(--ac-radius-md);
    box-shadow: var(--ac-shadow-sm);
    padding: var(--ac-card-pad);
    margin-bottom: var(--ac-gap);
    text-align: left;
}

/* Glass and gradient themes hang their personality on this hook. Flat themes
   leave --ac-surface-blur at 0px and the filter is a no-op, so the modifier is
   harmless to apply unconditionally. The translucent surface is required for
   the blur to be visible at all — see --ac-surface-glass in theme-tokens.css. */
.ac-panel--glass {
    background: var(--ac-surface-glass);
    backdrop-filter: blur(var(--ac-surface-blur));
    -webkit-backdrop-filter: blur(var(--ac-surface-blur));
}

.ac-panel--sunken {
    background: var(--ac-surface-sunken);
    box-shadow: none;
}

.ac-panel--flush {
    padding: 0;
    overflow: hidden;
}

.ac-panel--interactive {
    transition: var(--ac-transition);
}

.ac-panel--interactive:hover {
    transform: var(--ac-lift);
    box-shadow: var(--ac-shadow-lg);
    border-color: var(--ac-brand);
}

.ac-panel__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--ac-gap);
    margin: 0 0 var(--ac-gap);
}

.ac-panel__title {
    margin: 0;
    font-size: var(--ac-text-lg);
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text);
}

/* Accent stripe down the leading edge — used by the Bible plan cards and by
   several report pages to signal state. */
.ac-panel--accent { border-left: 4px solid var(--ac-brand); }
.ac-panel--accent-success { border-left: 4px solid var(--ac-success); }
.ac-panel--accent-warning { border-left: 4px solid var(--ac-warning); }
.ac-panel--accent-danger { border-left: 4px solid var(--ac-danger); }


/* ============================================================================
   STAT TILE
   ============================================================================
   Unifies .stat-card and .stats-card. The two names were the same idea and
   are both replaced by this one.
   ============================================================================ */

.ac-stat-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--ac-gap);
    margin-bottom: var(--ac-section-gap);
}

@media (min-width: 992px) {
    .ac-stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .ac-stat-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .ac-stat-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.ac-stat {
    background: var(--ac-surface);
    border: var(--ac-border-width) solid var(--ac-border);
    border-radius: var(--ac-radius-md);
    box-shadow: var(--ac-shadow-sm);
    padding: var(--ac-card-pad);
    text-align: center;
    position: relative;
    overflow: hidden;
    height: 100%;
}

/* Only tiles that actually navigate somewhere get the hover treatment. The
   originals applied `cursor:pointer` to non-interactive tiles too. */
a.ac-stat,
button.ac-stat,
.ac-stat--clickable {
    cursor: pointer;
    transition: var(--ac-transition);
    text-decoration: none;
    display: block;
}

a.ac-stat:hover,
button.ac-stat:hover,
.ac-stat--clickable:hover {
    transform: var(--ac-lift);
    box-shadow: var(--ac-shadow-lg);
    border-color: var(--ac-brand);
}

/* Top edge wipe on hover — carried over from .bible-stats-card. */
.ac-stat--clickable::before,
a.ac-stat::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 4px;
    background: var(--ac-brand);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s ease;
}

.ac-stat--clickable:hover::before,
a.ac-stat:hover::before { transform: scaleX(1); }

.ac-stat__icon {
    font-size: var(--ac-text-xl);
    color: var(--ac-brand);
    margin-bottom: 0.5rem;
    opacity: 0.85;
}

.ac-stat__value {
    font-size: var(--ac-text-3xl);
    font-weight: 800;
    line-height: 1.1;
    color: var(--ac-text);
}

.ac-stat__label {
    font-size: var(--ac-text-xs);
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text-muted);
    letter-spacing: var(--ac-label-tracking);
    text-transform: var(--ac-label-transform);
    margin-top: 0.25rem;
}

.ac-stat__delta { font-size: var(--ac-text-xs); margin-top: 0.375rem; }
.ac-stat__delta--up { color: var(--ac-success-text); }
.ac-stat__delta--down { color: var(--ac-danger-text); }

/* Semantic tinting of the value, replacing the four hardcoded gradient
   variants on .bible-stats-card (.chapters/.days/.completed/.active).

   These deliberately use the -text (ink) tokens, not the fill tokens — see
   the status block in theme-tokens.css. --ac-warning as text on a white card
   measures about 2.1:1; --ac-warning-text measures 8:1, and dark mode
   inverts it to a light tint so the same rule holds in both modes. */
.ac-stat--brand .ac-stat__value { color: var(--ac-brand); }
.ac-stat--success .ac-stat__value { color: var(--ac-success-text); }
.ac-stat--warning .ac-stat__value { color: var(--ac-warning-text); }
.ac-stat--danger .ac-stat__value { color: var(--ac-danger-text); }
.ac-stat--info .ac-stat__value { color: var(--ac-info-text); }


/* ============================================================================
   BUTTONS — the site convention
   ============================================================================
   There are three button roles, and which one you pick decides whether the
   label may be dropped. Getting this wrong is how an interface becomes a row
   of mystery glyphs.

   1. COMMIT ACTIONS — Save, Add, Submit, Delete-in-a-confirm-dialog.
      ALWAYS labelled. Icon optional and decorative. These are infrequent and
      consequential; the words are the affordance. Never icon-only, no matter
      how obvious the glyph seems.

   2. ROW ACTIONS — edit/delete repeated on every row of a table or list.
      Icon-only via .ac-icon-btn. The label repeats N times and becomes noise,
      and the column header already says what the column is. REQUIRED: both
      `aria-label` (screen readers) and `data-bs-toggle="tooltip"` +
      `data-bs-title` (sighted hover). One without the other is a bug.

   3. NAVIGATION — Previous/Next, Back, tabs. Labelled, icon leading or
      trailing to signal direction.

   Use Bootstrap Icons (`<i class="bi bi-...">`), never emoji. Emoji were used
   throughout this codebase as icons (➕ ✏️ 🗑️ 📧 🔐) and are the single biggest
   reason older screens read as dated: they render as a different picture on
   every OS and font, ignore `currentColor` so they cannot follow a theme, and
   cannot be sized against the type scale.
   ============================================================================ */

.ac-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: var(--ac-border-width) solid var(--ac-border-strong);
    border-radius: var(--ac-radius-sm);
    background: var(--ac-surface);
    color: var(--ac-text-muted);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    transition: var(--ac-transition-fast);
}

.ac-icon-btn:hover {
    background: var(--ac-surface-sunken);
    border-color: var(--ac-brand);
    color: var(--ac-brand);
}

.ac-icon-btn:focus-visible {
    outline: none;
    border-color: var(--ac-brand);
    box-shadow: var(--ac-focus-ring);
}

.ac-icon-btn:disabled,
.ac-icon-btn[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
}

/* Destructive. Stays quiet until hovered rather than shouting red in every
   row — a table of ten solid-red buttons reads as ten errors. The intent is
   still unmistakable on approach, and the confirm dialog carries the weight. */
.ac-icon-btn--danger:hover {
    background: var(--ac-danger-soft);
    border-color: var(--ac-danger);
    color: var(--ac-danger-text);
}

/* No resting border — for dense clusters where a box per action is too much. */
.ac-icon-btn--ghost {
    border-color: transparent;
    background: transparent;
}

.ac-icon-btn--sm { width: 1.875rem; height: 1.875rem; font-size: 0.875rem; }
.ac-icon-btn--lg { width: 2.75rem; height: 2.75rem; font-size: 1.25rem; }

/* Cluster of row actions. Keeps them on one line and hard against the trailing
   edge, which is where a scanning eye expects them. */
.ac-actions {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    white-space: nowrap;
}


/* ============================================================================
   STATUS BADGE
   ============================================================================
   Replaces six independent .status-badge implementations. Each of those
   defined its own state colours, which is why "pending" was amber on one
   page and yellow on another. States are now semantic and theme-driven.
   ============================================================================ */

.ac-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.75rem;
    border-radius: var(--ac-radius-pill);
    font-size: var(--ac-text-xs);
    font-weight: var(--ac-weight-semibold);
    line-height: 1.4;
    white-space: nowrap;
    background: var(--ac-neutral-soft);
    color: var(--ac-neutral-text);
}

.ac-badge i { font-size: 0.9em; }

.ac-badge--brand   { background: var(--ac-brand-soft);   color: var(--ac-brand-active); }
.ac-badge--success { background: var(--ac-success-soft); color: var(--ac-success-text); }
.ac-badge--warning { background: var(--ac-warning-soft); color: var(--ac-warning-text); }
.ac-badge--danger  { background: var(--ac-danger-soft);  color: var(--ac-danger-text); }
.ac-badge--info    { background: var(--ac-info-soft);    color: var(--ac-info-text); }
.ac-badge--neutral { background: var(--ac-neutral-soft); color: var(--ac-neutral-text); }

/* Domain aliases so migrating markup can keep reading naturally. These are
   the state names the existing .status-badge blocks actually used. */
.ac-badge--active,
.ac-badge--accepted,
.ac-badge--sent      { background: var(--ac-success-soft); color: var(--ac-success-text); }
.ac-badge--pending   { background: var(--ac-warning-soft); color: var(--ac-warning-text); }
.ac-badge--declined,
.ac-badge--inactive,
.ac-badge--failed    { background: var(--ac-danger-soft);  color: var(--ac-danger-text); }
.ac-badge--notsent,
.ac-badge--draft     { background: var(--ac-neutral-soft); color: var(--ac-neutral-text); }

.ac-badge--solid { background: var(--ac-brand); color: var(--ac-brand-contrast); }
.ac-badge--outline {
    background: transparent;
    border: var(--ac-border-width) solid currentColor;
}

/* Small coloured dot for inline status without a full badge. */
.ac-dot {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--ac-neutral);
    margin-right: 0.375rem;
    vertical-align: baseline;
}

.ac-dot--success { background: var(--ac-success); }
.ac-dot--warning { background: var(--ac-warning); }
.ac-dot--danger { background: var(--ac-danger); }
.ac-dot--brand { background: var(--ac-brand); }


/* ============================================================================
   EMPTY STATE
   ============================================================================
   Replaces four variants. Standardises on no background (the two versions
   that had one looked like a broken card), with --sunken available when the
   surrounding layout needs the contrast.
   ============================================================================ */

.ac-empty {
    text-align: center;
    padding: var(--ac-section-gap) var(--ac-gap);
    color: var(--ac-text-muted);
}

.ac-empty--sunken {
    background: var(--ac-surface-sunken);
    border-radius: var(--ac-radius-md);
}

.ac-empty__icon {
    font-size: 3rem;
    line-height: 1;
    color: var(--ac-text-subtle);
    margin-bottom: var(--ac-gap);
    display: block;
}

.ac-empty__title {
    font-size: var(--ac-text-lg);
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text);
    margin-bottom: 0.5rem;
}

.ac-empty__body {
    font-size: var(--ac-text-sm);
    max-width: 34rem;
    margin: 0 auto var(--ac-gap);
}


/* ============================================================================
   FILTER / TOOLBAR BAR
   ============================================================================
   Generalised from the .bulk-actions and assorted filter rows. Wraps rather
   than overflowing, which several of the originals did on phones.
   ============================================================================ */

.ac-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    padding: 0.875rem var(--ac-card-pad);
    background: var(--ac-surface-sunken);
    border: var(--ac-border-width) solid var(--ac-border);
    border-radius: var(--ac-radius-md);
    margin-bottom: var(--ac-gap);
}

.ac-toolbar__label {
    font-size: var(--ac-text-xs);
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text-muted);
    letter-spacing: var(--ac-label-tracking);
    text-transform: var(--ac-label-transform);
}

.ac-toolbar__spacer { margin-left: auto; }

.ac-toolbar__group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}


/* ============================================================================
   DATA TABLE
   ============================================================================
   A themed wrapper that scrolls sideways INSIDE its own box. site.css already
   learned this lesson the hard way (see the .table-nowrap comment there) —
   this bakes the fix into the pattern.
   ============================================================================ */

.ac-table-wrap {
    background: var(--ac-surface);
    border: var(--ac-border-width) solid var(--ac-border);
    border-radius: var(--ac-radius-md);
    box-shadow: var(--ac-shadow-sm);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.ac-table {
    width: 100%;
    margin: 0;
    border-collapse: separate;
    border-spacing: 0;
    color: var(--ac-text);
}

.ac-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--ac-surface-sunken);
    color: var(--ac-text-muted);
    font-size: var(--ac-text-xs);
    font-weight: var(--ac-weight-semibold);
    letter-spacing: var(--ac-label-tracking);
    text-transform: var(--ac-label-transform);
    text-align: left;
    padding: var(--ac-table-row-pad) var(--ac-gap);
    border-bottom: var(--ac-border-width) solid var(--ac-border);
    white-space: nowrap;
}

.ac-table tbody td {
    padding: var(--ac-table-row-pad) var(--ac-gap);
    border-bottom: var(--ac-border-width) solid var(--ac-border);
    vertical-align: middle;
}

.ac-table tbody tr:last-child td { border-bottom: 0; }
.ac-table tbody tr { transition: var(--ac-transition-fast); }
.ac-table tbody tr:hover { background: var(--ac-brand-soft); }

.ac-table__num { text-align: right; font-variant-numeric: tabular-nums; }
.ac-table__actions { text-align: right; white-space: nowrap; }

/* Opt-in, per the same reasoning as .table-nowrap in site.css: wrapping is
   the default and only specific columns escape it. */
.ac-table--nowrap th,
.ac-table--nowrap td { white-space: nowrap; }


/* ============================================================================
   LIST ROW
   ============================================================================
   The avatar + title/meta + trailing-action row that the people, group,
   prayer and team screens each rebuild.
   ============================================================================ */

.ac-list { display: flex; flex-direction: column; }

.ac-list-row {
    display: flex;
    align-items: center;
    gap: var(--ac-gap);
    padding: 0.875rem var(--ac-card-pad);
    border-bottom: var(--ac-border-width) solid var(--ac-border);
    text-decoration: none;
    color: inherit;
    transition: var(--ac-transition-fast);
}

.ac-list-row:last-child { border-bottom: 0; }
.ac-list-row:hover { background: var(--ac-surface-sunken); color: inherit; }

.ac-list-row__body { flex: 1 1 auto; min-width: 0; }

.ac-list-row__title {
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ac-list-row__meta {
    font-size: var(--ac-text-sm);
    color: var(--ac-text-muted);
}

.ac-list-row__trailing { flex: 0 0 auto; margin-left: auto; }


/* ============================================================================
   AVATAR / THUMBNAIL
   ============================================================================
   Replaces .profile-thumbnail-wrapper and .thumbnail-preview (4 pages each).
   ============================================================================ */

.ac-avatar {
    display: inline-block;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    object-fit: cover;
    background: var(--ac-surface-sunken);
    border: var(--ac-border-width) solid var(--ac-border);
}

.ac-avatar--sm { width: 2rem; height: 2rem; }
.ac-avatar--lg { width: 4rem; height: 4rem; }
.ac-avatar--xl { width: 6rem; height: 6rem; }

.ac-thumb {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: var(--ac-radius-sm);
    background: var(--ac-surface-sunken);
}

.ac-thumb--square { aspect-ratio: 1 / 1; }

/* Colour swatch for per-row colour data (event types, tags). The fill is set
   inline because it IS the data; everything else is themed. */
.ac-swatch {
    display: inline-block;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--ac-radius-xs);
    border: var(--ac-border-width) solid var(--ac-border-strong);
    vertical-align: middle;
}

/* Enlarge-on-hover, for the small profile thumbnails in the attendance and
   people screens. Replaces the .profile-thumbnail-wrapper / .thumbnail-preview
   pair that was duplicated across 4 pages.

   Uses :focus-within rather than the original :focus so the preview also opens
   for a keyboard user who tabs to it — the wrapper still needs tabindex="0"
   for that to be reachable. */
.ac-hover-preview {
    position: relative;
    display: inline-block;
}

.ac-hover-preview__panel {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 1000;
    margin-top: 0.25rem;
    padding: 0.25rem;
    background: var(--ac-surface-raised);
    border: var(--ac-border-width) solid var(--ac-border);
    border-radius: var(--ac-radius-sm);
    box-shadow: var(--ac-shadow-lg);
}

.ac-hover-preview:hover .ac-hover-preview__panel,
.ac-hover-preview:focus-within .ac-hover-preview__panel {
    display: block;
}

.ac-hover-preview__panel img {
    display: block;
    border-radius: var(--ac-radius-xs);
    object-fit: cover;
}

/* Sticky strip for running totals that must stay visible while the user works
   down a long list (the attendance screens). Needs an opaque background of its
   own or the content scrolling underneath shows through. */
.ac-sticky-bar {
    position: sticky;
    top: 0;
    z-index: 1020;
    background: var(--ac-bg);
    padding: 0.5rem 0 0.25rem;
}


/* ============================================================================
   UPLOAD DROP ZONE
   ============================================================================
   Replaces .file-upload-zone (3 pages).
   ============================================================================ */

.ac-dropzone {
    border: 2px dashed var(--ac-border-strong);
    border-radius: var(--ac-radius-md);
    background: var(--ac-surface-sunken);
    padding: var(--ac-section-gap);
    text-align: center;
    color: var(--ac-text-muted);
    cursor: pointer;
    transition: var(--ac-transition);
}

.ac-dropzone:hover,
.ac-dropzone--active {
    border-color: var(--ac-brand);
    background: var(--ac-brand-soft);
    color: var(--ac-brand-active);
}

.ac-dropzone__icon {
    font-size: 2.5rem;
    display: block;
    margin-bottom: 0.5rem;
}


/* ============================================================================
   HELP / CALLOUT
   ============================================================================
   Replaces .help-section (3 pages) and the various tinted "note" boxes.
   ============================================================================ */

.ac-callout {
    background: var(--ac-surface-sunken);
    border-left: 4px solid var(--ac-border-strong);
    border-radius: var(--ac-radius-sm);
    padding: var(--ac-gap) var(--ac-card-pad);
    font-size: var(--ac-text-sm);
    color: var(--ac-text-muted);
    margin-bottom: var(--ac-gap);
}

.ac-callout__title {
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text);
    margin-bottom: 0.375rem;
}

.ac-callout--brand   { background: var(--ac-brand-soft);   border-left-color: var(--ac-brand);   color: var(--ac-brand-active); }
.ac-callout--info    { background: var(--ac-info-soft);    border-left-color: var(--ac-info);    color: var(--ac-info-text); }
.ac-callout--warning { background: var(--ac-warning-soft); border-left-color: var(--ac-warning); color: var(--ac-warning-text); }
.ac-callout--danger  { background: var(--ac-danger-soft);  border-left-color: var(--ac-danger);  color: var(--ac-danger-text); }
.ac-callout--success { background: var(--ac-success-soft); border-left-color: var(--ac-success); color: var(--ac-success-text); }


/* ============================================================================
   SECTION HEADING
   ============================================================================ */

.ac-section {
    margin-bottom: var(--ac-section-gap);
}

.ac-section__heading {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    font-size: var(--ac-text-xs);
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text-muted);
    letter-spacing: var(--ac-label-tracking);
    text-transform: var(--ac-label-transform);
    margin-bottom: 0.75rem;
}

.ac-section__heading::after {
    content: '';
    flex: 1 1 auto;
    height: var(--ac-border-width);
    background: var(--ac-border);
}


/* ============================================================================
   FORM SCAFFOLDING
   ============================================================================ */

.ac-field { margin-bottom: var(--ac-gap); }

.ac-field__label {
    display: block;
    font-size: var(--ac-text-sm);
    font-weight: var(--ac-weight-medium);
    color: var(--ac-text);
    margin-bottom: 0.375rem;
}

.ac-field__hint {
    font-size: var(--ac-text-xs);
    color: var(--ac-text-muted);
    margin-top: 0.25rem;
}

/* Ink token, not the fill token — this is text on a surface, and dark mode
   needs it to invert to a light tint. */
.ac-field__error {
    font-size: var(--ac-text-xs);
    color: var(--ac-danger-text);
    margin-top: 0.25rem;
}

.ac-field-row {
    display: grid;
    gap: var(--ac-gap);
    grid-template-columns: 1fr;
}

@media (min-width: 768px) {
    .ac-field-row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ac-field-row--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Sticky save bar for long edit forms — currently hand-rolled on the Worship
   and Bulletin editors. */
.ac-form-actions {
    position: sticky;
    bottom: 0;
    z-index: 10;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: var(--ac-gap) var(--ac-card-pad);
    background: var(--ac-surface);
    border-top: var(--ac-border-width) solid var(--ac-border);
    box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.06);
    margin-top: var(--ac-section-gap);
}


/* ============================================================================
   MODAL / DIALOG
   ============================================================================
   Bootstrap's .modal is already bridged to the tokens in theme-tokens.css, so
   these are refinements on top rather than a replacement.

   The `.modal-header.bg-danger.text-white` pattern used across this codebase is
   replaced by .ac-modal--danger. A solid red header bar makes every destructive
   dialog shout before the user has read anything; a red top rule plus a red
   title carries the same signal at the weight it deserves, and it survives a
   theme change (bg-danger + text-white assumes a dark red, which not every
   theme's danger colour is).
   ============================================================================ */

.ac-modal .modal-content {
    border: var(--ac-border-width) solid var(--ac-border);
    border-radius: var(--ac-radius-lg);
    box-shadow: var(--ac-shadow-lg);
}

.ac-modal .modal-header {
    align-items: flex-start;
    gap: var(--ac-gap);
    padding: var(--ac-card-pad);
    border-bottom: var(--ac-border-width) solid var(--ac-border);
}

.ac-modal .modal-title {
    font-size: var(--ac-text-lg);
    font-weight: var(--ac-weight-semibold);
    color: var(--ac-text);
}

.ac-modal .modal-body { padding: var(--ac-card-pad); }

.ac-modal .modal-footer {
    gap: 0.5rem;
    padding: var(--ac-gap) var(--ac-card-pad);
    background: var(--ac-surface-sunken);
    border-top: var(--ac-border-width) solid var(--ac-border);
    border-radius: 0 0 var(--ac-radius-lg) var(--ac-radius-lg);
}

/* Bootstrap's .modal-footer puts `margin: .25rem` on every child, which fights
   the flex gap and misaligns a footer that mixes bare buttons with buttons
   wrapped in a <form> (as the delete dialogs do). */
.ac-modal .modal-footer > * { margin: 0; }

/* Destructive variant. */
.ac-modal--danger .modal-content { border-top: 3px solid var(--ac-danger); }
.ac-modal--danger .modal-title { color: var(--ac-danger-text); }

.ac-modal__icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--ac-radius-pill);
    background: var(--ac-danger-soft);
    color: var(--ac-danger-text);
    font-size: 1.25rem;
}

/* Consequence list inside a confirm dialog — what the user is about to lose. */
.ac-consequences {
    margin: 0 0 var(--ac-gap);
    padding-left: 1.25rem;
    font-size: var(--ac-text-sm);
    color: var(--ac-text-muted);
}

.ac-consequences li { margin-bottom: 0.25rem; }


/* ============================================================================
   UTILITIES
   ============================================================================
   A deliberately short list. These exist because they were the utilities
   pages kept re-declaring locally; resist growing this section — if a page
   needs something new, it usually needs a component instead.
   ============================================================================ */

.ac-muted { color: var(--ac-text-muted); }
.ac-subtle { color: var(--ac-text-subtle); }
.ac-brand-text { color: var(--ac-brand); }
.ac-scripture { font-family: var(--ac-font-scripture); line-height: var(--ac-leading-relaxed); }
.ac-nums { font-variant-numeric: tabular-nums; }

.ac-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ac-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Visible only to screen readers — needed by several icon-only buttons that
   currently have no accessible name at all. */
.ac-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.ac-skeleton {
    background: linear-gradient(90deg,
        var(--ac-surface-sunken) 25%,
        var(--ac-border) 37%,
        var(--ac-surface-sunken) 63%);
    background-size: 400% 100%;
    animation: ac-shimmer 1.4s ease infinite;
    border-radius: var(--ac-radius-xs);
    min-height: 1rem;
}

@keyframes ac-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .ac-skeleton { animation: none; }
}


/* ============================================================================
   PRINT
   ============================================================================
   Themes are a screen concern. Print output should be ink-cheap and legible
   regardless of which theme is active — a dark theme must not produce a black
   page. Several report pages carry their own @media print block; this makes
   that unnecessary.
   ============================================================================ */

@media print {
    :root {
        --ac-bg: #ffffff;
        --ac-bg-image: none;
        --ac-surface: #ffffff;
        --ac-surface-sunken: #ffffff;
        --ac-surface-raised: #ffffff;
        --ac-text: #000000;
        --ac-text-muted: #333333;
        --ac-text-subtle: #666666;
        --ac-border: #cccccc;
        --ac-shadow-sm: none;
        --ac-shadow-md: none;
        --ac-shadow-lg: none;
        --ac-shadow-glow: none;
    }

    .ac-panel,
    .ac-stat,
    .ac-table-wrap {
        box-shadow: none;
        break-inside: avoid;
    }

    .ac-toolbar,
    .ac-form-actions,
    .ac-page-header__actions {
        display: none !important;
    }

    .ac-table thead th { position: static; }
}
