/*
 * LVB Multi-Event Visitor Management Platform
 * Project overrides on top of the Osen (Bootstrap 5) theme.
 *
 * Keep this file small. Anything the theme already does well should not be
 * repeated here.
 */

/* ==========================================================================
   Brand sizing

   The theme sets the sidebar wordmark to the full 70px of the topbar, which
   suited the old mark: a roundel lockup carrying a lot of internal padding, so
   70px of box was maybe 40px of ink. The HeyJoin.me wordmark is cropped tight
   and is a 3:1 lockup, so the same 70px would render 210px wide in a 260px
   sidebar and shout. These are the knobs the theme exposes for exactly this.
   ========================================================================== */
:root {
    --osen-logo-lg-height: 34px;
    --osen-logo-sm-height: 30px;
}

/* ==========================================================================
   Status indicators

   Pale `bg-*-subtle` pills wash out badly — light text on a light tint fails
   contrast and reads as unfinished. These use the opposite arrangement: a
   small saturated dot carries the colour, while the label stays at full body
   contrast so it is legible in both themes and at a glance across a table.
   ========================================================================== */
.status {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.4;
    color: var(--osen-body-color, #4c4c5c);
    white-space: nowrap;
    vertical-align: middle;
}

.status::before {
    content: "";
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background-color: var(--status-color, var(--osen-secondary-color, #9ba6b7));
    /* A faint halo lifts the dot off both light and dark table rows. */
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-color, transparent) 18%, transparent);
}

.status-lg {
    font-size: 0.9375rem;
    gap: 0.55rem;
}

.status-lg::before {
    width: 0.625rem;
    height: 0.625rem;
}

/* Muted states drop the halo — nothing to draw attention to. */
.status-muted {
    color: var(--osen-secondary-color, #9ba6b7);
}

.status-muted::before {
    box-shadow: none;
}

.status-success { --status-color: #16a34a; }
.status-danger  { --status-color: #dc2626; }
.status-warning { --status-color: #d97706; }
.status-info    { --status-color: #0284c7; }
.status-primary { --status-color: #4f46e5; }
.status-muted   { --status-color: #9ca3af; }
.status-dark    { --status-color: #475569; }

/* Slightly brighter dots in dark mode, where mid-tones go muddy. */
[data-bs-theme="dark"] .status-success { --status-color: #22c55e; }
[data-bs-theme="dark"] .status-danger  { --status-color: #f87171; }
[data-bs-theme="dark"] .status-warning { --status-color: #fbbf24; }
[data-bs-theme="dark"] .status-info    { --status-color: #38bdf8; }
[data-bs-theme="dark"] .status-primary { --status-color: #818cf8; }
[data-bs-theme="dark"] .status-dark    { --status-color: #94a3b8; }

/* A live, in-progress state earns a gentle pulse — used sparingly. */
.status-pulse::before {
    animation: status-pulse 2s ease-out infinite;
}

@keyframes status-pulse {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--status-color) 45%, transparent); }
    70%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--status-color) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--status-color) 0%, transparent); }
}

/* ==========================================================================
   Chips

   For values rather than states — a price, a code, a count. Bordered and
   neutral, so they never compete with the status dots for attention.
   ========================================================================== */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    border-radius: 0.375rem;
    background-color: var(--osen-body-bg, #fafdff);
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.5;
    color: var(--osen-body-color, #4c4c5c);
    white-space: nowrap;
}

.chip-muted {
    color: var(--osen-secondary-color, #9ba6b7);
    font-weight: 500;
}

.chip-accent {
    border-color: color-mix(in srgb, #16a34a 35%, var(--osen-border-color, #e7e9eb));
    color: #15803d;
}

[data-bs-theme="dark"] .chip-accent {
    color: #4ade80;
}

/* Money owed but not yet sent, and money kept. Same restraint as the others:
   a tinted border and coloured text, never a filled block. */
.chip-warn {
    border-color: color-mix(in srgb, #d97706 35%, var(--osen-border-color, #e7e9eb));
    color: #b45309;
}

[data-bs-theme="dark"] .chip-warn {
    color: #fbbf24;
}

.chip-danger {
    border-color: color-mix(in srgb, #dc2626 35%, var(--osen-border-color, #e7e9eb));
    color: #b91c1c;
}

[data-bs-theme="dark"] .chip-danger {
    color: #f87171;
}

/* ==========================================================================
   Filter selects (Select2)

   The stock widget ships a hard blue highlight bar and square corners that
   look nothing like the rest of the panel. These overrides bring it in line:
   matching radius, subtle hover, and tags that read as removable chips.
   ========================================================================== */
.select2-container {
    width: 100% !important;
}

/* --- Closed control ---------------------------------------------------- */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
    min-height: calc(1.5em + 0.9rem + 2px);
    padding: 0.15rem 0.35rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    border-radius: 0.5rem;
    background-color: var(--osen-body-bg, #fafdff);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single {
    border-color: var(--osen-primary, #465dff);
    box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--osen-primary, #465dff) 18%, transparent);
    outline: 0;
}

.select2-container--default .select2-selection--single .select2-selection__rendered {
    padding-left: 0.5rem;
    color: var(--osen-body-color, #4c4c5c);
    line-height: calc(1.5em + 0.6rem);
}

.select2-container--default .select2-selection--single .select2-selection__placeholder,
.select2-container--default .select2-search--inline .select2-search__field::placeholder {
    color: var(--osen-secondary-color, #9ba6b7);
}

.select2-container--default .select2-selection--single .select2-selection__arrow {
    height: calc(1.5em + 0.9rem);
}

/* --- Selected tags ----------------------------------------------------- */
.select2-container--default .select2-selection--multiple .select2-selection__choice {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0.15rem 0.2rem 0.15rem 0;
    padding: 0.1rem 0.45rem;
    border-radius: 0.375rem;
    color: var(--osen-body-color, #4c4c5c);
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.5;

    /* Solid values first: an older WebView that cannot parse color-mix()
       discards those declarations, and a tag with no background is unreadable.
       Browsers that do support it simply apply the tinted pair below. */
    border: 1px solid #c7cffd;
    background-color: #eef1ff;
    border-color: color-mix(in srgb, var(--osen-primary, #465dff) 30%, var(--osen-border-color, #e7e9eb));
    background-color: color-mix(in srgb, var(--osen-primary, #465dff) 10%, var(--osen-body-bg, #fafdff));
}

[data-bs-theme="dark"] .select2-container--default .select2-selection--multiple .select2-selection__choice {
    border-color: #3f4c8a;
    background-color: #2b3346;
    border-color: color-mix(in srgb, var(--osen-primary, #465dff) 40%, var(--osen-border-color, #37394d));
    background-color: color-mix(in srgb, var(--osen-primary, #465dff) 18%, var(--osen-body-bg, #17181e));
}

/* Select2 puts the remove button first; make it a quiet × rather than a
   heavy red block. */
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
    order: 2;
    margin: 0 0 0 0.1rem;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--osen-secondary-color, #9ba6b7);
    font-size: 1rem;
    line-height: 1;
}

.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
    background: transparent;
    color: var(--osen-danger, #ff6d43);
}

.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
    margin-top: 0.3rem;
    color: var(--osen-body-color, #4c4c5c);
    font-family: inherit;
    font-size: 0.875rem;
}

/* --- Dropdown ---------------------------------------------------------
   The panel floats over table rows, so its background must be fully opaque.
   Every colour here carries a literal fallback: this theme renames the
   Bootstrap custom properties to --osen-*, and a bare var() that resolves to
   nothing leaves the panel see-through.
   --------------------------------------------------------------------- */
.select2-dropdown {
    border: 1px solid var(--osen-border-color, #e7e9eb);
    border-radius: 0.75rem;
    background-color: var(--osen-body-bg, #fafdff);
    box-shadow: 0 10px 30px -12px rgba(15, 23, 42, 0.28),
                0 2px 6px -2px rgba(15, 23, 42, 0.12);
    overflow: hidden;
    z-index: 1056;   /* above modals' backdrop-adjacent content and sticky headers */
}

[data-bs-theme="dark"] .select2-dropdown {
    border-color: var(--osen-border-color, #37394d);
    background-color: var(--osen-body-bg, #17181e);
    box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.6),
                0 2px 6px -2px rgba(0, 0, 0, 0.4);
}

.select2-container--default .select2-results > .select2-results__options {
    padding: 0.375rem;
    max-height: 16rem;
    background-color: var(--osen-body-bg, #fafdff);
    /* A thin, quiet scrollbar — the stock one is a heavy grey slab. */
    scrollbar-width: thin;
    scrollbar-color: rgba(133, 141, 158, 0.45) transparent;
}

[data-bs-theme="dark"] .select2-container--default .select2-results > .select2-results__options {
    background-color: var(--osen-body-bg, #17181e);
}

.select2-container--default .select2-results > .select2-results__options::-webkit-scrollbar {
    width: 6px;
}

.select2-container--default .select2-results > .select2-results__options::-webkit-scrollbar-thumb {
    border-radius: 3px;
    background-color: rgba(133, 141, 158, 0.45);
}

.select2-container--default .select2-results > .select2-results__options::-webkit-scrollbar-track {
    background: transparent;
}

.select2-container--default .select2-results__option {
    padding: 0.45rem 0.6rem;
    border-radius: 0.5rem;
    color: var(--osen-body-color, #4c4c5c);
    font-size: 0.875rem;
}

/* The stock solid-blue highlight is what makes this widget look cheap. */
.select2-container--default .select2-results__option--highlighted[aria-selected],
.select2-container--default .select2-results__option--highlighted[data-selected] {
    background-color: color-mix(in srgb, var(--osen-primary, #465dff) 12%, transparent);
    color: var(--osen-body-color, #4c4c5c);
}

.select2-container--default .select2-results__option[aria-selected="true"],
.select2-container--default .select2-results__option[data-selected="true"] {
    background-color: color-mix(in srgb, var(--osen-primary, #465dff) 8%, transparent);
    color: var(--osen-primary, #465dff);
    font-weight: 600;
}

/* A tick marks what is already chosen, since multi-select hides the
   selection behind a scrolled tag list. */
.select2-container--default .select2-results__option[aria-selected="true"]::after,
.select2-container--default .select2-results__option[data-selected="true"]::after {
    content: "\2713";
    float: right;
    font-weight: 700;
}

.select2-search--dropdown {
    padding: 0.5rem 0.5rem 0.25rem;
}

.select2-search--dropdown .select2-search__field {
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    border-radius: 0.5rem;
    background-color: var(--osen-body-bg, #fafdff);
    color: var(--osen-body-color, #4c4c5c);
}

.select2-container--default .select2-results__message {
    color: var(--osen-secondary-color, #9ba6b7);
    font-size: 0.875rem;
}

/* Count pill on a filter label, so an active filter is obvious when the
   control is collapsed. */
.filter-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.15rem;
    height: 1.15rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    background-color: var(--osen-primary, #465dff);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
}

/* ==========================================================================
   Action menus

   One restrained trigger per row instead of a growing line of tinted icon
   buttons — which stop scaling the moment a row needs more than two actions,
   and pull attention away from the data.
   ========================================================================== */
.action-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    border-radius: 0.5rem;
    background-color: transparent;
    color: var(--osen-secondary-color, #9ba6b7);
    font-size: 1.05rem;
    line-height: 1;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.action-trigger:hover,
.action-trigger:focus-visible,
.action-trigger[aria-expanded="true"] {
    border-color: var(--osen-secondary-border-subtle, var(--osen-border-color, #e7e9eb));
    background-color: var(--osen-tertiary-bg, rgba(133, 141, 158, 0.12));
    color: var(--osen-body-color, #4c4c5c);
}

.action-trigger::after {
    display: none;   /* no Bootstrap caret — the icon is the affordance */
}

.actions-menu {
    --osen-dropdown-min-width: 13rem;
    padding: 0.375rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    border-radius: 0.75rem;
    box-shadow: 0 10px 30px -12px rgba(15, 23, 42, 0.28),
                0 2px 6px -2px rgba(15, 23, 42, 0.12);
}

[data-bs-theme="dark"] .actions-menu {
    box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.6),
                0 2px 6px -2px rgba(0, 0, 0, 0.4);
}

.actions-menu .dropdown-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.625rem;
    border-radius: 0.5rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--action-color, var(--osen-body-color, #4c4c5c));
    white-space: nowrap;
}

.actions-menu .dropdown-item i {
    flex: 0 0 1rem;
    font-size: 1rem;
    color: var(--action-icon, var(--osen-secondary-color, #9ba6b7));
}

.actions-menu .dropdown-item:hover,
.actions-menu .dropdown-item:focus {
    background-color: color-mix(in srgb, var(--action-color, var(--osen-body-color, #4c4c5c)) 9%, transparent);
    color: var(--action-color, var(--osen-body-color, #4c4c5c));
}

.actions-menu .dropdown-item:hover i,
.actions-menu .dropdown-item:focus i {
    color: var(--action-color, var(--osen-body-color, #4c4c5c));
}

/* The action's meaning sets its colour, so destructive choices read as
   destructive before they are clicked. */
.action-primary { --action-color: #4f46e5; --action-icon: #4f46e5; }
.action-success { --action-color: #15803d; --action-icon: #16a34a; }
.action-danger  { --action-color: #dc2626; --action-icon: #dc2626; }
.action-warning { --action-color: #b45309; --action-icon: #d97706; }
.action-info    { --action-color: #0369a1; --action-icon: #0284c7; }

[data-bs-theme="dark"] .action-primary { --action-color: #a5b4fc; --action-icon: #a5b4fc; }
[data-bs-theme="dark"] .action-success { --action-color: #4ade80; --action-icon: #4ade80; }
[data-bs-theme="dark"] .action-danger  { --action-color: #fca5a5; --action-icon: #fca5a5; }
[data-bs-theme="dark"] .action-warning { --action-color: #fcd34d; --action-icon: #fcd34d; }
[data-bs-theme="dark"] .action-info    { --action-color: #7dd3fc; --action-icon: #7dd3fc; }

.actions-menu .dropdown-header {
    padding: 0.375rem 0.625rem 0.25rem;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--osen-secondary-color, #9ba6b7);
}

.actions-menu .dropdown-divider {
    margin: 0.375rem 0.25rem;
    opacity: 0.6;
}

.actions-menu form {
    margin: 0;
}

/* A menu inside a horizontally scrolling table would otherwise be clipped. */
.table-responsive.actions-open {
    overflow: visible;
}

@media (max-width: 767.98px) {
    /* In stacked-card mode the trigger sits alone on its row, so give it a
       label rather than leaving a bare icon floating. */
    .action-trigger {
        width: auto;
        height: 2.375rem;
        padding: 0 0.75rem;
        gap: 0.4rem;
    }

    .action-trigger .action-trigger-label {
        display: inline;
        font-size: 0.875rem;
        font-weight: 500;
    }
}

.action-trigger .action-trigger-label {
    display: none;
}

/* ==========================================================================
   Mobile: stacked tables
   Admin tables are the usual mobile failure point. Add `.table-stack` to a
   table and `data-label="Column name"` to each <td>; below 768px the rows
   collapse into readable cards instead of scrolling sideways.
   ========================================================================== */
@media (max-width: 767.98px) {
    .table-stack thead {
        display: none;
    }

    .table-stack tbody tr {
        display: block;
        margin-bottom: 0.75rem;
        padding: 0.25rem 0.5rem;
        border: 1px solid var(--osen-border-color, #e7e9eb);
        border-radius: 0.5rem;
        background-color: var(--osen-card-bg, var(--osen-body-bg, #fafdff));
    }

    .table-stack tbody td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        padding: 0.4rem 0.25rem;
        border: 0;
        border-bottom: 1px dashed var(--osen-border-color, #e7e9eb);
        white-space: normal !important;
    }

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

    .table-stack tbody td::before {
        content: attr(data-label);
        flex: 0 0 38%;
        font-weight: 600;
        font-size: 0.75rem;
        text-transform: uppercase;
        letter-spacing: 0.02em;
        color: var(--osen-secondary-color, #9ba6b7);
    }

    /* Cells that only hold buttons read better full width. */
    .table-stack tbody td.td-actions {
        justify-content: flex-end;
    }

    .table-stack tbody td.td-actions::before {
        flex: 1 1 auto;
    }

    /* Stacked rows already show one card per person, so a lone checkbox with
       no label reads as a stray tick — give it the row's name instead. */
    .table-stack tbody td.td-check::before {
        content: "Select";
        flex: 0 0 38%;
    }
}

/* ==========================================================================
   Bulk selection
   ========================================================================== */
.td-check {
    width: 2.75rem;
    text-align: center;
}

.bulk-bar {
    padding: 0.25rem 0.5rem 0.25rem 0.75rem;
    border: 1px solid var(--osen-border-color, #eaedf1);
    border-radius: 0.5rem;
    background-color: var(--osen-tertiary-bg, #f9fafb);
}

/* ==========================================================================
   Mobile: comfortable tap targets
   ========================================================================== */
@media (max-width: 767.98px) {
    .btn,
    .form-control,
    .form-select {
        min-height: 44px;
    }

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

    /* Stop iOS Safari zooming the page when a field is focused. */
    .form-control,
    .form-select {
        font-size: 16px;
    }

    .page-title-head {
        align-items: flex-start;
    }

    .card-header .btn {
        width: 100%;
    }

    .card-header > div:last-child {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        width: 100%;
        margin-top: 0.5rem;
    }
}

/* ==========================================================================
   Event context switcher in the topbar
   ========================================================================== */
.event-switcher .topbar-link {
    max-width: 15rem;
}

.event-switcher .event-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ==========================================================================
   "Powered by" credit — admin and public footers share this
   ========================================================================== */
.powered-by {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.375rem;
    font-size: 0.8125rem;
    line-height: 1.35;
}

.powered-by__mark {
    display: inline-flex;
    align-items: center;
}

.powered-by__logo {
    height: 34px;
    width: auto;
    /* The mark sits optically low against small caps text. */
    display: block;
}

/* Both colourways of a mark ship in the markup and CSS picks one, so the swap
   rides the theme toggle instead of a page load. Default is the light ground,
   which is what every one of these surfaces is until somebody flips the
   switch. Used by the footers and by the public header. */
.brand-art--light {
    display: none;
}

html[data-bs-theme="dark"] .brand-art--light {
    display: block;
}

html[data-bs-theme="dark"] .brand-art--dark {
    display: none;
}

.powered-by__name {
    font-weight: 600;
    color: var(--osen-emphasis-color, #313a46);
}

.powered-by__tail {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.powered-by__dot {
    opacity: 0.5;
}

/* Who builds it. Deliberately quieter than the product mark beside it — one
   step down in size and weight — so the footer reads "HeyJoin.me, by Modi
   Infoway" rather than presenting two brands of equal rank. */
.powered-by__maker {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.375rem;
    font-size: 0.9231em;
}

.powered-by__maker-link {
    gap: 0.3rem;
    color: inherit;
}

.powered-by__maker-logo {
    height: 18px;
    width: auto;
    display: block;
}

.powered-by__maker-name {
    font-weight: 600;
}

.powered-by__sep {
    opacity: 0.5;
}

/* On a phone the whole credit would otherwise become four cramped lines;
   dropping the separator and stacking the two claims reads far better. */
@media (max-width: 575.98px) {
    .powered-by {
        justify-content: center;
        text-align: center;
        font-size: 0.75rem;
    }

    .powered-by__tail {
        flex-direction: column;
        gap: 0.125rem;
    }

    .powered-by__dot {
        display: none;
    }

    /* The maker credit stacks the same way, but the separator stays: the
       membership has to keep reading as Modi Infoway's rather than floating
       free under the organiser's event. */
    .powered-by__maker {
        justify-content: center;
    }
}

/* ==========================================================================
   Pagination footer
   ========================================================================== */
.pagination-bar__size {
    width: auto;
    min-width: 7rem;
}

.pagination-bar .pagination {
    margin-bottom: 0;
}

/* On a phone the count and the page links stack; centre both so the footer
   does not read as two ragged left-aligned blocks. */
@media (max-width: 575.98px) {
    .pagination-bar > div {
        justify-content: center;
    }

    .pagination-bar__links {
        width: 100%;
    }

    .pagination-bar__links .pagination {
        justify-content: center;
    }
}

/* ==========================================================================
   Drill-down stat cards

   Every figure on the dashboard opens the list it was counted from, so the
   affordance has to read as clickable without turning the card into a wall
   of blue links.
   ========================================================================== */
.stat-card__headline,
.stat-card__line {
    text-decoration: none;
    border-radius: 0.375rem;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.stat-card__line {
    padding: 0.15rem 0.35rem;
    margin-inline: -0.35rem;
}

.stat-card__headline:hover,
.stat-card__line:hover,
.stat-card__headline:focus-visible,
.stat-card__line:focus-visible {
    background-color: var(--osen-tertiary-bg, #f9fafb);
}

.stat-card__line:hover .text-muted {
    color: var(--osen-body-color, #4c4c5c) !important;
}

/* The arrow stays out of the way until the figure is pointed at. */
.stat-card__go {
    opacity: 0;
    transition: opacity 0.12s ease, transform 0.12s ease;
    transform: translateX(-0.25rem);
}

.stat-card__headline:hover .stat-card__go,
.stat-card__headline:focus-visible .stat-card__go {
    opacity: 1;
    transform: translateX(0);
}

/* Touch devices have no hover, so the cue must always be visible there. */
@media (hover: none) {
    .stat-card__go {
        opacity: 0.5;
        transform: translateX(0);
    }
}

/* ==========================================================================
   Inline toggles

   Used where a single flag is the most common edit — showing or hiding a form
   field, enabling a type — so it is one tap rather than opening an editor.
   ========================================================================== */
.toggle-switch {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding-left: 2.5rem;
    margin-bottom: 0;
}

.toggle-switch .form-check-input {
    margin-left: -2.5rem;
    width: 2rem;
    height: 1.1rem;
    cursor: pointer;
    flex-shrink: 0;
}

.toggle-switch .form-check-label {
    cursor: pointer;
    font-size: 0.8125rem;
    font-weight: 500;
    white-space: nowrap;
}

/* Checked colour follows the meaning of the flag, not one global accent:
   "Shown" is a good state, "Required" is a caution. */
.toggle-switch--success .form-check-input:checked {
    background-color: #16a34a;
    border-color: #16a34a;
}

.toggle-switch--warning .form-check-input:checked {
    background-color: #d97706;
    border-color: #d97706;
}

.toggle-switch--danger .form-check-input:checked {
    background-color: #dc2626;
    border-color: #dc2626;
}

.toggle-switch .form-check-input:disabled {
    opacity: 0.55;
    cursor: progress;
}

/* ==========================================================================
   Sign-in

   A split screen: the story on the left, the form on the right. The left half
   is pure CSS — gradients and a dot grid — so it costs no image requests and
   stays sharp on any display.
   ========================================================================== */
.auth-body {
    margin: 0;
}

.auth-shell {
    display: grid;
    grid-template-columns: 1fr;
    min-height: 100vh;
    min-height: 100dvh;
}

@media (min-width: 992px) {
    .auth-shell {
        grid-template-columns: 1.05fr 1fr;
    }
}

/* --- Left: the showcase ------------------------------------------------- */
.auth-showcase {
    position: relative;
    overflow: hidden;
    flex-direction: column;
    padding: 3.5rem;
    background: linear-gradient(150deg, #0b1533 0%, #14224d 45%, #0a1128 100%);
    color: #eef1f8;
    isolation: isolate;
}

/* --- Living aurora ------------------------------------------------------
   Four blurred colour fields drifting at different speeds. Only `transform`
   is animated — never filter, size or background-position — so the whole
   thing composites on the GPU and costs nothing per frame. `screen` blending
   lets them glow where they overlap instead of muddying into grey. */
.auth-showcase__aurora {
    position: absolute;
    inset: -25%;
    z-index: -1;
    overflow: hidden;
}

.aurora-blob {
    position: absolute;
    border-radius: 50%;
    filter: blur(70px);
    mix-blend-mode: screen;
    will-change: transform;
    opacity: 0.55;
}

.aurora-blob--indigo {
    width: 34rem;
    height: 34rem;
    top: 2%;
    left: 48%;
    background: radial-gradient(circle, #4f6bff 0%, rgba(79, 107, 255, 0) 68%);
    animation: aurora-drift-a 26s ease-in-out infinite;
}

.aurora-blob--violet {
    width: 30rem;
    height: 30rem;
    top: 38%;
    left: 4%;
    background: radial-gradient(circle, #8b5cf6 0%, rgba(139, 92, 246, 0) 68%);
    animation: aurora-drift-b 32s ease-in-out infinite;
}

/* The house red, so the panel belongs to the brand rather than to Bootstrap. */
.aurora-blob--crimson {
    width: 26rem;
    height: 26rem;
    bottom: 4%;
    left: 34%;
    background: radial-gradient(circle, #c81e3a 0%, rgba(200, 30, 58, 0) 68%);
    animation: aurora-drift-c 29s ease-in-out infinite;
    opacity: 0.45;
}

.aurora-blob--teal {
    width: 24rem;
    height: 24rem;
    top: 12%;
    left: 6%;
    background: radial-gradient(circle, #06b6d4 0%, rgba(6, 182, 212, 0) 68%);
    animation: aurora-drift-d 35s ease-in-out infinite;
    opacity: 0.32;
}

@keyframes aurora-drift-a {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    33%      { transform: translate3d(-8%, 12%, 0) scale(1.14); }
    66%      { transform: translate3d(6%, -6%, 0) scale(0.92); }
}

@keyframes aurora-drift-b {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); }
    40%      { transform: translate3d(14%, -10%, 0) scale(0.9); }
    75%      { transform: translate3d(-6%, 8%, 0) scale(1.18); }
}

@keyframes aurora-drift-c {
    0%, 100% { transform: translate3d(0, 0, 0) scale(0.95); }
    45%      { transform: translate3d(-12%, -14%, 0) scale(1.2); }
    80%      { transform: translate3d(8%, 4%, 0) scale(1); }
}

@keyframes aurora-drift-d {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1.1); }
    50%      { transform: translate3d(18%, 16%, 0) scale(0.88); }
}

/* A slow sheen crossing the panel, so the surface reads as lit rather than
   painted. */
.auth-showcase__sheen {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, 0.07) 50%, transparent 70%);
    background-size: 250% 250%;
    animation: aurora-sheen 14s linear infinite;
    pointer-events: none;
}

@keyframes aurora-sheen {
    0%   { background-position: 120% 0; }
    100% { background-position: -20% 0; }
}

/* Motion is decoration here — hold the composition still for anyone who has
   asked their system for less of it. */
@media (prefers-reduced-motion: reduce) {
    .aurora-blob,
    .auth-showcase__sheen {
        animation: none;
    }
}

.auth-showcase__grid {
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image: radial-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px);
    background-size: 22px 22px;
    /* Fades the grid out toward the bottom so it never fights the text. */
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 72%);
    mask-image: linear-gradient(to bottom, #000 0%, transparent 72%);
    opacity: 0.5;
}

.auth-showcase__inner {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    max-width: 34rem;
    margin: auto;
    width: 100%;
}

.auth-showcase__brand {
    margin-bottom: auto;
}

.auth-showcase__logo {
    display: block;
    height: auto;
    width: 11rem;
    max-width: none;
}

.auth-showcase__body {
    padding: 3rem 0;
}

.auth-showcase__title {
    font-size: clamp(1.9rem, 2.6vw, 2.6rem);
    font-weight: 700;
    line-height: 1.18;
    letter-spacing: -0.02em;
    color: #fff;
    margin-bottom: 0.9rem;
}

.auth-showcase__lead {
    font-size: 1rem;
    line-height: 1.6;
    color: rgba(238, 241, 248, 0.72);
    margin-bottom: 2.25rem;
}

.auth-highlights {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 1.15rem;
}

.auth-highlight {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    font-size: 0.9375rem;
}

.auth-highlight strong {
    display: block;
    color: #fff;
    font-weight: 600;
    margin-bottom: 0.15rem;
}

.auth-highlight__detail {
    display: block;
    color: rgba(238, 241, 248, 0.62);
    font-size: 0.875rem;
    line-height: 1.5;
}

.auth-highlight__icon {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.65rem;
    font-size: 1.1rem;
    color: #cdd7ff;
    background-color: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.12);
}

.auth-showcase__foot {
    margin-top: auto;
    font-size: 0.8125rem;
    color: rgba(238, 241, 248, 0.55);
}

.auth-showcase__dot {
    margin: 0 0.4rem;
    opacity: 0.6;
}

/* The maker credit on the dark half. Inherits the foot's muted colour rather
   than taking a link colour, because it is a credit that happens to dial us,
   not a call to action competing with the sign-in button. */
.auth-showcase__maker {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    color: inherit;
    text-decoration: none;
    font-weight: 600;
    transition: color 0.12s ease;
}

.auth-showcase__maker:hover,
.auth-showcase__maker:focus-visible {
    color: rgba(238, 241, 248, 0.9);
}

.auth-showcase__maker-logo {
    height: 1.15em;
    width: auto;
    display: block;
    border-radius: 50%;
}

/* --- Right: the form ---------------------------------------------------- */
.auth-panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1.25rem;
    background-color: var(--osen-body-bg, #fafdff);
}

@media (min-width: 992px) {
    .auth-panel {
        padding: 3rem;
    }
}

.auth-panel__inner {
    width: 100%;
    max-width: 25rem;
}

/* Sign-up: paired fields need the room, so the column uses most of the
   panel instead of the sign-in form's narrow strip. */
.auth-panel--wide .auth-panel__inner {
    max-width: 40rem;
}

@media (min-width: 992px) {
    .auth-panel--wide {
        padding: 3rem 2rem;
    }
}

.auth-panel__brand {
    display: block;
    margin-bottom: 2rem;
    text-align: center;
}

.auth-form__title {
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin-bottom: 0.35rem;
}

.auth-form__sub {
    color: var(--osen-secondary-color, #9ba6b7);
    margin-bottom: 1.75rem;
}

/* Icon inside the control, and a reveal button that does not overlap it. */
.auth-input {
    position: relative;
}

.auth-input__icon {
    position: absolute;
    top: 50%;
    left: 0.85rem;
    transform: translateY(-50%);
    font-size: 1.05rem;
    color: var(--osen-secondary-color, #9ba6b7);
    pointer-events: none;
}

.auth-input .form-control {
    height: 3rem;
    padding-left: 2.6rem;
    padding-right: 2.75rem;
    border-radius: 0.65rem;
}

.auth-input .form-control:focus {
    box-shadow: 0 0 0 0.22rem color-mix(in srgb, var(--osen-primary, #465dff) 16%, transparent);
}

.auth-input__reveal {
    position: absolute;
    top: 50%;
    right: 0.35rem;
    transform: translateY(-50%);
    display: grid;
    place-items: center;
    width: 2.1rem;
    height: 2.1rem;
    padding: 0;
    border: 0;
    border-radius: 0.45rem;
    background: transparent;
    color: var(--osen-secondary-color, #9ba6b7);
    cursor: pointer;
}

.auth-input__reveal:hover,
.auth-input__reveal:focus-visible {
    color: var(--osen-body-color, #4c4c5c);
    background-color: var(--osen-tertiary-bg, #f1f3f7);
}

.auth-capslock {
    margin-top: 0.4rem;
    font-size: 0.8125rem;
    font-weight: 500;
    color: #b45309;
}

.auth-submit {
    height: 3rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    border-radius: 0.65rem;
    font-weight: 600;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.auth-submit:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px color-mix(in srgb, var(--osen-primary, #465dff) 32%, transparent);
}

.auth-submit i {
    transition: transform 0.12s ease;
}

.auth-submit:hover i {
    transform: translateX(2px);
}

.auth-form__help,
.auth-panel__foot {
    text-align: center;
    font-size: 0.8125rem;
    color: var(--osen-secondary-color, #9ba6b7);
}

.auth-form__help {
    margin: 1.5rem 0 0;
}

.auth-panel__foot {
    margin: 2.5rem 0 0;
}

/* Someone who prefers less motion gets the design without the movement. */
@media (prefers-reduced-motion: reduce) {
    .auth-submit,
    .auth-submit i {
        transition: none;
    }

    .auth-submit:hover {
        transform: none;
    }
}

/* A wide lockup (circle + stacked wordmark), so it is sized by width — set by
   height alone the wordmark renders a couple of pixels tall. */
.auth-panel__logo {
    height: auto;
    width: 8rem;
    max-width: 60%;
}

/* Grid and flex children default to min-width:auto, so a long unbroken line —
   the "Powered by ... Softagone Technologies LLP" credit — can push the track
   wider than the viewport and scroll the whole page sideways on a phone. */
.auth-showcase,
.auth-panel {
    min-width: 0;
}

.auth-panel__inner,
.auth-panel__foot,
.auth-form__help {
    min-width: 0;
    overflow-wrap: break-word;
}


/* On a narrow phone the 25rem cap plus panel padding is wider than the screen,
   which pushes the whole page sideways. Below sm the form simply fills it. */
@media (max-width: 575.98px) {
    .auth-panel {
        padding: 1.75rem 1rem;
    }

    .auth-panel__inner {
        max-width: 100%;
    }
}

/* The heart in the sign-in headline. Drawn as an SVG so it takes the brand
   red and renders identically everywhere — the emoji does neither. */
.auth-heart {
    display: inline-block;
    width: 0.92em;
    height: 0.92em;
    vertical-align: -0.06em;
    color: #e11d48;
}

.auth-heart svg {
    display: block;
    width: 100%;
    height: 100%;
    filter: drop-shadow(0 0 12px rgba(225, 29, 72, 0.55));
    animation: auth-heartbeat 2.4s ease-in-out infinite;
    transform-origin: center;
}

@keyframes auth-heartbeat {
    0%, 100%   { transform: scale(1); }
    14%        { transform: scale(1.16); }
    28%        { transform: scale(1); }
    42%        { transform: scale(1.1); }
    56%        { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .auth-heart svg {
        animation: none;
    }
}

.auth-showcase__madeby {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: rgba(238, 241, 248, 0.78);
    font-weight: 500;
}

/* ==========================================================================
   Sidebar aurora

   The sign-in cover's treatment, dialled well down. The sidebar is on screen
   on every admin page all day, so this is deliberately quieter and slower
   than the login: three fields instead of four, longer cycles, lower opacity.
   Only `transform` animates, so it composites on the GPU and never triggers
   layout or paint.
   ========================================================================== */
.sidenav-aurora {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
    /* Light menus have no dark ground for the colour to glow against, so the
       effect only paints on the dark one. */
    display: none;
}

[data-menu-color="dark"] .sidenav-aurora {
    display: block;
}

/* The menu's own content sits above the wash.

   Deliberately NOT including .button-sm-hover here: the theme already gives
   the collapse toggle `position: absolute; right: 12px; top: 0; z-index: 1`,
   so it clears the aurora by itself. Adding it to this rule overrode that
   absolute placement with `relative` and dropped the button out of its corner
   into normal flow, leaving it floating under the logo. */
.sidenav-menu > .logo,
.sidenav-menu > [data-simplebar] {
    position: relative;
    z-index: 1;
}

.sidenav-aurora__blob {
    position: absolute;
    border-radius: 50%;
    filter: blur(55px);
    mix-blend-mode: screen;
    will-change: transform;
}

.sidenav-aurora__blob--indigo {
    width: 20rem;
    height: 20rem;
    top: -4rem;
    left: -6rem;
    background: radial-gradient(circle, #4f6bff 0%, rgba(79, 107, 255, 0) 68%);
    opacity: 0.4;
    animation: sidenav-drift-a 38s ease-in-out infinite;
}

.sidenav-aurora__blob--violet {
    width: 18rem;
    height: 18rem;
    top: 38%;
    right: -7rem;
    background: radial-gradient(circle, #8b5cf6 0%, rgba(139, 92, 246, 0) 68%);
    opacity: 0.32;
    animation: sidenav-drift-b 45s ease-in-out infinite;
}

/* The house red, low and slow, so the rail reads as Modi Infoway's. */
.sidenav-aurora__blob--crimson {
    width: 17rem;
    height: 17rem;
    bottom: -5rem;
    left: -4rem;
    background: radial-gradient(circle, #c81e3a 0%, rgba(200, 30, 58, 0) 68%);
    opacity: 0.3;
    animation: sidenav-drift-c 52s ease-in-out infinite;
}

@keyframes sidenav-drift-a {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    50%      { transform: translate3d(18%, 26%, 0) scale(1.15); }
}

@keyframes sidenav-drift-b {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1.08); }
    50%      { transform: translate3d(-20%, -22%, 0) scale(0.9); }
}

@keyframes sidenav-drift-c {
    0%, 100% { transform: translate3d(0, 0, 0) scale(0.95); }
    50%      { transform: translate3d(14%, -28%, 0) scale(1.2); }
}

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

/* Tighten the capability list so it reads as a specification rather than a
   paragraph: the feature name leads, the description sits quietly under it. */
.auth-highlight strong {
    font-size: 0.9375rem;
    letter-spacing: -0.005em;
    margin-bottom: 0.2rem;
}

.auth-highlight__detail {
    /* Wide enough that each item settles on two lines, so the three read as a
       compact set rather than a tall wall of text. */
    max-width: 42ch;
}

/* ==========================================================================
   Public event landing page

   Deliberately not built from admin cards. A stack of identical bordered
   boxes with grey headers reads as a database screen; a landing page needs
   rhythm — a full-bleed hero, a dark authority band, then light sections with
   one clear conversion block carrying the most weight.

   Every colour derives from --lp-accent, set inline from the event's own
   theme_color, so a second event on the same install looks like itself.
   ========================================================================== */
.lp {
    --lp-ink: #0b1533;
    --lp-ink-soft: #14224d;
}

/* --- Hero --------------------------------------------------------------- */
.lp-hero {
    background-color: var(--lp-ink);
}

.lp-hero__art {
    display: block;
    width: 100%;
    height: auto;
    /* No max-height and no object-fit: the banner is approved artwork with
       its own composition, so it scales whole rather than being cropped. */
}

/* --- Authority band ----------------------------------------------------- */
.lp-factbar {
    background: linear-gradient(135deg, var(--lp-ink) 0%, var(--lp-ink-soft) 100%);
    color: #eef1f8;
    border-bottom: 3px solid var(--lp-accent);
}

.lp-factbar__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.25rem;
    padding: 1.1rem 0;
}

.lp-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 1.75rem;
    flex: 1 1 auto;
    min-width: 0;
}

.lp-fact {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    min-width: 0;
}

.lp-fact__icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 0.6rem;
    font-size: 1.05rem;
    color: #fff;
    background-color: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.14);
}

.lp-fact__label {
    display: block;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(238, 241, 248, 0.55);
}

.lp-fact__value {
    display: block;
    font-size: 0.9375rem;
    font-weight: 600;
    color: #fff;
}

.lp-fact__muted {
    font-weight: 400;
    color: rgba(238, 241, 248, 0.6);
}

.lp-factbar__action {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-left: auto;
}

.lp-countdown {
    text-align: right;
    line-height: 1.15;
}

.lp-countdown__value {
    font-size: 1.5rem;
    font-weight: 700;
    color: #fff;
}

.lp-countdown__unit {
    display: block;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(238, 241, 248, 0.6);
}

/* --- The call to action ------------------------------------------------- */
.lp-cta {
    --lp-cta-shadow: color-mix(in srgb, var(--lp-accent) 38%, transparent);
    background-color: var(--lp-accent);
    border: 1px solid var(--lp-accent);
    color: #fff;
    font-weight: 600;
    border-radius: 0.6rem;
    padding-inline: 1.5rem;
    transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
}

.lp-cta:hover,
.lp-cta:focus-visible {
    color: #fff;
    filter: brightness(1.08);
    transform: translateY(-1px);
    box-shadow: 0 8px 22px var(--lp-cta-shadow);
}

.lp-cta--block {
    display: block;
    width: 100%;
}

/* --- Identity ----------------------------------------------------------- */
.lp-intro {
    text-align: center;
    max-width: 44rem;
    margin: 0 auto 2.5rem;
}

.lp-intro__title {
    font-size: clamp(1.6rem, 3.4vw, 2.4rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    margin-bottom: 0.5rem;
}

.lp-intro__tagline {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--lp-accent);
    margin-bottom: 0.5rem;
}

.lp-intro__lead {
    font-size: 1rem;
    color: var(--osen-secondary-color, #9ba6b7);
    margin-bottom: 0;
}

.lp-referral {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1rem;
    padding: 0.45rem 0.9rem;
    border-radius: 2rem;
    font-size: 0.875rem;
    background-color: color-mix(in srgb, var(--lp-accent) 10%, transparent);
    color: var(--lp-accent);
}

/* --- Conversion block --------------------------------------------------- */
.lp-register {
    max-width: 34rem;
    margin: 0 auto 3rem;
    padding: 2.25rem;
    text-align: center;
    border-radius: 1rem;
    background-color: var(--osen-secondary-bg, #fff);
    border: 1px solid var(--osen-border-color, #e7e9eb);
    /* Lifted off the page: this is the one thing the visitor came to do. */
    box-shadow: 0 18px 45px rgba(11, 21, 51, 0.09);
}

/* Room for a row of tiers. At 34rem two cards cannot sit side by side, and
   stacking them turns a comparison into a memory test. */
.lp-register--choices {
    max-width: 46rem;
}

.lp-register__eyebrow {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--lp-accent);
    margin-bottom: 0.35rem;
}

.lp-register__title {
    font-size: 1.375rem;
    font-weight: 700;
    margin-bottom: 0.75rem;
}

.lp-register__note {
    color: var(--osen-secondary-color, #9ba6b7);
    margin-bottom: 1.25rem;
}

.lp-register__closed {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.65rem;
    text-align: left;
    color: var(--osen-secondary-color, #9ba6b7);
}

.lp-register__closed i {
    font-size: 1.35rem;
}

.lp-price {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    margin-bottom: 1.35rem;
}

.lp-price__label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--osen-secondary-color, #9ba6b7);
}

.lp-price__value {
    font-size: 2.25rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
}

.lp-assurances {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.35rem 1.1rem;
    list-style: none;
    padding: 0;
    margin: 1.25rem 0 0;
    font-size: 0.8125rem;
    color: var(--osen-secondary-color, #9ba6b7);
}

.lp-assurances li {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* Several types on offer: a comparable row rather than stacked cards.
   These sit directly under a loud hero, so a pair of plain outlined boxes
   reads as an afterthought. Depth, a real price hierarchy, and one clear
   action each — the way a ticket is actually chosen. */
.lp-tiers {
    display: grid;
    gap: 1.125rem;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    text-align: left;
}

.lp-tiers--single {
    max-width: 24rem;
    margin-inline: auto;
}

.lp-tier {
    --lp-tier-line: color-mix(in srgb, var(--lp-accent) 22%, transparent);
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 1.6rem 1.5rem 1.5rem;
    border-radius: 1.1rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    background:
        linear-gradient(180deg,
            color-mix(in srgb, var(--lp-accent) 4%, transparent) 0%,
            transparent 42%),
        /* --osen-card-bg is scoped by Bootstrap to .card and resolves to
           nothing here, which fell back to white and put white cards on a
           near-black page. --osen-body-bg is set at the root and sits just off
           the panel in both themes, so the cards read as inset either way. */
        var(--osen-body-bg, #fff);
    box-shadow: 0 1px 2px rgba(11, 21, 51, 0.04);
    overflow: hidden;
    transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}

/* A hairline of the event's own colour along the top edge — enough to feel
   considered, short of the ribbons and badges that read as cheap. */
.lp-tier::before {
    content: '';
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    background: linear-gradient(90deg,
        var(--lp-accent) 0%,
        color-mix(in srgb, var(--lp-accent) 45%, transparent) 100%);
}

.lp-tier:hover {
    transform: translateY(-3px);
    border-color: var(--lp-tier-line);
    box-shadow: 0 18px 38px -22px rgba(11, 21, 51, 0.45);
}

.lp-tier.is-full {
    opacity: 0.72;
}

.lp-tier.is-full:hover {
    transform: none;
    box-shadow: 0 1px 2px rgba(11, 21, 51, 0.04);
}

.lp-tier__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.85rem;
}

.lp-tier__name {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--osen-secondary-color, #9ba6b7);
    margin: 0;
}

.lp-tier__flag {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    padding: 0.2rem 0.5rem;
    border-radius: 0.35rem;
    color: var(--osen-secondary-color, #9ba6b7);
    background: color-mix(in srgb, var(--osen-secondary-color, #9ba6b7) 12%, transparent);
    white-space: nowrap;
}

.lp-tier__price {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    margin: 0 0 0.35rem;
}

.lp-tier__amount {
    font-size: 2.35rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
}

.lp-tier__per {
    font-size: 0.8125rem;
    color: var(--osen-secondary-color, #9ba6b7);
}

.lp-tier__deposit {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--lp-accent);
    margin: 0 0 0.75rem;
}

.lp-tier__note {
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--osen-secondary-color, #9ba6b7);
    margin: 0 0 1rem;
}

.lp-tier__perks {
    list-style: none;
    padding: 0;
    margin: 0 0 1.35rem;
    display: grid;
    gap: 0.45rem;
    font-size: 0.8125rem;
    color: var(--osen-body-color, #313a46);
}

.lp-tier__perks li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}

.lp-tier__perks i {
    flex: none;
    margin-top: 0.1rem;
    font-size: 0.95rem;
    color: var(--lp-accent);
}

/* One action per card, sized for a thumb. */
.lp-tier__action {
    --lp-tier-glow: color-mix(in srgb, var(--lp-accent) 38%, transparent);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: auto;
    padding: 0.8rem 1.15rem;
    border-radius: 0.7rem;
    background-color: var(--lp-accent);
    color: #fff;
    font-weight: 600;
    font-size: 0.9375rem;
    text-decoration: none;
    transition: filter 0.14s ease, box-shadow 0.14s ease, transform 0.14s ease;
}

.lp-tier__action:hover,
.lp-tier__action:focus-visible {
    color: #fff;
    filter: brightness(1.08);
    box-shadow: 0 10px 24px -8px var(--lp-tier-glow);
}

.lp-tier__action i {
    transition: transform 0.14s ease;
}

.lp-tier:hover .lp-tier__action i {
    transform: translateX(3px);
}

.lp-tier__action--full {
    background: var(--osen-secondary-bg, #eef2f7);
    color: var(--osen-secondary-color, #9ba6b7);
    justify-content: center;
    cursor: not-allowed;
}

.lp-tier__action--full:hover {
    filter: none;
    box-shadow: none;
}

@media (max-width: 575.98px) {
    .lp-tier {
        padding: 1.35rem 1.25rem 1.25rem;
    }

    .lp-tier__amount {
        font-size: 2rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .lp-tier,
    .lp-tier__action,
    .lp-tier__action i {
        transition: none;
    }

    .lp-tier:hover {
        transform: none;
    }
}

/* --- Content sections --------------------------------------------------- */
.lp-section {
    margin-bottom: 3rem;
}

.lp-section__title {
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    text-align: center;
    margin-bottom: 1.75rem;
}

.lp-section--dark {
    padding: 2.5rem 1.5rem;
    border-radius: 1rem;
    background: linear-gradient(135deg, var(--lp-ink) 0%, var(--lp-ink-soft) 100%);
    color: #eef1f8;
}

.lp-section--dark .lp-section__title {
    color: #fff;
}

.lp-features {
    display: grid;
    gap: 1.25rem;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.lp-features--single {
    max-width: 34rem;
    margin-inline: auto;
    text-align: center;
}

.lp-features--single .lp-feature__icon {
    margin-inline: auto;
}

.lp-feature__icon {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    margin-bottom: 0.75rem;
    border-radius: 0.75rem;
    font-size: 1.3rem;
    color: var(--lp-accent);
    background-color: color-mix(in srgb, var(--lp-accent) 12%, transparent);
}

.lp-features--onDark .lp-features--single {
    max-width: 34rem;
    margin-inline: auto;
    text-align: center;
}

.lp-features--single .lp-feature__icon {
    margin-inline: auto;
}

.lp-feature__icon {
    color: #fff;
    background-color: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.14);
}

.lp-feature__heading {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 0.3rem;
}

.lp-feature__body {
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--osen-secondary-color, #9ba6b7);
    margin-bottom: 0;
}

.lp-features--onDark .lp-feature__body {
    color: rgba(238, 241, 248, 0.66);
}

.lp-audience {
    display: grid;
    gap: 0.75rem;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.lp-audience__item {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    padding: 0.85rem 1rem;
    border-radius: 0.65rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
}

.lp-audience__item i {
    color: var(--lp-accent);
    font-size: 1.15rem;
    flex: 0 0 auto;
    margin-top: 0.1rem;
}

.lp-audience__item span {
    display: block;
    font-size: 0.875rem;
    color: var(--osen-secondary-color, #9ba6b7);
}

.lp-prose {
    max-width: 44rem;
    margin: 0 auto;
    white-space: pre-line;
    line-height: 1.7;
}

.lp-faq {
    max-width: 44rem;
    margin: 0 auto;
}

.lp-faq .accordion-button {
    font-weight: 600;
}

/* --- Organisers --------------------------------------------------------- */
.lp-address {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 0.5rem;
    text-align: center;
    color: var(--osen-secondary-color, #9ba6b7);
    margin-bottom: 1.5rem;
}

.lp-contacts {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.lp-contact {
    display: flex;
    gap: 0.9rem;
    padding: 1.1rem;
    border-radius: 0.75rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
}

.lp-contact__avatar {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    font-weight: 700;
    color: #fff;
    background-color: var(--lp-accent);
}

.lp-contact__body strong {
    display: block;
}

.lp-contact__role {
    display: block;
    font-size: 0.8125rem;
    color: var(--osen-secondary-color, #9ba6b7);
    margin-bottom: 0.5rem;
}

.lp-contact__links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 0.9rem;
    font-size: 0.8125rem;
}

.lp-contact__links a {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    text-decoration: none;
}

/* --- Pinned mobile CTA -------------------------------------------------- */
.lp-sticky {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030;
    padding: 0.65rem 1rem calc(0.65rem + env(safe-area-inset-bottom));
    background-color: var(--osen-secondary-bg, #fff);
    border-top: 1px solid var(--osen-border-color, #e7e9eb);
    box-shadow: 0 -6px 24px rgba(11, 21, 51, 0.1);
}

.lp-sticky__inner {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.lp-sticky__price {
    line-height: 1.2;
    min-width: 0;
}

.lp-sticky__price strong {
    font-size: 1.15rem;
}

.lp-sticky__label {
    display: block;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--osen-secondary-color, #9ba6b7);
}

.lp-sticky .lp-cta {
    margin-left: auto;
    white-space: nowrap;
}

/* --- Narrow screens ----------------------------------------------------- */
@media (max-width: 767.98px) {
    .lp-factbar__inner {
        gap: 1rem;
    }

    .lp-facts {
        gap: 0.9rem;
        width: 100%;
    }

    .lp-factbar__action {
        width: 100%;
        margin-left: 0;
        justify-content: space-between;
    }

    .lp-countdown {
        text-align: left;
    }

    .lp-register {
        padding: 1.5rem 1.25rem;
    }

    .lp-section--dark {
        padding: 1.75rem 1.15rem;
    }

    /* Room for the pinned bar so it never covers the last section. */
    .lp:last-of-type {
        padding-bottom: 4.5rem;
    }
}

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

    .lp-cta:hover {
        transform: none;
    }
}

/* The vendor mark dials the vendor, so it needs to look tappable and carry a
   proper touch target on a phone. */
.powered-by__link {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem;
    margin: -0.15rem;
    border-radius: 0.35rem;
    text-decoration: none;
    transition: opacity 0.12s ease;
}

.powered-by__link:hover,
.powered-by__link:focus-visible {
    opacity: 0.75;
}

/* The pinned CTA is fixed to the viewport, so without this it sits on top of
   the footer and hides the credit line entirely on a phone. The class is put
   on <body> by the landing script only when the bar is actually rendered, so
   no other page reserves space it does not need. */
@media (max-width: 991.98px) {
    body.has-sticky-cta {
        padding-bottom: 4.75rem;
    }
}

/* A 12% tint is invisible against white at this size — the icon tile read as
   an empty gap above each heading. */
.lp-feature__icon {
    background-color: color-mix(in srgb, var(--lp-accent) 15%, #fff);
}

/* ==========================================================================
   Scan result

   A coloured edge on the sheet so "let them in" or "stop" registers before
   any of the words do — gate staff read this at arm's length, in a queue.
   ========================================================================== */
.scan-result {
    border: 0;
    border-top: 5px solid var(--scan-tone, var(--osen-border-color, #e7e9eb));
    border-radius: 0.9rem;
    overflow: hidden;
}

.scan-result--success { --scan-tone: #16a34a; }
.scan-result--danger  { --scan-tone: #dc2626; }
.scan-result--warning { --scan-tone: #d97706; }
.scan-result--info    { --scan-tone: #0284c7; }
.scan-result--primary { --scan-tone: #4f46e5; }
.scan-result--secondary { --scan-tone: #64748b; }

#result-body .result-icon {
    font-size: 3rem;
    line-height: 1;
}

/* ==========================================================================
   Poster photo framing

   A live circular preview of exactly what the compositor will cut out, so the
   member sees the crop before committing rather than discovering afterwards
   that the poster took the top of their head.
   ========================================================================== */
.poster-crop__stage {
    position: relative;
    width: 100%;
    max-width: 20rem;
    margin: 0 auto;
    aspect-ratio: 1;
    border-radius: 50%;
    overflow: hidden;
    background-color: var(--osen-tertiary-bg, #f1f3f7);
    cursor: grab;
    touch-action: none;
}

.poster-crop__stage:active {
    cursor: grabbing;
}

.poster-crop__canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* A ring echoing the template's gold circle, so the preview reads as the
   poster rather than as a plain thumbnail. */
.poster-crop__ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    pointer-events: none;
    box-shadow: inset 0 0 0 4px rgba(212, 160, 23, 0.9),
                inset 0 0 0 6px rgba(255, 255, 255, 0.35);
}

/* ==========================================================================
   Landing page, second pass

   What made the first version read as unfinished, in order of damage:

   1. Body copy sat on --osen-secondary-color (#9ba6b7). That is a *label*
      grey. Paragraphs set in it look faded rather than quiet, and on a phone
      in daylight they are close to unreadable. Copy now uses a proper ink
      colour and the pale grey is reserved for labels.
   2. Features were bare icon-and-text on a flat page, so a section of them
      read as a bulleted list. They are surfaces now.
   3. Icon tiles were a 15% tint at 2.75rem — grey smudges. Bigger, stronger,
      with a defined edge.
   4. Sections opened straight onto a heading with no structure above it.
   ========================================================================== */
.lp {
    /* Body copy. Dark enough to read, soft enough not to compete with headings. */
    --lp-ink-body: #4a5568;
    --lp-ink-quiet: #77808f;
    --lp-line: #e6e9ef;
    --lp-surface: #ffffff;
}

[data-bs-theme="dark"] .lp {
    --lp-ink-body: #b6bece;
    --lp-ink-quiet: #8b94a5;
    --lp-line: #2b3040;
    --lp-surface: #1b1e2b;
}

/* --- Section structure --------------------------------------------------- */
.lp-section__eyebrow {
    text-align: center;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--lp-accent);
    margin-bottom: 0.5rem;
}

.lp-section__title {
    margin-bottom: 2rem;
}

/* A short accent rule under the title gives the section a spine. */
.lp-section__title::after {
    content: "";
    display: block;
    width: 2.5rem;
    height: 3px;
    margin: 0.75rem auto 0;
    border-radius: 3px;
    background-color: var(--lp-accent);
}

.lp-section--dark .lp-section__eyebrow {
    color: #ffffff;
    opacity: 0.65;
}

.lp-section--dark .lp-section__title::after {
    background-color: rgba(255, 255, 255, 0.4);
}

/* --- Intro --------------------------------------------------------------- */
.lp-intro__lead {
    font-size: 1.0625rem;
    line-height: 1.7;
    color: var(--lp-ink-body);
    max-width: 40rem;
    margin-inline: auto;
}

/* --- Feature cards ------------------------------------------------------- */
.lp-feature {
    padding: 1.5rem;
    border-radius: 0.9rem;
    border: 1px solid var(--lp-line);
    background-color: var(--lp-surface);
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.lp-feature:hover {
    transform: translateY(-2px);
    border-color: color-mix(in srgb, var(--lp-accent) 35%, var(--lp-line));
    box-shadow: 0 12px 30px rgba(11, 21, 51, 0.08);
}

.lp-feature__icon {
    width: 3.25rem;
    height: 3.25rem;
    margin-bottom: 1rem;
    border-radius: 0.85rem;
    font-size: 1.5rem;
    color: #fff;
    /* Solid accent rather than a tint: at 15% the tile read as a grey smudge
       and the icon inside it disappeared. */
    background: linear-gradient(135deg,
        var(--lp-accent) 0%,
        color-mix(in srgb, var(--lp-accent) 72%, #000) 100%);
    box-shadow: 0 6px 16px color-mix(in srgb, var(--lp-accent) 30%, transparent);
}

.lp-feature__heading {
    font-size: 1.0625rem;
    font-weight: 650;
    letter-spacing: -0.01em;
    margin-bottom: 0.4rem;
}

.lp-feature__body {
    font-size: 0.9375rem;
    line-height: 1.65;
    color: var(--lp-ink-body);
    margin-bottom: 0;
}

/* --- Agenda timeline ----------------------------------------------------- */
.lp-agenda {
    list-style: none;
    margin: 0 auto;
    padding: 0;
    max-width: 34rem;
    position: relative;
}

.lp-agenda__item {
    position: relative;
    display: flex;
    gap: 1rem;
    padding-bottom: 1.75rem;
}

.lp-agenda__item:last-child {
    padding-bottom: 0;
}

/* The thread between steps — this is what turns a list into a running order. */
.lp-agenda__item:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 1.125rem;
    top: 2.5rem;
    bottom: 0.35rem;
    width: 2px;
    background: linear-gradient(to bottom,
        rgba(255, 255, 255, 0.28),
        rgba(255, 255, 255, 0.06));
}

.lp-agenda__marker {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    font-size: 0.875rem;
    font-weight: 700;
    color: #fff;
    background-color: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.28);
}

.lp-agenda__body {
    padding-top: 0.25rem;
    min-width: 0;
}

.lp-agenda__heading {
    font-size: 1.0625rem;
    font-weight: 600;
    color: #fff;
    margin-bottom: 0.2rem;
}

.lp-agenda__detail {
    font-size: 0.9375rem;
    line-height: 1.6;
    color: rgba(238, 241, 248, 0.7);
    margin-bottom: 0;
}

/* --- Audience ------------------------------------------------------------ */
.lp-audience__item {
    padding: 1rem 1.15rem;
    border-radius: 0.75rem;
    background-color: var(--lp-surface);
    transition: border-color 0.15s ease;
}

.lp-audience__item:hover {
    border-color: color-mix(in srgb, var(--lp-accent) 35%, var(--lp-line));
}

.lp-audience__item strong {
    font-weight: 600;
}

.lp-audience__item span {
    color: var(--lp-ink-body);
    line-height: 1.55;
}

/* --- Contacts ------------------------------------------------------------ */
.lp-contact {
    background-color: var(--lp-surface);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.lp-contact:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 30px rgba(11, 21, 51, 0.08);
}

.lp-contact__role {
    color: var(--lp-ink-quiet);
}

.lp-address {
    color: var(--lp-ink-body);
}

.lp-prose {
    color: var(--lp-ink-body);
}

.lp-register__note {
    color: var(--lp-ink-body);
}

/* --- Phones -------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .lp-feature {
        padding: 1.25rem;
    }

    .lp-feature__icon {
        width: 2.75rem;
        height: 2.75rem;
        font-size: 1.25rem;
        margin-bottom: 0.75rem;
    }

    .lp-section__title {
        margin-bottom: 1.5rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .lp-feature,
    .lp-contact {
        transition: none;
    }

    .lp-feature:hover,
    .lp-contact:hover {
        transform: none;
    }
}

/* ==========================================================================
   Fact bar, second pass

   What was wrong: three facts crammed into a wrapping flex row, so on a phone
   Date and Time sat side by side at half width while Venue took a full line —
   an accidental layout, not a chosen one. Labels were 11px and the values
   fought them for space. The countdown and the button then shared a row with
   nothing separating them.

   Now: one fact per row on a phone with hairline rules between, three across
   with vertical dividers from md up, and the action block sits on its own
   surface so it reads as the thing to do rather than a fourth fact.
   ========================================================================== */
.lp-factbar {
    /* A touch of depth under the banner, rather than a flat slab. */
    background:
        radial-gradient(120% 140% at 15% 0%, rgba(79, 107, 255, 0.22) 0%, transparent 55%),
        linear-gradient(135deg, var(--lp-ink) 0%, var(--lp-ink-soft) 100%);
    border-bottom: 3px solid var(--lp-accent);
}

.lp-factbar__inner {
    display: grid;
    gap: 0;
    padding: 0;
}

.lp-facts {
    display: grid;
    grid-template-columns: 1fr;
    margin: 0;
    padding: 0;
}

.lp-fact {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.9rem 0;
    min-width: 0;
}

/* Hairlines between stacked facts. Lighter than a border so the bar keeps
   feeling like one surface rather than a table. */
.lp-fact + .lp-fact {
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.lp-fact__icon {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.7rem;
    font-size: 1.15rem;
    background-color: rgba(255, 255, 255, 0.09);
    border: 1px solid rgba(255, 255, 255, 0.15);
}

.lp-fact__text {
    min-width: 0;
}

.lp-fact__label {
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: rgba(238, 241, 248, 0.5);
    margin-bottom: 0.1rem;
}

.lp-fact__value {
    margin: 0;
    font-size: 1rem;
    font-weight: 650;
    letter-spacing: -0.01em;
    color: #fff;
    line-height: 1.3;
}

/* --- The action block ----------------------------------------------------- */
.lp-factbar__action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin: 0 0 1rem;
    padding: 0.85rem 1rem;
    border-radius: 0.85rem;
    background-color: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.12);
}

.lp-countdown {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    text-align: left;
}

.lp-countdown__value {
    font-size: 1.75rem;
    font-weight: 750;
    letter-spacing: -0.03em;
    line-height: 1;
    color: #fff;
}

.lp-countdown__unit {
    display: block;
    max-width: 4.5rem;
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    line-height: 1.2;
    color: rgba(238, 241, 248, 0.55);
}

.lp-cta--bar {
    flex: 0 0 auto;
    padding-block: 0.65rem;
    font-size: 0.9375rem;
}

/* --- md and up: three across, action on the right ------------------------- */
@media (min-width: 768px) {
    .lp-factbar__inner {
        grid-template-columns: 1fr auto;
        align-items: center;
        gap: 1.75rem;
        padding: 1.1rem 0;
    }

    /* Sized to content, not equal thirds: an equal split gave "19 Sep 2026"
       the same width as "Hotel Keshwaras, Jamnagar", so the short fact had
       room to spare while the long one wrapped mid-word. */
    .lp-facts {
        grid-template-columns: repeat(3, auto);
        justify-content: start;
    }

    .lp-fact {
        padding: 0 1.25rem 0 0;
    }

    /* Vertical dividers instead of the stacked hairlines. */
    .lp-fact + .lp-fact {
        border-top: 0;
        border-left: 1px solid rgba(255, 255, 255, 0.1);
        padding-left: 1.25rem;
    }

    /* Date and time are short and read badly broken across lines. */
    .lp-fact__value {
        white-space: nowrap;
    }

    /* The venue is the one that can genuinely be long, so it keeps the right
       to wrap — bounded, so it cannot crowd out the action block. */
    .lp-fact:last-child .lp-fact__value {
        white-space: normal;
        max-width: 15rem;
    }

    .lp-factbar__action {
        margin: 0;
    }

    .lp-countdown__unit {
        max-width: none;
    }
}

/* ==========================================================================
   Organiser photographs
   ========================================================================== */
.lp-contact__avatar--photo {
    object-fit: cover;
    /* An uploaded photo is rarely square; cover keeps faces from stretching. */
    background-color: var(--lp-line);
}

.contact-photo-preview {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 3.25rem;
    height: 3.25rem;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--osen-border-color, #e7e9eb);
}

.contact-photo-preview--empty {
    color: var(--osen-secondary-color, #9ba6b7);
    background-color: var(--osen-tertiary-bg, #f1f3f7);
    font-size: 1.25rem;
}

/* ==========================================================================
   Radio groups on the registration forms

   A dropdown hides two choices behind a tap and a scroll, and on a phone it
   opens a wheel over half the screen to answer a question you could have
   answered by looking at it. These are tiles instead: the whole thing is the
   target, and the chosen one is obvious from across a desk.
   ========================================================================== */
.radio-group {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: 0.55rem;
}

.radio-option {
    position: relative;
}

/* Kept in the document rather than display:none, so it is still focusable and
   still announced — the tile is decoration over a real radio button. */
.radio-option .form-check-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.radio-option .form-check-label {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    border-radius: 0.7rem;
    background-color: var(--osen-secondary-bg, #fff);
    font-weight: 500;
    cursor: pointer;
    transition: border-color 0.14s ease, background-color 0.14s ease, box-shadow 0.14s ease;
}

.radio-option__mark {
    flex: none;
    width: 1.15rem;
    height: 1.15rem;
    border-radius: 50%;
    border: 1.5px solid var(--osen-border-color, #c6ccdd);
    background-color: var(--osen-body-bg, #fff);
    transition: border-color 0.14s ease, box-shadow 0.14s ease;
}

.radio-option .form-check-input:hover + .form-check-label {
    border-color: color-mix(in srgb, var(--lvb-accent, #465dff) 40%, var(--osen-border-color, #e7e9eb));
}

/* The dot is an inset shadow rather than a pseudo-element, so it grows from
   the middle of the ring instead of being laid on top of it. */
.radio-option .form-check-input:checked + .form-check-label .radio-option__mark {
    border-color: var(--lvb-accent, #465dff);
    box-shadow: inset 0 0 0 0.28rem var(--lvb-accent, #465dff);
}

.radio-option .form-check-input:checked + .form-check-label {
    border-color: var(--lvb-accent, #465dff);
    background-color: color-mix(in srgb, var(--lvb-accent, #465dff) 7%, var(--osen-secondary-bg, #fff));
    box-shadow: 0 1px 2px color-mix(in srgb, var(--lvb-accent, #465dff) 18%, transparent);
}

/* Keyboard focus has to be visible on the tile, because the input it belongs
   to is invisible. */
.radio-option .form-check-input:focus-visible + .form-check-label {
    outline: 2px solid var(--lvb-accent, #465dff);
    outline-offset: 2px;
}

.radio-option .form-check-input.is-invalid + .form-check-label {
    border-color: var(--osen-danger, #dc3545);
}

@media (prefers-reduced-motion: reduce) {
    .radio-option .form-check-label,
    .radio-option__mark {
        transition: none;
    }
}

/* ==========================================================================
   Sponsor logo preview on the event form

   Drawn in the same frame the public page uses, so a wide logo shown in a
   square, or a square one in a circle, is noticed before it goes live.
   Logos are fitted, never cropped: `contain`, on white, because most arrive
   as a PNG made for a white background.
   ========================================================================== */
.sponsor-logo-preview {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    overflow: hidden;
    padding: 0.375rem;
    background-color: #fff;
    border: 1px solid var(--osen-border-color, #e7e9eb);
    color: var(--osen-secondary-color, #9ba6b7);
    font-size: 1.5rem;
}

.sponsor-logo-preview img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.sponsor-logo-preview--rectangle {
    width: 9rem;
    height: 5rem;
    border-radius: 0.5rem;
}

.sponsor-logo-preview--square {
    width: 5.5rem;
    height: 5.5rem;
    border-radius: 0.75rem;
}

.sponsor-logo-preview--circle {
    width: 5.5rem;
    height: 5.5rem;
    border-radius: 50%;
}

/* ==========================================================================
   "Add" buttons with a how-many picker (heyjoinme.js, [data-add-many])
   ========================================================================== */
.add-many {
    position: relative;
    flex-wrap: nowrap;
    width: auto;
}

.add-many .add-many-qty {
    flex: 0 0 auto;
    width: 4.25rem;
    padding-inline-end: 1.5rem;
}

.add-many-note {
    position: absolute;
    inset-block-start: 100%;
    inset-inline-end: 0;
    margin-block-start: 0.25rem;
    font-size: 0.75rem;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s ease;
    z-index: 2;
}

.add-many-note.is-shown {
    opacity: 1;
}

/* Sign-up: the code screen. */
.signup-code__to {
    margin: 0 0 0.5rem;
    font-size: 0.8125rem;
    color: var(--osen-secondary-color, #9ba6b7);
}

.signup-code__to strong {
    color: var(--osen-body-color, #4c4c5c);
    font-weight: 600;
}

.signup-code__input {
    letter-spacing: 0.35em;
    font-weight: 600;
    font-size: 1.05rem;
}

.signup-code__input::placeholder {
    letter-spacing: normal;
    font-weight: 400;
    font-size: 0.9375rem;
}

.signup-code__resend {
    padding: 0;
    border: 0;
    background: none;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--osen-primary, #465dff);
    cursor: pointer;
}

.signup-code__resend:disabled {
    color: var(--osen-secondary-color, #9ba6b7);
    cursor: default;
}

.signup-code__done {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    height: 3rem;
    padding: 0 0.9rem;
    border-radius: 0.65rem;
    background: color-mix(in srgb, #16a34a 10%, transparent);
    color: #15803d;
    font-weight: 600;
    font-size: 0.9375rem;
}
