:root {
    color-scheme: light;

    /* Official brand colors from the Grace Fellowship Brand Guide (page 3).
       Every other color token below is built from these, so correcting one
       here updates the whole site. */
    --brand-primary: #3D87CB;
    --brand-dark: #236192;
    --brand-gray: #8A8D8F;
    --brand-light-gray: #DFDEDE;
    --brand-charcoal: #363432;
    --brand-gradient: linear-gradient(180deg, var(--brand-dark) 0%, var(--brand-primary) 100%);

    /* Official typeface (brand guide page 4), loaded from Google Fonts in base.html. */
    --font-sans: 'Saira', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

    --color-bg: color-mix(in srgb, var(--brand-light-gray) 30%, #ffffff);
    --color-surface: #ffffff;
    --color-text: var(--brand-charcoal);
    --color-muted: var(--brand-gray);
    --color-border: var(--brand-light-gray);
    --color-primary: var(--brand-primary);
    --color-primary-dark: var(--brand-dark);
    --color-primary-soft: color-mix(in srgb, var(--brand-primary) 14%, transparent);
    --color-danger: #a83232;
    --color-danger-dark: #7a2424;
    --color-success-bg: #eef6ee;
    --color-success-border: #cfe8cf;
    --color-success-text: #2b6b3a;
    --color-error-bg: #fbeaea;
    --color-error-border: #f0c6c6;
    --color-error-text: #a33131;
    --color-table-header: color-mix(in srgb, var(--brand-light-gray) 45%, #ffffff);
    --color-tag-manage-bg: #fdf2e0;
    --color-tag-manage-text: #92600a;
    --color-tag-sensitive-bg: #fbe7e7;
    --color-tag-sensitive-text: #a33131;
    /* Google's published sign-in button colours, light and dark. */
    --google-surface: #ffffff;
    --google-border: #747775;
    --google-text: #1f1f1f;
    --radius: 8px;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
        --color-bg: color-mix(in srgb, var(--brand-charcoal) 55%, #000000);
        --color-surface: color-mix(in srgb, var(--brand-charcoal) 82%, #000000);
        --color-text: var(--brand-light-gray);
        --color-muted: var(--brand-gray);
        --color-border: color-mix(in srgb, var(--brand-charcoal) 72%, var(--brand-gray));
        --color-primary: var(--brand-primary);
        --color-primary-dark: color-mix(in srgb, var(--brand-primary) 62%, #ffffff);
        --color-primary-soft: color-mix(in srgb, var(--brand-primary) 24%, transparent);
        --color-danger: #e07575;
        --color-danger-dark: #f2a5a5;
        --color-success-bg: #16351d;
        --color-success-border: #2a5c37;
        --color-success-text: #8fd49f;
        --color-error-bg: #3a1e1e;
        --color-error-border: #5c2a2a;
        --color-error-text: #f2a5a5;
        --color-table-header: var(--brand-charcoal);
        --color-tag-manage-bg: #4a3a14;
        --color-tag-manage-text: #f0c374;
        --color-tag-sensitive-bg: #4a2020;
        --color-tag-sensitive-text: #f2a5a5;
        --google-surface: #131314;
        --google-border: #8e918f;
        --google-text: #e3e3e3;
    }
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --color-bg: color-mix(in srgb, var(--brand-charcoal) 55%, #000000);
    --color-surface: color-mix(in srgb, var(--brand-charcoal) 82%, #000000);
    --color-text: var(--brand-light-gray);
    --color-muted: var(--brand-gray);
    --color-border: color-mix(in srgb, var(--brand-charcoal) 72%, var(--brand-gray));
    --color-primary: var(--brand-primary);
    --color-primary-dark: color-mix(in srgb, var(--brand-primary) 62%, #ffffff);
    --color-primary-soft: color-mix(in srgb, var(--brand-primary) 24%, transparent);
    --color-danger: #e07575;
    --color-danger-dark: #f2a5a5;
    --color-success-bg: #16351d;
    --color-success-border: #2a5c37;
    --color-success-text: #8fd49f;
    --color-error-bg: #3a1e1e;
    --color-error-border: #5c2a2a;
    --color-error-text: #f2a5a5;
    --color-table-header: var(--brand-charcoal);
    --color-tag-manage-bg: #4a3a14;
    --color-tag-manage-text: #f0c374;
    --color-tag-sensitive-bg: #4a2020;
    --color-tag-sensitive-text: #f2a5a5;
    --google-surface: #131314;
    --google-border: #8e918f;
    --google-text: #e3e3e3;
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: var(--font-sans);
    background: var(--color-bg);
    color: var(--color-text);
    font-size: 17px;
    line-height: 1.5;
}

a {
    color: var(--color-primary-dark);
}

.site-header {
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
}

.site-header__inner {
    max-width: 960px;
    margin: 0 auto;
    padding: 0.75rem 1rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.site-title {
    display: flex;
    align-items: center;
    text-decoration: none;
}

/* The app's own name. The church logo is already a full wordmark, so this stays
   a small label set apart from it -- side by side at equal weight, the two read
   as two competing logos. */
.app-name {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    white-space: nowrap;
}

.site-logo {
    display: block;
    height: 36px;
    width: auto;
}

/* App shell: fixed left sidebar and slim top bar for signed-in pages */

:root {
    --sidebar-width: 216px;
}

.icon-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: none;
    border-radius: var(--radius);
    background: none;
    color: var(--color-text);
}

.icon-button:hover {
    background: var(--color-bg);
}

.sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 30;
    width: var(--sidebar-width);
    display: flex;
    flex-direction: column;
    padding: 1rem 0.75rem;
    overflow-y: auto;
    /* Dark blue at the top to primary blue at the bottom. On short windows the
       primary end sits below the fold, so the lower menu items stay on darker
       blue and keep enough contrast. */
    background: linear-gradient(180deg, var(--brand-dark) 0%, var(--brand-primary) max(100%, 56rem));
    color: #ffffff;
}

.sidebar__brand {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.25rem 0.5rem 1.25rem;
}

.sidebar__brand .site-logo {
    height: 40px;
}

.sidebar__close {
    display: none;
}

.sidebar .icon-button {
    color: #ffffff;
}

.sidebar .icon-button:hover {
    background: rgba(255, 255, 255, 0.12);
}

.sidebar__nav {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.sidebar__link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem;
    border-radius: var(--radius);
    color: #ffffff;
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
}

.sidebar__link .nav-icon {
    flex-shrink: 0;
    color: rgba(255, 255, 255, 0.8);
}

.sidebar__link:hover {
    background: rgba(255, 255, 255, 0.12);
}

.sidebar__link--active,
.sidebar__link--active:hover {
    background: rgba(255, 255, 255, 0.18);
    color: #ffffff;
}

.sidebar__link--active .nav-icon {
    color: #ffffff;
}

.sidebar__link--active::before {
    content: '';
    position: absolute;
    top: 0.45rem;
    bottom: 0.45rem;
    left: -0.75rem;
    width: 4px;
    border-radius: 0 4px 4px 0;
    background: var(--brand-light-gray);
}

.sidebar__footer {
    /* Pushed to the bottom of the sidebar, well clear of the church logo. */
    margin-top: auto;
    padding: 0.9rem 0.75rem 0.25rem;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
    color: rgba(255, 255, 255, 0.6);
}

.sidebar-backdrop {
    display: none;
}

.app-main {
    margin-left: var(--sidebar-width);
    min-height: 100vh;
}

.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 56px;
    padding: 0.5rem 1.5rem;
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
}

.topbar__menu,
.topbar__brand {
    display: none;
}

.topbar__brand .site-logo {
    height: 30px;
}

.topbar__actions {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-width: 0;
    margin-left: auto;
}

.topbar .link-button {
    white-space: nowrap;
}

/* Shrinks with an ellipsis on narrow screens so it never pushes "Log out" off the edge. */
.topbar__user {
    min-width: 0;
    text-decoration: none;
    max-width: 10rem;
    overflow: hidden;
    color: var(--color-muted);
    font-size: 0.9rem;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Below this width the sidebar hides behind the hamburger and slides in. */
@media (max-width: 800px) {
    .sidebar {
        visibility: hidden;
        transform: translateX(-100%);
        transition: transform 0.25s ease, visibility 0s linear 0.25s;
    }

    body.sidebar-open .sidebar {
        visibility: visible;
        transform: none;
        box-shadow: 0 0 24px rgba(0, 0, 0, 0.25);
        transition: transform 0.25s ease;
    }

    .sidebar__close {
        display: inline-flex;
    }

    .sidebar-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 25;
        background: rgba(0, 0, 0, 0.4);
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.25s ease;
    }

    body.sidebar-open .sidebar-backdrop {
        opacity: 1;
        pointer-events: auto;
    }

    .app-main {
        margin-left: 0;
    }

    .topbar {
        padding: 0.5rem 1rem;
    }

    .topbar__menu,
    .topbar__brand {
        display: inline-flex;
        /* Without this they give up their width first when the bar is short of
           room, and the hamburger -- the only way to the menu on a phone -- was
           being squeezed from 40px down to 22px. */
        flex-shrink: 0;
    }

    .topbar__actions {
        gap: 0.75rem;
    }
}

/* The smallest phones. The owner's bar carries a "View as" link as well, and at
   320px it pushed Log out off the edge. Tighter spacing and a slightly smaller
   logo make room for everything. */
@media (max-width: 360px) {
    .topbar {
        gap: 0.5rem;
        padding: 0.5rem 0.75rem;
    }

    .topbar__actions {
        gap: 0.5rem;
    }

    .topbar__brand .site-logo {
        height: 26px;
    }

    /* Next to "View as" the username was squeezed to nothing here anyway, but its
       gap still took room; drop it outright. Other accounts keep theirs. */
    .topbar__actions:has(.topbar__link) .topbar__user {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .sidebar,
    .sidebar-backdrop {
        transition: none !important;
    }
}

@media print {
    .sidebar,
    .sidebar-backdrop,
    .topbar {
        display: none !important;
    }

    .app-main {
        margin-left: 0;
    }
}

.logout-form {
    margin: 0;
}

.link-button {
    background: none;
    border: none;
    padding: 0;
    color: var(--color-primary-dark);
    font: inherit;
    font-weight: 500;
    cursor: pointer;
    text-decoration: underline;
}

/* Stays a link when pointed at: `button:hover` further down would otherwise fill it with the text's
   own colour, hiding the words ("Log out", "Remove", "Save key"). */
.link-button:hover {
    background: none;
    text-decoration-thickness: 2px;
}

.page {
    max-width: 960px;
    margin: 0 auto;
    padding: 1.5rem 1rem 3rem;
}

h1 {
    margin-top: 0;
    font-weight: 600;
    letter-spacing: -0.01em;
}

h2,
h3,
h4 {
    font-weight: 600;
}

/* Form controls don't inherit the page font by default. */
button,
input,
select,
textarea {
    font-family: inherit;
}

.page-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.page-heading h1 {
    margin-bottom: 0;
}

.page-heading__actions {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.button {
    display: inline-block;
    padding: 0.5rem 1.1rem;
    border-radius: var(--radius);
    background: var(--color-primary);
    color: white;
    font-weight: 600;
    text-decoration: none;
}

.button:hover {
    background: var(--color-primary-dark);
}

.button-danger {
    background: var(--color-danger);
}

.button-danger:hover {
    background: var(--color-danger-dark);
}

.confirm-card {
    max-width: 480px;
    background: var(--color-surface);
    padding: 1.5rem;
    border-radius: var(--radius);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.search-form {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.search-form select {
    /* A dropdown is as wide as its longest option. Ministry Purchases has "Open
       (pending, approved, or ordered)", which made it wider than a 320px phone. */
    max-width: 100%;
}

.search-form input[type="search"] {
    flex: 1 1 260px;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    font-size: 1rem;
}

button {
    padding: 0.6rem 1.25rem;
    border: none;
    border-radius: var(--radius);
    background: var(--color-primary);
    color: white;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
}

button:hover {
    background: var(--color-primary-dark);
}

.clear-link {
    font-size: 0.9rem;
}

.table-scroll {
    /* Anything absolutely positioned inside a table -- a visually hidden column
       heading, say -- takes its position from the nearest positioned ancestor.
       Without one here, that is somewhere outside this wrapper, so the element
       escapes the sideways scroll and widens the whole page on a narrow phone
       instead of scrolling with the table. */
    position: relative;
    overflow-x: auto;
}

.data-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--color-surface);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.data-table th,
.data-table td {
    text-align: left;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--color-border);
    white-space: nowrap;
}

.data-table th {
    background: var(--color-table-header);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-muted);
}

.data-table tr:last-child td {
    border-bottom: none;
}

.data-table a {
    font-weight: 600;
    text-decoration: none;
}

.data-table a:hover {
    text-decoration: underline;
}

.detail-list {
    background: var(--color-surface);
    border-radius: var(--radius);
    padding: 1rem 1.5rem;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.detail-list dt {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-muted);
    margin-top: 0.75rem;
}

.detail-list dt:first-child {
    margin-top: 0;
}

.detail-list dd {
    margin: 0.15rem 0 0;
    font-size: 1.05rem;
}

.member-list {
    list-style: none;
    padding: 0;
    background: var(--color-surface);
    border-radius: var(--radius);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.member-list li {
    padding: 0.75rem 1.5rem;
    border-bottom: 1px solid var(--color-border);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.member-list li:last-child {
    border-bottom: none;
}

.member-role {
    color: var(--color-muted);
    font-size: 0.9rem;
}

.empty-state {
    color: var(--color-muted);
    font-style: italic;
}

/* Only set once a script is listening, so nothing looks clickable that isn't. */
.data-table--clickable tbody tr {
    cursor: pointer;
}

.data-table--clickable tbody tr:hover {
    background: var(--color-table-header);
}

.dialog {
    width: min(42rem, calc(100vw - 2rem));
    max-height: calc(100vh - 4rem);
    padding: 0;
    border: none;
    border-radius: var(--radius);
    background: var(--color-bg);
    color: var(--color-text);
}

.dialog::backdrop {
    background: rgba(16, 24, 40, 0.55);
}

.dialog__body {
    /* The permission list is long, so the dialog scrolls rather than the page. */
    overflow-y: auto;
    max-height: calc(100vh - 4rem);
    padding: 1.5rem;
}

.dialog__close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 1;
    color: var(--color-muted);
}

.dialog__loading {
    margin: 0;
    color: var(--color-muted);
}

.dialog .page-heading {
    /* Clear of the close button in the corner. */
    padding-right: 2.5rem;
}

/* Right-hand side of a member row: the role, and the control to unassign. */
.member-list__end {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.link-button--danger {
    color: var(--color-danger);
}

/* Assigning someone to a ministry, from either side. Wraps to stacked fields on
   a phone, where a single row would be far too cramped. */
.assign-form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.75rem;
    margin-top: 1rem;
    padding: 1rem 1.25rem;
    border-radius: var(--radius);
    background: var(--color-surface);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.assign-form__field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    flex: 1 1 12rem;
}

.assign-form__field label {
    font-size: 0.85rem;
    font-weight: 600;
}

.assign-form select {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-bg);
    color: var(--color-text);
    font-family: inherit;
    font-size: 0.95rem;
}

.assign-form + .field-help {
    margin-top: 0.5rem;
}

.pagination {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 1rem;
    font-size: 0.95rem;
}

.messages {
    list-style: none;
    padding: 0;
    margin: 0 0 1.5rem;
}

.messages__item {
    padding: 0.75rem 1rem;
    border-radius: var(--radius);
    margin-bottom: 0.5rem;
    background: var(--color-success-bg);
    border: 1px solid var(--color-success-border);
}

.messages__item--error {
    background: var(--color-error-bg);
    border-color: var(--color-error-border);
}

.edit-form {
    max-width: 480px;
    background: var(--color-surface);
    padding: 1.5rem;
    border-radius: var(--radius);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.form-field {
    margin-bottom: 1.1rem;
}

.form-field label {
    display: block;
    font-weight: 600;
    margin-bottom: 0.3rem;
}

.form-field input,
.form-field select,
.form-field textarea {
    width: 100%;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    font-size: 1rem;
    font-family: inherit;
}

.field-error {
    color: var(--color-danger);
    font-size: 0.9rem;
    margin: 0.3rem 0 0;
}

.field-help {
    color: var(--color-muted);
    font-size: 0.85rem;
    margin: 0.3rem 0 0;
}

.field-help ul {
    margin: 0.2rem 0 0;
    padding-left: 1.1rem;
}

/* Filled in from the chosen Directory person on the Add User form; edit them there
   instead of here (people/static/people/js/user-create-autofill.js). */
.form-field input[readonly] {
    background: var(--color-tag-manage-bg);
    color: var(--color-muted);
    cursor: not-allowed;
}

.form-actions {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-top: 1.5rem;
}

.button-secondary {
    color: var(--color-muted);
    text-decoration: underline;
}

/* The issued password, shown once. Big and monospaced because it gets read out
   loud or copied by hand. */
.one-time-password {
    margin: 1.25rem 0;
    padding: 1.25rem 1.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
}

.one-time-password h2 {
    margin: 0 0 0.75rem;
    font-size: 1rem;
}

.one-time-password__value {
    margin: 0 0 0.75rem;
}

.one-time-password__value code {
    display: inline-block;
    padding: 0.6rem 1rem;
    border-radius: var(--radius);
    background: var(--color-bg);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 1.35rem;
    letter-spacing: 0.06em;
    user-select: all;
}

.login-card {
    max-width: 360px;
    margin: 2rem auto;
    background: var(--color-surface);
    padding: 2rem;
    border-radius: var(--radius);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

/* Two-step sign-in pages: the QR code and backup codes need more room than the log-in card. */
.login-card--wide {
    max-width: 460px;
}

.two-factor-qr {
    display: inline-block;
    margin: 0.5rem 0 1rem;
    padding: 0.25rem;
    border-radius: var(--radius);
    /* A QR code scans as dark on light; keep it that way in dark mode. */
    background: #fff;
    line-height: 0;
}

.two-factor-key,
.backup-codes {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.two-factor-key {
    overflow-wrap: anywhere;
    font-size: 0.95rem;
}

.backup-codes {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.4rem 1.5rem;
    margin: 1rem 0;
    padding: 1rem 1.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    list-style: none;
    font-size: 1.05rem;
    letter-spacing: 0.05em;
}

.two-factor-status {
    font-weight: 600;
}

.login-card__app {
    /* Bigger than the sidebar label: here it's the only thing naming the app,
       and the card has room for it. */
    font-size: 0.95rem;
    letter-spacing: 0.16em;
    margin: 0 0 0.5rem;
    color: var(--color-muted);
}

.login-card label {
    display: block;
    font-weight: 600;
    margin-bottom: 0.3rem;
}

.login-card input {
    width: 100%;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    margin-bottom: 1rem;
    font-size: 1rem;
}

/* "or" rule between the password form and the Google button. */
.login-or {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 1.25rem 0;
    color: var(--color-muted);
    font-size: 0.85rem;
}

.login-or::before,
.login-or::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--color-border);
}

/* Google's own button colours, so it still looks right once it's wired up.
   Overrides the site button style, which is a solid blue with no border. */
.btn-google {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.6rem 1rem;
    border: 1px solid var(--google-border);
    background: var(--google-surface);
    color: var(--google-text);
    font-size: 0.95rem;
}

.btn-google__mark {
    flex-shrink: 0;
}

/* Dimmed enough to read as unavailable, not so much that the design is lost. */
.btn-google[disabled],
.btn-google[disabled]:hover {
    background: var(--google-surface);
    opacity: 0.7;
    cursor: not-allowed;
}

.login-hint {
    margin: 0.6rem 0 0;
    color: var(--color-muted);
    font-size: 0.85rem;
    text-align: center;
}

.form-error {
    color: var(--color-danger);
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (max-width: 600px) {
    .data-table {
        font-size: 0.9rem;
    }

    .data-table th,
    .data-table td {
        padding: 0.5rem 0.6rem;
    }
}

/* Theme toggle */

.theme-toggle-form {
    margin: 0;
}

.theme-toggle-btn {
    background: none;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    width: 36px;
    height: 36px;
    padding: 0;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
    color: var(--color-text);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.theme-toggle-btn:hover {
    background: var(--color-border);
}

/* Tab bar (Users & Roles group filter) */

.tab-bar {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
    border-bottom: 1px solid var(--color-border);
    flex-wrap: wrap;
}

.tab-bar__item {
    padding: 0.6rem 1rem;
    text-decoration: none;
    color: var(--color-muted);
    font-weight: 600;
    border-bottom: 3px solid transparent;
    margin-bottom: -1px;
}

.tab-bar__item:hover {
    color: var(--color-text);
}

.tab-bar__item--active {
    color: var(--color-primary-dark);
    border-bottom-color: var(--color-primary);
}

/* Status tags (Active / Inactive) */

.status-tag {
    display: inline-block;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

.status-tag--active {
    background: var(--color-success-bg);
    color: var(--color-success-text);
}

.status-tag--inactive {
    background: var(--color-error-bg);
    color: var(--color-error-text);
}

/* Toggle-switch checkboxes (permission toggles) */

input.toggle-switch[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 44px;
    height: 24px;
    min-width: 44px;
    background: var(--color-border);
    border-radius: 999px;
    position: relative;
    cursor: pointer;
    outline: none;
    transition: background 0.15s ease;
    flex-shrink: 0;
}

input.toggle-switch[type="checkbox"]::before {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #ffffff;
    transition: transform 0.15s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

input.toggle-switch[type="checkbox"]:checked {
    background: var(--color-primary);
}

input.toggle-switch[type="checkbox"]:checked::before {
    transform: translateX(20px);
}

input.toggle-switch[type="checkbox"]:focus-visible {
    box-shadow: 0 0 0 3px var(--color-primary-dark);
}

/* Permission sections (grouped toggles on Add User / per-user pages) */

.permissions-form {
    max-width: 640px;
}

.permission-section {
    margin: 1.5rem 0;
    padding-top: 1.25rem;
    border-top: 1px solid var(--color-border);
}

.permission-section:first-of-type {
    border-top: none;
    padding-top: 0;
}

.permission-section__title {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-muted);
    margin: 0 0 0.75rem;
}

.permission-item {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 0;
}

.permission-item__info {
    flex: 1 1 auto;
}

.permission-item__label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 600;
    margin-bottom: 0.2rem;
}

.permission-item__description {
    margin: 0;
    color: var(--color-muted);
    font-size: 0.9rem;
    line-height: 1.4;
}

.permission-tag {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.permission-tag--manage {
    background: var(--color-tag-manage-bg);
    color: var(--color-tag-manage-text);
}

.permission-tag--sensitive {
    background: var(--color-tag-sensitive-bg);
    color: var(--color-tag-sensitive-text);
}

/* Per-user permissions page actions row */

.user-detail-actions {
    display: flex;
    gap: 1.25rem;
    margin: 1rem 0 1.5rem;
    flex-wrap: wrap;
}

.button-secondary-action {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    color: var(--color-primary-dark);
    padding: 0.5rem 1rem;
    border-radius: var(--radius);
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
}

.button-secondary-action:hover {
    background: var(--color-bg);
}

/* Pill-style segmented control (Finance section tabs) */

.pill-nav {
    margin-bottom: 1.5rem;
    overflow-x: auto;
    scrollbar-width: none;
}

.pill-nav::-webkit-scrollbar {
    display: none;
}

.pill-nav__track {
    position: relative;
    display: inline-flex;
    gap: 0.25rem;
    padding: 0.3rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-surface);
}

.pill-nav__indicator {
    position: absolute;
    top: 0.3rem;
    bottom: 0.3rem;
    left: 0;
    width: 0;
    border-radius: 999px;
    background: var(--color-primary);
    opacity: 0;
    /* A shade deeper while it moves (pill-nav.js): the same blue, never a different one. */
    --pill-nav-moving: color-mix(in srgb, var(--color-primary) 87%, #000000);
    transition: transform 0.28s ease, width 0.28s ease, background-color 0.28s ease;
}

/* A glide deepens the shade on the way and is back to the resting blue as it arrives, so
   nothing changes colour once it's there. pill-nav.js matches the length to the glide's. */
@keyframes pill-nav-moving {
    35%,
    65% {
        background-color: var(--pill-nav-moving);
    }
}

.pill-nav__indicator--gliding {
    animation: pill-nav-moving 0.28s ease;
}

.pill-nav__option {
    position: relative;
    z-index: 1;
    padding: 0.45rem 1.05rem;
    border-radius: 999px;
    color: var(--color-muted);
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.28s ease;
}

.pill-nav__option:hover {
    color: var(--color-text);
}

/* Without JavaScript the active option paints its own background; once the
   script has positioned the sliding indicator, the indicator takes over. */
.pill-nav__option--active,
.pill-nav__option--active:hover {
    background: var(--color-primary);
    color: #fff;
}

.pill-nav--ready .pill-nav__option--active {
    background: transparent;
}

/* The pill can be dragged to another tab (pill-nav.js), and the tab it sits under is its
   handle. A finger pressed there moves the pill, not the page. */
.pill-nav--ready .pill-nav__option--active {
    cursor: grab;
    touch-action: none;
    -webkit-touch-callout: none;
}

.pill-nav.pill-nav--dragging,
.pill-nav.pill-nav--dragging .pill-nav__option {
    cursor: grabbing;
    -webkit-user-select: none;
    user-select: none;
}

/* Held and dragged, it stays the deeper shade, fading in as it's picked up; on release it
   fades back to the resting blue as it snaps to its tab. */
.pill-nav.pill-nav--dragging .pill-nav__indicator {
    background-color: var(--pill-nav-moving);
    transition: background-color 0.2s ease;
}

.pill-nav--ready .pill-nav__indicator {
    opacity: 1;
}

/* On a phone, tabs that don't fit wrap onto another row. They used to scroll
   sideways with the scrollbar hidden, so a tab past the edge gave no sign it
   existed at all. Desktop is untouched: nothing here applies above 600px. */
@media (max-width: 600px) {
    .pill-nav {
        overflow-x: visible;
    }

    .pill-nav__track {
        flex-wrap: wrap;
        max-width: 100%;
    }

    /* A 999px radius over two rows would be an oval. pill-nav.js adds the class
       only once the tabs really have wrapped, so a bar that still fits on one row
       keeps its round ends. */
    .pill-nav--wrapped .pill-nav__track {
        border-radius: 1.5rem;
    }

    /* Sized to the one active tab by pill-nav.js, not stretched across both rows. */
    .pill-nav--wrapped .pill-nav__indicator {
        bottom: auto;
    }
}

@media (prefers-reduced-motion: reduce) {
    .pill-nav__indicator,
    .pill-nav__option,
    .pill-nav.pill-nav--dragging .pill-nav__indicator {
        transition: none;
    }

    .pill-nav__indicator--gliding {
        animation: none;
    }
}

@media print {
    .pill-nav {
        display: none !important;
    }
}

/* View As: the preview banner rides above every page, including access-denied ones. */

.preview-banner {
    position: sticky;
    top: 0;
    z-index: 40;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.6rem 1.25rem;
    background: var(--color-tag-manage-bg);
    color: var(--color-tag-manage-text);
    font-size: 0.92rem;
    font-weight: 600;
}

.preview-banner form {
    margin: 0;
}

.preview-banner button {
    padding: 0.3rem 0.85rem;
    border: 1px solid currentColor;
    border-radius: var(--radius);
    background: transparent;
    color: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.preview-banner button:hover {
    background: color-mix(in srgb, currentColor 12%, transparent);
}

.topbar__link {
    color: var(--color-primary-dark);
    font-size: 0.92rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.topbar__link:hover {
    text-decoration: underline;
}

.view-as-intro {
    max-width: 46rem;
    color: var(--color-muted);
}

/* Directory lists: positions on a profile, and the tick-box list on the person form. */

.chip-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.chip-list li {
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    background: var(--color-table-header);
    font-size: 0.85rem;
    font-weight: 600;
}

.new-family {
    margin: -0.4rem 0 1.1rem;
}

.new-family summary {
    color: var(--color-primary-dark);
    cursor: pointer;
    font-size: 0.92rem;
    font-weight: 600;
}

.new-family .form-field {
    margin-top: 0.6rem;
}

.directory-list-intro {
    max-width: 46rem;
    color: var(--color-muted);
}

.row-links {
    display: flex;
    gap: 0.75rem;
    white-space: nowrap;
}

.row-links__danger {
    color: var(--color-error-text);
}

/* Photos: a person's beside their name, a family's above its details. */

.page-heading__title {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    min-width: 0;
}

.page-heading__title h1 {
    min-width: 0;
    overflow-wrap: anywhere;
}

.photo-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}

.photo-panel--family {
    align-items: flex-start;
    margin: 1.25rem 0 1.5rem;
}

.photo {
    display: block;
    background: var(--color-primary-soft);
}

.photo--person {
    width: 7rem;
    height: 7rem;
    border-radius: 50%;
    /* Fills the circle from whatever shape the photo is, rather than squashing it. */
    object-fit: cover;
}

.photo--initials {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-primary-dark);
    font-size: 2.25rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.photo--family {
    width: 100%;
    max-width: 36rem;
    height: auto;
    max-height: 26rem;
    border-radius: var(--radius);
    object-fit: cover;
}

.photo--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 20rem;
    aspect-ratio: 3 / 2;
    border: 2px dashed var(--color-border);
    background: none;
    color: var(--color-muted);
    cursor: pointer;
}

.photo--empty:hover {
    border-color: var(--color-primary);
    color: var(--color-primary-dark);
}

.photo--empty .nav-icon {
    width: 2.75rem;
    height: 2.75rem;
}

.photo-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.35rem 1rem;
    font-size: 0.9rem;
}

/* Stacked under a profile photo, so the panel is no wider than the photo and the
   name sits right beside it. */
.photo-panel--person .photo-actions {
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
}

.photo-panel--family .photo-actions {
    justify-content: flex-start;
}

.photo-actions form {
    /* Holds the hidden file picker in place, rather than letting it widen the page. */
    position: relative;
    margin: 0;
}

.photo-upload__choose {
    cursor: pointer;
    color: var(--color-primary-dark);
    font-weight: 500;
    text-decoration: underline;
}

/* Set by photo-upload.js, which submits as soon as a photo is chosen. */
.photo-upload--auto input[type="file"],
.photo-upload--auto .photo-upload__submit {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.photo-upload--auto .photo-upload__choose:focus-within {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
    border-radius: 2px;
}

.photo-upload--busy .photo-upload__choose {
    cursor: progress;
    color: var(--color-muted);
    text-decoration: none;
}

.photo-remove .link-button {
    color: var(--color-muted);
    font-weight: 500;
}

/* The photo on a person's or family's Edit form: the current one beside the picker. */
.photo-field {
    display: flex;
    align-items: center;
    gap: 0.9rem;
}

.photo-field__current {
    flex-shrink: 0;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    object-fit: cover;
    background: var(--color-primary-soft);
}

.photo-field__current--wide {
    width: 5.25rem;
    border-radius: var(--radius);
}

.photo-field__controls {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}

.form-field .photo-field__controls input[type="file"] {
    padding: 0.45rem 0.5rem;
    font-size: 0.9rem;
}

.form-field .photo-field__remove {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.92rem;
    font-weight: 400;
}

/* Form inputs are full width by default. */
.form-field .photo-field__remove input {
    width: auto;
    margin: 0;
    padding: 0;
}

/* The small photo beside each name in the directory and a family's member list. */
.avatar {
    display: inline-block;
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    object-fit: cover;
    background: var(--color-primary-soft);
}

.avatar--initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-primary-dark);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

/* The link covers the photo too, but only the name is underlined: a link's
   underline would otherwise carry through to the initials. */
a.name-link,
.data-table a.name-link:hover {
    display: inline-flex;
    align-items: center;
    gap: 0.65rem;
    /* A photo has no text baseline, which would lift the name above the rest of the row. */
    vertical-align: middle;
    text-decoration: none;
}

a.name-link .name-link__text {
    text-decoration: underline;
}

/* The directory underlines names only on hover, as it did before. */
.data-table a.name-link .name-link__text {
    text-decoration: none;
}

.data-table a.name-link:hover .name-link__text {
    text-decoration: underline;
}

@media (max-width: 600px) {
    .page-heading__title {
        gap: 0.9rem;
    }

    .photo--person {
        width: 5.5rem;
        height: 5.5rem;
    }

    .photo--initials {
        font-size: 1.75rem;
    }
}

@media print {
    .photo-actions {
        display: none;
    }
}

/* The new permission system's screens. Everything on them is saved but not yet
   checked, so the notice is loud on purpose. */
.preview-notice {
    margin: 0 0 1.25rem;
    padding: 0.9rem 1.1rem;
    border: 2px dashed var(--color-tag-manage-text);
    border-radius: var(--radius);
    background: var(--color-tag-manage-bg);
    color: var(--color-text);
}

.preview-notice strong {
    display: block;
    margin-bottom: 0.25rem;
    color: var(--color-tag-manage-text);
    font-size: 0.82rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.preview-notice p {
    margin: 0;
}

.preview-notice--live {
    border-style: solid;
    border-color: var(--color-success-text);
    background: var(--color-success-bg);
}

.preview-notice--live strong {
    color: var(--color-success-text);
}

.preview-handoff {
    max-width: 640px;
    margin-top: 1.75rem;
    padding: 1rem 1.1rem;
    border: 2px dashed var(--color-tag-manage-text);
    border-radius: var(--radius);
    background: var(--color-tag-manage-bg);
}

.preview-handoff .permission-item__description {
    margin-bottom: 0.75rem;
}

.capability-intro {
    max-width: 46rem;
    color: var(--color-muted);
}

.capability-form {
    max-width: 720px;
}

.capability-category + .capability-category {
    margin-top: 2rem;
}

.capability-category__title {
    margin: 1.5rem 0 0.25rem;
    font-size: 1.15rem;
}

.capability-module {
    margin: 0.75rem 0;
}

.capability-item {
    align-items: center;
    padding: 0.6rem 0.75rem;
    border-left: 4px solid transparent;
    border-radius: 6px;
}

/* Sensitive capabilities stand out: a strong left edge and a tint, as the tier warrants. */
.capability-item--sensitive {
    border-left-color: var(--color-danger);
    background: color-mix(in srgb, var(--color-danger) 7%, transparent);
}

.permission-tag--everyday {
    background: var(--color-table-header);
    color: var(--color-muted);
}

.capability-sources {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin: 0.3rem 0 0;
}

/* Allowed to wrap, and the column to shrink, so a long "From current toggle: ..."
   never pushes the toggle off a narrow phone. */
.capability-item .permission-item__info {
    min-width: 0;
}

.capability-source {
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--color-table-header);
    color: var(--color-muted);
    font-size: 0.78rem;
}

.capability-source--role {
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
}

.capability-source--individual {
    background: var(--color-success-bg);
    color: var(--color-success-text);
}

/* Locked: it comes from the role or a current toggle, and is changed there. */
input.toggle-switch[type="checkbox"]:disabled {
    cursor: not-allowed;
    opacity: 0.55;
}

.grant-level-form {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

.grant-level-form select {
    padding: 0.3rem 0.45rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
    font-family: inherit;
}

/* An uploaded logo that is the other kind of logo, drawn as a plain shape so it reads on
   this background: only one of the church's two logos was uploaded (see people/branding.py). */
.site-logo--white {
    filter: brightness(0) invert(1);
}

.site-logo--black {
    filter: brightness(0);
}

/* A church's own logo, where it sits on the page's own background (the top bar and the sign-in
   page): the logo for light backgrounds by day, the one for dark backgrounds in dark mode. The
   logo that comes with the site is one colour that reads on both, so it has no second image. */
.site-logo--on-dark {
    display: none;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .site-logo--on-light {
        display: none;
    }

    :root:not([data-theme="light"]) .site-logo--on-dark {
        display: block;
    }
}

:root[data-theme="dark"] .site-logo--on-light {
    display: none;
}

:root[data-theme="dark"] .site-logo--on-dark {
    display: block;
}

/* Site Settings */
.settings-form {
    max-width: 560px;
}

.settings-section + .settings-section {
    margin-top: 1.75rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--color-border);
}

.settings-section__heading {
    margin: 0 0 0.35rem;
    font-size: 1.05rem;
}

.settings-section > .field-help {
    margin-bottom: 1rem;
}

.logo-input__current {
    display: inline-flex;
    align-items: center;
    margin-bottom: 0.6rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: #ffffff;
}

/* The logo for dark backgrounds is shown on the sidebar's own gradient. */
.logo-input__current--dark {
    border-color: transparent;
    background: var(--brand-gradient);
}

.logo-input__current img {
    display: block;
    max-width: 100%;
    height: 40px;
    width: auto;
}

.form-field .logo-input input[type="file"] {
    padding: 0.4rem;
}

.form-field .logo-input__clear {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0.5rem 0 0;
    font-weight: 400;
}

.form-field .logo-input__clear input {
    width: auto;
    margin: 0;
}

.color-input {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
}

.form-field .color-input input[type="color"] {
    flex: 0 0 auto;
    width: 3rem;
    padding: 0.15rem;
    background: var(--color-surface);
    cursor: pointer;
}

.form-field .color-input input[type="text"] {
    flex: 1 1 auto;
    min-width: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    text-transform: uppercase;
}

/* A miniature of the sidebar and a page, redrawn as the colours are changed. */
.brand-preview {
    display: flex;
    overflow: hidden;
    margin-top: 0.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-bg);
    color: var(--brand-charcoal);
    font-size: 0.85rem;
}

.brand-preview__side {
    display: flex;
    flex: 0 0 8rem;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.85rem 0.75rem;
    background: linear-gradient(180deg, var(--brand-dark) 0%, var(--brand-primary) 100%);
    color: #ffffff;
}

.brand-preview__logo {
    display: block;
    align-self: flex-start;
    max-width: 100%;
    height: 24px;
    width: auto;
    margin-bottom: 0.4rem;
}

.brand-preview__page {
    flex: 1 1 auto;
    padding: 0.85rem 1rem;
    background: #ffffff;
    border-left: 1px solid var(--brand-light-gray);
}

.brand-preview__page p {
    margin: 0.35rem 0 0.75rem;
}

.brand-preview__quiet {
    color: var(--brand-gray);
}

.brand-preview__button {
    display: inline-block;
    padding: 0.35rem 0.8rem;
    border-radius: var(--radius);
    background: var(--brand-primary);
    color: #ffffff;
    font-weight: 600;
}
