/* SinglePager Portal — design system on top of DaisyUI v5 + Tailwind v4 */

/* ── Body font ─────────────────────────────────────────────────────────── */
body { font-family: 'Inter', ui-sans-serif, system-ui, sans-serif; color: #3A3A3A; }

/* ── Corporate theme: modern rounded corners ───────────────────────────── */
[data-theme="corporate"] {
    --rounded-box:   0.75rem;
    --rounded-btn:   0.5rem;
    --rounded-badge: 1rem;
    --tab-radius:    0.375rem;
}

/* ── Number input: hide spin arrows ────────────────────────────────────── */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* ── Sidebar nav link ───────────────────────────────────────────────────── */
.nav-link { display: flex; align-items: center; gap: 0.5rem; }

/* ── Helper-text labels: wrap instead of overflowing narrow columns ────────── */
.label:has(> .label-text-alt:only-child) {
    white-space: normal;
    height: auto;
}

/* ── Table: column headers ──────────────────────────────────────────────── */
.table thead th {
    font-size: 0.8125rem;
    text-transform: none;
    letter-spacing: normal;
    font-weight: 700;
    color: #1f2937;
    opacity: 1;
    border-bottom: 2px solid #e5e7eb;
}

/* ── Template / module card selection ───────────────────────────────────── */
.template-card.selected {
    border-color: var(--color-primary, #0068a7) !important;
    background: rgba(0, 104, 167, 0.05) !important;
}
.module-card.selected {
    border-color: var(--color-primary, #0068a7) !important;
    background: color-mix(in srgb, var(--color-primary, #0068a7) 5%, transparent) !important;
}

/* ── Transition helper ──────────────────────────────────────────────────── */
.transition-all { transition: all 0.2s ease; }

/* ═══════════════════════════════════════════════════════════════════════════
   DESIGN SYSTEM — Clean & Premium
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Brand tokens ───────────────────────────────────────────────────────── */
:root {
    --sp-primary:       #0068a7;
    --sp-primary-dark:  #005590;
    --sp-primary-rgb:   0, 104, 167;
    --sp-surface:       #f8fafc;
    --sp-border:        #e2e8f0;
    --sp-text-muted:    #64748b;
    --sp-shadow-sm:     0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04);
    --sp-shadow-md:     0 4px 12px rgba(0,0,0,.08), 0 2px 4px rgba(0,0,0,.04);
    --sp-shadow-lg:     0 10px 32px rgba(0,0,0,.10), 0 4px 12px rgba(0,0,0,.06);
}

/* ── Gradient hero backgrounds ──────────────────────────────────────────── */
.hero-gradient {
    background: linear-gradient(135deg, #004f82 0%, var(--sp-primary) 50%, #0090d4 100%);
}
.hero-gradient-dark {
    background: linear-gradient(145deg, #0d1f35 0%, #0b3d6b 50%, var(--sp-primary) 100%);
}

/* ── Status icon circles ────────────────────────────────────────────────── */
.status-circle {
    width: 80px; height: 80px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    margin: 0 auto 1.25rem;
}
.status-circle.success { background: rgba(34,197,94,.12); color: #16a34a; }
.status-circle.error   { background: rgba(239,68,68,.12);  color: #dc2626; }
.status-circle.warning { background: rgba(245,158,11,.12); color: #d97706; }
.status-circle.info    { background: rgba(var(--sp-primary-rgb),.12); color: var(--sp-primary); }
.status-circle.neutral { background: #f1f5f9; color: #64748b; }

/* ── Receipt row ────────────────────────────────────────────────────────── */
.receipt-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.625rem 0;
    border-bottom: 1px solid var(--sp-border);
    font-size: 0.875rem;
    gap: 1rem;
}
.receipt-row:last-child { border-bottom: none; }
.receipt-label { color: var(--sp-text-muted); flex-shrink: 0; }
.receipt-value { font-weight: 500; text-align: right; overflow-wrap: break-word; }

/* ── Section label (small uppercase) ───────────────────────────────────── */
.section-label {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--sp-text-muted);
}

/* ── Product card hover ─────────────────────────────────────────────────── */
.product-card {
    transition: box-shadow 0.2s ease, transform 0.15s ease;
}
.product-card:hover {
    box-shadow: var(--sp-shadow-lg);
    transform: translateY(-2px);
}

/* ── Scrollbar hidden ───────────────────────────────────────────────────── */
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

/* ── Page scrollbar: overlay style, invisible until the page is scrolled ──
   Thumb stays transparent at rest; JS (base.html) toggles .is-scrolling on
   <html> while a scroll is in progress (and briefly after), which is the
   only way to detect "currently scrolling" — pure CSS :hover only covers
   mouse position, not scroll activity. */
html {
    scrollbar-gutter: auto;
}
::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}
::-webkit-scrollbar-track {
    background: transparent;
}
::-webkit-scrollbar-thumb {
    background-color: transparent;
    border-radius: 8px;
}
html.is-scrolling::-webkit-scrollbar-thumb {
    background-color: rgba(0, 0, 0, 0.25);
}

/* ── Checkout step indicator ────────────────────────────────────────────── */
.step-pill {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.5rem; height: 1.5rem; border-radius: 50%;
    background: var(--sp-primary); color: white;
    font-size: 0.75rem; font-weight: 700; flex-shrink: 0;
}

/* ── Safe primary foreground: text/icons/borders using the merchant's ────
   Primary Color AS a foreground color against a white/light card (prices,
   category labels, "Powered by" icon, selected-thumbnail border) instead of
   as a filled button/badge background. Regular text-primary/border-primary
   just reflect --color-primary verbatim, so a merchant-chosen white (or any
   very light) Primary Color makes them disappear against the same white
   card. --color-primary-text (set in layouts/base.html, darkened until it
   clears WCAG 4.5:1 against white) is the readable stand-in; the fallback
   chain covers pages where no merchant branding override is present. */
.text-primary-safe { color: var(--color-primary-text, var(--color-primary, var(--sp-primary))) !important; }
.border-primary-safe { border-color: var(--color-primary-text, var(--color-primary, var(--sp-primary))) !important; }

/* ── Toggle switches: fixed airpay blue when enabled, regardless of any ─── */
/* per-merchant brand color override (unlike toggle-primary, which follows  */
/* --color-primary and would shift with the merchant's own branding).       */
.toggle-airpay-blue:checked,
.toggle-airpay-blue[aria-checked="true"] {
    --input-color: #0068a7;
}

/* ── Publish/Unpublish globe icon: fixed airpay blue on hover ───────────── */
#btnUnpublish:hover .bx-globe,
#btnPublish:hover .bx-globe,
button[title="Unpublish"]:hover .bx-globe,
button[title="Publish Now"]:hover .bx-globe {
    color: #0068a7;
}

/* ── Publish/Unpublish buttons: fixed width so the strip doesn't reflow ── */
/* when toggling between "Publish Now" and "Unpublish" (different text    */
/* lengths would otherwise resize the button/card on every state change). */
#btnUnpublish, #btnPublish,
button[title="Unpublish"], button[title="Publish Now"] {
    min-width: 7.5rem;
    justify-content: center;
}

/* ── Full-bleed alerts ──────────────────────────────────────────────────────
   The test-mode / preview banners are DaisyUI alerts that span the viewport,
   and a box radius on a full-width bar reads as a mistake. Tailwind's
   rounded-none would need a CSS rebuild to exist; this does not. */
.alert.sp-bleed { border-radius: 0; }

/* ── Softer daisyUI hover-3d tilt ──────────────────────────────────────────
   daisyUI hardcodes rotate3d(..., 10deg) plus a 1.05 hover scale, which on a
   card- or logo-sized element reads as a flip rather than a tilt. Same
   direction logic (--transform still comes from the quadrant under the
   cursor), gentler angle. Global so the landing cards, the school logo and the
   event banner can't drift apart. Unlayered, so it wins over the @layer'd
   component rule regardless of source order. */
.hover-3d > :first-child { transform: rotate3d(var(--transform), 0, 2.5deg); }
.hover-3d:hover > :first-child { scale: 1.02; }

@media (prefers-reduced-motion: reduce) {
    /* Flat and still clickable. */
    .hover-3d > :first-child,
    .hover-3d:hover > :first-child {
        transform: none;
        scale: 1;
        transition: none;
    }
}

/* ── "Opens in" countdown (partials/countdown_script.html) ─────────────────
   Chrome/labels only — the digit strip itself is DaisyUI's .countdown. Both
   renderings live here rather than in the two pages' own <style> blocks so the
   pill and the panel can't drift apart. Colours follow the site's brand var
   with the storefront blue as fallback, matching every other public surface. */
.sl-countdown { padding-block: .22rem; }
.sl-cd-title {
    font-size: .6rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: .03em;
    text-transform: uppercase;
    white-space: nowrap;
    opacity: .85;
}
.sl-cd-label {
    font-size: .55rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: .04em;
    text-transform: uppercase;
    opacity: .7;
}
.sp-cd-title {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #8a9bb0;
    margin-bottom: .6rem;
}
.cd-panel .countdown { color: var(--pl-primary, #0068a7); }
.cd-panel-label {
    margin-top: .3rem;
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #8a9bb0;
}

/* ── Field labels: size, and where the required asterisk sits ─────────────
   daisyUI never gives .fieldset-legend / .fieldset-label a font-size of their
   own — they inherit it from .fieldset, which sets .75rem. Almost every form
   in this app lays its fields out in a plain grid instead of a real <fieldset>,
   so both inherited the page's 16px while the text-sm / text-xs hints sitting
   right beside them did not. That is the "three different font sizes on one
   form" the Add/Edit Event modal shows.

   Sized explicitly here so a label no longer depends on an ancestor that isn't
   there; the second rule of each pair hands the real <fieldset> forms
   (campaign_form.html and friends) back exactly what they render today. */
.fieldset-legend           { font-size: 0.875rem; }
.fieldset .fieldset-legend { font-size: 0.75rem; }
.fieldset-label            { font-size: 0.75rem; }
.fieldset .fieldset-label  { font-size: inherit; }

/* .fieldset-legend is also a flex row with justify-content:space-between and
   gap:.5rem. On a shrink-to-fit <legend> that is invisible, which is why the
   storefront never showed it — but the admin forms use
   <label class="fieldset-legend">, which FILLS its grid cell. The required
   asterisk was therefore thrown to the far right of the column, landing beside
   the NEXT field's label ("Event Title            *  Event Type").

   Start-aligned with the gap collapsed, so the asterisk sits against the word
   it belongs to. payment/formbuilder.html carries its own inline copy of the
   two gap rules; this supersedes it. */
.fieldset-legend { justify-content: flex-start; gap: 0; }
.fieldset-legend .text-error { margin-left: 0.1em; }

/* .label-text-alt has NO rule in the built CSS at all, so every
   "Accepted formats: … Max file size: … MB" upload hint rendered at full body
   size in the default text colour — the loudest line under the field instead
   of the quietest, and a third size next to the two above. Matched to
   .fieldset-label, which is what the sibling hint on the same field uses. */
.label-text-alt {
    font-size: 0.75rem;
    color: color-mix(in oklab, var(--color-base-content) 60%, transparent);
}

/* ── Row actions: keep them on one line ───────────────────────────────────
   The action cells (Pay Link / send / ⋮) held loose inline elements, so they
   wrapped onto two or three lines at narrow widths and every row ended up a
   different height with the buttons staggered. One flex row, no wrapping.

   flex-START, not flex-end: every other column in the roster reads from the
   left, so a right-aligned action column left its header ("Quick Pay Link",
   "Actions") floating away from the buttons it named and made the header row
   look ragged. The headers are plain left-aligned <th>s to match — see
   admin/students.html.

   Used only by admin/students.html (roster, attendee and walk-in tables); no
   other module's list reads this class. */
.row-actions {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.25rem;
    flex-wrap: nowrap;
}

/* ── Print styles ───────────────────────────────────────────────────────── */
/* margin:0 on @page suppresses the browser's own header/footer band (URL,
   date/time, page number) — that band is drawn inside the page margin, so
   zeroing it removes the browser chrome instead of just hiding it. Content
   would then run edge-to-edge, so the lost margin is restored on body so the
   printed page still has breathing room. */
@page {
    margin: 0;
}
@media print {
    body {
        margin: 1.5cm;
    }
    .no-print { display: none !important; }
    .navbar { display: none !important; }
    footer { display: none !important; }
    .card {
        box-shadow: none !important;
        border: 1px solid #ccc !important;
    }
    .break-all {
        word-break: break-word !important;
        overflow-wrap: break-word !important;
    }
    .break-words {
        overflow-wrap: break-word !important;
    }
    .print-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    /* Items table: table-layout:fixed is set inline on the element, but a
       browser's print engine can still ignore it unless reinforced here —
       same reasoning as .break-all/.break-words above. Without this a long
       unbroken product name can grow the Product column in print even though
       it wraps correctly on screen. */
    table[style*="table-layout:fixed"] { table-layout: fixed !important; }
}
