:root {
    /* Saval Brand & Design Guidelines v1 -- Forest is the primary (links,
       focus rings, active states, icon badges); Trailblaze is the one CTA
       accent (also doubles as the "notice this" attention color); Danger
       is reserved for genuinely destructive actions only. --sv-teal/-rose
       keep their old names to minimize churn across this file, but now
       carry the new Forest/Danger values rather than the retired muted
       teal/plain rose. */
    --sv-teal: #3E6B47;
    --sv-teal-dark: #2F5438;
    --sv-teal-tint: #3E6B4718;
    --sv-rose: #B0483A;
    --sv-trailblaze: #C96A3A;
    --sv-trailblaze-dark: #B25A2E;
    --sv-trailblaze-tint: #C96A3A18;
    --sv-on-accent: #FFF6EE;
    --sv-ink: #16231A;
    --sv-ink-soft: #5A6353;
    --sv-muted: #6b7280;
    --sv-border: #e3e6e8;
    --sv-sunken: #E7E4D6;
    --sv-line: #DEDAC9;
    --sv-surface: #fff;
    --sv-bg: #f2f4f5;
    --sv-radius-sm: 8px;
    --sv-radius-md: 12px;
    --sv-radius-lg: 18px;
    --sv-shadow-sm: 0 1px 2px rgba(16, 24, 32, .06), 0 1px 1px rgba(16, 24, 32, .04);
    --sv-shadow-md: 0 4px 14px rgba(16, 24, 32, .08), 0 1px 3px rgba(16, 24, 32, .06);
    --sv-shadow-lg: 0 12px 32px rgba(16, 24, 32, .14), 0 2px 6px rgba(16, 24, 32, .06);
    --sv-ease: cubic-bezier(.2, .7, .3, 1);
}

* {
    scrollbar-color: #c2c8cc transparent;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-thumb {
    background: #c2c8cc;
    border-radius: 20px;
}

::-webkit-scrollbar-thumb:hover {
    background: #a7aeb3;
}

body {
    margin: 0;
    padding: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background-color: var(--sv-bg);
    background-image: radial-gradient(circle at 12% 0%, #3E6B4712, transparent 45%),
        radial-gradient(circle at 100% 0%, #B0483A10, transparent 40%);
    background-attachment: fixed;
    color: var(--sv-ink);
    -webkit-font-smoothing: antialiased;
}

.env-banner {
    background-color: #B0483A;
    color: #fff;
    text-align: center;
    font-size: 13px;
    font-weight: bold;
    padding: 6px 12px;
    letter-spacing: 0.02em;
}

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: rgba(255, 255, 255, .85);
    backdrop-filter: blur(10px) saturate(160%);
    -webkit-backdrop-filter: blur(10px) saturate(160%);
    padding: 12px 24px;
    box-shadow: var(--sv-shadow-sm);
    border-bottom: 1px solid var(--sv-border);
    /* Stays pinned while scrolling through a long item list -- keeps the
       balance and cart visible everywhere, not just at the top. */
    position: sticky;
    top: 0;
    z-index: 8;
}

.topbar-left {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    text-decoration: none;
    cursor: pointer;
    flex-shrink: 0;
}

/* Scoped to .topbar-left (the logo only) rather than .topbar -- this used
   to be ".topbar img", which (unintentionally, due to higher specificity
   than .topbar-avatar's own width/height) stretched the topbar avatar to
   an oval: 32px wide (from .topbar-avatar) but 40px tall (from this rule
   winning the height fight). The avatar lives in .topbar-right, so
   scoping this to .topbar-left excludes it entirely. */
.topbar-left img {
    height: 40px;
}

.topbar-title {
    font-weight: bold;
    color: #3E6B47;
    font-size: 11px;
    line-height: 1;
}

.topbar-right {
    display: flex;
    align-items: center;
    gap: 16px;
}

.topbar-balance {
    font-size: 14px;
    font-weight: bold;
    color: #3E6B47;
}

.topbar-balance.insufficient {
    color: #B0483A;
}

.topbar-avatar-link {
    display: inline-flex;
    line-height: 0;
    border-radius: 50%;
    transition: box-shadow .15s var(--sv-ease);
}

.topbar-avatar-link:hover {
    box-shadow: 0 0 0 3px #3E6B4730;
}

.topbar-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--sv-border);
}

.topbar-avatar-fallback {
    background: #3E6B47;
    color: #fff;
    font-size: 13px;
    font-weight: bold;
}

.logout-link {
    background: none;
    border: none;
    color: var(--sv-teal);
    cursor: pointer;
    font-size: 14px;
    text-decoration: none;
    padding: 6px 12px;
    border-radius: 20px;
    transition: background .15s var(--sv-ease);
}

.logout-link:hover {
    background: var(--sv-teal-tint);
    text-decoration: underline;
}

.cart-icon-button {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background-color: #3E6B47;
    color: #fff;
    border: 2px solid #3E6B47;
    border-radius: 24px;
    padding: 10px 16px;
    cursor: pointer;
    text-decoration: none;
    transition: background-color .15s ease, border-color .15s ease;
}

.cart-icon-button .cart-icon-svg {
    /* Uses currentColor for both stroke and fill, so it automatically
       matches this button's text color in every state (white on the
       filled/teal state, teal on the white/empty outline state) --
       avoids relying on emoji rendering, which varies enough across
       browsers/OSes to blend into the background (same class of issue
       hit with the lock emoji earlier). */
    flex-shrink: 0;
}

/* A count badge, not an error -- Trailblaze (the same accent that doubles
   as the "notice this" attention-indicator color), not Danger. */
.cart-icon-button .cart-badge-count {
    background: var(--sv-trailblaze);
    color: var(--sv-on-accent);
    border-radius: 999px;
    min-width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: bold;
    padding: 0 6px;
}

/* Bordered, not muted-grey -- a grey-on-white (and grey-on-grey badge)
   button nearly disappeared against the white topbar. Still visually
   distinct from the "has items" filled state without going invisible. */
.cart-icon-button.empty {
    background-color: #fff;
    border: 2px solid #3E6B47;
    color: #3E6B47;
}

.cart-icon-button.empty .cart-badge-count {
    background: #3E6B47;
    color: #fff;
}

.page {
    max-width: 900px;
    margin: 0 auto;
    padding: 24px 16px 60px;
}

/* Standalone, no-login vendor confirmation page reached via a scanned QR
   code -- narrower and centered vertically, since it's a single simple
   card, not a full portal page. */
.vendor-redeem-page {
    max-width: 420px;
    padding-top: 15vh;
}

.vendor-redeem-page .profile-card h1 {
    font-size: 18px;
    margin: 0 0 12px;
}

.redeem-already-note {
    text-align: center;
    color: #3E6B47;
    font-weight: bold;
    margin-top: 12px;
}

.greeting-card {
    background: linear-gradient(155deg, #fff 0%, #f7fbfa 100%);
    border: 1px solid var(--sv-border);
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-md);
    padding: 24px;
    margin-bottom: 24px;
}

.greeting-card h1 {
    margin: 0 0 6px;
    font-size: 22px;
}

.greeting-card .profile-line {
    color: #666;
    font-size: 14px;
    margin: 4px 0;
}

.greeting-card .portal-blurb {
    margin-top: 14px;
    font-size: 14px;
    color: #444;
    line-height: 1.5;
}

.membership-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 12px;
    background: #B0483A30;
    color: #B0483A;
    font-size: 12px;
    font-weight: bold;
    margin-left: 8px;
}

.membership-pill.active {
    background: #3E6B4730;
    color: #3E6B47;
}

.profile-header-card {
    display: flex;
    align-items: center;
    gap: 18px;
    background: #fff;
    border: 1px solid var(--sv-border);
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-md);
    padding: 24px;
    margin-bottom: 24px;
}

.profile-header-avatar {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    box-shadow: 0 0 0 3px #fff, 0 0 0 5px var(--sv-teal-tint);
}

.profile-header-avatar-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #3E6B47;
    color: #fff;
    font-size: 26px;
    font-weight: bold;
}

.profile-header-card h1 {
    margin: 0 0 4px;
    font-size: 20px;
    display: inline;
}

.profile-header-card .profile-line {
    margin: 6px 0 0;
    font-size: 13px;
    color: #666;
}

.profile-card {
    background: #fff;
    border: 1px solid var(--sv-border);
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-sm);
    padding: 18px 22px;
    margin-bottom: 20px;
    transition: box-shadow .15s var(--sv-ease);
}

/* Health > Dashboard's clickable status cards -- one per system component.
   Placeholder cards (not-yet-built components, e.g. Authorizations) drop
   the hover/pointer affordance so it's visually obvious they're inert. */
.admin-dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 16px;
}

.admin-dashboard-card {
    position: relative;
    background: #fff;
    border: 1px solid var(--sv-border);
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-sm);
    padding: 18px 20px;
    cursor: pointer;
    overflow: hidden;
    transition: box-shadow .18s var(--sv-ease), transform .18s var(--sv-ease), border-color .18s var(--sv-ease);
}

.admin-dashboard-card::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 4px;
    background: var(--sv-teal);
    opacity: .55;
}

.admin-dashboard-card:hover {
    box-shadow: var(--sv-shadow-lg);
    transform: translateY(-2px);
    border-color: #d7dcdf;
}

.admin-dashboard-card-placeholder {
    cursor: default;
    opacity: 0.55;
}

.admin-dashboard-card-placeholder:hover {
    box-shadow: var(--sv-shadow-sm);
    transform: none;
    border-color: var(--sv-border);
}

.admin-dashboard-card-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    margin-bottom: 8px;
}

.admin-dashboard-card-status-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: currentColor;
}

.admin-dashboard-card-metric {
    font-size: 1.4em;
    font-weight: 700;
    margin-bottom: 4px;
}

.admin-dashboard-card-sub {
    font-size: 0.85em;
    color: #777;
}

/* Every admin list (Catalog, Fulfillment, Benefit, Custom, Team) collapses
   to just this summary line while its create/edit/detail panel is open --
   the list underneath isn't useful to see while attention is on the form,
   and collapsing it keeps the now-relevant panel from getting pushed
   further down the page. Expanded by default; toggled programmatically by
   each tab's own open*/close* functions, but the summary itself stays
   click-to-toggle too since <details> is native. */
.admin-collapsible > summary {
    cursor: pointer;
    font-weight: bold;
    color: #333;
    list-style: none;
}

.admin-collapsible > summary::-webkit-details-marker {
    display: none;
}

.admin-collapsible > summary::before {
    content: "▸ ";
    display: inline-block;
    transition: transform 0.15s ease;
}

.admin-collapsible[open] > summary::before {
    transform: rotate(90deg);
}

.admin-collapsible > summary ~ * {
    margin-top: 12px;
}

/* Client-side filter bar sitting above a list's <details> -- filters
   what's already loaded into state (challengeState/teamChallengeState),
   never triggers another fetch. Stays visible/usable regardless of the
   list's own collapsed/expanded state below it. */
.admin-search-wrap {
    position: relative;
    max-width: 480px;
    margin-bottom: 12px;
}

.admin-search-wrap.admin-search-wrap-inline {
    margin-bottom: 0;
}

.admin-search-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: #9aa0a6;
    pointer-events: none;
}

.admin-search-input {
    width: 100%;
    box-sizing: border-box;
    padding: 12px 40px 12px 42px;
    border: 1px solid #dcdfe3;
    border-radius: 24px;
    font-size: 15px;
    background: #f7f8f9;
    transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}

.admin-search-input:focus {
    outline: none;
    border-color: #3E6B47;
    background: #fff;
    box-shadow: 0 0 0 3px #3E6B4730;
}

/* Matches .admin-search-input's exact height/padding/shape so a chapter or
   year box sitting next to a search input in the same filter bar lines up
   instead of falling back to the browser's default (shorter, square) select
   or number-input chrome. */
.admin-filter-select {
    box-sizing: border-box;
    padding: 12px 14px;
    border: 1px solid #dcdfe3;
    border-radius: 24px;
    font-size: 15px;
    background: #f7f8f9;
    transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}

.admin-filter-select:focus {
    outline: none;
    border-color: #3E6B47;
    background: #fff;
    box-shadow: 0 0 0 3px #3E6B4730;
}

.admin-search-clear {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 26px;
    height: 26px;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: #9aa0a6;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.admin-search-clear:hover {
    background: #eceef0;
    color: #555;
}

.admin-search-results {
    max-width: 480px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.admin-search-result-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #eceef0;
    border-radius: 10px;
    background: #fff;
    cursor: pointer;
    text-align: left;
    font-size: 14px;
    transition: background 0.12s ease, border-color 0.12s ease;
}

.admin-search-result-item:hover {
    background: #f5f9f8;
    border-color: #3E6B4750;
}

.admin-search-result-avatar {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: #3E6B47;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: bold;
    text-transform: uppercase;
}

.admin-search-result-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.admin-search-result-name {
    font-weight: 600;
    color: #222;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.admin-search-result-meta {
    font-size: 12px;
    color: #777;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.admin-activity-id-link {
    color: #3E6B47;
    text-decoration: underline;
    cursor: pointer;
}

.admin-activity-id-link:hover {
    color: #2F5438;
}

.admin-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px;
    margin-bottom: 12px;
}

.admin-filter-field {
    display: flex;
    flex-direction: column;
    min-width: 140px;
}

.admin-filter-field-grow {
    flex: 1 1 220px;
}

.admin-filter-field .admin-field-label {
    margin-bottom: 4px;
}

.profile-field-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid #f0f0f0;
    font-size: 14px;
}

.profile-field-row:last-of-type {
    border-bottom: none;
}

/* Groups one Member Benefit Application's status pill + progress bar +
   caption as a unit -- separated from the next application in the list the
   same way .profile-field-row separates simpler rows. */
.benefit-application-row {
    padding: 12px 0;
    border-bottom: 1px solid #f0f0f0;
}

.benefit-application-row:last-of-type {
    border-bottom: none;
}

.benefit-application-row .profile-field-row {
    border-bottom: none;
    padding-top: 0;
}

.benefit-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.benefit-icon-button {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1px solid #ccc;
    background: #fff;
    color: #888;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
}

/* Trailblaze instead of grey when there's an unread message -- Trailblaze's
   second job per the brand guideline is exactly this "small unread/
   attention indicator" case, same accent as the cart's item-count badge. */
.benefit-message-button.unread {
    border-color: var(--sv-trailblaze);
    color: var(--sv-trailblaze);
}

.benefit-message-dot {
    position: absolute;
    top: -2px;
    right: -2px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--sv-trailblaze);
    border: 1.5px solid #fff;
}

.benefit-message-note {
    padding: 6px 0;
    border-bottom: 1px solid #f0f0f0;
}

.benefit-message-note:last-of-type {
    border-bottom: none;
}

.benefit-message-note-meta {
    font-size: 11px;
    color: #888;
}

.profile-field-label {
    color: #666;
    font-weight: bold;
    flex-shrink: 0;
}

.profile-field-value {
    color: #333;
    text-align: right;
    /* Lets a long value (mailing address, email) wrap onto multiple lines
       within the row instead of forcing the row wider than the page. */
    min-width: 0;
    flex: 1;
    overflow-wrap: break-word;
}

.profile-badge-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 6px 0 12px;
}

.profile-badge {
    background: #3E6B4730;
    color: #3E6B47;
    font-size: 12px;
    font-weight: bold;
    padding: 4px 10px;
    border-radius: 12px;
}

/* The one primary-action button used across every page (Save, Apply,
   Add to cart, Edit) -- Trailblaze per the brand guideline's "Primary CTA"
   pattern, not Forest, since Forest is reserved for links/focus/active
   states rather than buttons. */
.profile-button {
    padding: 10px 18px;
    border: none;
    border-radius: var(--sv-radius-sm);
    background-color: var(--sv-trailblaze);
    color: var(--sv-on-accent);
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    margin-top: 12px;
    /* Closer to the ~44px recommended minimum touch target than the
       previous 8px vertical padding gave. */
    min-height: 40px;
    box-sizing: border-box;
    box-shadow: 0 1px 2px #C96A3A40;
    transition: background-color .15s var(--sv-ease), box-shadow .15s var(--sv-ease), transform .1s var(--sv-ease);
}

.profile-button:hover:not(:disabled) {
    background-color: var(--sv-trailblaze-dark);
    box-shadow: 0 3px 10px #C96A3A45;
}

.profile-button:active:not(:disabled) {
    transform: translateY(1px);
}

.profile-button:disabled {
    background-color: #d8dadc;
    color: #97999c;
    cursor: default;
    box-shadow: none;
}

/* A real, clickable secondary action (Cancel/Clear/Close) needs to read as
   "interactive" -- it previously shared the same #ccc grey (plus inherited
   white text from .profile-button) as .profile-button:disabled below, so
   every secondary button in the portal looked disabled. Outline style
   instead: dark text, bordered, distinct from both the primary teal button
   and the disabled grey state. (User-reported UX feedback.) */
.profile-cancel-button {
    background-color: #fff;
    color: #444;
    border: 1px solid #d3d6d8;
    margin-left: 8px;
    box-shadow: var(--sv-shadow-sm);
}

.profile-cancel-button:hover {
    background-color: #f7f8f9;
    border-color: #b3b3b3;
}

.profile-edit-form {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #f0f0f0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.profile-edit-form input,
.profile-edit-form select,
.profile-edit-form textarea {
    padding: 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    /* 16px, not 13 -- anything smaller triggers iOS Safari's automatic
       zoom-on-focus, which is jarring on a form field. Applies to every
       text input/select/textarea fix below in this file for the same
       reason. */
    font-size: 16px;
    box-sizing: border-box;
    font-family: inherit;
}

.profile-edit-form-actions {
    margin-top: 4px;
}

/* Required-field invalid state -- toggled by markFieldValidity() in
   checkout.js (and reusable anywhere else a .profile-edit-form is used) on
   a blocked "Continue", cleared as soon as the member fixes the field. */
.profile-edit-form input.field-invalid,
.profile-edit-form select.field-invalid,
.profile-edit-form textarea.field-invalid {
    border-color: #d9534f;
    background-color: #fdf2f2;
}

.sig-edit-row {
    display: flex;
    gap: 6px;
    margin-bottom: 6px;
    flex-wrap: wrap;
    align-items: center;
}

.sig-edit-row input {
    flex: 1;
    min-width: 100px;
}

.sig-edit-row select {
    flex: 1;
    min-width: 100px;
}

.sig-remove-row-button {
    background: none;
    border: 1px solid #ccc;
    border-radius: 50%;
    width: 28px;
    height: 28px;
    min-width: 28px;
    line-height: 1;
    font-size: 16px;
    color: #666;
    cursor: pointer;
    padding: 0;
}

.sig-remove-row-button:hover {
    background: #f0f0f0;
    color: #333;
}

.menu-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
}

.menu-card {
    display: block;
    background: #fff;
    border: 1px solid var(--sv-border);
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-sm);
    padding: 24px;
    text-decoration: none;
    color: #333;
    transition: box-shadow .18s var(--sv-ease), transform .18s var(--sv-ease), border-color .18s var(--sv-ease);
}

.menu-card:hover {
    box-shadow: var(--sv-shadow-lg);
    transform: translateY(-3px);
    border-color: #d7dcdf;
}

.menu-card.disabled {
    opacity: .6;
    cursor: default;
    pointer-events: none;
}

.menu-card .menu-icon {
    font-size: 28px;
    margin-bottom: 10px;
}

.menu-card h2 {
    margin: 0 0 6px;
    font-size: 17px;
    color: #3E6B47;
}

.menu-card p {
    margin: 0;
    font-size: 13px;
    color: #666;
}

.menu-card .coming-soon {
    display: inline-block;
    margin-top: 8px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: #B0483A;
    font-weight: bold;
}

.back-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 16px;
    color: var(--sv-teal);
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
    transition: transform .12s var(--sv-ease);
}

.back-link:hover {
    text-decoration: underline;
    transform: translateX(-2px);
}

/* The one deliberately bold "hero" moment on the Rewards page --
   primary-to-ink gradient, matching the brand guideline's Hero/Streak
   Card pattern (reserved for a moment worth calling out, not every card). */
.balance-card {
    background: linear-gradient(135deg, var(--sv-teal), var(--sv-ink) 130%);
    color: #fff;
    border-radius: var(--sv-radius-md);
    padding: 20px 24px;
    margin-bottom: 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    box-shadow: var(--sv-shadow-md);
}

.balance-card .balance-number {
    font-size: 32px;
    font-weight: bold;
}

.balance-card .balance-label {
    font-size: 13px;
    opacity: .85;
}

.balance-card .balance-profile-line {
    font-size: 12px;
    opacity: .8;
    margin-top: 6px;
}

.chapter-banner {
    background: #fdf3e7;
    border: 1px solid #f0c04960;
    border-radius: var(--sv-radius-sm);
    padding: 14px 18px;
    margin-bottom: 20px;
    font-size: 13px;
    color: #7a5a20;
    line-height: 1.5;
    box-shadow: var(--sv-shadow-sm);
}

/* Same visual language as .chapter-banner, for an outright expired/invalid
   state (accept-invite.js) rather than an informational heads-up. */
.admin-warning-banner {
    background: #fdf2f2;
    border: 1px solid #d9534f60;
    border-radius: var(--sv-radius-sm);
    padding: 14px 18px;
    margin-bottom: 14px;
    font-size: 14px;
    color: #a33;
    line-height: 1.5;
    box-shadow: var(--sv-shadow-sm);
}

.tier-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 16px;
    margin-bottom: 32px;
}

.tier-box {
    background: #fff;
    border: 1px solid var(--sv-border);
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-sm);
    padding: 22px 18px;
    text-align: center;
    cursor: pointer;
    transition: box-shadow .18s var(--sv-ease), transform .18s var(--sv-ease), border-color .18s var(--sv-ease);
}

.tier-box:hover {
    box-shadow: var(--sv-shadow-md);
    transform: translateY(-2px);
    border-color: #d7dcdf;
}

.tier-box-name {
    font-size: 15px;
    font-weight: bold;
    color: #3E6B47;
    margin-bottom: 6px;
}

.tier-fine-print {
    display: block;
    font-size: 10px;
    font-weight: normal;
    text-transform: none;
    letter-spacing: normal;
    color: #999;
    margin-top: 2px;
}

.tier-box-threshold {
    font-size: 13px;
    color: #666;
    margin-bottom: 12px;
}

.tier-box-count {
    font-size: 13px;
    font-weight: bold;
    color: #3E6B47;
}

.tier-box-lock {
    display: flex;
    justify-content: center;
}

.tier-box.locked {
    cursor: default;
    background: #f7f7f7;
    filter: grayscale(60%);
}

.tier-box.locked:hover {
    box-shadow: var(--sv-shadow-sm);
    transform: none;
}

/* Chapter-blocked -- distinct from points-locked, same "unavailable"
   language and treatment used on item cards. */
.tier-box.unavailable {
    background: #f7f7f7;
    filter: grayscale(80%);
}

.tier-box-status {
    font-size: 12px;
    color: #B0483A;
    font-weight: bold;
    margin-top: 4px;
}

/* Unlocked but nothing seeded in it yet -- distinct from both "locked"
   (can't reach it) and "unavailable" (chapter has no offer): this tier is
   reachable, it's just empty right now. Not grayscaled like the other two
   blocked states since the member did nothing wrong here. */
.tier-box.empty {
    cursor: default;
}

.tier-box.empty .tier-box-status {
    color: #888;
}

/* Coming Soon specifically (not the sold-out flavor of "empty") gets its
   own accent, matching the item-card treatment -- distinct from both the
   red "blocked" states and the neutral grey "sold out" state. */
.tier-box.coming-soon .tier-box-status {
    color: #4a90c4;
}

.tier-box.empty:hover {
    box-shadow: var(--sv-shadow-sm);
    transform: none;
}

.reward-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 16px;
    margin-bottom: 32px;
}

.reward-card {
    background: #fff;
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-sm);
    padding: 18px;
    display: flex;
    flex-direction: column;
    /* Without a cap, a tier with a single item stretches its one card
       (and, via aspect-ratio below, its image) across the full grid row. */
    max-width: 340px;
}

.reward-card .reward-image {
    /* object-fit: contain (not cover) + a neutral background + padding --
       standardizes how source images render regardless of their actual
       aspect ratio or content (a product photo vs. a vendor's logo SVG
       with built-in whitespace), instead of `cover` zoom-cropping some of
       them to look oversized relative to others. */
    width: calc(100% + 36px);
    aspect-ratio: 4 / 3;
    max-height: 200px;
    object-fit: contain;
    background: #f4f4f4;
    border-radius: 6px;
    margin: -18px -18px 12px;
    padding: 16px;
    box-sizing: border-box;
}

.reward-card .tier-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: #8e7b69;
    font-weight: bold;
}

.reward-card h3 {
    margin: 6px 0;
    font-size: 16px;
}

.reward-card .reward-vendor {
    font-size: 12px;
    color: #888;
    margin-bottom: 6px;
}

.reward-card .reward-description {
    font-size: 13px;
    color: #555;
    line-height: 1.4;
    margin: 0 0 10px;
}

.reward-card .reward-delivery {
    font-size: 12px;
    color: #3E6B47;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 5px;
}

.reward-card .point-cost {
    font-size: 20px;
    font-weight: bold;
    color: #3E6B47;
    margin-bottom: 10px;
}

.reward-card .variant-select {
    margin-bottom: 10px;
    padding: 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    font-size: 16px;
}

.reward-card .qty-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
    color: #555;
    margin-bottom: 10px;
}

.reward-card .quantity-input {
    width: 56px;
    padding: 6px 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    font-size: 16px;
}

.reward-card .quantity-input:disabled {
    background: #f4f4f4;
    color: #aaa;
}

/* The one CTA on a reward card -- Trailblaze, matching .profile-button. */
.reward-card .add-to-cart-row {
    margin-top: auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px;
    border-radius: 4px;
    background-color: var(--sv-trailblaze);
    color: var(--sv-on-accent);
    cursor: pointer;
    font-size: 14px;
}

.reward-card .add-to-cart-row input[type="checkbox"] {
    width: 16px;
    height: 16px;
    cursor: pointer;
}

.reward-card .add-to-cart-row:has(input:disabled) {
    background-color: #ccc;
    /* White text on this light grey was hard to read -- dark text gives
       real contrast instead of just being technically visible. */
    color: #555;
    cursor: default;
}

.reward-card .add-to-cart-row input:disabled {
    cursor: default;
}

.reward-card .card-top-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
}

.lock-badge {
    font-size: 16px;
    line-height: 1;
}

/* Locked = can't afford it yet -- dimmed rather than hidden, paired with
   a progress bar, so it reads as "almost there" instead of a hard wall. */
.reward-card.locked {
    background: #f7f7f7;
}

.reward-card.locked .tier-label,
.reward-card.locked h3 {
    opacity: .55;
}

.reward-card.locked .point-cost {
    opacity: .7;
}

.progress-track {
    width: 100%;
    height: 6px;
    background: #e6e6e6;
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 8px;
}

.progress-fill {
    height: 100%;
    background: #3E6B47;
    border-radius: 3px;
}

.progress-caption {
    font-size: 12px;
    color: #888;
    margin-bottom: 10px;
}

/* Unavailable = your chapter has no offer here at all, regardless of
   points -- visually distinct from "locked" (points-away) so it doesn't
   imply saving more will help. */
.reward-card.unavailable {
    background: #f7f7f7;
    filter: grayscale(60%);
}

.reward-card.unavailable .tier-label,
.reward-card.unavailable h3,
.reward-card.unavailable .point-cost {
    opacity: .5;
}

/* Coming Soon = nothing is wrong, it just hasn't launched -- deliberately
   NOT grayscaled/dimmed like the other blocked states above, so it reads
   as "anticipated" rather than "restricted." */
.reward-card.coming-soon {
    background: #eaf3fb;
}

.reward-card.coming-soon .tier-label,
.reward-card.coming-soon h3,
.reward-card.coming-soon .point-cost {
    opacity: .8;
}

.reward-card.coming-soon .add-to-cart-row:has(input:disabled) {
    background-color: #4a90c4;
    color: #fff;
}

.cart-item-row {
    background: #fff;
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-sm);
    padding: 14px 18px;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.cart-item-info {
    /* Without this, a flex item's default min-width:auto keeps a long
       reward title at its full intrinsic width, pushing the row (and the
       whole page) wider than the viewport instead of wrapping. */
    min-width: 0;
    flex: 1;
}

.cart-item-title,
.cart-item-vendor {
    overflow-wrap: break-word;
}

.cart-item-title {
    font-size: 14px;
    font-weight: bold;
}

.cart-item-vendor {
    font-size: 12px;
    color: #888;
}

.cart-item-delivery-note {
    font-size: 12px;
    color: #a67c00;
    margin-top: 4px;
}

.cart-item-fulfillment-toggle {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 6px;
}

.cart-item-fulfillment-toggle label {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 13px;
    color: #555;
    min-height: 24px;
}

.cart-qty-input {
    width: 52px;
    padding: 6px 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    font-size: 16px;
}

.cart-item-points {
    font-size: 14px;
    font-weight: bold;
    color: #3E6B47;
    white-space: nowrap;
}

.cart-item-remove {
    background: none;
    border: none;
    color: #B0483A;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    padding: 8px;
    min-width: 32px;
    min-height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.points-summary {
    background: #fff;
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-sm);
    padding: 14px 18px;
    margin: 16px 0;
}

.points-summary-row {
    display: flex;
    justify-content: space-between;
    font-size: 14px;
    color: #555;
    padding: 4px 0;
}

.points-summary-row.points-summary-final {
    border-top: 1px solid #eee;
    margin-top: 6px;
    padding-top: 10px;
    font-size: 16px;
    font-weight: bold;
    color: #3E6B47;
}

.points-summary.insufficient .points-summary-final {
    color: #B0483A;
}

.address-gate {
    background: #fdf3e7;
    border: 1px solid #f0c04960;
    border-radius: var(--sv-radius-md);
    padding: 16px 18px;
    margin: 16px 0;
}

.address-gate-text {
    margin: 0 0 10px;
    font-size: 13px;
    color: #7a5a20;
    line-height: 1.5;
}

.address-gate-confirm-line {
    margin: 0 0 12px;
    font-size: 14px;
    font-weight: bold;
    color: #333;
}

.terms-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 13px;
    color: #555;
    line-height: 1.4;
    margin: 16px 0;
    cursor: pointer;
}

.terms-row input[type="checkbox"] {
    margin-top: 2px;
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    cursor: pointer;
}

/* The one CTA on the cart-review screen -- Trailblaze, matching .profile-button. */
.submit-order-button {
    width: 100%;
    padding: 14px;
    border: none;
    border-radius: 6px;
    background-color: var(--sv-trailblaze);
    color: var(--sv-on-accent);
    cursor: pointer;
    font-size: 15px;
    font-weight: bold;
}

.submit-order-button:disabled {
    background-color: #ccc;
    cursor: default;
}

/* PayPal's SDK renders its buttons at the container's full width -- capped
   and centered here so they don't stretch edge-to-edge across the wider
   900px cart review column. */
#paypalButtonsContainer {
    max-width: 400px;
    margin: 12px auto 0;
}

.section-title {
    font-size: 16px;
    font-weight: bold;
    margin: 32px 0 12px;
    color: #333;
}

.history-details {
    margin-top: 32px;
}

.history-summary {
    /* Collapsed by default (no `open` attribute in the HTML) -- keeps
       history off the page's primary real estate while still being one
       tap away, matching the site's no-extra-pages convention. */
    margin: 0 0 12px;
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
}

.history-summary::-webkit-details-marker {
    display: none;
}

.history-summary::before {
    content: "▸";
    font-size: 13px;
    color: #3E6B47;
    transition: transform .15s ease;
}

.history-details[open] .history-summary::before {
    transform: rotate(90deg);
}

#historyCount {
    font-weight: normal;
    color: #888;
    font-size: 14px;
}

/* Wraps both .history-table and .admin-table -- on a phone-width screen
   neither fits without either shrinking columns unreadably or blowing out
   the whole page width; this contains the horizontal scroll to just the
   table itself instead. */
.table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.history-table {
    width: 100%;
    border-collapse: collapse;
    background: #fff;
    border-radius: var(--sv-radius-md);
    overflow: hidden;
    box-shadow: var(--sv-shadow-sm);
}

.history-table th,
.history-table td {
    text-align: left;
    padding: 10px 14px;
    font-size: 13px;
    border-bottom: 1px solid #eee;
}

.history-table th {
    background: #f4f4f4;
    color: #666;
    font-weight: bold;
}

.status-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: bold;
    background: #f0c04930;
    color: #a67c00;
}

.status-pill.redeemed {
    background: #3E6B4730;
    color: #3E6B47;
}

.status-pill.failed {
    background: #B0483A30;
    color: #B0483A;
}

.empty-state {
    text-align: center;
    color: #888;
    padding: 24px;
    font-size: 14px;
}

.toast {
    position: fixed;
    bottom: 28px;
    left: 50%;
    transform: translateX(-50%);
    background: #2b2f33;
    color: #fff;
    padding: 13px 22px;
    border-radius: 30px;
    font-size: 14px;
    font-weight: 500;
    box-shadow: var(--sv-shadow-lg);
    display: none;
    /* Must outrank every modal overlay (.admin-modal-overlay: 100,
       .admin-lightbox-overlay: 200) -- toasts fired from inside a modal
       (e.g. the region-override "Target isn't set yet" warning) were
       rendering invisibly behind it at z-index 10. */
    z-index: 300;
    animation: sv-toast-in .22s var(--sv-ease);
}

@keyframes sv-toast-in {
    from { opacity: 0; transform: translate(-50%, 10px); }
    to { opacity: 1; transform: translate(-50%, 0); }
}

.toast.error {
    background: var(--sv-rose);
}

.toast.success {
    background: var(--sv-teal);
}

/* Internal-only admin tool (catalog builder + fulfillment queue) -- wider
   than the member-facing .page since it's tables/forms, not cards. */
.admin-page {
    max-width: 900px;
}

.admin-tabs {
    display: flex;
    gap: 6px;
    margin-bottom: 18px;
    flex-wrap: wrap;
    padding: 5px;
    background: #eaedee;
    border-radius: 24px;
    width: fit-content;
    max-width: 100%;
}

.admin-tab-button {
    padding: 9px 18px;
    border: none;
    border-radius: 20px;
    background: transparent;
    color: var(--sv-muted);
    cursor: pointer;
    font-size: 14px;
    font-weight: 600;
    transition: background .15s var(--sv-ease), color .15s var(--sv-ease), box-shadow .15s var(--sv-ease);
}

.admin-tab-button:hover:not(.active) {
    background: #dde1e2;
    color: var(--sv-ink);
}

.admin-tab-button.active {
    background: var(--sv-teal);
    color: #fff;
    box-shadow: 0 2px 8px #3E6B4750;
}

/* No global textarea styling exists anywhere in this file -- every
   textarea in the portal is plain browser-default. Scoped to Support's
   reply box specifically (that's what was asked for), not a global sweep. */
.admin-support-message-box {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    border: 1px solid #ccc;
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
    resize: vertical;
    min-height: 120px;
}

.admin-support-message-box:focus {
    outline: none;
    border-color: #3E6B47;
    box-shadow: 0 0 0 3px #3E6B4730;
}

/* Feedback/Referral type badges -- Feedback vs. Referral carries no
   urgency/severity difference, so per the brand guideline (one accent
   color earning its keep, not a different hue per card with no semantic
   meaning) both share one neutral sunken-pill style; the label text alone
   distinguishes them. */
.admin-support-type-badge {
    display: inline-block;
    font-size: 11px;
    font-weight: bold;
    padding: 3px 10px;
    border-radius: 12px;
    white-space: nowrap;
    background: var(--sv-sunken);
    color: var(--sv-ink-soft);
}

.admin-support-title-link {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: #222;
    cursor: pointer;
    text-decoration: underline;
    text-align: left;
}

#supportRespondSubject {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    font-size: 16px;
    border: 1px solid #ccc;
    border-radius: 6px;
}

/* Status badges -- same pill shape as the type badges, colored by where
   the ticket is in its lifecycle: New (needs attention) -> Open (seen,
   in progress) -> Responded (replied). All three transitions are automatic
   -- no manual status control anywhere in the UI. */
.admin-support-status-badge {
    display: inline-block;
    font-size: 11px;
    font-weight: bold;
    padding: 3px 10px;
    border-radius: 12px;
    white-space: nowrap;
}

/* New = needs attention -> Trailblaze (its "notice this" job). Open = seen,
   in progress, nothing urgent -> neutral. Responded = done -> Forest. */
.admin-support-status-new {
    background: var(--sv-trailblaze-tint);
    color: var(--sv-trailblaze-dark);
}

.admin-support-status-open {
    background: var(--sv-sunken);
    color: var(--sv-ink-soft);
}

.admin-support-status-responded {
    background: #3E6B4725;
    color: var(--sv-teal);
}

.admin-support-title-link.admin-support-unread {
    font-weight: bold;
}

/* Draft/Review/Use-Suggested-Text need to read as three different actions
   at a glance, not three identical buttons -- Draft and Review are both
   "ask AI" (secondary, neutral outline, per the brand guideline's OAuth-row
   pattern of never accent-coloring a non-primary action), Use is the one
   action that actually commits a suggestion into the real (sendable)
   message, so it alone gets the Trailblaze CTA treatment. */
.admin-ai-draft-button {
    background-color: #fff;
    color: var(--sv-ink-soft);
    border: 1px solid var(--sv-line);
}

.admin-ai-draft-button:hover {
    background-color: var(--sv-sunken);
}

.admin-ai-review-button {
    background-color: #fff;
    color: var(--sv-ink-soft);
    border: 1px solid var(--sv-line);
}

.admin-ai-review-button:hover {
    background-color: var(--sv-sunken);
}

.admin-ai-use-button {
    background-color: var(--sv-trailblaze);
    color: var(--sv-on-accent);
}

.admin-ai-use-button:hover {
    background-color: var(--sv-trailblaze-dark);
}

/* A real, always-visible preview -- a textarea's placeholder attribute is
   invisible the moment the field has any real text in it, which silently
   hid every AI suggestion whenever there was already a draft to review. */
.admin-suggested-draft-box {
    background: var(--sv-sunken);
    border: 1px solid var(--sv-line);
    border-radius: 6px;
    padding: 10px 12px;
    margin: 8px 0;
}

.admin-suggested-draft-label {
    font-size: 11px;
    font-weight: bold;
    color: var(--sv-ink-soft);
    text-transform: uppercase;
    margin-bottom: 4px;
}

#supportSuggestedDraftText {
    font-size: 14px;
    white-space: pre-wrap;
    margin-bottom: 8px;
}

.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.admin-table th {
    text-align: left;
    color: var(--sv-muted);
    font-weight: 700;
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: 10px 8px;
    border-bottom: 2px solid var(--sv-border);
    background: #fafbfb;
}

.admin-table td {
    padding: 10px 8px;
    border-bottom: 1px solid #f0f0f0;
    vertical-align: middle;
    overflow-wrap: break-word;
}

.admin-table tbody tr {
    transition: background-color .1s var(--sv-ease);
}

.admin-table tbody tr:hover {
    background-color: #f6f9f8;
}

/* .profile-button's own margin-top:12px is meant for a standalone button
   sitting below a form field -- inside a table cell it just pushes the
   button down out of line with the rest of the row's plain text. */
.admin-table td .profile-button {
    margin-top: 0;
}

/* Auto table layout sized this table's Dates column off whatever the
   longest Owner/Chapters value in the current rows happened to be,
   producing a different (and often much too wide or narrow) Dates width
   on every reload -- colgroup + fixed layout in admin.html gives every
   column a stable, predictable share instead. */
.admin-table-challenge {
    table-layout: fixed;
}

.admin-table-challenge td {
    overflow-wrap: break-word;
}

.admin-table-challenge td:nth-child(5) {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.admin-table-challenge td:last-child {
    padding-left: 16px;
}

/* The confirm text + two buttons are wider than this (fixed-width, narrow)
   actions column can ever hold on one line -- table-layout: fixed doesn't
   let them spill sideways into view the way auto layout would have, so
   most of it was rendering off the right edge of the table instead.
   Stacking vertically keeps everything within the column's actual width. */
.admin-row-delete-confirm,
.admin-row-notify-confirm {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    margin-top: 4px;
}

.admin-form {
    margin-top: 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.admin-form input[type="text"],
.admin-form input[type="number"],
.admin-form select,
.admin-form textarea {
    padding: 9px 12px;
    border-radius: var(--sv-radius-sm);
    border: 1px solid #d3d6d8;
    background: #fbfcfc;
    font-size: 16px;
    box-sizing: border-box;
    width: 100%;
    transition: border-color .15s var(--sv-ease), background .15s var(--sv-ease), box-shadow .15s var(--sv-ease);
}

.admin-form input[type="text"]:focus,
.admin-form input[type="number"]:focus,
.admin-form select:focus,
.admin-form textarea:focus {
    outline: none;
    border-color: var(--sv-teal);
    background: #fff;
    box-shadow: 0 0 0 3px var(--sv-teal-tint);
}

/* Applies across every admin form (Catalog, Vendor, Custom/Wizard's
   Warehouse, Team) since they all share .admin-form -- a visibly
   different background is the one signal that reliably reads as "don't
   bother typing here" before a click, unlike a border-color change alone
   (easy to miss) or just cursor:not-allowed (only visible on hover).
   :read-only covers text/number/textarea fields marked readonly (e.g.
   Team's auto-generated ID); :disabled covers everything toggled via
   .disabled = true (e.g. Name/Category once a record already exists) --
   <select> only ever supports the latter. */
.admin-form input:read-only,
.admin-form input:disabled,
.admin-form select:disabled,
.admin-form textarea:read-only,
.admin-form textarea:disabled {
    background-color: #e9e9e9;
    color: #777;
    cursor: not-allowed;
}

/* Checkbox-group replacement for <select multiple> -- picking more than
   one option this way doesn't require shift/ctrl-click, which is easy to
   get wrong and silently lose a selection. */
.admin-checkbox-group {
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 8px;
    max-height: 160px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: #fff;
    box-sizing: border-box;
}

.admin-checkbox-option {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: normal;
    color: #333;
    cursor: pointer;
}

.admin-checkbox-option input[type="checkbox"] {
    margin: 0;
}

.admin-selected-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.admin-selected-row .admin-hint {
    margin: 0;
}

.admin-clear-selection-button {
    background: none;
    border: 1px solid #ccc;
    border-radius: 50%;
    width: 22px;
    height: 22px;
    min-width: 22px;
    line-height: 1;
    font-size: 14px;
    color: #666;
    cursor: pointer;
    padding: 0;
}

.admin-clear-selection-button:hover {
    background: #f0f0f0;
    color: #333;
}

.admin-wizardry-badge {
    color: var(--sv-trailblaze-dark);
    font-weight: bold;
}

.admin-field-label {
    display: block;
    font-size: 12px;
    font-weight: bold;
    color: #666;
    margin-top: 8px;
}

.admin-subsection-title {
    font-size: 14px;
    font-weight: bold;
    color: #333;
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid #f0f0f0;
}

.admin-variant-row {
    display: flex;
    gap: 6px;
    margin-bottom: 6px;
    flex-wrap: wrap;
}

.admin-variant-row input {
    flex: 1;
    min-width: 90px;
    font-size: 16px;
    box-sizing: border-box;
}

.admin-danger-button {
    background-color: #B0483A;
}

.admin-inline-row {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}

.admin-inline-row select {
    flex: 1;
    min-width: 140px;
    font-size: 16px;
}

.admin-inline-row input[type="text"] {
    flex: 1;
    min-width: 140px;
    font-size: 16px;
    padding: 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    box-sizing: border-box;
}

.admin-hint {
    font-size: 11px;
    color: #888;
    margin: 2px 0 4px;
}

.field-invalid {
    outline: 2px solid #c0392b !important;
    outline-offset: 2px;
    border-radius: 4px;
}

.link-button {
    background: none;
    border: none;
    padding: 0;
    color: #3E6B47;
    font-weight: bold;
    font-size: inherit;
    cursor: pointer;
    text-decoration: underline;
}

.admin-image-preview {
    max-width: 160px;
    max-height: 160px;
    border-radius: 6px;
    border: 1px solid #f0f0f0;
    margin-top: 4px;
}

.admin-manage-targets-day {
    border: 1px solid #d8d8d8;
    border-radius: var(--sv-radius-md);
    background: #fafafa;
    padding: 4px 14px 14px;
    margin-bottom: 10px;
}

.admin-manage-targets-textarea {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    font: inherit;
    resize: vertical;
    word-break: break-all;
}

.admin-manage-targets-textarea[readonly] {
    background: #f0f0f0;
    color: #666;
}

.admin-manage-targets-geocode-retry {
    margin: 4px 0 10px;
    padding: 8px 10px;
    border: 1px solid var(--sv-trailblaze);
    border-radius: 6px;
    background: var(--sv-trailblaze-tint);
}

.admin-manage-targets-geocode-retry-message {
    margin: 0 0 6px;
    color: var(--sv-trailblaze-dark);
}

.admin-manage-targets-geocode-retry-input {
    width: 100%;
    box-sizing: border-box;
    padding: 6px 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    font: inherit;
    margin-bottom: 6px;
}

.admin-manage-targets-geocode-retry-actions {
    display: flex;
    gap: 8px;
}

.admin-hide-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 1.5em;
    white-space: nowrap;
}

.admin-quality-flag {
    display: block;
    font-size: 0.85em;
    white-space: nowrap;
}

.admin-quality-flag-warn {
    color: #a8483a;
}

.admin-quality-flag-ok {
    color: var(--sv-teal);
}

.admin-quality-ack {
    display: block;
    font-size: 0.8em;
    margin-top: 4px;
}

.admin-hide-badge-hidden {
    color: #a8483a;
}

.admin-hide-badge-visible {
    color: var(--sv-teal);
}

.admin-manage-targets-day summary {
    display: flex;
    align-items: center;
    gap: 12px;
    cursor: pointer;
    padding: 10px 0;
    font-weight: 700;
    list-style: none;
}

.admin-manage-targets-day summary::-webkit-details-marker {
    display: none;
}

.admin-manage-targets-day summary .admin-manage-targets-day-title {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
}

.admin-manage-targets-day summary .admin-manage-targets-day-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-manage-targets-day summary .admin-manage-targets-day-arrow {
    font-size: 0.7em;
    color: #888;
    transition: transform 0.15s ease;
    flex-shrink: 0;
}

.admin-manage-targets-day[open] summary .admin-manage-targets-day-arrow {
    transform: rotate(180deg);
}

.admin-manage-targets-day[open] summary {
    border-bottom: 1px solid #e2e2e2;
    margin-bottom: 10px;
}

.admin-generated-image-grid {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.admin-generated-image-option {
    position: relative;
    cursor: pointer;
    border: 3px solid transparent;
    border-radius: 8px;
    padding: 2px;
    line-height: 0;
}

.admin-generated-image-option img {
    display: block;
    width: 140px;
    height: 140px;
    object-fit: cover;
    border-radius: 6px;
}

.admin-generated-image-option.selected {
    border-color: var(--sv-teal);
}

.admin-generated-image-option.selected::after {
    content: "\2713";
    position: absolute;
    top: -8px;
    right: -8px;
    width: 22px;
    height: 22px;
    line-height: 22px;
    text-align: center;
    border-radius: 50%;
    background: var(--sv-teal);
    color: #fff;
    font-size: 13px;
    font-weight: bold;
}

.admin-status-pending {
    color: var(--sv-trailblaze-dark);
    font-weight: bold;
}

.admin-status-redeemed {
    color: #3E6B47;
    font-weight: bold;
}

.admin-status-expired {
    color: #B0483A;
    font-weight: bold;
}

.admin-email-resend-row {
    display: flex;
    gap: 6px;
    margin-top: 4px;
}

.admin-email-resend-row input {
    flex: 1;
    min-width: 140px;
    font-size: 16px;
    box-sizing: border-box;
}

.admin-required-mark {
    color: #B0483A;
}

.admin-char-counter-over {
    color: #B0483A;
    font-weight: bold;
}

.admin-field-invalid {
    border-color: #B0483A !important;
    background-color: #fdf0f0;
}

.admin-title-link {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: #3E6B47;
    text-decoration: underline;
    cursor: pointer;
    text-align: left;
}

.admin-title-link:hover {
    color: #2F5438;
}

.admin-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(20, 24, 28, 0.55);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
    padding: 20px;
    animation: sv-fade-in .15s var(--sv-ease);
}

@keyframes sv-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes sv-modal-in {
    from { opacity: 0; transform: translateY(8px) scale(.98); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

.admin-modal {
    background: #fff;
    border-radius: var(--sv-radius-md);
    box-shadow: var(--sv-shadow-lg);
    padding: 22px 26px;
    max-width: 560px;
    width: 100%;
    /* .admin-modal-overlay is display:flex, so this is a flex item --
       flex items default to min-width:auto (won't shrink below their
       content's natural width), which silently overflows the viewport on
       narrow screens whenever a modal has any longer free-flowing text
       (a paragraph, a preview headline) rather than short form-field
       labels. Existing modals never hit this by luck of short content;
       fix it structurally so no future modal has to rediscover it. */
    min-width: 0;
    max-height: 85vh;
    overflow-y: auto;
    overflow-wrap: break-word;
    animation: sv-modal-in .18s var(--sv-ease);
}

/* Roster view needs real table width (member name/role/distance/last
   activity columns) that the default popup's 560px is too narrow for. */
.admin-modal-wide {
    max-width: 800px;
}

.admin-checkbox-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    font-size: 14px;
}

.admin-roster-team {
    border: 1px solid #eee;
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 8px;
}

/* AchievementCard preview -- mirrors the real Flutter widget's palette
   (achievement_card.dart) so an admin reviews something close to what a
   recipient will actually see, not just the raw hero image + text fields.
   Colors pulled directly from that file, not re-derived. */
.achievement-preview {
    background: #201A14;
    border-radius: 12px;
    overflow: hidden;
    margin: 8px 0 16px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}

.achievement-preview-hero {
    position: relative;
    aspect-ratio: 16 / 7;
    background: #538885 center / cover no-repeat;
    display: flex;
    align-items: flex-end;
    min-width: 0;
}

.achievement-preview-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0.05) 0%,
        rgba(0, 0, 0, 0.15) 45%,
        rgba(0, 0, 0, 0.90) 100%
    );
}

.achievement-preview-badge {
    position: absolute;
    top: 10px;
    left: 10px;
    background: linear-gradient(135deg, #E8B84B, #F6D488);
    color: #4A3610;
    font-weight: 800;
    font-size: 11px;
    letter-spacing: 0.4px;
    padding: 5px 10px 5px 8px;
    border-radius: 100px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
    z-index: 1;
}

.achievement-preview-hero-text {
    position: relative;
    z-index: 1;
    padding: 0 14px 12px;
    width: 100%;
    /* Flex item of .achievement-preview-hero -- same min-width:auto
       shrink-blocking issue as .admin-modal, just nested one level
       deeper. width:100% alone doesn't override a flex item's default
       content-based minimum width. */
    min-width: 0;
}

.achievement-preview-headline {
    color: #fff;
    font-weight: 800;
    font-size: 19px;
    text-shadow: 0 0 8px rgba(0, 0, 0, 0.45);
}

.achievement-preview-challenge {
    color: rgba(255, 255, 255, 0.9);
    font-weight: 500;
    font-size: 12.5px;
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.achievement-preview-body {
    padding: 12px 14px 16px;
}

.achievement-preview-name {
    color: #F6D488;
    font-weight: 800;
    font-size: 17px;
    letter-spacing: 0.1px;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

.achievement-preview-goal-badge {
    display: inline-block;
    font-weight: 700;
    font-size: 12px;
    padding: 6px 10px;
    border-radius: 8px;
    margin-top: 10px;
}

.achievement-preview-goal-badge-met {
    background: rgba(179, 201, 156, 0.16);
    border: 1px solid rgba(179, 201, 156, 0.4);
    color: #B3C99C;
}

.achievement-preview-goal-badge-unmet {
    background: rgba(217, 96, 96, 0.16);
    border: 1px solid rgba(217, 96, 96, 0.45);
    color: #E38C8C;
}

.achievement-preview-meta {
    color: #A49D90;
    font-size: 11px;
    margin-top: 1px;
}

.achievement-preview-message {
    color: #CDD6C1;
    font-size: 12.5px;
    line-height: 1.4;
    margin-top: 10px;
    white-space: pre-wrap;
}

.achievement-preview-stats {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.achievement-preview-stat {
    flex: 1;
    background: rgba(179, 201, 156, 0.14);
    border: 1px solid rgba(179, 201, 156, 0.3);
    border-radius: 10px;
    padding: 8px 10px;
}

.achievement-preview-stat-value {
    color: #B3C99C;
    font-weight: 800;
    font-size: 14px;
}

.achievement-preview-stat-label {
    color: #CDD6C1;
    font-size: 10px;
}

.achievement-preview-cta {
    margin-top: 14px;
}

.achievement-preview-cta-button {
    display: inline-block;
    border: 1.5px solid #B3C99C;
    color: #B3C99C;
    font-size: 12px;
    font-weight: 700;
    padding: 6px 14px;
    border-radius: 100px;
}

.achievement-preview-cta-note {
    color: #A49D90;
    font-size: 11px;
    margin-top: 6px;
}

.achievement-preview-cta-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.admin-roster-team summary {
    cursor: pointer;
    font-size: 14px;
}

.admin-roster-team table {
    margin-top: 10px;
}

.admin-roster-add-member {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed #ddd;
}

.admin-roster-add-member select,
.admin-roster-add-member input[type="text"] {
    margin-bottom: 6px;
}

.admin-roster-delete-team {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed #ddd;
}

.admin-nowrap {
    white-space: nowrap;
}

.admin-roster-create-team {
    margin-bottom: 14px;
    padding-bottom: 14px;
    border-bottom: 1px solid #eee;
}

#manageRosterCreateTeamForm {
    margin-top: 10px;
}

.admin-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--sv-border);
}

.admin-modal-header h3 {
    margin: 0;
}

.admin-modal-close {
    background: none;
    border: none;
    border-radius: 50%;
    width: 30px;
    height: 30px;
    font-size: 22px;
    line-height: 1;
    color: #888;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    transition: background .12s var(--sv-ease), color .12s var(--sv-ease);
}

.admin-modal-close:hover {
    background: #f0f1f2;
    color: #333;
}

.admin-modal .admin-image-preview {
    margin-top: 8px;
}

.admin-image-preview {
    cursor: zoom-in;
}

.admin-lightbox-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 200;
    padding: 40px;
}

.admin-lightbox-overlay img {
    max-width: 100%;
    max-height: 100%;
    border-radius: 6px;
    cursor: default;
}

.admin-lightbox-close {
    position: absolute;
    top: 16px;
    right: 24px;
    color: #fff;
    font-size: 32px;
}

.admin-inactive-badge {
    background: #ccc;
    color: #555;
    font-size: 11px;
    font-weight: bold;
    padding: 2px 8px;
    border-radius: 10px;
}

.admin-test-event-badge {
    background: #fff3cd;
    color: #856404;
    font-size: 11px;
    font-weight: bold;
    padding: 2px 8px;
    border-radius: 10px;
    margin-left: 6px;
}

.admin-archived-badge {
    background: #e0e0e0;
    color: #555;
    font-size: 11px;
    font-weight: bold;
    padding: 2px 8px;
    border-radius: 10px;
    margin-left: 6px;
}

.admin-show-archived-label {
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    margin-bottom: 0;
}

.admin-row-inactive {
    opacity: .55;
}

.admin-row-past {
    opacity: .55;
}

.reward-vendor-line {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: #666;
    margin: 4px 0;
}

.reward-vendor-logo {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    object-fit: cover;
}

.reward-vendor-logo-fallback {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #3E6B47;
    color: #fff;
    font-size: 9px;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
}

.show-qr-button {
    margin-left: 8px;
    padding: 6px 10px;
    border: 1px solid #3E6B47;
    border-radius: 12px;
    background: #fff;
    color: #3E6B47;
    font-size: 11px;
    cursor: pointer;
}

.qr-detail-box {
    text-align: center;
    padding: 12px;
    background: #f7f7f7;
    border-radius: var(--sv-radius-md);
}

.qr-detail-box p {
    font-size: 13px;
    color: #555;
    margin: 0 0 8px;
}

/* Admin Zone: Manage Roles modal -- one bordered "row" per vendor/chapter
   scope grant, each holding a picker + its own role-chip group (reuses
   .admin-checkbox-group/.admin-checkbox-option for the chips themselves). */
.admin-scope-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
    border: 1px solid #ddd;
    border-radius: 6px;
    padding: 10px;
    margin-bottom: 8px;
    background: #fafafa;
}

.admin-scope-row-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

/* Amber "known issue" disclosure -- lower-severity than .admin-warning-hint
   (which is red, "you're about to lose access"). Remove once the linked
   issue ships. */
.admin-known-issue-note {
    margin-top: 8px;
    padding: 8px 10px;
    border: 1px solid var(--sv-trailblaze);
    border-radius: 6px;
    background: var(--sv-trailblaze-tint);
    color: var(--sv-trailblaze-dark);
    font-size: 13px;
}

/* Shown when unchecking Super Admin mid-edit -- same warning-box treatment
   as .admin-manage-targets-geocode-retry, just red instead of amber since
   this is a "you're about to lose access" warning, not a retry prompt. */
.admin-warning-hint {
    padding: 8px 10px;
    border: 1px solid var(--sv-rose);
    border-radius: 6px;
    background: #B0483A18;
    color: var(--sv-rose);
    font-weight: bold;
}
