/* ScanRaise - Design tokens and base styles */

/* HTML [hidden] attribute must beat any CSS display rule. Without this,
   buttons toggled hidden via JS keep rendering when component CSS uses
   display:flex/grid (caught session 16 on /live overlays, session 17
   on /login SSO buttons). Site-wide via this core stylesheet. */
[hidden] { display: none !important; }

:root {
    --accent: #2563eb;
    --accent-light: #eff6ff;
    --text-primary: #111827;
    --text-secondary: #4b5563;
    /* Was #9ca3af, which is 3.0:1 on white and FAILS WCAG 2.1 AA (4.5:1
       required for normal text). Lifted to #6b7280 (5.74:1). Cascades to
       every consumer: .stat .label, th, .muted, .feature-card .desc,
       .org-card .meta, .txt-muted-*, .au* auto-utils, login subdivider
       labels, and ~25 other places that all use var(--text-muted). */
    --text-muted: #6b7280;
    /* Stronger muted for very-small (<= 12px) usage where extra contrast
       margin matters. Used by table headers and dense badges. */
    --text-muted-strong: #4b5563;
    --border: #e5e7eb;
    --bg: #ffffff;
    --bg-muted: #f9fafb;
}

/* Anchor-link scroll offset.
 * The site nav is sticky at ~64px tall. Without this, clicking an in-page
 * anchor (e.g. /help#sso-microsoft, /faq#section10) scrolls the target
 * heading UNDER the nav and the user lands mid-paragraph. scroll-padding-top
 * adds the offset for any scroll-into-view operation, including hash
 * navigation and JS scrollIntoView() calls. 80 = 64 nav + 16 breathing room.
 */
html {
    scroll-padding-top: 80px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    color: var(--text-primary);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    /* The nav is rendered into the DOM by nav.js after page parse and is
       position: fixed (below). Reserve its 65px slot here so the rest of
       the page lays out at the correct y-offset from the very first paint,
       eliminating the layout-jump that used to happen when nav.js inserted
       the nav node into the document. */
    padding-top: 65px;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Global nav */
.site-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    max-width: 1100px;
    margin: 0 auto;
    padding: 16px 24px;
    background: white;
    position: sticky;
    top: 0;
    z-index: 1000;
}
.site-nav-border {
    border-bottom: 1px solid var(--border);
    background: white;
    /* Was sticky, which only worked once the element was in flow and
       caused a 65px layout-shift when nav.js inserted it. fixed takes
       the element out of flow entirely; body padding-top reserves the
       slot so content lays out correctly from first paint. */
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1000;
}
.site-nav .logo {
    font-size: 24px;
    font-weight: 800;
    color: var(--text-primary);
    text-decoration: none;
    letter-spacing: -0.3px;
}
.site-nav .logo span { color: var(--accent); }
.site-nav .logo:hover { text-decoration: none; }

/* Prevent nav layout shift on first paint:
   1. Reserve dimensions for Lucide icon placeholders so when Lucide loads
      async and replaces the empty <i data-lucide="..."> with a sized SVG,
      surrounding text doesn't jump.
   2. Hide the entire nav-border wrapper until nav.js finishes building it
      and adds .nav-ready (set in next animation frame so icons can render).
   Was causing visible nav jump on every page load. */
.site-nav .logo > i,
.site-nav .logo > svg,
.site-nav .nav-hamburger > i,
.site-nav .nav-hamburger > svg,
.site-nav .nav-close > i,
.site-nav .nav-close > svg {
    display: inline-block;
    width: 22px;
    height: 22px;
    vertical-align: middle;
    flex-shrink: 0;
}
.site-nav-border:not(.nav-ready) { visibility: hidden; }
.site-nav .nav-links {
    display: flex;
    align-items: center;
    gap: 24px;
}
.site-nav .nav-links a {
    font-size: 14px;
    font-weight: 500;
    color: var(--text-secondary);
    text-decoration: none;
}
.site-nav .nav-links a:hover {
    color: var(--text-primary);
    text-decoration: none;
}
.site-nav .nav-cta {
    display: inline-block;
    padding: 8px 18px;
    background: var(--accent);
    color: white !important;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    transition: opacity 0.15s;
}
.site-nav .nav-cta:hover { opacity: 0.9; }

/* Card-layout dropdown shown next to "Download printable cards" buttons.
   Used on the org dashboard, campaign-created page, and group page.
   Visual matches the secondary-button border/font so the dropdown reads
   as a paired control rather than a foreign select. */
.card-layout-select {
    font-size: 13px;
    padding: 7px 10px;
    border: 1.5px solid var(--border, #e5e7eb);
    border-radius: 6px;
    background: white;
    color: var(--text-primary, #111);
    cursor: pointer;
    font-family: inherit;
}
.card-layout-select:hover { border-color: var(--accent, #2563eb); }
.card-layout-select:focus { outline: 2px solid var(--accent, #2563eb); outline-offset: 2px; }

/* Tablet */
@media (max-width: 768px) {
    .grid-2 { grid-template-columns: 1fr !important; }
    .stats { grid-template-columns: repeat(2, 1fr) !important; }
    table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .wrap { padding: 20px 16px 60px; }
    .head { flex-direction: column; gap: 12px; }
    .head h1 { font-size: 24px; }
}

/* Small desktop - full nav bar, hamburger hidden */
@media (min-width: 1024px) {
    .site-nav .nav-links a.hide-mobile { display: inline; }
    .nav-hamburger { display: none !important; }
    .nav-close { display: none !important; }
    .site-nav .nav-links {
        position: static !important;
        width: auto !important;
        height: auto !important;
        flex-direction: row !important;
        box-shadow: none !important;
        padding: 0 !important;
        background: transparent !important;
    }
}

/* Standard desktop */
@media (min-width: 1440px) {
    .wrap { max-width: 1200px; }
}

/* Large desktop (1080p) */
@media (min-width: 1920px) {
    .wrap { max-width: 1400px; }
}

/* Ultra-wide / 4K */
@media (min-width: 2560px) {
    .wrap { max-width: 1600px; }
}

/* Mobile */
@media (max-width: 500px) {
    .site-nav .nav-links { gap: 14px; }
    .stats { grid-template-columns: 1fr 1fr !important; gap: 8px; }
    .stat { padding: 14px; }
    .stat .value { font-size: 22px; }
    .section { padding: 16px; }
    .section h2 { font-size: 16px; }
    .filter-bar { flex-direction: column; }
    .filter-bar input, .filter-bar select, .filter-bar button { width: 100%; }
    .btn { padding: 10px 16px; font-size: 13px; }
    .group-card { flex-direction: column; align-items: flex-start; }
}

/* Small mobile */
@media (max-width: 375px) {
    .site-nav { padding: 12px 16px; }
    .site-nav .logo { font-size: 20px; }
    .site-nav .nav-cta { padding: 6px 14px; font-size: 13px; }
    .wrap { padding: 16px 12px 60px; }
    .stats { grid-template-columns: 1fr !important; }
}

/* Nav icon sizing. Width/height set on the <i data-lucide> placeholder
   AND on the SVG it gets replaced with, so Lucide swap doesn't change
   the box dimensions. Without this the logo briefly collapses to 0x0
   while Lucide loads, then pops to 29x29, shifting the wordmark. */
/* Logo QR mark sizing + alignment baseline (low specificity defaults).
   Overridden by the .site-nav scoped rule below for the nav-bar logo. */
.logo-icon { width: 29px; height: 29px; vertical-align: 2px; margin-right: 3px; display: inline-block; color: #0f172a; }
i.logo-icon { line-height: 0; }
/* In-nav logo: 26x26 (looks balanced against the 24px wordmark
   cap-height), inherits vertical-align: middle from the shared rule
   so the line-box stays predictable across Chrome and Safari (no
   65.5px Safari overflow). Visual offset done via position: relative
   instead of vertical-align — keeps the icon's bounding-box flow at
   middle while painting it 3px lower so it sits on the wordmark's
   optical center (the wordmark's lowercase descenders pull its
   visual center below the geometric middle). Color override beats
   the global [data-lucide] accent paint. */
.site-nav .logo > i.logo-icon,
.site-nav .logo > svg.logo-icon {
    width: 26px;
    height: 26px;
    color: #0f172a;
    position: relative;
    top: -2px;
}
.site-nav .logo .logo-icon svg path,
.site-nav .logo .logo-icon svg rect,
.site-nav .logo .logo-icon svg line { stroke: #0f172a; }
.nav-hamburger i, .nav-close i { display: inline-block; width: 24px; height: 24px; line-height: 0; }

/* Lucide swap color fix. Lucide replaces every <i data-lucide="..."> with
   an inline <svg> after page load. Page CSS that targeted `i` selectors
   (e.g. `.mode i { color: var(--accent) }`, `.feat i { color }`,
   `.benefit i { color }`, `.pain i { color }`) silently misses after the
   swap because the element is now an <svg>, and icons render in the
   parent's text color (typically near-black) instead of brand blue.
   Solution: target by the data-lucide attribute, which Lucide preserves
   on the swapped <svg>. This globally tints every Lucide icon brand-blue
   unless a more specific rule overrides (e.g. red x-circle, green check). */
[data-lucide] { color: var(--accent); }

/* Hamburger menu button - hidden on desktop, visible below 1024px */
.nav-hamburger {
    display: none;
    background: none;
    border: none;
    cursor: pointer;
    padding: 8px;
    color: var(--text-primary);
    line-height: 0;
}
.nav-hamburger svg { width: 24px; height: 24px; }

/* Close button inside mobile menu - hidden on desktop */
.nav-close {
    display: none;
    background: none;
    border: none;
    cursor: pointer;
    padding: 8px;
    color: var(--text-primary);
    line-height: 0;
    align-self: flex-end;
}
.nav-close svg { width: 24px; height: 24px; }

/* Mobile nav (< 1024px) */
@media (max-width: 1023px) {
    .nav-hamburger { display: block; }
    .nav-close { display: block; }

    .site-nav .nav-links {
        position: fixed;
        top: 0;
        right: -100%;
        width: 280px;
        height: 100vh;
        background: white;
        flex-direction: column;
        align-items: flex-start;
        padding: 24px;
        gap: 0;
        box-shadow: -4px 0 24px rgba(0,0,0,0.12);
        transition: right 0.25s ease;
        z-index: 10001;
        overflow-y: auto;
    }
    .site-nav .nav-links.nav-open {
        right: 0;
    }
    /* Apply the row-with-divider treatment to every top-level link inside
       the mobile drawer, not just .hide-mobile. Without this, plain
       anchors (Pricing / How it works / Help / Find QR / Sign in) collapse
       into a tight unspaced stack with no breathing room or tap targets. */
    .site-nav .nav-links a.hide-mobile,
    .site-nav .nav-links > a:not(.nav-cta),
    .site-nav .nav-utility > a:not(.nav-cta) {
        display: block;
        width: 100%;
        padding: 14px 0;
        border-bottom: 1px solid var(--border);
        font-size: 16px;
        color: var(--text-primary);
        min-height: 44px;
        line-height: 1.4;
    }
    .site-nav .nav-utility > a:not(.nav-cta):last-of-type {
        border-bottom: none;
    }
    .site-nav .nav-links .nav-cta {
        margin-top: 16px;
        text-align: center;
        width: 100%;
        padding: 12px 18px;
    }
}

/* Backdrop overlay when mobile menu is open. Lives on <body> via
   data-nav-open attribute, NOT as a ::before of .nav-links. The pseudo-
   element approach broke because .nav-links creates its own stacking
   context (z-index: 10001) and a ::before with z-index: -1 inside that
   context paints OVER the parent's background, turning the white panel
   gray and making text unreadable. Body-level pseudo dodges that.

   But: .nav-links is nested inside .site-nav-border (z-index: 1000,
   position: fixed) which itself creates a stacking context. The body
   backdrop at z=10000 paints ABOVE that nav wrapper's stacking context,
   so it dims the panel along with the page. Hoist the nav wrapper to
   z=10002 while the menu is open so the panel's z=10001 within its
   parent's context still ends up above the body backdrop. */
body[data-nav-open="1"]::before {
    content: '';
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.45);
    z-index: 10000;
    pointer-events: none;
}
body[data-nav-open="1"] .site-nav-border {
    z-index: 10002;
}

/* ── Accessibility styles (moved from a11y.css so every page that loads
   scanraise.css gets them - the old a11y.css was only linked from 4 of 45
   pages, causing the skip-to-content link to render visibly unstyled and
   focus indicators to be missing on subpages). ───────────────────────── */

.sr-skip-link {
    position: absolute;
    top: -100px;
    left: 16px;
    background: #2563eb;
    color: #fff;
    padding: 12px 24px;
    border-radius: 0 0 8px 8px;
    font-weight: 700;
    font-size: 14px;
    z-index: 100000;
    text-decoration: none;
    transition: top 0.15s ease;
}
.sr-skip-link:focus {
    top: 0;
    outline: 3px solid #f59e0b;
    outline-offset: 2px;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid #2563eb;
    outline-offset: 2px;
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

@media (forced-colors: active) {
    .nav-cta, .btn, button {
        border: 2px solid ButtonText;
    }
}
