/* Every component's styles: one block per component in templates/components/. */

/* Button */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: var(--tap);
    padding: var(--space-2) var(--space-5);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font: inherit;
    font-weight: 650;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease), border-color var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease);
}

.btn--lg {
    min-height: 52px;
    font-size: var(--text-lg);
}

/* Full width on phones only: the page's one big action (Post a shift). */
@media (max-width: 599px) {
    .btn--block-phone {
        width: 100%;
    }
}

.btn--block {
    display: flex;
    width: 100%;
}

.btn--primary {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.btn--primary:hover {
    background: var(--color-primary-strong);
    color: var(--color-on-primary);
}

.btn--secondary {
    background: var(--color-surface);
    border-color: var(--color-border-input);
    color: var(--color-ink);
}

.btn--secondary:hover {
    background: var(--color-surface-sunken);
    color: var(--color-ink);
}

.btn--ghost {
    background: transparent;
    /* The strong shade: it keeps 4.5:1 on the tinted hover and on info banners. */
    color: var(--color-primary-strong);
}

.btn--ghost:hover {
    background: var(--color-primary-tint);
}

/* A ghost button standing alone lines its text up with the text above it. */
.btn--flush {
    margin-inline-start: calc(-1 * var(--space-5));
}

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

.btn--danger-quiet {
    border-color: var(--color-danger);
    background: var(--color-surface);
    color: var(--color-danger);
}

.btn--danger-quiet:hover {
    background: var(--color-danger-tint);
}

.btn--danger:hover {
    background: var(--color-danger-strong);
    color: var(--color-on-danger);
}

.btn[disabled],
.btn[aria-disabled='true'] {
    opacity: 0.55;
    cursor: not-allowed;
}

.btn .btn__spinner {
    display: none;
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spin 700ms linear infinite;
}

.btn[aria-busy='true'] .btn__spinner {
    display: inline-block;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

@media (prefers-reduced-motion: reduce) {
    .btn .btn__spinner {
        animation-duration: 2s;
    }
}

/* OAuthButtons: provider-branded neutral buttons */
.btn--provider {
    background: var(--color-surface);
    border-color: var(--color-border-input);
    color: var(--color-ink);
}

.btn--provider:hover {
    background: var(--color-surface-sunken);
    color: var(--color-ink);
}

.divider {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    color: var(--color-muted);
    font-size: var(--text-sm);
}

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

/* Icon */
.icon {
    width: 1.25em;
    height: 1.25em;
    flex: none;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.icon--filled {
    fill: currentColor;
    stroke: none;
}

/* Card */
.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-1);
    padding: var(--space-5);
}

.card--link {
    display: block;
    border-color: var(--color-border-input);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--motion-fast) var(--ease), box-shadow var(--motion-fast) var(--ease);
}

/* A card you can tap says so: link colour and a chevron. */
.card--link .card__title {
    color: var(--color-primary-strong);
}

.card__chevron {
    margin-left: auto;
}

.card--link:hover {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-2);
    color: inherit;
}

.card__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
    font-size: var(--text-lg);
}

/* PageHeader (inside a stack, the stack's gap is the only spacing) */
.stack > .page-header {
    margin-bottom: 0;
}

.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-5);
}

.page-header__subtitle {
    margin-top: var(--space-2);
    color: var(--color-muted);
}

/* CheckedMark: a filled seal with the tick cut out, in the brand colour. */
.checked-mark {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--color-primary);
    vertical-align: -0.2em;
}

.checked-mark .icon__seal {
    fill: var(--color-primary);
    stroke: var(--color-primary);
}

.checked-mark .icon__tick {
    stroke: var(--color-on-primary);
    stroke-width: 2.5;
}

.checked-mark--words {
    padding: var(--space-1) var(--space-3) var(--space-1) var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--color-primary-tint);
    color: var(--color-primary-strong); /* never primary on tint: 4.28:1 */
    font-size: var(--text-sm);
    font-weight: 600;
    white-space: nowrap;
    vertical-align: middle;
}

/* StatusBadge */
.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-pill);
    font-size: var(--text-sm);
    font-weight: 600;
    white-space: nowrap;
}

.badge--neutral {
    background: var(--color-surface-sunken);
    color: var(--color-ink);
}

.badge--info {
    background: var(--color-info-tint);
    color: var(--color-primary-strong); /* never primary on tint: 4.28:1 */
}

.badge--success {
    background: var(--color-success-tint);
    color: var(--color-success);
}

.badge--warning {
    background: var(--color-warning-tint);
    color: var(--color-warning);
}

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

/* Banner */
.banner {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
}

.banner__body {
    flex: 1;
    overflow-wrap: anywhere;
}

.banner__title {
    font-weight: 650;
}

.banner--info {
    background: var(--color-info-tint);
    border-color: var(--color-primary);
}

.banner a:not(.btn) {
    color: var(--color-primary-strong);
}

.banner--success {
    background: var(--color-success-tint);
    border-color: var(--color-success);
}

.banner--warning {
    background: var(--color-warning-tint);
    border-color: var(--color-warning);
}

.banner--danger {
    background: var(--color-danger-tint);
    border-color: var(--color-danger);
}

/* EmptyState and ErrorState */
.state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-6) var(--space-4);
    text-align: center;
}

.state__icon {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--color-primary-tint);
    color: var(--color-primary-strong);
}

.state--error .state__icon {
    background: var(--color-danger-tint);
    color: var(--color-danger);
}

.state .cluster {
    justify-content: center;
}

.state__body {
    max-width: 36ch;
    color: var(--color-muted);
    overflow-wrap: anywhere;
}

dd {
    overflow-wrap: anywhere;
}

/* SummaryList: read-only details, label above value */
.summary {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.summary dt {
    color: var(--color-muted);
    font-size: var(--text-sm);
}

.summary dd {
    font-variant-numeric: tabular-nums;
}

/* A sum: its last row is the total, set apart (How it works, cost previews). */
.summary--sum > div:last-child {
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border);
    font-weight: 700;
}

.example__title {
    margin-bottom: var(--space-2);
    font-size: var(--text-md);
}

/* Toasts */
.toasts {
    position: fixed;
    z-index: 50;
    inset: auto var(--space-4) calc(var(--space-4) + 64px + env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    pointer-events: none;
}

@media (min-width: 900px) {
    .toasts {
        /* below the 56 px app bar, so Sign out stays reachable */
        inset: calc(56px + var(--space-4)) var(--space-4) auto auto;
        align-items: flex-end;
    }
}

/* Notices: important news and failures, kept on the page as banners */
.notices {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.toast {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    max-width: 420px;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--color-ink);
    color: var(--color-canvas);
    box-shadow: var(--shadow-3);
    pointer-events: auto;
    animation: toast-in var(--motion-base) var(--ease);
}

.toast__close {
    display: grid;
    place-items: center;
    width: var(--tap);
    height: var(--tap);
    margin: calc(-1 * var(--space-3)) calc(-1 * var(--space-3)) calc(-1 * var(--space-3)) 0;
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
}

@keyframes toast-in {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
}

/* Form theme */
.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.field__label {
    font-weight: 600;
}

legend.field__label {
    margin-bottom: var(--space-1);
}

.field__optional {
    color: var(--color-muted);
    font-weight: 400;
}

.field__hint {
    color: var(--color-muted);
    font-size: var(--text-sm);
}

.field__error {
    display: flex;
    align-items: flex-start;
    gap: var(--space-1);
    color: var(--color-danger);
    font-size: var(--text-sm);
    font-weight: 600;
}

.field__error .icon {
    margin-top: 0.1em;
}

.input,
.select {
    width: 100%;
    min-width: 0;
    min-height: var(--tap);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-border-input);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-ink);
    font: inherit;
    font-size: max(16px, 1rem); /* below 16 px iOS zooms in on focus */
}

.input--area {
    min-height: 6rem;
    line-height: 1.5;
    resize: vertical;
}

.input:focus-visible,
.select:focus-visible {
    border-color: var(--color-primary);
}

/* Date and time fields focus their own parts (month, hour…, the calendar
   button), so :focus-visible does not follow: show the ring whenever focus
   is anywhere inside them. */
.input:is([type='date'], [type='time']):is(:focus, :focus-within) {
    border-color: var(--color-primary);
    outline: 2px solid var(--color-ink);
    outline-offset: 2px;
    box-shadow: var(--focus-ring);
}

.input[aria-invalid='true'],
.select[aria-invalid='true'] {
    border-color: var(--color-danger);
}

.input[readonly] {
    background: var(--color-surface-sunken);
}

.input-group {
    position: relative;
    display: flex;
}

.input-group .input {
    padding-right: calc(var(--tap) + var(--space-2));
}

.input-group__action {
    position: absolute;
    inset: 0 0 0 auto;
    display: grid;
    place-items: center;
    width: var(--tap);
    border: 0;
    background: transparent;
    color: var(--color-muted);
    cursor: pointer;
}

.check {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
}

/* The label is the 44 px target, without leaving dead space under a one-line row. */
.check label {
    padding-block: 10px;
    margin-block: -10px;
}


.check input {
    flex: none;
    width: 22px;
    height: 22px;
    margin: 1px 0 0;
    accent-color: var(--color-primary);
}

.segmented {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    padding: var(--space-1);
    border-radius: var(--radius-sm);
    background: var(--color-surface-sunken);
    border: 1px solid var(--color-border-input);
}

.segmented__option {
    position: relative;
}

.segmented__option input {
    position: absolute;
    opacity: 0;
}

.segmented__option label {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--tap);
    border-radius: var(--radius-sm);
    font-weight: 600;
    cursor: pointer;
}

/* Selected is a filled button, not a shade: it reads without colour vision. */
.segmented__option input:checked + label {
    background: var(--color-primary);
    color: var(--color-on-primary);
    box-shadow: var(--shadow-1);
}

.segmented__option input:focus-visible + label {
    outline: 2px solid var(--color-ink);
    outline-offset: 2px;
    box-shadow: var(--focus-ring);
}

.segmented:has(input[aria-invalid='true']) {
    border-color: var(--color-danger);
}

.form-errors {
    margin-bottom: var(--space-2);
}

/* DataTable */
.table-wrap {
    overflow-x: auto;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
}

.table th,
.table td {
    padding: var(--space-3) var(--space-4);
    text-align: left;
    border-bottom: 1px solid var(--color-border);
}

.table th {
    color: var(--color-muted);
    font-weight: 600;
}

/* A row's name never wraps a word a line on a phone (billing review BB23). */
.table th[scope='row'] {
    min-width: 12ch;
}

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

.table .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Pagination */
.pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: var(--space-4);
    color: var(--color-muted);
    font-size: var(--text-sm);
}

/* Logo: the calendar mark with a tangerine dot, ringed in the surface it sits on. */
.logo {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.logo::after {
    content: '';
    position: absolute;
    top: -3px;
    right: -3px;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    background: var(--color-accent);
    box-shadow: 0 0 0 2px var(--color-surface);
}

@media (max-width: 599px) {
    .pagination__status {
        flex-basis: 100%;
        order: -1;
        text-align: center;
    }
}

/* PageHeader back link (pages below a tab's root) */
.page-header__back {
    gap: var(--space-1);
    margin-bottom: var(--space-1);
    font-size: var(--text-sm);
    font-weight: 600;
    text-decoration: none;
}

@media (min-width: 900px) {
    .page-header .page-header__back--phones {
        display: none;
    }
}

/* RowLink and row lists: full-width rows, at least 56 px tall */
.row-list {
    margin: 0;
    padding: 0;
    list-style: none;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.row-list > li + li {
    border-top: 1px solid var(--color-border);
}

.row-link {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 56px;
    padding: var(--space-3) var(--space-4);
    color: var(--color-ink);
    text-decoration: none;
}

/* Inside a clipped list, the focus ring is drawn inside the row. */
.row-list .row-link:focus-visible,
.checklist .row-link:focus-visible {
    outline-offset: -6px;
    box-shadow: inset 0 0 0 4px var(--color-accent);
}

a.row-link:hover {
    background: var(--color-surface-sunken);
    color: var(--color-ink);
}

.row-link__icon {
    color: var(--color-primary-strong);
}

.row-link__text {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-width: 0;
    overflow-wrap: anywhere;
}

.row-link__label {
    font-weight: 600;
}

.row-link__detail {
    color: var(--color-muted);
    font-size: var(--text-sm);
}

/* A row that isn't a link (an invitation): its text, then its actions under it, never squeezed beside it (LA17). */
.list-item {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-height: 56px;
    padding: var(--space-3) var(--space-4);
}

.list-item__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow-wrap: anywhere;
}

.list-item__label {
    font-weight: 600;
}

/* A button named with a long email wraps inside the row, never past it (lending gate LC2). */
.list-item .btn {
    max-width: 100%;
    overflow-wrap: anywhere;
    text-align: start;
    white-space: normal;
}

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

/* The lend page's people (lending audit LB2): the choice and its Call button on one row from 600 px, stacked below. */
.person-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.person-choice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--color-border);
}

.person-list .person-choice:last-child {
    border-bottom: 0;
}

.person-choice__text {
    flex: 1 1 16rem;
    min-width: 0;
}

.person-choice__stack {
    display: flex;
    flex-direction: column;
}

.person-choice .check label {
    display: flex;
    flex-direction: column;
}

/* "Your staff lent out" after the day groups (lending audit LB17). */
.lent-out {
    margin-top: var(--space-5);
}

.lent-out__group {
    margin: var(--space-2) 0 0;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-muted);
}

/* A status naming a centre ("Released by Little Oaks Child Care") wraps inside its row (lending gate LD5). */
.row-link__badge .badge {
    max-width: 100%;
    white-space: normal;
}

/* SetupChecklist */
.checklist {
    padding: 0;
    overflow: hidden;
}

.checklist__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-4) var(--space-2);
}

.checklist__steps {
    margin: 0;
    padding: 0;
    list-style: none;
}

.checklist__step {
    border-top: 1px solid var(--color-border);
}

.checklist__mark {
    color: var(--color-muted);
}

.checklist__step.is-done .checklist__mark {
    color: var(--color-success);
}

.checklist__step.is-done .row-link__label {
    color: var(--color-muted);
}

.checklist__action {
    padding: 0 var(--space-4) var(--space-3) calc(var(--space-4) + 1.25em + var(--space-3));
}

.checklist__optional {
    padding: var(--space-3) var(--space-4) 0;
    border-top: 1px solid var(--color-border);
}

/* Optional rows line up with the steps' text, after where a step's mark sits. */
.checklist__optional,
.checklist > .row-link {
    padding-inline-start: calc(var(--space-4) + 1.25em + var(--space-3));
}

.checklist__step.is-waiting .checklist__mark {
    color: var(--color-info);
}

/* DocumentCard */
.document-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.document-card__title {
    font-size: var(--text-lg);
}

.document-view {
    width: 100%;
    height: auto;
    border-radius: var(--radius-sm);
}

/* File field: one large target; the real input stays focusable but unseen */
.file-field {
    position: relative;
}

.file-field__input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.file-field:has(.file-field__input:focus-visible) .file-field__chooser {
    outline: 2px solid var(--color-ink);
    outline-offset: 2px;
    box-shadow: var(--focus-ring);
}

.file-field:has(.file-field__input[aria-invalid='true']) .file-field__chooser {
    border-color: var(--color-danger);
}

.file-field__chooser {
    min-height: 56px;
    border-style: dashed;
    text-wrap: balance;
}

.file-field__preview {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
}

.file-field__thumb {
    max-width: 100%;
    max-height: 240px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
}

.file-field__name {
    overflow-wrap: anywhere;
}

/* Sheet: a confirmation dialog rising from the bottom on phones */
.sheet {
    width: min(100% - 2 * var(--space-4), 420px);
    margin: auto auto var(--space-4);
    padding: var(--space-5);
    /* An edge as well as the shadow: in dark mode the shadow hardly shows. */
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    color: var(--color-ink);
    box-shadow: var(--shadow-3);
    /* A long email in its title or buttons wraps inside it (lending gate LD1). */
    overflow-wrap: anywhere;
}

.sheet .btn {
    max-width: 100%;
    white-space: normal;
}

.sheet::backdrop {
    background: var(--color-scrim);
}

@media (min-width: 600px) {
    .sheet {
        margin: auto;
    }
}

.sheet__actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* SegmentedNav: sibling pages, links not radios */
.segmented-nav {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: var(--space-1);
    padding: var(--space-1);
    border-radius: var(--radius-md);
    background: var(--color-surface-sunken);
}

.segmented-nav__item {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--tap);
    border-radius: var(--radius-sm);
    color: var(--color-muted);
    font-weight: 600;
    text-align: center;
    text-decoration: none;
}

.segmented-nav__item[aria-current='page'] {
    background: var(--color-surface);
    color: var(--color-primary-strong);
    font-weight: 750;
    /* an edge, not only a shade: 3:1 against the track in both themes */
    box-shadow: inset 0 0 0 1px var(--color-border-input), var(--shadow-1);
}

/* Chips: saved values, each with a 44 px remove button, 8 px apart */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-height: var(--tap);
    padding-left: var(--space-3);
    border: 1px solid var(--color-border-input);
    border-radius: var(--radius-pill);
    background: var(--color-surface);
}

.chip__detail {
    color: var(--color-muted);
    font-size: var(--text-sm);
}

.chip__remove {
    display: grid;
    place-items: center;
    width: var(--tap);
    height: var(--tap);
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--color-muted);
    cursor: pointer;
}

.chip__remove:hover {
    background: var(--color-surface-sunken);
    color: var(--color-ink);
}

/* Weekly hours, and every list of choices: sentences of several lines stay apart, each box on its first line (admin audit AB5) */
.radio-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.radio-list .check {
    align-items: flex-start;
    min-height: var(--tap);
}

/* "In your own words" belongs to "Something else": hidden while another reason is chosen (admin audit AB29). */
.field:has(input[value='other']:not(:checked)) + .field:has(textarea[name$='[other]']) {
    display: none;
}

.radio-list:has([aria-invalid='true']) {
    padding-inline-start: var(--space-3);
    border-inline-start: 3px solid var(--color-danger);
}

.radio-list .check label {
    display: flex;
    flex: 1;
    align-items: center;
    align-self: stretch;
    margin-block: 0;
    padding-block: 10px;
}

.radio-list input {
    flex: none;
    width: 22px;
    height: 22px;
    margin-top: 11px;
    accent-color: var(--color-primary);
}

.day-hours {
    display: grid;
    gap: var(--space-2);
    padding: var(--space-3) 0;
    border-top: 1px solid var(--color-border);
}

.day-hours__times {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-3);
}

.day-group--invalid {
    padding-inline-start: var(--space-3);
    border-inline-start: 3px solid var(--color-danger);
}

.day-hours input[disabled] {
    opacity: 0.55;
}

.field-pair {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-3);
}

@media (max-width: 419px) {
    .field-pair {
        grid-template-columns: 1fr;
    }
}

/* Weekly hours from 600 px: the day beside its times, half the height. */
@media (min-width: 600px) {
    .day-hours {
        grid-template-columns: 10rem 1fr;
        align-items: center;
    }
}

/* Setting rows: a label and a detail, with the action on the right (below on narrow screens) */
.setting-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border);
}

/* A card that starts with a setting row has no rule above it (lending audit LB14). */
.card > .setting-row:first-child {
    padding-top: 0;
    border-top: 0;
}

.setting-row__text {
    display: flex;
    flex: 1 1 14rem;
    flex-direction: column;
    min-width: 0;
    overflow-wrap: anywhere;
}

.setting-row__label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 600;
}

.setting-row__detail {
    color: var(--color-muted);
    font-size: var(--text-sm);
}

/* ShiftCard: the whole card is one link (shifts review S35) */
.shift-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding-inline-end: calc(var(--space-5) + 1.25em);
}

.shift-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
}

.shift-card__title {
    margin: 0;
    color: var(--color-primary-strong);
    font-size: var(--text-md);
}

.shift-card__line {
    font-variant-numeric: tabular-nums;
}

.shift-card__chevron {
    position: absolute;
    inset-block: 0;
    inset-inline-end: var(--space-4);
    display: flex;
    align-items: center;
    color: var(--color-primary-strong);
}

/* A shift that went while the feed was open: still there, plainly not available,
   and still readable (no fading: SB6). */
.shift-card.is-taken {
    border-color: var(--color-border);
    background: var(--color-surface-sunken);
    box-shadow: none;
}

.shift-card.is-taken .shift-card__title {
    color: var(--color-ink);
}

.feed__day {
    margin: var(--space-2) 0 0;
    font-size: var(--text-md);
}

/* StickyAction: the accept bar, above the tab bar on phones (shifts review S13) */
.sticky-action {
    position: fixed;
    inset: auto 0 calc(60px + env(safe-area-inset-bottom));
    z-index: 9;
    border-top: 1px solid var(--color-border);
    background: var(--color-surface);
    box-shadow: var(--shadow-2);
}

.sticky-action__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-3);
    max-width: 640px;
    margin: 0 auto;
    padding: var(--space-3) var(--space-4);
}

.sticky-action__summary {
    margin: 0;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

/* The page keeps its last lines clear of the bar, and focus never hides under it (SB7). */
.has-sticky-action {
    padding-bottom: 88px;
}

html:has(.sticky-action) {
    scroll-padding-bottom: 180px;
}

/* On phones the button fills the bar (SB17). */
@media (max-width: 599px) {
    .sticky-action__inner > *:not(.sticky-action__summary),
    .sticky-action__inner .btn {
        flex: 1 1 100%;
        width: 100%;
    }
}

/* A short window (a phone on its side, zoomed text): the bar stops floating. */
@media (max-height: 500px) {
    .sticky-action {
        position: static;
        box-shadow: none;
    }
}

/* From 900 px the tabs are at the top: the bar sits at the bottom of the window. Beside a side nav it
   starts after it, so its content lines up with the page's column (lending audit LB16). */
@media (min-width: 900px) {
    .sticky-action {
        inset-block-end: 0;
    }

    .with-side-nav:has(> .side-nav) .sticky-action {
        inset-inline-start: 240px;
    }

    /* Its content starts where the page's column does: the page is up to 1100 px, centred in what's left (LC8). */
    .with-side-nav:has(> .side-nav) .sticky-action__inner {
        margin-inline: max(0px, calc((100vw - 240px - 1100px) / 2)) auto;
    }
}

/* The keyboard is open (a field has focus): the bar steps aside like the tab bar. */
@media (max-width: 899px) {
    body:has(:is(input:not([type='checkbox'], [type='radio'], [type='submit'], [type='button']), select, textarea):focus) .sticky-action {
        display: none;
    }
}

/* A list that starts closed (past shifts), with a chevron that turns when it opens (shifts gate G11) */
.disclosure__summary {
    min-height: var(--tap);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    cursor: pointer;
    font-weight: 650;
    list-style: none;
}

.disclosure__summary::-webkit-details-marker {
    display: none;
}

.disclosure__summary::before {
    content: '';
    flex: none;
    width: 0.5em;
    height: 0.5em;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(-45deg);
    transition: transform var(--motion-fast) var(--ease);
}

.disclosure[open] .disclosure__summary::before {
    transform: rotate(45deg);
}

.disclosure[open] .disclosure__summary {
    margin-bottom: var(--space-2);
}

/* A shift's history: time, then what happened */
.history {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.history__when {
    display: block;
    color: var(--color-muted);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

/* The post form's live cost and the line above its button */
.cost-preview {
    padding: var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface-sunken);
}

/* On the sunken background the link takes the strong shade, to keep 4.5:1. */
.cost-preview a {
    color: var(--color-primary-strong);
}

.post-summary:not(:empty) {
    font-weight: 650;
}

.input--money {
    max-width: 10rem;
    font-variant-numeric: tabular-nums;
}

/* Offline: a strip at the top of the window while the connection is gone (S28). */
.offline-banner {
    position: sticky;
    top: 0;
    z-index: 60;
    padding: var(--space-2) var(--space-4);
    border-bottom: 2px solid var(--color-warning);
    background: var(--color-warning-tint);
    color: var(--color-ink);
    font-weight: 650;
    text-align: center;
}

/* Which shift a sign-in is for (S15). */
.shift-hint {
    margin: 0;
    padding: var(--space-3) var(--space-4);
    border-inline-start: 4px solid var(--color-primary-strong);
    border-radius: var(--radius-sm);
    background: var(--color-surface-sunken);
}

/* What confirmed hours come to (SB3) */
.hours-total {
    margin: 0;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--color-surface-sunken);
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

.row-link__badge {
    margin-top: var(--space-1);
}

/* The audit log, one column at every width (admin review AD27) */
.audit-list {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
}

.audit-list__entry {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding-block: var(--space-3);
}

.audit-list__entry + .audit-list__entry {
    border-top: 1px solid var(--color-border);
}

.audit-list__meta {
    margin: 0;
}

.audit-list__details .summary {
    margin-top: var(--space-2);
}

/* A stored secret: its state, and the field to replace it (admin review AD10) */
.secret-field__state {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    color: var(--color-success);
}

.secret-field__state .icon {
    flex: none;
}

/* Masked as it is typed, without type="password" (which password managers fill in). */
.input--secret {
    -webkit-text-security: disc;
    font-family: ui-monospace, monospace;
}

/* A value to copy into another service (AD36) */
.copy-value__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.copy-value__text {
    overflow-wrap: anywhere;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    background: var(--color-surface-sunken);
    font-size: var(--text-sm);
    user-select: all;
}

.btn[data-copied]::after {
    content: ' ✓' / '';
}

/* The month or view a row of links is on (fees owed's months) */
.tap-link[aria-current='page'] {
    color: var(--color-ink);
    font-weight: 750;
    text-decoration: none;
}

/* The server's "are you sure?" step, beside the form's buttons (AD11) */
.confirm-step:focus {
    outline: 2px solid var(--color-ink);
    box-shadow: var(--focus-ring);
}

/* Document review: the document as wide as it can be, the details beside it from 900 px (admin review AD6) */
.review__panes {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

/* Two panes once both fit beside the side-less focus page: below that, stacked (admin audit AB23). */
@media (min-width: 1000px) {
    .review__panes {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 360px;
        align-items: start;
    }

    /* Sticky only while it fits; never a scroll box of its own, which hid Approve below the fold (admin gate AC8). */
    .review__details {
        position: sticky;
        top: calc(56px + var(--space-4));
        align-self: start;
    }
}

.doc-viewer {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* A fixed height, the pages scrolling inside: drawing a PDF never moves the page around it (no layout shift). */
.doc-viewer__frame {
    overflow: auto;
    height: min(80dvh, 1100px);
    padding: var(--space-3);
    border-radius: var(--radius-md);
    background: var(--color-surface-sunken);
}

.doc-viewer__frame:fullscreen {
    height: 100%;
    background: var(--color-canvas);
}

.doc-viewer__pages {
    --doc-scale: 1;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    width: calc(100% * var(--doc-scale));
}

.doc-viewer__figure {
    margin: 0;
}

.doc-viewer__page {
    display: block;
    width: 100%;
    height: auto;
    background: var(--color-paper);
    box-shadow: var(--shadow-1);
}

.doc-viewer__status:empty {
    display: none;
}

.doc-viewer__zoom {
    min-width: 4ch;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* A card that is a fieldset: its legend is the card's title, inside it, not on its border (F7 alert pages). */
fieldset.card > legend.card__title {
    float: left;
    width: 100%;
    font-family: var(--font-heading);
    word-spacing: var(--heading-word-spacing);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.01em;
}

fieldset.card > legend.card__title + * {
    clear: both;
}

/* An external link inside a sentence: its icon stays in the line (app gate AE1). */
.external-link--inline .icon {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
}

/* Ratings and reviews (R5, educators review EA13): drawn stars, always with words beside them. */
.rating {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2);
}

.rating__stars {
    color: var(--color-star);
    letter-spacing: 0.08em;
    white-space: nowrap;
}

.review-item {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

/* A review as a row of a list: the row's own padding. */
.row-list > li > .review-item {
    padding: var(--space-3) var(--space-4);
}

.review-item__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2);
}

.review-item__comment {
    overflow-wrap: anywhere;
}

/* The ask step's picker (R4, EA15): a radio card, the profile link under it, outside the label. */
.pick {
    align-items: center;
}

/* The name line above the details, never side by side as flex items (Prompt B RB3).
   As specific as `.radio-list .check label`, which centres its items. */
.radio-list .check.pick label {
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
}

/* The profile at the end of the row, not a second row of its own (owner's UI review, 2026-10-22). */
.pick__link {
    flex: none;
    margin-inline-start: auto;
    padding-inline: var(--space-2);
}

/* A search field with its button beside it (R4 Educators): the button lines up with the field, not its label. */
.search-row {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
}

.search-row > .field {
    flex: 1;
    min-width: 0;
}

/* Email templates (owner, 2026-10-23): the message as it is sent, plain
   text whose aligned lines ("When:     Tuesday") stay aligned. */
#email_template_body {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.9375rem;
    line-height: 1.5;
}

.placeholder-list {
    display: grid;
    gap: var(--space-3, 0.75rem);
    margin: 0;
}

.placeholder-list dt {
    font-weight: 600;
}

.placeholder-list dd {
    margin: 0.125rem 0 0;
}
