body {
    background: #f5f6f4;
}

/* ---- Top header ---- */
.site-header {
    background: var(--btn-green);
}
.site-header__inner {
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 10px 24px;
}
.site-logo img {
    height: 40px;
    display: block;
}
.site-header__event {
    color: #fff;
    font-weight: 600;
    font-size: 0.9rem;
}
.site-header__event .ti {
    color: var(--btn-highlight);
}
.site-header__search {
    flex: 1 1 auto;
    justify-content: center;
    padding: 0 16px;
}
.site-header__search .input-group {
    max-width: 360px;
}
.site-header__account {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 16px;
    font-size: 0.9rem;
}
.site-header__name {
    font-weight: 600;
    color: #fff;
}
.badge-role {
    display: inline-block;
    margin-left: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--btn-highlight);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    vertical-align: middle;
}
.site-header__account a {
    color: #fff;
    text-decoration: none;
}
.site-header__account a:hover {
    text-decoration: underline;
}

/* ---- App shell: sidebar + content ---- */
.app-shell--sidebar {
    display: flex;
    align-items: flex-start;
}
/* Responsive off-canvas sidebar (Niki, 28-Aug-2026) - Bootstrap's own
   .offcanvas-xl handles the breakpoint switch: below xl (1200px) this is a
   sliding drawer opened by .admin-sidebar-toggle in inc/header.php; at xl
   and up, Bootstrap forces the outer .offcanvas element to
   background:transparent!important and a 400px --bs-offcanvas-width, so
   the actual visual styling (width, background, border, padding) lives on
   .offcanvas-body instead, which Bootstrap doesn't touch with !important
   and a plain rule here can override normally. */
.admin-sidebar {
    --bs-offcanvas-width: 240px;
    flex-shrink: 0;
}
.admin-sidebar .offcanvas-body {
    width: 240px;
    background: #fff;
    border-right: 1px solid #e3e6e1;
    padding: 20px 12px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
/* Desktop only: keeps the sidebar's white background/border reaching the
   bottom of the page even with few links - see the comment above
   .admin-sidebar. Deliberately NOT applied below 1200px (Niki, 28-Aug-2026):
   in mobile drawer mode .admin-sidebar is position:fixed;top:0;bottom:0 (an
   exact viewport-height box) and Bootstrap already sizes .offcanvas-body to
   fill exactly what's left under the "Menu" header bar via flex-grow:1 - a
   min-height here would fight that once the (currently commented-out)
   Stalls links push content past one screen, forcing the body taller than
   the fixed drawer with no scrollbar and no way to reach the overflow
   (page scroll is locked by Bootstrap while the drawer is open). */
@media (min-width: 1200px) {
    .admin-sidebar .offcanvas-body {
        min-height: calc(100vh - 61px);
    }
}
/* Mobile drawer: let it scroll internally once content is taller than the
   screen, rather than silently overflowing past the fixed-position nav.
   Bootstrap's own default already sets this below 1200px - stated
   explicitly here since the app now deliberately depends on it. */
@media (max-width: 1199.98px) {
    .admin-sidebar .offcanvas-body {
        overflow-y: auto;
    }
}
/* Log Out link, pinned to the bottom of the sidebar (see inc/menu-admin.php
   / inc/menu-customer.php). margin-top:auto takes up the free space above it
   so it and the footer image sit at the bottom in both the desktop sidebar
   and the mobile drawer. */
.admin-sidebar__link--logout {
    margin-top: auto;
    border-top: 1px solid #e3e6e1;
    border-radius: 0;
    color: #8a8f87;
}
.admin-sidebar__link--logout:hover {
    color: #333;
}
.admin-sidebar__footer-image {
    padding-top: 20px;
    /* Pulls out past .offcanvas-body's own 12px left/right padding (see
       .admin-sidebar .offcanvas-body above) so the image runs edge-to-edge
       instead of sitting inset like the nav links do. */
    margin-left: -12px;
    margin-right: -12px;
    text-align: center;
}
.admin-sidebar__footer-image img {
    display: block;
    width: 100%;
    height: auto;
    margin: 0 auto;
}
.admin-sidebar-toggle {
    background: transparent;
    border: 0;
    color: #fff;
    font-size: 1.4rem;
    line-height: 1;
    padding: 0.25rem 0.5rem;
    margin-right: 0.5rem;
    cursor: pointer;
}
.admin-sidebar-toggle:hover {
    color: var(--btn-sage-lt);
}
.admin-sidebar__link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border-radius: 8px;
    color: #333;
    text-decoration: none;
    font-size: 0.92rem;
}
.admin-sidebar__link:hover {
    background: var(--btn-sage-lt);
}
.admin-sidebar__link.active {
    background: var(--btn-green);
    color: #fff;
}
.admin-sidebar__link .ti {
    width: 18px;
    text-align: center;
}
/* Indented sub-links (e.g. the order-type shortcuts under Invoices/Orders).
   Aligned to the parent link's text by matching its 12px padding + 10px gap
   + 18px icon. */
.admin-sidebar__sublink {
    display: block;
    padding: 5px 12px 5px 40px;
    border-radius: 8px;
    color: #6b7066;
    text-decoration: none;
    font-size: 0.86rem;
}
.admin-sidebar__sublink:hover {
    background: var(--btn-sage-lt);
    color: #333;
}
.admin-sidebar__sublink.active {
    background: var(--btn-green);
    color: #fff;
}
.admin-sidebar__group-label {
    margin: 14px 12px 4px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #8a8f87;
}
.admin-sidebar__group-label--admin {
    color: var(--btn-highlight);
}

/* Collapsible sidebar sections (inc/menu-admin.php) - native <details>, no JS.
   Only the section containing the current page is rendered with `open`. */
.admin-sidebar__group {
    margin-top: 10px;
}
.admin-sidebar__group + .admin-sidebar__group {
    margin-top: 2px;
}
.admin-sidebar__group-toggle,
.admin-sidebar__subgroup-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
    list-style: none;
}
.admin-sidebar__group-toggle::-webkit-details-marker,
.admin-sidebar__subgroup-toggle::-webkit-details-marker {
    display: none;
}
.admin-sidebar__group-toggle {
    margin: 4px 12px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--btn-sage-dk);
}
.admin-sidebar__group-toggle:hover {
    color: color-mix(in srgb, var(--btn-highlight) 80%, black);
}
.admin-sidebar__subgroup-toggle {
    padding: 8px 12px;
    border-radius: 8px;
    color: #333;
    font-size: 0.92rem;
}
.admin-sidebar__subgroup-toggle:hover {
    background: var(--btn-sage-lt);
}
.admin-sidebar__subgroup-toggle .ti {
    width: 18px;
    text-align: center;
}
/* The subgroup heading is a link (goes to the invoices list) wrapped in the
   <summary> - clicking the label navigates, clicking the chevron area still
   just expands/collapses. */
.admin-sidebar__subgroup-link {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}
.admin-sidebar__subgroup-link:hover {
    color: inherit;
    text-decoration: none;
}
.admin-sidebar__group-toggle::after,
.admin-sidebar__subgroup-toggle::after {
    content: "\25B8";
    margin-left: auto;
    font-size: 0.85em;
    transition: transform 0.15s ease;
}
details[open] > .admin-sidebar__group-toggle::after,
details[open] > .admin-sidebar__subgroup-toggle::after {
    transform: rotate(90deg);
}
@media (prefers-reduced-motion: reduce) {
    .admin-sidebar__group-toggle::after,
    .admin-sidebar__subgroup-toggle::after {
        transition: none;
    }
}
.app-content {
    flex: 1;
    min-width: 0;
    padding: 24px;
}
/* DataTables right-aligns any column it detects as a date (dt-type-date). The
   customer invoice tables want their Date column left-aligned like the rest. */
#clientInvoicesTable th:first-child,
#clientInvoicesTable td:first-child,
#customerInvoicesTable th:first-child,
#customerInvoicesTable td:first-child {
    text-align: left;
}

/* ---- Dashboard: KPI tiles ---- */
.kpi-card {
    height: 100%;
}
.kpi-card__icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1.2rem;
    margin-bottom: 8px;
}
.kpi-card__icon--stalls { background: var(--btn-green); }
.kpi-card__icon--adverts { background: #6f42c1; }
.kpi-card__icon--trees { background: var(--btn-sage-dk); }
.kpi-card__icon--finance { background: #0d6efd; }
.kpi-card__label {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #8a8f87;
}
.kpi-card__value {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--btn-green);
}
/* Finance tile: each row links to the matching filter on the invoices list. */
.kpi-card a.d-flex {
    padding: 1px 0;
}
.kpi-card a.d-flex:hover {
    opacity: 0.7;
}

/* ---- Dashboard: attention needed / activity feed ---- */
.attention-item, .activity-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px solid #eee;
}
.attention-item:last-child, .activity-item:last-child {
    border-bottom: none;
}
.attention-item__icon {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 0.85rem;
}
.attention-item__icon--danger { background: #dc3545; }
.attention-item__icon--warning { background: var(--btn-highlight); }
.attention-item__icon--info { background: #0d6efd; }
.activity-item__date {
    color: #8a8f87;
    font-size: 0.8rem;
    width: 84px;
    flex-shrink: 0;
}

@media (min-width: 1200px) {
    .h1, h1 {
        font-size: 2rem;
    }
}

.site-footer {
    padding: 16px 24px;
    text-align: center;
}

/* ---- Brand colours instead of Bootstrap's default blue (Niki, 28-Aug-2026)
   - Bootstrap 5.3 bakes each component's own colour into local custom
   properties with a hardcoded hex fallback rather than always reading the
   root theme colour at render time, so both the root-level variables and
   each component's own custom properties are overridden here to be safe. */
:root {
    --bs-primary: var(--btn-green-mid);
    --bs-primary-rgb: 56, 87, 64;
    /* Link treatment (Niki, 28-Aug-2026): resting link is a soft muted
       teal-blue with no underline, so it reads as a link without the harsh
       default Bootstrap blue; hover brings the brand sage-green and the
       underline in. */
    --btn-link: var(--btn-blue);
    --bs-link-color: var(--btn-link);
    --bs-link-color-rgb: 47, 111, 143;
    --bs-link-hover-color: var(--btn-green-mid);
    --bs-link-hover-color-rgb: 56, 87, 64;
}

/* Content links (not buttons/tabs/pagination/dropdown items, which Bootstrap
   styles itself) - no underline at rest, underline on hover. Scoped to
   .site-main so the header/sidebar/footer link rules above are untouched. */
.site-main a:not(.btn):not(.nav-link):not(.page-link):not(.dropdown-item) {
    text-decoration: none;
}
.site-main a:not(.btn):not(.nav-link):not(.page-link):not(.dropdown-item):hover {
    text-decoration: underline;
}
.btn-primary {
    --bs-btn-bg: var(--btn-green-mid);
    --bs-btn-border-color: var(--btn-green-mid);
    --bs-btn-hover-bg: color-mix(in srgb, var(--btn-green-mid) 85%, black);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--btn-green-mid) 85%, black);
    --bs-btn-active-bg: color-mix(in srgb, var(--btn-green-mid) 75%, black);
    --bs-btn-active-border-color: color-mix(in srgb, var(--btn-green-mid) 75%, black);
    --bs-btn-disabled-bg: var(--btn-green-mid);
    --bs-btn-disabled-border-color: var(--btn-green-mid);
    --bs-btn-focus-shadow-rgb: 56, 87, 64;
}
.btn-info {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--btn-sage-dk);
    --bs-btn-border-color: var(--btn-sage-dk);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: color-mix(in srgb, var(--btn-sage-dk) 85%, black);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--btn-sage-dk) 85%, black);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: color-mix(in srgb, var(--btn-sage-dk) 75%, black);
    --bs-btn-active-border-color: color-mix(in srgb, var(--btn-sage-dk) 75%, black);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--btn-sage-dk);
    --bs-btn-disabled-border-color: var(--btn-sage-dk);
    --bs-btn-focus-shadow-rgb: 104, 137, 102;
}
.form-check-input:checked {
    background-color: var(--btn-green-mid);
    border-color: var(--btn-green-mid);
}
.form-check-input:focus,
.form-control:focus,
.form-select:focus {
    border-color: var(--btn-sage-md);
    box-shadow: 0 0 0 0.25rem rgba(56, 87, 64, 0.25);
}
.nav-tabs .nav-link {
    color: #495057;
}
.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus {
    border-color: var(--btn-sage-lt) var(--btn-sage-lt) #dee2e6;
    color: var(--btn-green-mid);
}
.nav-tabs .nav-link.active {
    color: var(--btn-green-mid);
    font-weight: 600;
}
.alert-info {
    --bs-alert-color: var(--btn-green-mid);
    --bs-alert-bg: var(--btn-sage-lt);
    --bs-alert-border-color: var(--btn-sage-md);
}

/* Red asterisk after a required field's label - add class="frm-required" to
   the <label>, not the input, and pair it with the input's own `required`
   attribute (this is purely visual, not itself a validation mechanism). */
.frm-required::after {
    content: " *";
    color: #dc3545;
}

/* Bootstrap 5 dropped .form-group's built-in spacing (the framework now
   expects utility classes like .mb-3 instead) - this restores the old
   margin so existing pages don't need every form-group div rewritten. */
.form-group {
    margin-bottom: 1rem;
}

/* Bootstrap's own .modal/.modal-backdrop z-index (1055/1050) should already
   put the modal above its backdrop, but it wasn't - reported on both a
   deeply-nested modal (admin/interest.php's View, inside .card >
   .table-responsive > table > tr > td) and a shallow one (the Copy Emails
   modal, a direct sibling of .card), so this isn't a nesting/stacking-
   context problem, just needs forcing explicitly. !important since a plain
   override may have been masked by the cache-busting bug fixed alongside
   this (27-Aug-2026) rather than actually taking effect. */
.modal-backdrop {
    z-index: 1050 !important;
}
.modal {
    z-index: 1060 !important;
}

/* DataTables (the base/non-Bootstrap-styled CDN build, see admin/invoices.php
   and admin/customers.php) renders its "Show [x] entries" and "Search:
   [box]" controls with no margin around the select/input, so the label text
   sits flush against them - both the modern dt-length/dt-search class names
   (DataTables 2.x+) and the classic *_length/*_filter id suffix (still
   present alongside them) are covered here in case either changes. */
.dt-length select,
select[id$="_length"] {
    margin: 0 0.4em;
}
.dt-search input[type="search"],
input[id$="_filter"] {
    margin-left: 0.5em;
}

/* Back to top - ported from new/httpdocs/assets/css/app.css (Niki,
   28-Aug-2026). Hidden until assets/js/app.js adds .is-visible after
   scrolling past a threshold. right/bottom and the shadow are httpdocs'
   --space-6/--shadow-md values written out literally, since this admin
   app's design-tokens.css doesn't carry httpdocs' full spacing/shadow
   scale - --btn-highlight is already shared between both. */
.back-to-top {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 1030;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--btn-highlight);
    color: #fff;
    font-size: 32px;
    text-decoration: none;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8px 24px rgba(8, 37, 27, 0.10);
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
}
.back-to-top.is-visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
.back-to-top:hover {
    background: color-mix(in srgb, var(--btn-highlight) 85%, black);
    color: #fff;
}

/* Solid highlight-orange button (same --btn-highlight as .back-to-top). Used
   for the "Add Stall / Advert / Tree / Sponsor" shortcuts on the customer
   page. */
.btn-highlight {
    background: var(--btn-highlight);
    border-color: var(--btn-highlight);
    color: #fff;
}
.btn-highlight:hover,
.btn-highlight:focus,
.btn-highlight:active {
    background: color-mix(in srgb, var(--btn-highlight) 85%, black);
    border-color: color-mix(in srgb, var(--btn-highlight) 85%, black);
    color: #fff;
}

/* Solid button in the brand link-blue (--btn-link, the muted teal-blue used
   for content links - not Bootstrap's default blue). Used for the "How this
   works" help buttons on the stallholder pages. */
.btn-brand-blue {
    background: var(--btn-link);
    border-color: var(--btn-link);
    color: #fff;
}
.btn-brand-blue:hover,
.btn-brand-blue:focus,
.btn-brand-blue:active {
    background: color-mix(in srgb, var(--btn-link) 85%, black);
    border-color: color-mix(in srgb, var(--btn-link) 85%, black);
    color: #fff;
}

/* Solid button in the brand blue-teal (--btn-blue) - the "pay by card" call
   to action on the dashboard, the to-do list, the invoices list and the
   admin "take card payment" buttons. Deliberately not green (green reads as
   "already paid" elsewhere) and not Bootstrap's loud default blue. */
.btn-pay {
    background: var(--btn-blue);
    border-color: var(--btn-blue);
    color: #fff;
}
.btn-pay:hover,
.btn-pay:focus,
.btn-pay:active {
    background: var(--btn-blue-dk);
    border-color: var(--btn-blue-dk);
    color: #fff;
}

/* Selectable sponsorship package cards on /book-sponsor. */
.sponsor-choice {
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.sponsor-choice:hover {
    border-color: var(--btn-highlight);
}
.sponsor-choice:has(input[name="choice"]:checked) {
    border-color: var(--btn-highlight);
    box-shadow: 0 0 0 0.2rem rgba(243, 146, 0, 0.35);
}

/* Briefly draws the eye to a row that has just appeared (e.g. the postcode
   "Select Address" dropdown after a lookup). JS adds .field-reveal-flash to
   the row, then removes it after ~2.5s. */
@keyframes field-reveal-flash {
    0%, 100% { background-color: rgba(243, 146, 0, 0); }
    12%, 55% { background-color: rgba(243, 146, 0, 0.3); }
}
.field-reveal-flash {
    animation: field-reveal-flash 1.1s ease-in-out 2;
    border-radius: 0.5rem;
}
.field-reveal-flash select,
.field-reveal-flash .form-select {
    border-color: var(--btn-highlight);
    box-shadow: 0 0 0 0.2rem rgba(243, 146, 0, 0.45);
}
@media (prefers-reduced-motion: reduce) {
    .field-reveal-flash {
        animation: none;
        background-color: rgba(243, 146, 0, 0.22);
    }
}

/* Honeypot field for spam bots - hidden from everyone, including screen
   readers (a legitimate assistive-tech user must never be able to find and
   fill this in, or they'd get wrongly rejected as a bot). Off-screen rather
   than display:none/visibility:hidden, since some bots specifically skip
   fields hidden that way. */
.hp-field {
    position: absolute;
    left: -9999px;
    top: -9999px;
    width: 1px; height: 1px;
    overflow: hidden;
}

/* ---- Auth pages (login, and register once it exists) ---- */
.auth-page {
    display: flex;
    justify-content: center;
    padding: 48px 16px;
}
.auth-card {
    width: 100%;
    max-width: 400px;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(8, 37, 27, 0.10);
    padding: 32px;
    text-align: center;
}
.auth-card__logo {
    height: 75px;
    margin-bottom: 16px;
}
.auth-card h1 {
    font-size: 1.5rem;
    margin-bottom: 20px;
}
.auth-card form {
    text-align: left;
}
.auth-card__link {
    margin: 16px 0 0;
    font-size: 0.9rem;
}
.auth-card hr {
    margin: 12px 0;
    border-color: var(--btn-sage-lt);
}
.auth-card__register-label {
    font-weight: 600;
    color: var(--btn-green);
    margin-bottom: 8px;
}
.auth-password-toggle {
    color: #fff;
}

/* Print button next to an invoice number (admin/invoices.php) - links to
   invoice-view.php, the number itself is now plain bold text rather than
   the link. */
.btn-invoice-print {
    background: var(--btn-green);
    border-color: var(--btn-green);
    color: #fff;
}
.btn-invoice-print:hover {
    background: color-mix(in srgb, var(--btn-green) 85%, white);
    border-color: color-mix(in srgb, var(--btn-green) 85%, white);
    color: #fff;
}
.btn-invoice-print .ti-printer {
    font-weight: 600;
}

/* Back arrow (order-edit.php and anywhere else that wants one) - plain
   icon button, no border/fill, matching the subtlety of a "just navigate"
   affordance rather than a real action button. */
.btn-icon-back {
    background: transparent;
    border: 0;
    color: var(--btn-green-mid);
    font-size: 1.4rem;
    line-height: 1;
    padding: 0.25rem;
    cursor: pointer;
}
.btn-icon-back:hover {
    color: var(--btn-green);
}

/* Compliance Grid status glyphs (admin/stallholder-compliance.php) - a small
   size bump on top of the standard icon weight so a dense column of ticks and
   crosses reads at a glance. */
.compliance-icon {
    font-size: 1.15rem;
    vertical-align: -0.15em;
}
