* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
    margin: 0; font-family: var(--font-sans); color: var(--color-text);
    background: var(--color-bg-gradient), var(--color-bg);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
}
a { color: var(--color-accent); text-decoration: none; }
a:hover { color: var(--color-accent-hover); }
svg { display: block; }

/* Accessible, visible focus ring everywhere — never remove without a replacement */
:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
    border-radius: var(--radius-sm);
}
button, [role="button"], .nav-item, a { cursor: pointer; }

/* ── App shell ────────────────────────────────────────────────────────────── */
.saas-shell { display: flex; min-height: 100vh; }
.saas-sidebar {
    width: var(--sidebar-width); background: var(--color-sidebar-bg);
    -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
    border-right: 1px solid var(--color-sidebar-border);
    display: flex; flex-direction: column; position: sticky; top: 0; overflow-y: auto;
    flex-shrink: 0; transition: transform var(--transition-slow); z-index: 200;
    /* 100vh on mobile browsers is the LARGEST possible viewport (toolbar
       hidden) — with the address bar/bottom toolbar actually showing, the
       real visible area is shorter, so a sidebar sized to 100vh runs past
       the bottom of the screen and the theme-toggle/log-out row in
       .sidebar-footer ends up rendered behind that browser chrome. 100dvh
       tracks the actual visible viewport; browsers without dvh support just
       ignore that line and keep the 100vh fallback above it. */
    height: 100vh; height: 100dvh;
}
.sidebar-header { padding: var(--space-6) var(--space-5) var(--space-4); }
.sidebar-logo {
    display: flex; align-items: center; gap: var(--space-2); text-decoration: none;
    color: #fff; font-weight: 800; font-size: var(--text-lg); letter-spacing: -.01em;
}
/* Heights are tuned to the current wordmark's ~3.6:1 aspect ratio so the
   rendered width fits its container (264px sidebar, ~408px auth card) —
   a wider or narrower logo file needs these re-checked, not just height. */
.logo-img { height: 58px; width: auto; display: block; }
.logo-img-lg { height: 90px; width: auto; display: block; }
/* .mobile-header is a fixed --header-height (64px) bar — the desktop
   sidebar-header size above would overflow it, so this context gets its
   own smaller, still-larger-than-before size. */
.mobile-header .logo-img { height: 42px; }
/* Auth/legal cards go near-full-width below ~480px, leaving less room than
   the desktop card this size was tuned for — shrink to fit. */
@media (max-width: 480px) {
    .logo-img-lg { height: 64px; }
}
.sidebar-nav { flex: 1; padding: var(--space-2) var(--space-3); }
.nav-group { margin-bottom: var(--space-5); }
/* Permission-gated nav groups: hidden by default so there's no flash of a
   super-admin/role-gated section before applyPermissionVisibility() runs —
   JS explicitly reveals these for users who qualify, it never needs to hide
   them (that's already the resting state). */
[data-requires-permission], [data-requires-super-admin] { display: none; }
.nav-group-label {
    display: block; padding: var(--space-2) var(--space-3); font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em; color: var(--color-sidebar-text); opacity: .55;
}
.nav-item {
    display: flex; align-items: center; gap: var(--space-3); min-height: 44px;
    padding: var(--space-2) var(--space-3); border-radius: var(--radius-md);
    color: var(--color-sidebar-text); text-decoration: none; font-size: var(--text-sm); font-weight: 500;
    transition: background var(--transition), color var(--transition);
}
.nav-item svg { width: 18px; height: 18px; flex-shrink: 0; opacity: .85; }
.nav-item:hover { background: rgba(255,255,255,0.06); color: #fff; }
.nav-item.active { background: var(--color-sidebar-active-bg); color: var(--color-sidebar-active); }
.nav-item.active svg { opacity: 1; color: var(--color-sidebar-accent); }

/* ── Plan gating (premium feature upsell) — see js/plan-gate.v1.js ─────────── */
.plan-gate-badge {
    margin-left: auto; font-size: 10px; font-weight: 800; letter-spacing: .04em;
    padding: 2px 7px; border-radius: var(--radius-full); background: var(--color-accent-pink);
    color: var(--color-on-accent-pink); flex-shrink: 0;
}
/* .plan-gate-wrap holds nothing but the blurred container, so it's always
   exactly that container's size — the overlay's inset:0 below lines up
   with it precisely and can't bleed into unrelated regions that happen to
   share the container's original parent (see js/plan-gate.v1.js). */
.plan-gate-wrap { position: relative; }
.plan-gate-blurred { filter: blur(4px); pointer-events: none; user-select: none; }
.plan-gate-overlay {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    padding: var(--space-6); z-index: 50;
}
.plan-gate-card {
    max-width: 380px; width: 100%; text-align: center; background: var(--color-surface);
    border: 1px solid var(--color-border); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg);
    padding: var(--space-8) var(--space-6);
}
.plan-gate-icon {
    width: 56px; height: 56px; margin: 0 auto var(--space-4); border-radius: var(--radius-lg);
    background: var(--color-accent-pink);
    display: flex; align-items: center; justify-content: center; font-size: 24px; color: var(--color-on-accent-pink);
}
.plan-gate-icon svg { width: 26px; height: 26px; }
.plan-gate-tag {
    display: inline-block; font-size: var(--text-xs); font-weight: 700; letter-spacing: .03em;
    color: var(--color-accent-pink); background: var(--color-accent-pink-light); padding: 3px 10px;
    border-radius: var(--radius-full); margin-bottom: var(--space-3);
}
.plan-gate-title { margin: 0 0 var(--space-2); font-size: var(--text-xl); }
.plan-gate-desc { margin: 0 0 var(--space-5); font-size: var(--text-sm); color: var(--color-text-muted); line-height: 1.6; }
.plan-gate-cta { width: 100%; }
.plan-gate-cta svg { width: 16px; height: 16px; }
.plan-gate-caption { margin: var(--space-4) 0 0; font-size: var(--text-xs); color: var(--color-text-subtle); }

@media (max-width: 640px) {
    .plan-gate-overlay { padding: var(--space-4); }
    .plan-gate-card { padding: var(--space-6) var(--space-4); }
    .plan-gate-icon { width: 48px; height: 48px; font-size: 20px; }
    .plan-gate-icon svg { width: 22px; height: 22px; }
    .plan-gate-title { font-size: var(--text-lg); }
    .plan-gate-desc { font-size: var(--text-xs); margin-bottom: var(--space-4); }
}
.sidebar-footer {
    padding: var(--space-4); border-top: 1px solid var(--color-sidebar-border);
    display: flex; align-items: center; gap: var(--space-2);
    /* On notched/gesture-nav phones the theme toggle + log out row sits right
       at the screen edge — env(safe-area-inset-bottom) (only non-zero once
       the viewport meta has viewport-fit=cover) keeps it clear of the iOS
       home indicator / Android gesture bar. calc() with the fallback first
       means browsers without env() support just keep the plain space-4. */
    padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
}

.saas-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* ── Impersonation banner ─────────────────────────────────────────────────── */
.impersonation-banner {
    display: none; align-items: center; justify-content: center; gap: var(--space-4); flex-wrap: wrap;
    height: 44px; background: var(--color-warning); color: #211a06; font-size: var(--text-sm); font-weight: 700;
    padding: 0 var(--space-4); position: sticky; top: 0; z-index: 60; text-align: center;
}
.impersonation-banner .btn {
    background: #211a06; color: var(--color-warning); border-color: transparent; min-height: 30px; padding: var(--space-1) var(--space-3);
}
.impersonation-banner .btn:hover { background: #372c0d; }
body.impersonating .impersonation-banner { display: flex; }
body.impersonating .page-header { top: 44px; }

.page-header {
    padding: var(--space-6) var(--space-8); border-bottom: 1px solid var(--color-border);
    background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
    position: sticky; top: 0; z-index: 50;
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-4);
}
.page-title { font-size: var(--text-2xl); font-weight: 800; margin: 0; letter-spacing: -.01em; }
.page-subtitle { font-size: var(--text-sm); color: var(--color-text-muted); margin: var(--space-1) 0 0; }
.page-content { padding: var(--space-8); flex: 1; max-width: var(--content-max-width); }

/* ── User menu (header profile dropdown) ─────────────────────────────────── */
.user-menu { position: relative; }
.user-menu-trigger {
    display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-3) var(--space-1) var(--space-1);
    border: 1px solid var(--color-border); border-radius: var(--radius-full); background: var(--color-surface);
    cursor: pointer; transition: var(--transition); font-family: inherit; min-height: 44px;
}
.user-menu-trigger:hover { background: var(--color-surface-2); }
.user-menu-avatar {
    width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg, var(--color-accent), var(--color-accent-strong));
    color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: var(--text-sm);
    flex-shrink: 0;
}
.user-menu-name { font-size: var(--text-sm); font-weight: 600; color: var(--color-text); max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-trigger svg { width: 16px; height: 16px; color: var(--color-text-muted); transition: transform var(--transition); flex-shrink: 0; }
.user-menu.open .user-menu-trigger svg { transform: rotate(180deg); }

.user-menu-dropdown {
    display: none; position: absolute; top: calc(100% + var(--space-2)); right: 0; min-width: 200px;
    background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg); padding: var(--space-2); z-index: 200;
}
.user-menu.open .user-menu-dropdown { display: block; }
.user-menu-item {
    display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3); border-radius: var(--radius-md);
    color: var(--color-text); text-decoration: none; font-size: var(--text-sm); cursor: pointer; background: none; border: none;
    width: 100%; text-align: left; font-family: inherit; min-height: 40px;
}
.user-menu-item:hover { background: var(--color-surface-2); text-decoration: none; }
.user-menu-item svg { width: 18px; height: 18px; color: var(--color-text-muted); flex-shrink: 0; }
.user-menu-item.danger { color: var(--color-danger); }
.user-menu-item.danger svg { color: var(--color-danger); }
.user-menu-divider { height: 1px; background: var(--color-border); margin: var(--space-2) 0; }

.mobile-header { display: none; }
@media (max-width: 1023px) {
    /* .mobile-header becomes an in-flow flex sibling of .saas-main once
       visible — without this, saas-shell's default row direction puts them
       side by side instead of stacked (the fixed-position sidebar/overlay
       are unaffected either way since they're out of normal flow). */
    .saas-shell { flex-direction: column; }
    .saas-sidebar { position: fixed; left: 0; top: 0; transform: translateX(-100%); z-index: 300; }
    .saas-sidebar.open { transform: translateX(0); box-shadow: var(--shadow-lg); }
    .mobile-header {
        display: flex; align-items: center; gap: var(--space-4); height: var(--header-height); padding: 0 var(--space-4);
        background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
        border-bottom: 1px solid var(--color-border); position: sticky; top: 0; z-index: 100;
    }
    /* JS (app.v6.js) relocates #user-menu into .mobile-header on this
       breakpoint so there's a single top bar instead of the sticky
       .page-header stacking directly under the sticky .mobile-header. */
    .page-header { display: none; }
    .mobile-header .user-menu { margin-left: auto; }
    .mobile-header .user-menu-trigger { padding: 2px; border: none; background: transparent; min-height: auto; }
    .mobile-header .user-menu-trigger:hover { background: var(--color-surface-2); border-radius: 50%; }
    .mobile-header .user-menu-name, .mobile-header .user-menu-trigger svg { display: none; }
    .sidebar-overlay { display: none; position: fixed; inset: 0; background: rgba(10,9,20,.55); z-index: 250; }
    .sidebar-overlay.visible { display: block; }
    .page-content { padding: var(--space-5); }
    .page-header { padding: var(--space-5); }
    /* Icon + text naturally fill the row on their own (icon is fixed-width,
       .checklist-text is flex:1) — flex-basis:100% forces the button onto
       its own full-width line below rather than floating beside whichever
       line the wrapped description happens to reach, which looked lopsided
       on narrow viewports once the description ran to 2-3 lines. */
    .checklist-item { flex-wrap: wrap; }
    .checklist-item .btn { flex: 1 0 100%; margin-top: var(--space-2); }
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */
.btn {
    font-family: inherit; font-size: var(--text-sm); font-weight: 600; min-height: 44px;
    padding: var(--space-2) var(--space-5); border-radius: var(--radius-md); border: 1px solid transparent;
    cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    transition: background var(--transition), color var(--transition), border-color var(--transition),
                box-shadow var(--transition), transform var(--transition);
    white-space: nowrap;
}
.btn svg { width: 16px; height: 16px; }
.btn-primary {
    background: linear-gradient(135deg, var(--color-accent), var(--color-accent-hover)); color: var(--color-on-accent);
    box-shadow: 0 4px 14px rgba(var(--color-accent-rgb),.35);
}
/* color is redeclared in every :hover variant below, not just inherited from
   the base rule — a plain class selector (.btn-primary) loses to the global
   `a:hover { color: ... }` rule on specificity when a button is rendered as
   an <a> (several CTAs are links, not <button>s), which was silently turning
   button text the same color as its own background on hover. A :hover rule
   carries an extra pseudo-class in its specificity, which is enough to win
   against `a:hover` even though `a:hover` also has one — .btn-primary:hover
   (class+pseudo-class) beats a:hover (element+pseudo-class) either way. */
.btn-primary:hover { color: var(--color-on-accent); box-shadow: 0 6px 20px rgba(var(--color-accent-rgb),.45); transform: translateY(-1px); }
.btn-primary:active { transform: translateY(0); box-shadow: 0 2px 8px rgba(var(--color-accent-rgb),.35); }
.btn-secondary { background: var(--color-surface-2); color: var(--color-text); border-color: var(--color-border); }
.btn-secondary:hover { color: var(--color-text); background: var(--color-surface); border-color: var(--color-border-strong); }
.btn-danger { background: var(--color-danger); color: var(--color-on-accent); }
.btn-danger:hover { color: var(--color-on-accent); background: #DC2626; transform: translateY(-1px); }
.btn-ghost { background: transparent; color: var(--color-text-muted); }
.btn-ghost:hover { background: var(--color-surface-2); color: var(--color-text); }
.btn:disabled { opacity: .55; cursor: not-allowed; transform: none !important; box-shadow: none !important; }
.spinner {
    width: 14px; height: 14px; border-radius: 50%; border: 2px solid rgba(255,255,255,.4);
    border-top-color: #fff; animation: spin .7s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Cards ────────────────────────────────────────────────────────────────── */
.card {
    background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg);
    margin-bottom: var(--space-6); box-shadow: var(--shadow-sm); transition: box-shadow var(--transition), transform var(--transition);
}
.card-header { padding: var(--space-5) var(--space-6); border-bottom: 1px solid var(--color-border); }
.card-title { font-size: var(--text-lg); font-weight: 700; margin: 0; letter-spacing: -.005em; }
.card-subtitle { font-size: var(--text-sm); color: var(--color-text-muted); margin: var(--space-1) 0 0; }
.card-body { padding: var(--space-6); }
.card-footer { padding: var(--space-4) var(--space-6); border-top: 1px solid var(--color-border); display: flex; gap: var(--space-3); justify-content: flex-end; flex-wrap: wrap; }
.card-clickable { cursor: pointer; }
.card-clickable:hover { box-shadow: var(--shadow-md); border-color: var(--color-border-strong); }

/* ── Analytics: summary stat cards ───────────────────────────────────────── */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-6); }
.stat-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--space-5); box-shadow: var(--shadow-sm); }
.stat-card .stat-value { font-size: var(--text-2xl); font-weight: 700; letter-spacing: -.01em; line-height: 1.2; }
.stat-card .stat-label { font-size: var(--text-sm); color: var(--color-text-muted); margin-top: var(--space-1); }
.stat-card.stat-accent .stat-value { color: var(--color-accent); }
.stat-card.stat-danger .stat-value { color: var(--color-danger); }

.card-glass {
    background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border); box-shadow: var(--shadow-glass);
}

/* ── Alerts ───────────────────────────────────────────────────────────────── */
.alert { padding: var(--space-3) var(--space-4); border-radius: var(--radius-md); font-size: var(--text-sm); margin-bottom: var(--space-4); border: 1px solid transparent; line-height: 1.5; }
.alert-warning { background: var(--color-warning-light); color: #92400E; border-color: rgba(245,158,11,.25); }
.alert-success { background: var(--color-success-light); color: #065F46; border-color: rgba(16,185,129,.25); }
.alert-danger  { background: var(--color-danger-light); color: #991B1B; border-color: rgba(239,68,68,.25); }
.alert-info    { background: var(--color-info-light); color: #075985; border-color: rgba(14,165,233,.25); }

/* ── Badges ───────────────────────────────────────────────────────────────── */
.badge {
    display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px 3px 8px; border-radius: var(--radius-full);
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; line-height: 1.6;
}
.badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.badge-success { background: var(--color-success-light); color: #047857; }
.badge-warning { background: var(--color-warning-light); color: #B45309; }
.badge-danger  { background: var(--color-danger-light); color: #B91C1C; }
.badge-info    { background: var(--color-info-light); color: #0369A1; }
.badge-neutral { background: var(--color-surface-2); color: var(--color-text-muted); }

/* ── Forms ────────────────────────────────────────────────────────────────── */
.form-group { margin-bottom: var(--space-5); }
label { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--color-text); margin-bottom: var(--space-2); }
input[type="text"], input[type="email"], input[type="password"], input[type="url"], input[type="number"], input[type="date"], textarea, select {
    width: 100%; min-height: 44px; padding: var(--space-2) var(--space-3); border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text);
    font-family: inherit; font-size: var(--text-sm); transition: border-color var(--transition), box-shadow var(--transition);
}
textarea { min-height: 88px; resize: vertical; font-family: inherit; }
input::placeholder, textarea::placeholder { color: var(--color-text-subtle); }
input:hover, textarea:hover, select:hover { border-color: var(--color-border-strong); }
input:focus, textarea:focus, select:focus {
    outline: none; border-color: var(--color-accent); box-shadow: var(--shadow-focus);
}
code { font-family: var(--font-mono); background: var(--color-surface-2); padding: 2px 6px; border-radius: 6px; font-size: .9em; }
.var-chip { font-family: var(--font-mono); background: var(--color-surface-2); padding: 2px 6px; border-radius: 6px; font-size: .9em; border: 1px solid var(--color-border); color: var(--color-text); cursor: pointer; transition: background var(--transition), border-color var(--transition); }
.var-chip:hover, .var-chip:focus-visible { background: var(--color-accent-light); border-color: var(--color-accent); }

/* Trigger-keywords tag input — #keywords-input (a hidden field, not shown
   here) stays the actual comma-separated source of truth every other part
   of the form already reads/writes; this is purely the visible chip
   representation of that same value. Styled to read as one input box (same
   border/radius/focus treatment as a plain text input) with pills inside it
   rather than a separate widget bolted on next to a real input. */
.tag-input {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
    width: 100%; min-height: 44px; padding: 6px var(--space-3); border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md); background: var(--color-surface); transition: border-color var(--transition), box-shadow var(--transition);
}
.tag-input:focus-within { border-color: var(--color-accent); box-shadow: var(--shadow-focus); }
.tag-input input[type="text"] {
    flex: 1; min-width: 140px; border: none; background: transparent; padding: 4px 2px; min-height: auto;
}
.tag-input input[type="text"]:focus { outline: none; box-shadow: none; }
.tag-chip {
    display: inline-flex; align-items: center; gap: 5px; background: var(--color-accent-light); color: var(--color-accent);
    border-radius: var(--radius-full); padding: 3px 4px 3px 11px; font-size: var(--text-sm); font-weight: 600; white-space: nowrap;
}
.tag-chip-remove {
    display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%;
    border: none; background: transparent; color: inherit; cursor: pointer; font-size: 15px; line-height: 1; padding: 0;
}
.tag-chip-remove:hover, .tag-chip-remove:focus-visible { background: rgba(var(--color-accent-rgb), .2); }

/* Suggested-keyword chips under the trigger-keywords field — plain
   language, not code, so no font-mono unlike .var-chip above. Toggleable:
   .active reflects a phrase currently present in the keywords input. */
.keyword-preset-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.keyword-preset-chip {
    font-family: inherit; background: var(--color-surface-2); padding: 4px 11px; border-radius: var(--radius-full);
    font-size: var(--text-xs); border: 1px solid var(--color-border); color: var(--color-text-muted);
    cursor: pointer; transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.keyword-preset-chip:hover, .keyword-preset-chip:focus-visible { border-color: var(--color-accent); color: var(--color-text); }
.keyword-preset-chip.active { background: var(--color-accent-light); border-color: var(--color-accent); color: var(--color-accent); font-weight: 600; }

/* Custom toggle switch — built on the native checkbox, no extra markup needed */
.switch { display: inline-flex; align-items: center; gap: var(--space-3); cursor: pointer; min-height: 44px; font-size: var(--text-sm); font-weight: 500; color: var(--color-text); }
.switch input[type="checkbox"] {
    appearance: none; -webkit-appearance: none; margin: 0; flex-shrink: 0; position: relative;
    width: 42px; height: 24px; min-height: 0; border-radius: var(--radius-full);
    background: var(--color-border-strong); cursor: pointer; transition: background var(--transition);
}
.switch input[type="checkbox"]::before {
    content: ''; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%;
    background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform var(--transition);
}
.switch input[type="checkbox"]:checked { background: var(--color-accent); }
.switch input[type="checkbox"]:checked::before { transform: translateX(18px); }

/* Selectable option cards for radio choices — same appearance:none-on-the-
   native-input technique as .switch above (the input itself becomes the
   dot), plus :has() to style the whole card border/background on check. */
.radio-card-group { display: flex; flex-direction: column; gap: var(--space-2); }
.radio-card {
    display: flex; align-items: flex-start; gap: var(--space-3);
    padding: var(--space-4); border: 1.5px solid var(--color-border); border-radius: var(--radius-md);
    cursor: pointer; transition: border-color var(--transition), background-color var(--transition);
}
.radio-card:hover { border-color: var(--color-border-strong); }
.radio-card:has(input:checked) { border-color: var(--color-accent); background: var(--color-accent-light); }
.radio-card input[type="radio"] {
    appearance: none; -webkit-appearance: none; margin: 2px 0 0; flex-shrink: 0;
    width: 20px; height: 20px; min-height: 0; border-radius: 50%; position: relative;
    border: 1.5px solid var(--color-border-strong); background: var(--color-surface);
    cursor: pointer; transition: border-color var(--transition);
}
.radio-card input[type="radio"]::before {
    content: ''; position: absolute; inset: 3px; border-radius: 50%;
    background: var(--color-accent); transform: scale(0); transition: transform var(--transition);
}
.radio-card input[type="radio"]:checked { border-color: var(--color-accent); }
.radio-card input[type="radio"]:checked::before { transform: scale(1); }
.radio-card input[type="radio"]:focus-visible { border-radius: 50%; }
.radio-card-body { display: flex; flex-direction: column; gap: 2px; }
.radio-card-title { font-weight: 600; font-size: var(--text-sm); color: var(--color-text); }
.radio-card-desc { font-size: var(--text-xs); color: var(--color-text-muted); line-height: 1.4; }

/* ── Tables ───────────────────────────────────────────────────────────────── */
.table-wrapper { overflow-x: auto; border-radius: var(--radius-lg); }
.data-table { width: 100%; border-collapse: collapse; }
.data-table th {
    text-align: left; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
    color: var(--color-text-muted); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-border);
    background: var(--color-surface-2); position: sticky; top: 0;
}
.data-table td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-border); font-size: var(--text-sm); }
.data-table tbody tr { transition: background var(--transition); }
.data-table tbody tr:hover { background: var(--color-accent-light); }
.data-table tbody tr:last-child td { border-bottom: none; }
/* A bare <select width:100%> inside an auto-layout table cell can't resolve
   its own width (the column's width comes FROM the select's intrinsic
   content, which is nearly nothing) — collapses to a few px in some
   browsers, hiding the selected text entirely. Floor it. */
.data-table select { min-width: 110px; width: auto; }

/* A 6-8 column table (Order/Name/Account/Store/Keywords/Status/Actions, and
   similar shapes on other list pages) has no honest way to stay a real
   <table> on a narrow phone or tablet screen. table-wrapper's overflow-x:auto
   lets it scroll sideways, but nothing signals that's possible — in practice
   entire columns, including the Edit/Pause/Delete action buttons, were
   invisible and undiscoverable below ~1024px (confirmed at both 768px tablet
   and 375px mobile widths). Below that width every .data-table collapses
   into one stacked "card" per row instead. 1023px matches the breakpoint
   where the sidebar already collapses to the mobile hamburger header, so the
   two responsive behaviors switch together.
   Contract: every <td> in a table using this needs a data-label="Column
   Name" attribute (see each page's render function) — <thead> stays in the
   DOM (for screen readers) but is visually hidden at this width, so there's
   no other source for the label. An actions cell (no real column header)
   should use data-label="" explicitly, not omit the attribute — that's what
   switches it from a labeled row to an unlabeled, wrapping button row. */
@media (max-width: 1023px) {
    .table-wrapper { overflow-x: visible; }
    .data-table, .data-table tbody { display: block; width: 100%; }
    .data-table thead {
        position: absolute; width: 1px; height: 1px; overflow: hidden;
        clip: rect(0,0,0,0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
    }
    /* Row-cards sit inside a .card that's already var(--color-surface) (white).
       A flat --color-surface-2 fill (tried first) reads as an off-brand gray
       box — every other card in the app is white with a border+shadow, never
       a filled tint. Staying white but using the stronger border tone plus a
       real (not barely-there) shadow and extra margin gives each row its own
       floating-card boundary while matching the app's actual card language. */
    .data-table tr {
        display: block; border: 1px solid var(--color-border-strong); border-radius: var(--radius-lg);
        padding: var(--space-3) var(--space-4); margin-bottom: var(--space-4);
        background: var(--color-surface); box-shadow: var(--shadow-md);
    }
    .data-table tbody tr:hover { background: var(--color-surface); } /* hover highlight means nothing on touch */
    .data-table td {
        display: flex; justify-content: space-between; align-items: center; gap: var(--space-3);
        padding: var(--space-2) 0; text-align: right;
    }
    .data-table td:last-child { border-bottom: none; }
    .data-table td::before {
        content: attr(data-label); font-size: 11px; font-weight: 700; text-transform: uppercase;
        letter-spacing: .06em; color: var(--color-text-muted); text-align: left; flex-shrink: 0;
    }
    .data-table td[data-label=""] {
        display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: flex-start; padding-top: var(--space-3);
    }
    .data-table td[data-label=""]::before { content: none; }
}

/* ── Empty state ──────────────────────────────────────────────────────────── */
.empty-state { text-align: center; padding: var(--space-12) var(--space-6); color: var(--color-text-muted); }
.empty-state-icon {
    width: 56px; height: 56px; margin: 0 auto var(--space-4); border-radius: var(--radius-full);
    background: var(--color-accent-light); color: var(--color-accent);
    display: flex; align-items: center; justify-content: center;
}
.empty-state-icon svg { width: 26px; height: 26px; }
.empty-state h3 { color: var(--color-text); margin: 0 0 var(--space-2); font-size: var(--text-lg); }

/* ── Toasts ───────────────────────────────────────────────────────────────── */
#toast-container { position: fixed; bottom: var(--space-6); right: var(--space-6); z-index: 999; display: flex; flex-direction: column; gap: var(--space-2); max-width: calc(100vw - 2 * var(--space-6)); }
.toast {
    padding: var(--space-3) var(--space-4); border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
    font-size: var(--text-sm); font-weight: 500; color: #fff; animation: toast-in var(--transition-slow) ease;
}
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.toast-success { background: #059669; }
.toast-error   { background: #DC2626; }
.toast-info    { background: #0284C7; }
.toast-warning { background: #D97706; }

/* ── Dashboard: onboarding checklist ─────────────────────────────────────── */
.checklist-item { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; border-bottom: 1px solid var(--color-border); }
.checklist-item:last-child { border-bottom: none; }
.checklist-icon {
    width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.checklist-icon svg { width: 15px; height: 15px; }
.checklist-icon.done { background: var(--color-success-light); color: var(--color-success); }
.checklist-icon.pending { background: var(--color-surface-2); color: var(--color-text-subtle); border: 2px solid var(--color-border-strong); }
.checklist-text { flex: 1; min-width: 0; }
.checklist-text .title { font-weight: 600; font-size: var(--text-sm); }
.checklist-text .desc { font-size: var(--text-xs); color: var(--color-text-muted); margin-top: 2px; }

/* ── Dashboard: plan usage bars ──────────────────────────────────────────── */
.usage-row { padding: var(--space-3) 0; border-bottom: 1px solid var(--color-border); }
.usage-row:first-child { padding-top: 0; }
.usage-row:last-child { padding-bottom: 0; border-bottom: none; }
.usage-row-label { display: flex; justify-content: space-between; align-items: baseline; font-size: var(--text-sm); margin-bottom: var(--space-2); gap: var(--space-3); }
.usage-row-label .value { color: var(--color-text-muted); font-size: var(--text-xs); flex-shrink: 0; }
.usage-bar-track { height: 8px; border-radius: var(--radius-full); background: var(--color-surface-2); overflow: hidden; }
.usage-bar-fill { height: 100%; border-radius: var(--radius-full); background: var(--color-accent); transition: width var(--transition-slow); }
.usage-bar-fill.warning { background: var(--color-warning); }
.usage-bar-fill.danger { background: var(--color-danger); }

/* Each usage row also links to where that number is managed (Connect,
   Automation Rules, Store, Team, filtered Activity Log) — styled as a plain
   block so it reads the same as the non-clickable version, with a hover
   affordance as the only tell that it's interactive. */
/* Left/right only, not the shorthand — .usage-row already sets the
   top/bottom padding that creates the border-separated spacing between
   rows, and a shorthand here would silently override it back to 0. */
a.usage-row-link { display: block; text-decoration: none; color: inherit; border-radius: var(--radius-md); margin: 0 calc(-1 * var(--space-3)); padding-left: var(--space-3); padding-right: var(--space-3); transition: background var(--transition); }
a.usage-row-link:hover { background: var(--color-surface-2); }
a.usage-row-link:hover .usage-row-label span:first-child { color: var(--color-accent); }

/* ── Dashboard: account/store status rows ────────────────────────────────── */
.status-row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap;
    padding: var(--space-3) 0; border-bottom: 1px solid var(--color-border);
}
.status-row:last-child { border-bottom: none; }
.status-row-badges { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

/* ── Auth pages ───────────────────────────────────────────────────────────── */
/* This is the one layout in the app that's mostly empty space around a
   single centered card, so it's the one place extra atmosphere is pure
   upside — everywhere else (dashboard, tables) it would compete with real
   content, which is why this glow is scoped here instead of into the
   shared --color-bg-gradient every page already uses. */
.auth-shell {
    min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-6); position: relative; overflow: hidden;
    background-image: radial-gradient(circle, var(--color-auth-dot) 1px, transparent 1px); background-size: 26px 26px;
}
.auth-shell::before, .auth-shell::after {
    content: ''; position: absolute; width: 620px; height: 620px; border-radius: 50%;
    filter: blur(90px); pointer-events: none; z-index: 0;
}
.auth-shell::before { top: -220px; left: -160px; background: var(--color-auth-glow-a); }
.auth-shell::after  { bottom: -240px; right: -180px; background: var(--color-auth-glow-b); }
.auth-card { width: 100%; max-width: 408px; position: relative; z-index: 1; }
