/* ==========================================================================
   ACA base stylesheet
   Element defaults, a single typography scale, Bootstrap 4.1.3 overrides and
   the shared .aca-* component primitives. Depends on css/aca-tokens.css.
   Breakpoints: 991px (layout) and 576px (font-size) only.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Element defaults
   -------------------------------------------------------------------------- */

html {
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
}

body {
    color: var(--aca-fg);
    font-family: var(--aca-font);
    font-size: var(--aca-text);
    font-weight: 400;
    line-height: 1.5;
}

h1, .h1,
h2, .h2,
h3, .h3,
h4, .h4,
h5, .h5,
h6, .h6 {
    margin-top: 0;
    margin-bottom: var(--aca-space-3);
    color: inherit;
    font-family: inherit;
    font-weight: 600;
    line-height: 1.25;
}

h1, .h1 {
    font-size: var(--aca-text-2xl);
}

h2, .h2 {
    font-size: 1.5rem;
}

h3, .h3 {
    font-size: 1.25rem;
}

h4, .h4 {
    font-size: var(--aca-text-lg);
}

h5, .h5 {
    font-size: var(--aca-text);
}

h6, .h6 {
    font-size: var(--aca-text-sm);
}

p {
    margin-top: 0;
    margin-bottom: var(--aca-space-3);
}

a {
    color: var(--aca-fg-link);
    font-weight: 600;
    text-decoration: none;
    transition: color var(--aca-transition);
}

a:hover,
a:focus {
    color: var(--aca-fg-link-hover);
    text-decoration: underline;
}

hr {
    border: 0;
    border-top: 1px solid var(--aca-fg-line);
    margin: var(--aca-space-4) 0;
}

code, kbd, pre, samp {
    font-family: var(--aca-font-mono);
}

@media (max-width: 991px) and (min-width: 577px) {
    h1, .h1 {
        font-size: 1.5rem;
    }

    h2, .h2 {
        font-size: 1.375rem;
    }

    h3, .h3 {
        font-size: 1.125rem;
    }
}

@media (max-width: 576px) {
    h1, .h1 {
        font-size: 1.375rem;
    }

    h2, .h2 {
        font-size: 1.25rem;
    }

    h3, .h3 {
        font-size: 1.0625rem;
    }
}

/* --------------------------------------------------------------------------
   2. Focus visibility
   -------------------------------------------------------------------------- */

a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.btn:focus-visible,
.form-control:focus-visible,
.custom-select:focus-visible {
    outline: none;
    box-shadow: var(--aca-focus);
}

/* --------------------------------------------------------------------------
   3. Bootstrap 4.1.3 overrides on tokens
   -------------------------------------------------------------------------- */

.card {
    border: 1px solid var(--aca-line);
    border-radius: var(--aca-radius);
    box-shadow: var(--aca-shadow-sm);
}

.card-footer {
    background-color: var(--aca-surface-2);
    border-color: var(--aca-line);
}

/* A legacy Bootstrap card wears the same navy header as .aca-card (section 6,
   which also paints its lattice and restyles the controls inside it). */
.card > .card-header {
    position: relative;
    isolation: isolate;
    border-bottom: 0;
    border-radius: calc(var(--aca-radius) - 1px) calc(var(--aca-radius) - 1px) 0 0;
    background-color: var(--aca-chrome);
    color: var(--aca-on-chrome);
}

.modal-content {
    border: 1px solid var(--aca-line);
    border-radius: var(--aca-radius-lg);
    box-shadow: var(--aca-shadow-lg);
}

/* Restore modal dimming: style.css used to hide the backdrop entirely.
   Only the colour is changed here - Bootstrap keeps its own z-index (1040). */
.modal-backdrop {
    background-color: var(--aca-ink-strong);
}

.modal-backdrop.show {
    opacity: .35;
}

/* Bootstrap sizes these below the body size (75-87.5% of the root: 12-14px); the
   site's floor is --aca-text-xs, so every one of them is pinned to it. */
small,
.small,
.custom-select-sm,
.form-control-sm,
.col-form-label-sm,
.input-group-sm > .form-control,
.input-group-sm > .custom-select,
.input-group-sm > .input-group-prepend > .input-group-text,
.input-group-sm > .input-group-append > .input-group-text,
.btn-group-sm > .btn,
.pagination-sm .page-link,
.dropdown-header,
.valid-feedback,
.invalid-feedback,
.blockquote-footer,
.figure-caption,
.tooltip,
.popover,
code,
kbd,
pre,
samp,
sup,
sub {
    font-size: var(--aca-text-xs);
}

.badge {
    border-radius: var(--aca-radius-pill);
    font-size: var(--aca-text-xs);
    font-weight: 600;
    letter-spacing: .01em;
    padding: .35em .7em;
}

.alert {
    border: 1px solid transparent;
    border-radius: var(--aca-radius);
    font-size: var(--aca-text-sm);
}

.alert-success {
    background-color: var(--aca-success-soft);
    border-color: var(--aca-green-line);
    color: var(--aca-green-strong);
}

.alert-info {
    background-color: var(--aca-info-soft);
    border-color: var(--aca-info-line);
    /* The accent rail css/style.css used to add on top of this rule (S5, lane C). */
    border-left: 4px solid var(--aca-info);
    color: var(--aca-info);
}

.alert-warning {
    background-color: var(--aca-warning-soft);
    border-color: var(--aca-warning-line);
    color: var(--aca-warning);
}

.alert-danger {
    background-color: var(--aca-danger-soft);
    border-color: var(--aca-danger-line);
    color: var(--aca-danger);
}

.table {
    color: var(--aca-ink);
}

.table th,
.table td {
    padding: .5rem .75rem;
    vertical-align: middle;
    border-top: 1px solid var(--aca-line);
}

.table thead th {
    border-bottom: 1px solid var(--aca-line-strong);
    color: var(--aca-muted);
    font-size: var(--aca-text-xs);
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.list-group-item {
    border-color: var(--aca-line);
}

.form-control,
.custom-select {
    border: 1px solid var(--aca-line-strong);
    border-radius: var(--aca-radius-sm);
    color: var(--aca-ink);
    font-size: var(--aca-text-sm);
    transition: border-color var(--aca-transition), box-shadow var(--aca-transition);
}

/* 16px is the threshold below which iOS Safari zooms the page on focus - a device
   constant, not a type token. */
@media (max-width: 991px) {
    .form-control,
    .custom-select,
    .form-control-sm,
    .custom-select-sm {
        font-size: max(16px, var(--aca-text));
    }

    /* Bootstrap fixes the -sm input height for 14px text; a 16px line box needs 3px more. */
    .form-control-sm {
        height: auto;
    }
}

.form-control:focus,
.custom-select:focus {
    border-color: var(--aca-orange);
    box-shadow: var(--aca-focus);
}

.form-control::placeholder {
    color: var(--aca-muted);
}

.form-control:disabled,
.form-control[readonly] {
    background-color: var(--aca-surface-2);
}

label {
    color: var(--aca-fg-muted-strong);
    font-size: var(--aca-text-sm);
    font-weight: 600;
    margin-bottom: var(--aca-space-1);
}

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */

.btn {
    border-radius: var(--aca-radius-sm);
    font-family: inherit;
    font-size: var(--aca-text-sm);
    font-weight: 600;
    line-height: 1.4;
    padding: .45rem .9rem;
    transition: background-color var(--aca-transition), border-color var(--aca-transition), box-shadow var(--aca-transition), color var(--aca-transition);
}

/* Bootstrap's display on .btn beats the browser's own [hidden] rule; a button a page ships
   hidden until something is selected must stay hidden on every screen size. */
.btn[hidden],
.btn-block[hidden] {
    display: none;
}

.btn-lg {
    font-size: var(--aca-text);
    padding: .6rem 1.15rem;
}

.btn-sm {
    font-size: var(--aca-text-xs);
    padding: .3rem .65rem;
}

.btn-primary {
    background-color: var(--aca-orange);
    border-color: var(--aca-orange);
    color: var(--aca-on-brand);
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:not(:disabled):not(.disabled):active {
    background-color: var(--aca-orange-strong);
    border-color: var(--aca-orange-strong);
    color: var(--aca-on-brand);
}

.btn-danger {
    background-color: var(--aca-danger);
    border-color: var(--aca-danger);
    color: var(--aca-on-brand);
}

/* The quiet button reads the context tokens: grey-outlined on a light surface, a
   white ghost on the page ground or a coloured band (aca-tokens.css surface registry). */
.btn-outline-secondary {
    border-color: var(--aca-ghost-line);
    background-color: transparent;
    color: var(--aca-ghost-fg);
}

.btn-outline-secondary:hover,
.btn-outline-secondary:focus {
    background-color: var(--aca-ghost-bg);
    border-color: var(--aca-fg-muted);
    color: var(--aca-fg);
}

/* The chosen option of a toggle group (date presets, semester, view switches).
   Bootstrap's own rule is .btn-outline-secondary:not(:disabled):not(.disabled).active,
   so the same form is needed here or its grey fill wins whenever the button is
   not focused. */
.btn-outline-secondary.active,
.btn-outline-secondary:not(:disabled):not(.disabled).active,
.btn-outline-secondary:not(:disabled):not(.disabled):active,
.btn-outline-secondary:not(:disabled):not(.disabled).active:focus {
    background-color: var(--aca-ghost-active-bg);
    border-color: var(--aca-ghost-active-line);
    color: var(--aca-ghost-active-fg);
    box-shadow: none;
}

/* Red outline on a light surface; a light pill with red ink on a dark one. */
.btn-outline-danger {
    border-color: var(--aca-ghost-danger-line);
    background-color: var(--aca-ghost-danger-bg);
    color: var(--aca-danger);
}

/* Bootstrap restyles a disabled button (transparent outlines, its own blue for
   primary) with rules that out-rank the ones above; a disabled button keeps the
   same look and only fades (Bootstrap's opacity on .btn:disabled stays). */
.btn-outline-secondary:disabled,
.btn-outline-secondary.disabled {
    border-color: var(--aca-ghost-line);
    background-color: transparent;
    color: var(--aca-ghost-fg);
}

.btn-outline-danger:disabled,
.btn-outline-danger.disabled {
    border-color: var(--aca-ghost-danger-line);
    background-color: var(--aca-ghost-danger-bg);
    color: var(--aca-danger);
}

.btn-primary:disabled,
.btn-primary.disabled {
    background-color: var(--aca-orange);
    border-color: var(--aca-orange);
    color: var(--aca-on-brand);
}

.btn-danger:disabled,
.btn-danger.disabled {
    background-color: var(--aca-danger);
    border-color: var(--aca-danger);
    color: var(--aca-on-brand);
}

.btn-outline-danger:hover,
.btn-outline-danger:focus {
    background-color: var(--aca-danger);
    border-color: var(--aca-danger);
    color: var(--aca-on-brand);
}

.btn-link {
    color: var(--aca-fg-link);
    font-weight: 600;
}

/* Icon-only button: square, centred glyph; needs aria-label + title. */
.aca-btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    padding-right: 0;
    padding-left: 0;
}

.aca-btn-icon.btn-sm {
    width: 2.1rem;
}

.aca-btn-icon i {
    margin: 0;
}

@media (max-width: 991px) {
    .btn {
        min-height: 40px;
    }

    .btn-sm {
        min-height: 34px;
    }
}

/* --------------------------------------------------------------------------
   4b. The term switch (familyPortalTermSwitchHtml())
   THE Fall | Spring switch of every portal: full width with 44px buttons on a
   phone, inline with a 7rem minimum from 992px. The chosen term is solid brand
   orange with chrome ink on EVERY ground, hovered or focused too - navy, because
   white does not read on this orange. The idle term stays the quiet button and
   reads the context tokens; none is re-declared here.
   -------------------------------------------------------------------------- */

.aca-term-switch {
    display: flex;
    width: 100%;
}

.aca-term-switch > .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 0;
    min-height: 44px;
}

/* (0,5,0) and (0,6,0): above the toggle rule in section 4 and Bootstrap's own. */
.aca-term-switch > .btn-outline-secondary.active,
.aca-term-switch > .btn-outline-secondary:not(:disabled):not(.disabled).active,
.aca-term-switch > .btn-outline-secondary:not(:disabled):not(.disabled).active:hover,
.aca-term-switch > .btn-outline-secondary:not(:disabled):not(.disabled).active:focus {
    border-color: var(--aca-orange);
    background-color: var(--aca-orange);
    color: var(--aca-chrome);
    box-shadow: none;
}

.aca-term-switch > .btn-outline-secondary:not(:disabled):not(.disabled).active:focus-visible {
    box-shadow: var(--aca-focus);
}

@media (min-width: 992px) {
    .aca-term-switch {
        display: inline-flex;
        width: auto;
    }

    .aca-term-switch > .btn {
        flex: 0 0 auto;
        min-width: 7rem;
    }
}

@media print {
    .aca-term-switch {
        display: none;
    }
}

/* --------------------------------------------------------------------------
   5. Page header
   -------------------------------------------------------------------------- */

/* The chrome band a screen opens with (the store's steps, printPortalCardHeader()):
   the same band as the portals' welcome band, the lattice in orange on the right. */
.aca-page-header {
    position: relative;
    isolation: isolate;
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--aca-space-3);
    margin: 0 0 var(--aca-space-4);
    padding: var(--aca-space-4);
    border: 1px solid var(--aca-on-chrome-line);
    border-radius: var(--aca-radius-lg);
    background: var(--aca-chrome);
    color: var(--aca-on-chrome);
    box-shadow: var(--aca-shadow);
}

.aca-page-header::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: -1;
    width: 55%;
    border-top-right-radius: inherit;
    border-bottom-right-radius: inherit;
    background: linear-gradient(to right, transparent, var(--aca-orange) 45%);
    opacity: .2;
    -webkit-mask-image: var(--aca-pattern-star);
    mask-image: var(--aca-pattern-star);
    -webkit-mask-size: 56px 56px;
    mask-size: 56px 56px;
    pointer-events: none;
}

.aca-page-header__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: var(--aca-radius);
    background: var(--aca-orange);
    color: var(--aca-on-brand);
    font-size: var(--aca-text-lg);
}

.aca-page-header__text {
    flex: 1 1 auto;
    min-width: 0;
}

.aca-page-header__title {
    margin: 0;
    color: var(--aca-fg);
    font-size: var(--aca-text-xl);
    font-weight: 700;
    line-height: 1.25;
}

.aca-page-header__subtitle {
    margin: var(--aca-space-1) 0 0;
    color: var(--aca-fg-muted);
    font-size: var(--aca-text-sm);
    line-height: 1.4;
}

.aca-page-header__subtitle strong {
    color: var(--aca-fg);
}

.aca-page-header__actions {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    flex-wrap: wrap;
    gap: var(--aca-space-2);
}

@media (max-width: 991px) {
    .aca-page-header {
        flex-wrap: wrap;
    }

    .aca-page-header__actions {
        width: 100%;
    }
}

/* --------------------------------------------------------------------------
   6. Card
   -------------------------------------------------------------------------- */

.aca-card {
    position: relative;
    display: block;
    margin: 0 0 var(--aca-space-4);
    padding: 0;
    border: 1px solid var(--aca-line);
    border-radius: var(--aca-radius);
    background: var(--aca-surface);
    box-shadow: var(--aca-shadow-sm);
}

/* The header is a coloured band: the school's navy by default, the entity's
   own colour when the card carries data-accent, a white title, and the star
   lattice fading in under the actions. The same paint serves a legacy
   .card > .card-header (section 3) and every .modal-header (the modal shell
   below), so the lattice and the control rules here name all three. */
.aca-card__header {
    position: relative;
    isolation: isolate;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--aca-space-2);
    padding: var(--aca-space-3) var(--aca-space-4);
    border-radius: calc(var(--aca-radius) - 1px) calc(var(--aca-radius) - 1px) 0 0;
    background: var(--aca-chrome);
    color: var(--aca-on-chrome);
}

.aca-card__header::before,
.card > .card-header::before,
.modal-header::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: -1;
    width: 55%;
    border-top-right-radius: inherit;
    background: linear-gradient(to right, transparent, var(--aca-on-brand) 50%);
    opacity: .13;
    -webkit-mask-image: var(--aca-pattern-star);
    mask-image: var(--aca-pattern-star);
    -webkit-mask-size: 56px 56px;
    mask-size: 56px 56px;
    pointer-events: none;
}

/* The entity accents as header colours - the strong shade of each, so a white
   title reads on all of them (the brand orange itself is too light for white):
   family steel blue, course / success sea-green, book terracotta, staff / info
   teal, file stone, transaction bronze, warning amber, danger red. */
.aca-card[data-accent="family"] > .aca-card__header {
    background: var(--aca-accent-family-strong);
}

.aca-card[data-accent="course"] > .aca-card__header,
.aca-card[data-accent="success"] > .aca-card__header {
    background: var(--aca-accent-course);
}

.aca-card[data-accent="book"] > .aca-card__header {
    background: var(--aca-orange-strong);
}

.aca-card[data-accent="staff"] > .aca-card__header,
.aca-card[data-accent="info"] > .aca-card__header {
    background: var(--aca-accent-staff);
}

.aca-card[data-accent="file"] > .aca-card__header {
    background: var(--aca-accent-file);
}

.aca-card[data-accent="transaction"] > .aca-card__header {
    background: var(--aca-accent-transaction);
}

.aca-card[data-accent="warning"] > .aca-card__header {
    background: var(--aca-warning);
}

.aca-card[data-accent="danger"] > .aca-card__header {
    background: var(--aca-danger);
}

.aca-card__title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    color: inherit;
    font-size: var(--aca-text);
    font-weight: 600;
    line-height: 1.3;
}

/* Lighter line under the title (counts, context); takes the full header row. */
.aca-card__subtitle {
    flex: 1 1 100%;
    margin: -.2rem 0 0;
    color: var(--aca-fg-muted);
    font-size: var(--aca-text-xs);
    line-height: 1.35;
}

/* The header's action cluster: btn-sm outline buttons, icon buttons, a select. */
.aca-card__actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--aca-space-2);
    margin-left: auto;
}

/* A legacy Bootstrap .card-header converges on the same title typography. */
.card > .card-header > h1,
.card > .card-header > h2,
.card > .card-header > h3,
.card > .card-header > h4,
.card > .card-header > h5,
.card > .card-header > h6,
.card > .card-header > .card-title {
    margin: 0;
    color: inherit;
    font-size: var(--aca-text);
    font-weight: 600;
    line-height: 1.3;
}

/* Everything ON a band - ghost buttons, chips, links, muted text - reads the
   context tokens the band re-declares (aca-tokens.css surface registry), so
   the rules in sections 4 and 7 serve it unchanged. The one exception: the
   book header is the primary button's own colour, so there the button goes light. */
.aca-card[data-accent="book"] > .aca-card__header .btn-primary {
    border-color: var(--aca-on-brand);
    background-color: var(--aca-on-brand);
    color: var(--aca-orange-ink);
}

.aca-card[data-accent="book"] > .aca-card__header .btn-primary:hover,
.aca-card[data-accent="book"] > .aca-card__header .btn-primary:focus {
    border-color: var(--aca-orange-soft);
    background-color: var(--aca-orange-soft);
    color: var(--aca-orange-ink);
}

.aca-card__body {
    padding: var(--aca-space-4);
}

.aca-card__footer {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--aca-space-2);
    padding: var(--aca-space-3) var(--aca-space-4);
    border-top: 1px solid var(--aca-line);
    background: var(--aca-surface-2);
    border-radius: 0 0 calc(var(--aca-radius) - 1px) calc(var(--aca-radius) - 1px);
}

/* --------------------------------------------------------------------------
   7. Toolbar, status pills, chips
   -------------------------------------------------------------------------- */

.aca-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--aca-space-2);
}

.aca-status {
    display: inline-flex;
    align-items: center;
    padding: .2em .7em;
    border-radius: var(--aca-radius-pill);
    background: var(--aca-surface-2);
    color: var(--aca-muted-strong);
    font-size: var(--aca-text-sm);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}

.aca-status i,
.aca-status .fas,
.aca-status .far {
    margin-right: var(--aca-space-1);
    font-size: .85em;
}

.aca-status--pending {
    background: var(--aca-warning-soft);
    color: var(--aca-warning);
}

.aca-status--verified,
.aca-status--active {
    background: var(--aca-success-soft);
    color: var(--aca-green-strong);
}

.aca-status--cancelled,
.aca-status--inactive {
    background: var(--aca-surface-2);
    color: var(--aca-muted);
    text-decoration: none;
}

.aca-status--plan,
.aca-status--info {
    background: var(--aca-info-soft);
    color: var(--aca-info);
}

.aca-status--new {
    background: var(--aca-orange-soft);
    color: var(--aca-orange-ink);
}

.aca-status--danger {
    background: var(--aca-danger-soft);
    color: var(--aca-danger);
}

.aca-status--scholarship {
    background: var(--aca-scholarship-soft);
    color: var(--aca-scholarship);
}

/* A chip reads the context tokens too: a light pill on a light surface, a
   translucent white one on the page ground or a band. */
.aca-chip {
    display: inline-flex;
    align-items: center;
    padding: .25rem .75rem;
    border: 1px solid var(--aca-ghost-line);
    border-radius: var(--aca-radius-pill);
    background: var(--aca-ghost-chip-bg);
    color: var(--aca-ghost-fg);
    font-family: inherit;
    font-size: var(--aca-text-sm);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--aca-transition), border-color var(--aca-transition), color var(--aca-transition);
}

.aca-chip i {
    margin-right: var(--aca-space-1);
    font-size: .85em;
}

.aca-chip:hover {
    border-color: var(--aca-fg-accent);
    color: var(--aca-fg);
    text-decoration: none;
}

.aca-chip.is-active {
    background: var(--aca-ghost-active-bg);
    border-color: var(--aca-ghost-active-line);
    color: var(--aca-ghost-active-fg);
}

.aca-chip__count {
    margin-left: var(--aca-space-2);
    color: var(--aca-fg-muted);
    font-size: var(--aca-text-xs);
}

/* --------------------------------------------------------------------------
   8. Tabs
   -------------------------------------------------------------------------- */

.aca-tabs {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    margin: 0 0 var(--aca-space-4);
    padding: 0;
    border-bottom: 1px solid var(--aca-fg-line);
    list-style: none;
}

/* Wrapper emitted by Functions.php printTabbedPane(). */
.aca-tabs-container {
    background: var(--aca-surface);
    border: 1px solid var(--aca-line);
    border-radius: var(--aca-radius);
}

.aca-tabs-container > .aca-tabs {
    position: sticky;
    top: 0;
    z-index: 5;
    margin: 0;
    padding: 0 var(--aca-space-2);
    background: var(--aca-surface);
    border-radius: var(--aca-radius) var(--aca-radius) 0 0;
}

.aca-tabs-content {
    padding: var(--aca-space-3);
}

.aca-tab {
    display: inline-flex;
    align-items: center;
    margin: 0;
    padding: var(--aca-space-2) var(--aca-space-3);
    border: 0;
    border-bottom: 3px solid transparent;
    background: transparent;
    color: var(--aca-fg-muted-strong);
    font-family: inherit;
    font-size: var(--aca-text-sm);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--aca-transition), border-color var(--aca-transition);
}

.aca-tab i {
    margin-right: var(--aca-space-2);
    font-size: .9em;
}

.aca-tab:hover {
    color: var(--aca-fg);
    text-decoration: none;
}

.aca-tab.is-active {
    border-bottom-color: var(--aca-orange);
    color: var(--aca-fg-link);
}

.aca-tab:focus-visible {
    outline: none;
    border-radius: var(--aca-radius-sm) var(--aca-radius-sm) 0 0;
    box-shadow: var(--aca-focus);
}

.aca-tab__badge {
    margin-left: var(--aca-space-2);
    padding: 0 .45em;
    border-radius: var(--aca-radius-pill);
    background: var(--aca-ghost-bg);
    color: var(--aca-ghost-fg);
    font-size: var(--aca-text-xs);
}

.aca-tab-panel[hidden] {
    display: none;
}

/* When the strip cannot wrap (narrow viewports) it scrolls horizontally. */
.aca-tabs--scroll {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.aca-tabs--scroll::-webkit-scrollbar {
    display: none;
    height: 0;
}

@media (max-width: 991px) {
    .aca-tabs {
        flex-wrap: wrap;
    }

    .aca-tab {
        padding: var(--aca-space-2);
    }
}

/* --------------------------------------------------------------------------
   9. Tables
   -------------------------------------------------------------------------- */

/* The table box. It FLOWS (overflow visible): the table is designed to fit
   the width, and thead th sticks to whatever scrolls the page - the main
   pane, #mainBodyDiv or a .modal-body. A long list scrolls only as a fill
   panel's .aca-panel__scroll (below); a page sheet that caps a box's height
   gives it its own overflow. An overflow: auto box that never scrolls would
   only stop the header sticking. */
.aca-table-wrap {
    position: relative;
    border: 1px solid var(--aca-line);
    border-radius: var(--aca-radius);
    background: var(--aca-surface);
}

.aca-table-wrap .table {
    margin-bottom: 0;
}

.aca-table-wrap .table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--aca-surface-2);
}

.aca-table--compact th,
.aca-table--compact td {
    padding: .35rem .5rem;
    font-size: var(--aca-text-sm);
}

/* The panel: a long list or table card whose head stays in view
   (officeFamilyCardHtml()'s 'panel' key). Its head pins under the navbar (a
   fitted fill panel's flows instead, below), and the column headings of a
   table that does not scroll stick under the head (aca-panels.js writes
   --aca-panel-head-h). Row content stays at z-index 2 or below, so a
   dropdown (1000) still overlays the head. */
.aca-panel > .aca-card__header {
    position: sticky;
    top: 0;
    z-index: 4;
}

.aca-panel .aca-table-wrap .table thead th {
    top: var(--aca-panel-head-h, 0px);
}

/* The positioned box of its rows' absolute content (.aca-sr-only words), kept inside its clip. */
.aca-panel__scroll {
    position: relative;
}

/* Tabs in the head: the strip is part of the ONE pinned block, flush with the
   band's bottom edge, and reads the band's context tokens. */
.aca-panel__tabs {
    flex: 1 0 100%;
    margin: 0 0 calc(var(--aca-space-3) * -1);
    border-bottom: 0;
}

/* --fill, from 992px only: the card fits the pane under the navbar, less the
   16px gap it docks at and the column's 32px bottom padding (family_portal.css
   section 1), and its rows scroll inside .aca-panel__scroll once aca-panels.js
   docks it - until then the page moves first. The fitted card's head flows
   with it, so a panel the page scrolls past (one that is not the page's last
   block) leaves whole instead of pinning its head over the column headings.
   .is-cramped (a pane that leaves under 10rem of rows) turns the fill off,
   leaving the pinned head. A phone keeps one page scroll: nothing here
   touches height or overflow below 992px. */
@media screen and (min-width: 992px) {
    .aca-panel--fill:not(.is-cramped) {
        display: flex;
        flex-direction: column;
        max-height: calc(100vh - var(--aca-navbar-h) - var(--aca-space-4) - var(--aca-space-6));
        max-height: calc(100dvh - var(--aca-navbar-h) - var(--aca-space-4) - var(--aca-space-6));
    }

    .aca-panel--fill:not(.is-cramped) > .aca-card__header {
        position: relative;
    }

    .aca-panel--fill:not(.is-cramped) > *,
    .aca-panel--fill:not(.is-cramped) .aca-panel__grow > * {
        flex: none;
    }

    .aca-panel--fill:not(.is-cramped) .aca-panel__grow:not([hidden]) {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
    }

    .aca-panel--fill:not(.is-cramped) .aca-panel__scroll {
        flex: 1 1 auto;
        min-height: 0;
        overflow-x: hidden;
        overflow-y: auto;
        scrollbar-gutter: stable;
    }

    .aca-panel--fill:not(.is-cramped):not(.is-docked) .aca-panel__scroll {
        overflow-y: hidden;
    }

    .aca-panel--fill:not(.is-cramped) .aca-panel__scroll .table thead th {
        top: 0;
    }
}

/* The table itself: columns are designed to fit a phone (no sideways scroll),
   so cells wrap and only numbers, actions and the select box stay narrow. */
.aca-table {
    width: 100%;
    margin-bottom: 0;
}

.aca-table th,
.aca-table td {
    vertical-align: middle;
    overflow-wrap: anywhere;
}

.aca-table thead th {
    font-size: var(--aca-text-xs);
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--aca-muted-strong);
    border-top: 0;
}

.aca-table .aca-table__select {
    width: 2.5rem;
    text-align: center;
}

.aca-table .aca-table__select input {
    margin: 0;
    vertical-align: middle;
}

.aca-table .aca-table__num {
    width: 1%;
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.aca-table .aca-table__actions {
    width: 1%;
    text-align: right;
    white-space: nowrap;
}

.aca-table tbody tr.is-selected > td {
    background: var(--aca-orange-soft);
}

/* Stacked cell: one primary line plus a muted second line, which is how two
   or three former columns (family, age, contact, status chips) share one. */
.aca-cell__title {
    font-weight: 600;
    color: var(--aca-ink);
}

.aca-cell__sub {
    font-size: var(--aca-text-xs);
    line-height: 1.35;
    color: var(--aca-muted);
}

.aca-cell__sub > .aca-chip,
.aca-cell__sub > .aca-status {
    margin-top: .15rem;
    vertical-align: middle;
}

/* Sortable headers: th[data-sort] toggles asc/desc through AcaUI.sortTable();
   the arrow is the only indicator, orange when active. */
.aca-table th[data-sort] {
    cursor: pointer;
    user-select: none;
}

.aca-table th[data-sort]::after {
    content: "\2195";
    margin-left: .35em;
    opacity: .35;
    font-size: .9em;
}

.aca-table th[data-sort]:hover {
    color: var(--aca-ink);
}

.aca-table th[data-sort][aria-sort="ascending"]::after {
    content: "\2191";
    opacity: 1;
    color: var(--aca-orange);
}

.aca-table th[data-sort][aria-sort="descending"]::after {
    content: "\2193";
    opacity: 1;
    color: var(--aca-orange);
}

/* "Sort by" control for facts that live in a sub-line rather than a column. */
.aca-sort-select {
    width: auto;
    max-width: 14rem;
}

/* Narrow inputs side by side in one cell (from-to ayahs, score / max). */
.aca-table__inputs {
    white-space: nowrap;
}

.aca-table__inputs .form-control {
    display: inline-block;
    width: 4.5rem;
    vertical-align: middle;
}

/* Input grids (a form per row) cannot lose columns, so on a phone each row
   becomes a stacked card: the header row hides and every cell prints its own
   label from data-label. Desktop keeps the grid. */
@media (max-width: 576px) {
    .aca-table--stack thead {
        display: none;
    }

    .aca-table--stack tbody,
    .aca-table--stack tr,
    .aca-table--stack td {
        display: block;
        width: 100%;
    }

    .aca-table--stack tr {
        padding: var(--aca-space-2) 0;
        border-bottom: 1px solid var(--aca-line);
    }

    .aca-table--stack td {
        display: grid;
        grid-template-columns: 7rem 1fr;
        align-items: center;
        gap: var(--aca-space-2);
        padding: .2rem var(--aca-space-3);
        border: 0;
    }

    .aca-table--stack td::before {
        content: attr(data-label);
        font-size: var(--aca-text-xs);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .02em;
        color: var(--aca-muted-strong);
    }

    .aca-table--stack td.aca-table__select {
        grid-template-columns: 1fr auto;
        width: 100%;
        text-align: left;
    }

    .aca-table--stack td.aca-table__num {
        width: 100%;
        text-align: left;
    }
}

/* Key/value display: what a two-column label/value "table" should be. */
.aca-kv {
    display: grid;
    grid-template-columns: minmax(7rem, max-content) 1fr;
    gap: .35rem var(--aca-space-4);
    margin: 0;
}

.aca-kv > dt {
    font-weight: 500;
    color: var(--aca-fg-muted-strong);
}

.aca-kv > dd {
    margin: 0;
    color: var(--aca-fg);
    overflow-wrap: anywhere;
}

.aca-kv > dd.aca-kv__amount {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.aca-kv > .aca-kv__total {
    padding-top: .35rem;
    border-top: 1px solid var(--aca-line);
    font-weight: 700;
}

@media (max-width: 576px) {
    .aca-kv {
        grid-template-columns: 1fr;
        gap: .1rem;
    }

    .aca-kv > dd {
        margin-bottom: .5rem;
    }

    .aca-kv > dd.aca-kv__amount {
        text-align: left;
    }
}

/* --------------------------------------------------------------------------
   10. Toasts
   -------------------------------------------------------------------------- */

.aca-toast-region {
    position: fixed;
    top: calc(var(--aca-navbar-h) + 12px);
    /* Fixed to the screen, so in landscape the notch can sit over this edge. */
    right: max(12px, env(safe-area-inset-right, 0px));
    z-index: var(--aca-z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--aca-space-2);
    width: min(360px, calc(100vw - 24px));
    pointer-events: none;
}

.aca-toast {
    position: relative;
    display: flex;
    align-items: flex-start;
    padding: var(--aca-space-3) var(--aca-space-4);
    border: 1px solid var(--aca-line);
    border-left: 4px solid var(--aca-muted);
    border-radius: var(--aca-radius);
    background: var(--aca-surface);
    box-shadow: var(--aca-shadow-lg);
    color: var(--aca-ink);
    font-size: var(--aca-text-sm);
    line-height: 1.45;
    pointer-events: auto;
}

.aca-toast--success {
    border-left-color: var(--aca-success);
}

.aca-toast--info {
    border-left-color: var(--aca-info);
}

.aca-toast--warning {
    border-left-color: var(--aca-warning);
}

.aca-toast--danger {
    border-left-color: var(--aca-danger);
}

.aca-toast__icon {
    flex: 0 0 auto;
    margin-right: var(--aca-space-3);
    color: var(--aca-muted);
}

.aca-toast--success .aca-toast__icon {
    color: var(--aca-success);
}

.aca-toast--info .aca-toast__icon {
    color: var(--aca-info);
}

.aca-toast--warning .aca-toast__icon {
    color: var(--aca-warning);
}

.aca-toast--danger .aca-toast__icon {
    color: var(--aca-danger);
}

.aca-toast__body {
    flex: 1 1 auto;
    min-width: 0;
    word-wrap: break-word;
}

.aca-toast__close {
    flex: 0 0 auto;
    margin-left: var(--aca-space-3);
    padding: 0;
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: var(--aca-radius-sm);
    background: transparent;
    color: var(--aca-muted);
    font-size: var(--aca-text);
    line-height: 1;
    cursor: pointer;
}

.aca-toast__close:hover {
    background: var(--aca-surface-2);
    color: var(--aca-ink);
}

@media (max-width: 991px) {
    .aca-toast-region {
        left: max(12px, env(safe-area-inset-left, 0px));
        right: max(12px, env(safe-area-inset-right, 0px));
        width: auto;
    }
}

/* --------------------------------------------------------------------------
   11. Drawer backdrop
   The drawer shell itself is each page's own sidebar (.dataportal-sidebar,
   .reportcard-review-sidebar, ...); AcaUI.drawer() only owns the backdrop and
   the body lock.
   -------------------------------------------------------------------------- */

.aca-drawer__backdrop {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: calc(var(--aca-z-drawer) - 1);
    background: rgba(17, 24, 39, .35);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--aca-transition), visibility var(--aca-transition);
}

.aca-drawer__backdrop.is-open {
    opacity: 1;
    visibility: visible;
}

@media (max-width: 991px) {
    body.aca-drawer-open {
        overflow: hidden;
    }
}

/* --------------------------------------------------------------------------
   12. Empty state, skeleton, text utilities
   -------------------------------------------------------------------------- */

.aca-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--aca-space-6) var(--aca-space-4);
    color: var(--aca-fg-muted);
    text-align: center;
}

.aca-empty__icon {
    margin-bottom: var(--aca-space-3);
    color: var(--aca-fg-muted);
    font-size: 2rem;
    opacity: .55;
}

.aca-empty__title {
    margin: 0 0 var(--aca-space-1);
    color: var(--aca-fg-muted-strong);
    font-size: var(--aca-text);
    font-weight: 600;
}

.aca-empty__text {
    margin: 0;
    font-size: var(--aca-text-sm);
}

.aca-skeleton {
    display: block;
    height: 1rem;
    border-radius: var(--aca-radius-sm);
    background: linear-gradient(90deg, var(--aca-surface-2) 25%, var(--aca-line) 37%, var(--aca-surface-2) 63%);
    background-size: 400% 100%;
    animation: aca-skeleton-shimmer 1.4s ease infinite;
}

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

    100% {
        background-position: 0 50%;
    }
}

/* Replacement for the banned <small> element. */
.aca-muted {
    color: var(--aca-muted);
    font-size: var(--aca-text-sm);
}

.aca-text-sm {
    font-size: var(--aca-text-sm);
}

.aca-text-xs {
    font-size: var(--aca-text-xs);
}

.aca-truncate {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Letterheads and anything else that exists only on paper; the print block
   below turns it back on. */
.aca-print-only {
    display: none;
}

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

/* --------------------------------------------------------------------------
   12b. Bars (.aca-bar)
   One horizontal bar for a figure or a score: a track with a fill whose width
   is one of the .aca-fill-0 .. .aca-fill-100 steps, so the markup never carries
   an inline width. familyPortalBarHtml() (FamilyPortalShellFunctions.php)
   prints it. The fill is --aca-bar-fill (green, or its data-tone); a page
   sheet may colour .aca-bar__fill for its own card (report_card_grades.css).
   -------------------------------------------------------------------------- */

.aca-bar {
    --aca-bar-fill: var(--aca-green);
    display: block;
    height: var(--aca-bar-h);
    overflow: hidden;
    border-radius: var(--aca-radius-pill);
    background: var(--aca-ghost-bg);
}

.aca-bar--thin {
    height: var(--aca-bar-h-thin);
}

.aca-bar__fill {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--aca-bar-fill);
    transition: width .6s ease;
}

.aca-bar[data-tone="success"] {
    --aca-bar-fill: var(--aca-success);
}

.aca-bar[data-tone="info"] {
    --aca-bar-fill: var(--aca-info);
}

.aca-bar[data-tone="warning"] {
    --aca-bar-fill: var(--aca-warning);
}

.aca-bar[data-tone="danger"] {
    --aca-bar-fill: var(--aca-danger);
}

.aca-bar[data-tone="neutral"] {
    --aca-bar-fill: var(--aca-chrome);
}

@media (prefers-reduced-motion: reduce) {
    .aca-bar__fill {
        transition: none;
    }
}

/* The fill widths. The percentage is the only value a renderer computes per
   bar, so the whole 0-100 scale lives here instead of an inline style. */
.aca-fill-0 { width: 0%; }
.aca-fill-1 { width: 1%; }
.aca-fill-2 { width: 2%; }
.aca-fill-3 { width: 3%; }
.aca-fill-4 { width: 4%; }
.aca-fill-5 { width: 5%; }
.aca-fill-6 { width: 6%; }
.aca-fill-7 { width: 7%; }
.aca-fill-8 { width: 8%; }
.aca-fill-9 { width: 9%; }
.aca-fill-10 { width: 10%; }
.aca-fill-11 { width: 11%; }
.aca-fill-12 { width: 12%; }
.aca-fill-13 { width: 13%; }
.aca-fill-14 { width: 14%; }
.aca-fill-15 { width: 15%; }
.aca-fill-16 { width: 16%; }
.aca-fill-17 { width: 17%; }
.aca-fill-18 { width: 18%; }
.aca-fill-19 { width: 19%; }
.aca-fill-20 { width: 20%; }
.aca-fill-21 { width: 21%; }
.aca-fill-22 { width: 22%; }
.aca-fill-23 { width: 23%; }
.aca-fill-24 { width: 24%; }
.aca-fill-25 { width: 25%; }
.aca-fill-26 { width: 26%; }
.aca-fill-27 { width: 27%; }
.aca-fill-28 { width: 28%; }
.aca-fill-29 { width: 29%; }
.aca-fill-30 { width: 30%; }
.aca-fill-31 { width: 31%; }
.aca-fill-32 { width: 32%; }
.aca-fill-33 { width: 33%; }
.aca-fill-34 { width: 34%; }
.aca-fill-35 { width: 35%; }
.aca-fill-36 { width: 36%; }
.aca-fill-37 { width: 37%; }
.aca-fill-38 { width: 38%; }
.aca-fill-39 { width: 39%; }
.aca-fill-40 { width: 40%; }
.aca-fill-41 { width: 41%; }
.aca-fill-42 { width: 42%; }
.aca-fill-43 { width: 43%; }
.aca-fill-44 { width: 44%; }
.aca-fill-45 { width: 45%; }
.aca-fill-46 { width: 46%; }
.aca-fill-47 { width: 47%; }
.aca-fill-48 { width: 48%; }
.aca-fill-49 { width: 49%; }
.aca-fill-50 { width: 50%; }
.aca-fill-51 { width: 51%; }
.aca-fill-52 { width: 52%; }
.aca-fill-53 { width: 53%; }
.aca-fill-54 { width: 54%; }
.aca-fill-55 { width: 55%; }
.aca-fill-56 { width: 56%; }
.aca-fill-57 { width: 57%; }
.aca-fill-58 { width: 58%; }
.aca-fill-59 { width: 59%; }
.aca-fill-60 { width: 60%; }
.aca-fill-61 { width: 61%; }
.aca-fill-62 { width: 62%; }
.aca-fill-63 { width: 63%; }
.aca-fill-64 { width: 64%; }
.aca-fill-65 { width: 65%; }
.aca-fill-66 { width: 66%; }
.aca-fill-67 { width: 67%; }
.aca-fill-68 { width: 68%; }
.aca-fill-69 { width: 69%; }
.aca-fill-70 { width: 70%; }
.aca-fill-71 { width: 71%; }
.aca-fill-72 { width: 72%; }
.aca-fill-73 { width: 73%; }
.aca-fill-74 { width: 74%; }
.aca-fill-75 { width: 75%; }
.aca-fill-76 { width: 76%; }
.aca-fill-77 { width: 77%; }
.aca-fill-78 { width: 78%; }
.aca-fill-79 { width: 79%; }
.aca-fill-80 { width: 80%; }
.aca-fill-81 { width: 81%; }
.aca-fill-82 { width: 82%; }
.aca-fill-83 { width: 83%; }
.aca-fill-84 { width: 84%; }
.aca-fill-85 { width: 85%; }
.aca-fill-86 { width: 86%; }
.aca-fill-87 { width: 87%; }
.aca-fill-88 { width: 88%; }
.aca-fill-89 { width: 89%; }
.aca-fill-90 { width: 90%; }
.aca-fill-91 { width: 91%; }
.aca-fill-92 { width: 92%; }
.aca-fill-93 { width: 93%; }
.aca-fill-94 { width: 94%; }
.aca-fill-95 { width: 95%; }
.aca-fill-96 { width: 96%; }
.aca-fill-97 { width: 97%; }
.aca-fill-98 { width: 98%; }
.aca-fill-99 { width: 99%; }
.aca-fill-100 { width: 100%; }

/* --------------------------------------------------------------------------
   13. Print
   -------------------------------------------------------------------------- */

@media print {
    /* Letter at full size. Bootstrap 4.1.3's own print rules ask for an A3
       sheet and a 992px body, so every page was laid out at laptop width and
       then shrunk onto Letter, where 16px read like 9pt. Here the sheet is
       Letter and the page lays out at the paper's own width, about 720px - the
       phone layout every screen is designed for first. A named page (Class
       lists', Payments > Families') keeps its own size and margins, and the
       two register sheets zoom their 992px design onto the sheet. */
    @page {
        size: letter;
    }

    body,
    .container {
        /* Bootstrap's 992px minimum carries !important, so lifting it needs
           the same. */
        min-width: 0 !important;
    }

    .aca-navbar,
    .aca-offcanvas,
    .aca-offcanvas__backdrop,
    .aca-navbar__toggle,
    .aca-toast-region,
    .aca-tabbar {
        /* Bootstrap display utilities carry !important, so hiding chrome for
           print cannot be out-specified without it. */
        display: none !important;
    }

    .shadow,
    .shadow-sm,
    .shadow-lg {
        /* Bootstrap's print sheet takes every shadow off with !important, but
           its own shadow utilities outweigh that rule with !important of their
           own, and a shadow prints grey whatever "Background graphics" says. */
        box-shadow: none !important;
    }

    .aca-print-only {
        display: block;
    }

    /* The ground and the pane are aca-shell.css section 7's; the ink is ours. */
    body {
        color: var(--aca-print-ink);
    }

    /* Legacy scrolling boxes flow with the page here. */
    [class*="scrollable"] {
        /* Same reason: the height caps they override are themselves !important. */
        max-height: none !important;
        overflow: visible !important;
    }

    /* A panel prints whole: its fill is screen-only, and here its head and
       column headings stop pinning. */
    .aca-panel,
    .aca-panel__scroll {
        max-height: none;
        overflow: visible;
    }

    .aca-panel > .aca-card__header,
    .aca-panel .aca-table-wrap .table thead th {
        position: static;
    }

    /* Sheets break between whole things. A short card prints whole; a long
       list - a panel, or a card holding a table of more than five rows (the
       list sheets say the same of their own rows) - runs on from sheet to
       sheet, because kept whole it would leave the sheet before it nearly
       empty. A row never splits (Bootstrap keeps a table row whole) and a
       card's head never ends a sheet without its first row. */
    .aca-card,
    .card,
    .modal-content {
        box-shadow: none;
        break-inside: avoid;
    }

    .aca-panel {
        break-inside: auto;
    }

    /* Its own rule: a browser without :has() drops the whole list it is in. */
    .aca-card:has(tbody > tr:nth-child(6)),
    .card:has(tbody > tr:nth-child(6)) {
        break-inside: auto;
    }

    .aca-card__header,
    .card > .card-header {
        break-after: avoid;
    }

    /* Ink on white, whatever "Background graphics" says. A card, a tile, a
       table and a footer are filled with the two surface tokens, which are
       white on paper (aca-tokens.css), so every sheet's parchment empties at
       once; the coloured bands, the pills and the buttons lose their fill
       below, named at the weight of the rules that paint them, so no page
       sheet clears its own.
       The coloured bands and the page ground print as ink on white, their
       lattice dropped; the context tokens they carry go with them (a dialog's
       band named at the weight of the modal shell's later colour below). */
    #mainBodyDiv,
    .aca-card__header,
    .card > .card-header,
    .modal-content .modal-header,
    .aca-page-header,
    .family-hero {
        --aca-fg: var(--aca-print-ink);
        --aca-fg-strong: var(--aca-print-ink);
        --aca-fg-muted: var(--aca-print-ink-muted);
        --aca-fg-muted-strong: var(--aca-print-ink-muted);
        --aca-fg-line: var(--aca-print-line);
        --aca-fg-link: var(--aca-print-ink);
        --aca-fg-link-hover: var(--aca-print-ink);
        --aca-fg-accent: var(--aca-print-ink);
        --aca-fg-green: var(--aca-print-ink);
        --aca-ghost-line: var(--aca-print-line);
        --aca-ghost-fg: var(--aca-print-ink-muted);
        --aca-ghost-bg: transparent;
        --aca-ghost-chip-bg: transparent;
        --aca-ghost-active-bg: transparent;
        --aca-ghost-active-line: var(--aca-print-ink-muted);
        --aca-ghost-active-fg: var(--aca-print-ink);
        --aca-ghost-danger-bg: transparent;
        --aca-ghost-danger-line: var(--aca-print-ink);
        color: var(--aca-print-ink);
    }

    .aca-card__header,
    .aca-card[data-accent] > .aca-card__header,
    .card > .card-header,
    .modal-content .modal-header,
    .aca-page-header {
        border-bottom: 1px solid var(--aca-print-ink);
        border-radius: 0;
        background: none;
        box-shadow: none;
    }

    .aca-card__header::before,
    .card > .card-header::before,
    .modal-header::before,
    .aca-page-header::before,
    #mainBodyDiv::before {
        display: none;
    }

    .aca-card__subtitle,
    .modal-subtitle,
    .aca-page-header__title,
    .aca-page-header__subtitle,
    .aca-page-header__icon {
        background: none;
        color: var(--aca-print-ink);
    }

    a {
        color: var(--aca-print-ink);
        text-decoration: none;
    }

    /* A status pill and a chip print as their word in ink inside an ink
       outline: the tone's tint is gone on paper (or, ticked, a fill behind
       the words), so the word carries the meaning. A grey (quiet) one - the
       --inactive and --cancelled tones - has a dashed outline, and the chosen chip of
       a row (an active filter, a pressed choice) a second ring outside its
       own. Named at the weight of section 7's chosen chip and the choice
       chip's pressed state (aca-forms.css section 9). */
    .aca-status,
    .aca-chip,
    .aca-chip.is-active,
    .aca-chip.aca-chip--choice[aria-pressed="true"] {
        border: 1px solid currentColor;
        background: none;
        color: var(--aca-fg);
    }

    .aca-status--inactive,
    .aca-status--cancelled {
        border-style: dashed;
    }

    /* A button cannot be pressed on paper, so one a page still prints is its
       word in an ink outline, whatever its colour on screen - named at the
       weight of the chosen toggle's rule (section 4 and Bootstrap's) and of
       the book band's light button (section 6). A link-styled button stays a
       word, and a chosen toggle takes the chip's second ring. */
    .btn:not(.btn-link),
    .btn:not(.btn-link):not(:disabled):not(.disabled).active,
    .aca-card[data-accent] > .aca-card__header .btn:not(.btn-link) {
        border-color: currentColor;
        background: none;
        color: var(--aca-fg);
    }

    .aca-chip.is-active,
    .aca-chip.aca-chip--choice[aria-pressed="true"],
    .btn:not(.btn-link).active {
        outline: 1px solid currentColor;
    }

    /* A bar is the figure itself: keep its track and fill on paper - the
       track in the line colour the card's rows print in, as its surface fill
       is white here. */
    .aca-bar,
    .aca-bar__fill {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .aca-bar {
        background: var(--aca-line);
    }
}

/* --------------------------------------------------------------------------
   14. Legacy utilities
   Carried over unchanged in value from css/style.css so existing Staff,
   Parent, Tuition, Registration and Office markup keeps working. Do not
   extend this block - new markup uses the .aca-* components above.
   -------------------------------------------------------------------------- */

/* Bootstrap 4 dropped the Bootstrap 3 .hidden / .block display helpers, but the
   app's markup still spells them. Moved here from css/style.css (S5, lane C);
   .hidden keeps the Bootstrap 3 semantics the markup expects, which is the one
   place in the design system where !important is deliberate - it has to beat
   Bootstrap's own !important .d-* display utilities on the same element. New
   markup uses the hidden attribute instead. */
.hidden {
    display: none !important;
}

.block {
    display: block;
}

@media (min-width: 992px) {
    .largeScreenRemove {
        /* Competes with Bootstrap .d-* display utilities, which are !important. */
        display: none !important;
    }

    .adjustableFont1 {
        font-size: 32pt;
        font-weight: bolder;
        text-align: center;
    }

    .adjustableFont2 {
        font-size: 26px;
        font-weight: bold;
        text-align: center;
    }

    .adjustableFont3 {
        font-size: 24px;
        text-align: center;
    }

    .adjustableFont4 {
        font-size: 19px;
        text-align: center;
    }

    .adjustableFont5 {
        font-size: var(--aca-text-xs);
        text-align: center;
    }
}

@media (max-width: 991px) {
    .smallScreenRemove {
        /* Competes with Bootstrap .d-* display utilities, which are !important. */
        display: none !important;
    }

    .adjustableFont1 {
        font-size: 5vw;
        font-weight: bolder;
        text-align: center;
    }

    .adjustableFont2 {
        font-size: 4.4vw;
        text-align: center;
    }

    .adjustableFont3 {
        /* 3.3vw alone drops to 12px on a 375px phone; keep body copy readable. */
        font-size: clamp(14px, 3.3vw, 24px);
        text-align: center;
    }

    .adjustableFont4 {
        font-size: 2.8vw;
        text-align: center;
    }

    .adjustableFont5 {
        font-size: 2.4vw;
        text-align: center;
    }
}

/* ==========================================================================
   AcaUI.bulkProgress — the shared progress / summary modal (_aca_script/aca-ui.js)
   used by every bulk email or bulk update flow. Tokens only.
   ========================================================================== */

.aca-bulk__count {
    color: var(--aca-muted);
    font-size: var(--aca-text-sm);
    font-weight: 600;
}

.aca-bulk__list {
    max-height: 19rem;
    overflow-y: auto;
    border: 1px solid var(--aca-line);
    border-radius: var(--aca-radius-sm);
}

.aca-bulk__row {
    display: flex;
    align-items: flex-start;
    gap: var(--aca-space-2);
    padding: var(--aca-space-2) var(--aca-space-3);
    border-bottom: 1px solid var(--aca-line);
}

.aca-bulk__row:last-child {
    border-bottom: none;
}

.aca-bulk__icon {
    flex: 0 0 auto;
    margin-top: .15rem;
    color: var(--aca-muted);
}

.aca-bulk__label {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--aca-ink);
    font-size: var(--aca-text-sm);
}

.aca-bulk__note {
    color: var(--aca-muted);
    font-size: var(--aca-text-xs);
}

.aca-bulk__note:empty {
    display: none;
}

.aca-bulk__stats {
    display: flex;
    flex-wrap: wrap;
    gap: var(--aca-space-3);
    margin-bottom: var(--aca-space-4);
}

.aca-bulk__stat {
    flex: 1 1 7rem;
    padding: var(--aca-space-3);
    border: 1px solid var(--aca-line);
    border-radius: var(--aca-radius-sm);
    background: var(--aca-surface-2);
    text-align: center;
}

.aca-bulk__stat-value {
    display: block;
    color: var(--aca-ink);
    font-size: var(--aca-text-xl);
    font-weight: 700;
    line-height: 1.1;
}

.aca-bulk__stat-label {
    display: block;
    margin-top: var(--aca-space-1);
    color: var(--aca-muted);
    font-size: var(--aca-text-xs);
}

.aca-bulk__stat[data-variant="success"] .aca-bulk__stat-value {
    color: var(--aca-green-strong);
}

.aca-bulk__stat[data-variant="danger"] .aca-bulk__stat-value {
    color: var(--aca-danger);
}

.aca-bulk__stat[data-variant="warning"] .aca-bulk__stat-value {
    color: var(--aca-warning);
}

.aca-bulk__stat[data-variant="info"] .aca-bulk__stat-value {
    color: var(--aca-info);
}

/* ------------------------------------------------------------------
   Spinner. Bootstrap 4.1.3 (the pinned CDN build) has no .spinner-border;
   the app has always used it, so the class is defined here.
   ------------------------------------------------------------------ */
.spinner-border {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    vertical-align: text-bottom;
    border: .25em solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: aca-spinner .75s linear infinite;
}

.spinner-border-sm {
    width: 1rem;
    height: 1rem;
    border-width: .2em;
}

@keyframes aca-spinner {
    to {
        transform: rotate(360deg);
    }
}

/* ==========================================================================
   Modals
   --------------------------------------------------------------------------
   One shared modal shell for every portal, replacing the seven competing
   .modal-dialog and nine .modal-body height rules that used to be spread over
   style.css and the page sheets. _aca_script/aca-ui.js re-parents every .modal
   to <body> before it is shown, so Bootstrap's own z-index ladder is the only
   one in play here and no page needs a hand-rolled z-index.
   ========================================================================== */

/* Bootstrap 4.1.3 predates .modal-xl (added in 4.2). Moved from style.css. */
@media (min-width: 992px) {
    .modal-xl {
        max-width: 1140px;
    }
}

.modal-dialog.modal-lg {
    max-width: min(800px, calc(100vw - 2 * var(--aca-space-5)));
}

.modal-dialog.modal-xl {
    max-width: min(1140px, calc(100vw - 2 * var(--aca-space-5)));
}

/* The dialog gutter and the content cap have to agree, or .modal itself gains a
   few pixels of scroll on every open (Bootstrap's own margin is 1.75rem). */
.modal-dialog {
    margin-top: var(--aca-space-5);
    margin-bottom: var(--aca-space-5);
}

.modal-dialog-centered {
    min-height: calc(100% - 2 * var(--aca-space-5));
}

.modal-content {
    max-height: calc(100vh - 2 * var(--aca-space-5));
    max-height: calc(100dvh - 2 * var(--aca-space-5));
}

.modal-header,
.modal-footer {
    flex: 0 0 auto;
}

/* A dialog opens on the same navy band as a card: white title, lighter subtitle,
   the lattice under the close button (the card section's ::before rule paints
   it and restyles the buttons and chips here too - it names .modal-header). */
.modal-header {
    position: relative;
    isolation: isolate;
    align-items: center;
    border-bottom: 0;
    border-radius: calc(var(--aca-radius-lg) - 1px) calc(var(--aca-radius-lg) - 1px) 0 0;
    background: var(--aca-chrome);
    color: var(--aca-on-chrome);
}

.modal-header .close {
    color: var(--aca-on-brand);
    text-shadow: none;
    opacity: .75;
}

.modal-header .close:not(:disabled):not(.disabled):hover,
.modal-header .close:not(:disabled):not(.disabled):focus {
    color: var(--aca-on-brand);
    opacity: 1;
}

/* The body is the app's only modal scroll pane; nested caps are the exception. */
.modal-body {
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.modal-title {
    color: inherit;
    font-size: var(--aca-text-lg);
    font-weight: 600;
}

.modal-subtitle {
    display: block;
    color: var(--aca-fg-muted);
    font-size: var(--aca-text-sm);
    font-weight: 400;
}

/* Bootstrap 4.1.3 spaces footer buttons with margins on the children; zero them
   so a single gap rules and wrapped rows stay evenly spaced. A footer wraps at
   every width: a row wider than the dialog drops a line instead of spilling out. */
.modal-footer {
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--aca-space-2);
}

.modal-footer > :not(:last-child) {
    margin-right: 0;
}

.modal-footer > :not(:first-child) {
    margin-left: 0;
}

/* A destructive action pinned left. Bootstrap's .mr-auto carries !important and
   still outranks the margin reset above. */
.modal-footer .btn.mr-auto {
    margin-right: auto;
}

/* --------------------------------------------------------------------------
   Modal bottom sheet (<= 576px)
   Layout rules live at 576px rather than the usual 991px layout breakpoint
   because a bottom sheet IS the phone form factor - this is the documented
   exception to "576px is type only".
   -------------------------------------------------------------------------- */

@media (max-width: 576px) {
    /* The size classes are named too: their own width caps out-rank a bare
       .modal-dialog, and a capped sheet sat at the left edge with a gap beside it. */
    .modal-dialog,
    .modal-dialog.modal-lg,
    .modal-dialog.modal-xl {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        margin: 0;
        width: auto;
        max-width: none;
    }

    .modal-dialog-centered {
        min-height: 0;
        align-items: flex-end;
    }

    .modal-content {
        border: 0;
        border-radius: var(--aca-radius-lg) var(--aca-radius-lg) 0 0;
        max-height: calc(100vh - var(--aca-space-4));
        max-height: calc(100dvh - var(--aca-space-4));
    }

    .modal.fade .modal-dialog {
        transform: translate3d(0, 100%, 0);
    }

    .modal.show .modal-dialog {
        transform: none;
    }

    .modal-header {
        padding: var(--aca-space-3) var(--aca-space-4);
    }

    .modal-footer {
        /* The sheet is pinned to the bottom of the screen, so its buttons would sit
           under the iPhone home indicator. Bootstrap's own footer padding is 1rem. */
        padding-bottom: max(var(--aca-space-4), env(safe-area-inset-bottom, 0px));
    }

    .modal-footer .btn {
        flex: 1 1 calc(50% - var(--aca-space-2));
        min-height: 44px;
    }
}

/* ==========================================================================
   Scrollbars
   Folded in from the retired css/visible_scrollbars.css. Every scroll pane the
   app depends on keeps a visible (thin, tokenised) bar instead of the overlay
   scrollbar macOS and iOS hide until you move.
   ========================================================================== */

.aca-table-wrap,
.aca-tabs-content,
.modal-body,
.scrollable-table-body,
.aca-bulk__list,
.dataportal-main-content,
.dataportal-list-container,
.editfamily-tabs-container,
.reportcard-review-main,
.reportcard-review-sidebar-body {
    scrollbar-width: thin;
    scrollbar-color: var(--aca-line-strong) transparent;
}

.aca-table-wrap::-webkit-scrollbar,
.aca-tabs-content::-webkit-scrollbar,
.modal-body::-webkit-scrollbar,
.scrollable-table-body::-webkit-scrollbar,
.aca-bulk__list::-webkit-scrollbar,
.dataportal-main-content::-webkit-scrollbar,
.dataportal-list-container::-webkit-scrollbar,
.editfamily-tabs-container::-webkit-scrollbar,
.reportcard-review-main::-webkit-scrollbar,
.reportcard-review-sidebar-body::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

.aca-table-wrap::-webkit-scrollbar-thumb,
.aca-tabs-content::-webkit-scrollbar-thumb,
.modal-body::-webkit-scrollbar-thumb,
.scrollable-table-body::-webkit-scrollbar-thumb,
.aca-bulk__list::-webkit-scrollbar-thumb,
.dataportal-main-content::-webkit-scrollbar-thumb,
.dataportal-list-container::-webkit-scrollbar-thumb,
.editfamily-tabs-container::-webkit-scrollbar-thumb,
.reportcard-review-main::-webkit-scrollbar-thumb,
.reportcard-review-sidebar-body::-webkit-scrollbar-thumb {
    background: var(--aca-line-strong);
    border-radius: var(--aca-radius-pill);
}

/* The tuition/flow book, course and cart panels take their height from a
   sibling class (.tuition-scroll-body--*, .tf-cart-scroll-body); the overflow
   was visible_scrollbars.css's only live contribution. */
.scrollable-table-body {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* Replaces css/ios_touch_fix.css: the grey iOS tap flash on a table row was the
   only part of that sheet any live markup still relied on. */
@media (hover: none) {
    tbody tr {
        -webkit-tap-highlight-color: transparent;
    }
}

/* ==========================================================================
   SimpleTable (_aca_script/simpleTable.js)
   Moved here from css/style.css and re-tokenised: the sortable header, the
   search box, the pager and the Class Editor book table that shares the
   pattern under its own prefix. No !important - aca-base.css loads after the
   Bootstrap CDN, so a same-specificity rule already wins.
   ========================================================================== */

table.simple-table,
table.simple-table thead th,
table.simple-table tbody td {
    font-size: var(--aca-text-sm);
}

table.simple-table thead tr th {
    word-wrap: break-word;
}

table.simple-table .btn,
table.simple-table input[type="button"],
table.simple-table input[type="text"],
table.simple-table input[type="email"],
table.simple-table select {
    font-size: inherit;
}

/* The search box is left out on purpose: it is a .form-control, so it already
   reads 14px here and picks up the iOS 16px floor above on a phone. */
.simple-table-pagination button,
.simple-table-info {
    font-size: var(--aca-text-sm);
}

.simple-table {
    margin-bottom: 0;
    width: 100%;
}

.simple-table .sortable {
    cursor: pointer;
    user-select: none;
    transition: background-color var(--aca-transition);
}

.simple-table .sortable:hover {
    background: var(--aca-line);
}

.simple-table .sortable.active-sort {
    background: var(--aca-orange-soft);
    color: var(--aca-ink);
    font-weight: 600;
    box-shadow: inset 0 -2px 0 var(--aca-orange);
}

.simple-table .sortable.active-sort:hover {
    background: var(--aca-orange-soft);
}

.simple-table .sort-icon {
    margin-left: var(--aca-space-1);
    font-size: 0.8em;
    opacity: 0.7;
    transition: opacity var(--aca-transition);
}

.simple-table .sortable:hover .sort-icon {
    opacity: 1;
}

.simple-table .sortable.active-sort .sort-icon {
    opacity: 1;
    color: var(--aca-warning);
    transform: scale(1.2);
}

.simple-table .fa-sort-up,
.simple-table .fa-sort-down {
    opacity: 1;
    color: var(--aca-warning);
}

.simple-table-search-container {
    padding-top: 0.2rem;
    padding-bottom: 0.2rem;
    padding-left: 1.6rem;
    background-color: var(--aca-surface-2);
    border-bottom: 1px solid var(--aca-line);
}

.simple-table-search {
    max-width: 300px;
    border: 2px solid var(--aca-accent-family);
    background-color: var(--aca-accent-family-soft);
}

.simple-table-pagination {
    padding: var(--aca-space-4);
    background-color: var(--aca-surface-2);
    border-top: 1px solid var(--aca-line);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.simple-table-info {
    color: var(--aca-muted);
}

@media (max-width: 576px) {
    table.simple-table,
    table.simple-table thead th,
    table.simple-table tbody td,
    .simple-table-pagination button,
    .simple-table-info {
        font-size: var(--aca-text-xs);
    }
}

/* --------------------------------------------------------------------------
   The Square card dialog (#squarePaymentModal)
   Shared since the Family Portal pays an existing order through the same dialog
   (_aca_script/SquareCheckout.js): the store builds it in
   TuitionFlow/GetFlowSquareModal.php, the portal in ParentPortal/GetOrderPayModal.php.
   Moved unchanged from css/tuition_flow.css. The dialog keeps the shared
   .modal-lg width, and every Square-owned element is capped so its iframe cannot
   push a horizontal scrollbar into the modal.
   -------------------------------------------------------------------------- */

#squarePaymentModal .modal-body {
    padding: 1.25rem;
    overflow-x: hidden;
}

/* The wallet buttons (Google Pay, Apple Pay, Cash App Pay). SquareCheckout.js
   unhides only the ones the device offers, so the stack can be empty. */
.tf-wallets {
    overflow: hidden;
}

.tf-wallet-btn {
    max-width: 100%;
    min-height: 48px;
    margin-bottom: var(--aca-space-3);
}

#google-pay-button,
#apple-pay-button,
#cash-app-pay-button {
    display: block;
    max-width: 100%;
}

/* Square draws Google Pay and Cash App Pay itself but nothing for Apple Pay: this <button> wears
   Apple's own button (Safari only - SquareCheckout.js shows it only when ApplePaySession exists).
   Black is Apple's style name for its mark, matching the Google Pay button above it (owner
   2026-09-23). The id selector out-ranks Bootstrap's [type="button"] appearance. */
#apple-pay-button {
    width: 100%;
    height: 48px;
    padding: 0;
    border: 0;
    border-radius: var(--aca-radius-sm);
    cursor: pointer;
    -webkit-appearance: -apple-pay-button;
    -apple-pay-button-type: plain;
    -apple-pay-button-style: black;
}

/* .tf-wallets clips anything outside it, so the keyboard ring is drawn inside the button. */
#apple-pay-button:focus-visible {
    box-shadow: none;
    outline: 3px solid var(--aca-orange);
    outline-offset: -3px;
}

#card-container {
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    overflow: hidden;
}

#card-container iframe,
.tf-wallet-btn iframe {
    max-width: 100%;
}

#payment-status-container[hidden] {
    display: none;
}

/* SquareCheckout.js paints a failed charge into #payment-status-container. */
.tf-pay-status--warning {
    border-radius: var(--aca-radius-sm);
    background: var(--aca-warning-soft);
    color: var(--aca-warning);
}

.tf-pay-status--danger {
    border-radius: var(--aca-radius-sm);
    background: var(--aca-danger-soft);
    color: var(--aca-danger);
}
