/* ══════════════════════════════════════════════════════════════════════
   shody-system.css — SHODY design system foundation ("Signal")
   ----------------------------------------------------------------------
   Single source of truth for design tokens, typography, motion, focus,
   status colors, the Bootstrap primitive overrides, and the shared
   partial components (badges, empty states, form fields, table wrappers).

   Loaded first by EVERY base template so the whole product speaks one
   visual language. App-specific shell + component styling lives in
   crm_dashboard/css/dashboard.css, which loads after this file and builds
   on these tokens.

   Design language: a living data-operations surface. Deep, refined
   command chrome frames luminous, high-density light workspaces. A
   disciplined indigo primary with a cyan "flow" accent for motion and
   activity. Numerics in tabular mono. Motion is purposeful and always
   respects prefers-reduced-motion.

   Historical note: the project once had four parallel status-color sets
   (base.html, crm_dashboard/base.html, monitoring, semantic/catalog).
   They all converge here. Do NOT introduce new hex literals in templates
   or per-page <style> blocks — reach for a token.
   ══════════════════════════════════════════════════════════════════════ */

/* ── Design tokens ─────────────────────────────────────────────────── */
:root {
    /* Brand / signal accent — indigo primary, cyan flow companion. */
    --shody-accent:            #4c6ef5;
    --shody-accent-strong:     #3b5bdb;
    --shody-accent-hover:      #5c7cff;
    --shody-accent-contrast:   #ffffff;
    --shody-accent-soft:       rgba(76, 110, 245, 0.10);
    --shody-accent-soft-2:     rgba(76, 110, 245, 0.16);
    --shody-accent-ring:       rgba(76, 110, 245, 0.30);
    --shody-flow:              #17b6cf;   /* cyan — flow lines, motion, activity */
    --shody-flow-soft:         rgba(23, 182, 207, 0.12);

    /* Status colors. Pick from this palette for any badge, KPI tile, or
     * state treatment. `-soft` = tinted background, plain = text/icon. */
    --shody-status-success:       #12b76a;
    --shody-status-success-ink:   #027a48;
    --shody-status-success-soft:  #ecfdf3;
    --shody-status-success-line:  #abefc6;
    --shody-status-warning:       #f79009;
    --shody-status-warning-ink:   #b54708;
    --shody-status-warning-soft:  #fffaeb;
    --shody-status-warning-line:  #fedf89;
    --shody-status-error:         #f04438;
    --shody-status-error-ink:     #b42318;
    --shody-status-error-soft:    #fef3f2;
    --shody-status-error-line:    #fecdca;
    --shody-status-info:          #2e90fa;   /* running / in-progress / neutral-active */
    --shody-status-info-ink:      #175cd3;
    --shody-status-info-soft:     #eff8ff;
    --shody-status-info-line:     #b2ddff;
    --shody-status-muted:         #667085;   /* not synced / disabled / n-a */
    --shody-status-muted-ink:     #475467;
    --shody-status-muted-soft:    #f9fafb;
    --shody-status-muted-line:    #e4e7ec;

    /* Legacy aliases kept for _status_badge.html + older references. */
    --shody-status-success-soft-tint: var(--shody-accent-soft);

    /* Categorical series palette (SDW-472). Chart series identity ONLY —
     * never a status, never a state. The order is the colorblind-safety
     * mechanism, not cosmetic: these eight hues in this sequence clear the
     * adjacent-pair CVD gate (worst 9.1 protan) and the normal-vision floor
     * (worst 19.6) against #ffffff, so a series is assigned the next slot in
     * order and slots are NEVER cycled. Past eight categories, fold the tail
     * into "Other" rather than reusing slot 1 — a repeated hue asserts two
     * different things are the same series.
     *
     * Series 3, 4 and 5 sit below 3:1 on white. That is allowed here because
     * every chart panel carries its figures table underneath, which is the
     * relief the contrast rule asks for; drop the table and this stops being
     * true. */
    --shody-series-1: #2a78d6;   /* blue    */
    --shody-series-2: #eb6834;   /* orange  */
    --shody-series-3: #1baf7a;   /* aqua    */
    --shody-series-4: #eda100;   /* yellow  */
    --shody-series-5: #e87ba4;   /* magenta */
    --shody-series-6: #008300;   /* green   */
    --shody-series-7: #4a3aa7;   /* violet  */
    --shody-series-8: #e34948;   /* red     */

    /* Workspace surfaces (light) */
    --shody-surface-0:   #ffffff;
    --shody-surface-1:   #f7f9fc;
    --shody-surface-2:   #eef2f8;
    --shody-surface-3:   #e6ecf5;

    /* Ink chrome (dark command surface). Env accent tints these at the
     * shell level; the raw ink stays sophisticated regardless of env. */
    --shody-ink-900:     #0b1220;
    --shody-ink-800:     #111a2e;
    --shody-ink-700:     #18233c;
    --shody-ink-600:     #22304d;

    /* Text */
    --shody-text-strong: #0f172a;
    --shody-text:        #1f2937;
    --shody-text-muted:  #5b6472;
    --shody-text-faint:  #8a93a3;
    --shody-text-invert: #ffffff;

    /* Borders / lines */
    --shody-border:        #e4e8f0;
    --shody-border-strong: #d3dae6;
    --shody-border-faint:  #eef1f6;

    /* Radii */
    --shody-r-xs:   6px;
    --shody-r-sm:   8px;
    --shody-r-md:   12px;
    --shody-r-lg:   16px;
    --shody-r-xl:   20px;
    --shody-r-pill: 999px;

    /* Spacing rhythm */
    --shody-gap-2xs: 0.25rem;
    --shody-gap-xs:  0.5rem;
    --shody-gap-sm:  0.75rem;
    --shody-gap-md:  1rem;
    --shody-gap-lg:  1.5rem;
    --shody-gap-xl:  2rem;

    /* Elevation — soft, layered, cool-tinted */
    --shody-shadow-1: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.06);
    --shody-shadow-2: 0 2px 6px rgba(15, 23, 42, 0.06), 0 8px 24px rgba(15, 23, 42, 0.07);
    --shody-shadow-3: 0 12px 32px rgba(15, 23, 42, 0.12), 0 2px 8px rgba(15, 23, 42, 0.06);
    --shody-shadow-pop: 0 20px 48px rgba(11, 18, 32, 0.22);

    /* Typography */
    --shody-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --shody-font-mono: ui-monospace, 'SF Mono', 'JetBrains Mono', 'Cascadia Code', 'Roboto Mono', Consolas, monospace;

    /* Motion */
    --shody-ease-out:      cubic-bezier(0.22, 1, 0.36, 1);
    --shody-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
    --shody-ease-spring:   cubic-bezier(0.34, 1.56, 0.64, 1);
    --shody-dur-1: 120ms;
    --shody-dur-2: 200ms;
    --shody-dur-3: 320ms;
    --shody-dur-4: 520ms;

    /* Back-compat aliases used by templates/base.html + partials. Keeping
     * these mapped means older markup keeps rendering with the new palette. */
    --text-primary:   var(--shody-text-strong);
    --text-secondary: var(--shody-text-muted);
    --text-muted:     var(--shody-text-faint);
    --border-color:   var(--shody-border);
    --shody-status-info-soft-legacy: var(--shody-status-info-soft);

    /* Workbook × Report-Out grammar (SDW-643) — landed in Phase 1 (SDW-647),
     * consumed from Phase 2 on. Purpose row-band tints + the consolidated
     * type scale (>=1.25 steps where hierarchy must read). */
    --shody-band-blue:     #eff6ff;   /* standard/new row band     */
    --shody-band-peach:    #fff8f1;   /* rehash row band           */
    --shody-band-lavender: #f6f4fb;   /* cancellations row band    */
    --shody-type-micro:        10px;    /* uppercase micro-labels  */
    --shody-type-meta:         11.5px;  /* stamps, hints, trios    */
    --shody-type-body:         13.5px;  /* panel prose, table text */
    --shody-type-panel-title:  14px;
    /* The computed lede — the one sentence a report page leads with. Added in
     * Phase 2 (SDW-648): the locked composition opens on it, but Phase 1's scale
     * had no step between the panel title and the page title, so the lede was
     * the only element on the surface with nowhere to sit. 1.22x over body,
     * 1.18x over the panel title: prose that reads as the conclusion without
     * competing with the report's own name. */
    --shody-type-lede:         16.5px;
    --shody-type-page-title:   26px;    /* report page title       */
    --shody-type-figure:       34px;    /* KPI figure              */
    --shody-type-figure-lead:  46px;    /* North Star lead figure  */
    /* Flag/judgment hues deliberately reuse --shody-status-* — a flag is a
     * status by rule, never a new color family. */
}

/* ── Base typography ───────────────────────────────────────────────── */
:root { --bs-body-font-family: var(--shody-font-sans); }
body {
    font-family: var(--shody-font-sans);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, h5, h6 { letter-spacing: -0.011em; }
code, pre, kbd, samp { font-family: var(--shody-font-mono); }

/* ── Reduced-motion: neutralize animation + transition globally ─────── */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── Motion keyframes (shared) ─────────────────────────────────────── */
@keyframes shody-spin { to { transform: rotate(360deg); } }
@keyframes shody-fade-up {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes shody-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes shody-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.45; }
}
@keyframes shody-signal-pulse {
    0%   { box-shadow: 0 0 0 0 var(--shody-accent-ring); }
    70%  { box-shadow: 0 0 0 6px rgba(76, 110, 245, 0); }
    100% { box-shadow: 0 0 0 0 rgba(76, 110, 245, 0); }
}
@keyframes shody-flow-dash { to { stroke-dashoffset: -1000; } }
@keyframes shody-shimmer {
    0%   { background-position: -180% 0; }
    100% { background-position: 180% 0; }
}

/* Staggered entrance helper — add .shody-enter to a container; direct
 * children fade/rise in sequence. Purely decorative, motion-safe. */
.shody-enter > * {
    animation: shody-fade-up var(--shody-dur-3) var(--shody-ease-out) both;
}
.shody-enter > *:nth-child(1) { animation-delay: 0.02s; }
.shody-enter > *:nth-child(2) { animation-delay: 0.06s; }
.shody-enter > *:nth-child(3) { animation-delay: 0.10s; }
.shody-enter > *:nth-child(4) { animation-delay: 0.14s; }
.shody-enter > *:nth-child(5) { animation-delay: 0.18s; }
.shody-enter > *:nth-child(6) { animation-delay: 0.22s; }
.shody-enter > *:nth-child(7) { animation-delay: 0.26s; }
.shody-enter > *:nth-child(8) { animation-delay: 0.30s; }

/* ── Global focus-visible ring ─────────────────────────────────────── */
:focus-visible {
    outline: 2px solid var(--shody-accent);
    outline-offset: 2px;
    border-radius: var(--shody-r-xs);
}
/* Mouse users don't get the ring on click, only keyboard users do. */
:focus:not(:focus-visible) { outline: none; }

/* Numeric / tabular helper — apply to any figure column or KPI. */
.shody-num, .tabular-nums {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}
.shody-mono { font-family: var(--shody-font-mono); }

/* ══════════════════════════════════════════════════════════════════════
   BOOTSTRAP PRIMITIVE OVERRIDES
   Re-skins Bootstrap 5 components so every page — even ones never touched
   individually — inherits the design language. Loaded before dashboard.css
   so the app shell can still specialize.
   ══════════════════════════════════════════════════════════════════════ */

/* Buttons */
.btn {
    --bs-btn-border-radius: var(--shody-r-sm);
    border-radius: var(--shody-r-sm);
    font-weight: 600;
    font-size: 0.82rem;
    letter-spacing: 0.005em;
    padding: 0.5rem 0.95rem;
    transition: background-color var(--shody-dur-1) var(--shody-ease-standard),
                border-color var(--shody-dur-1) var(--shody-ease-standard),
                color var(--shody-dur-1) var(--shody-ease-standard),
                box-shadow var(--shody-dur-2) var(--shody-ease-out),
                transform var(--shody-dur-1) var(--shody-ease-out);
}
.btn:active { transform: translateY(0.5px); }
.btn-primary {
    --bs-btn-bg: var(--shody-accent);
    --bs-btn-border-color: var(--shody-accent);
    --bs-btn-hover-bg: var(--shody-accent-strong);
    --bs-btn-hover-border-color: var(--shody-accent-strong);
    --bs-btn-active-bg: var(--shody-accent-strong);
    --bs-btn-active-border-color: var(--shody-accent-strong);
    --bs-btn-disabled-bg: var(--shody-accent);
    --bs-btn-disabled-border-color: var(--shody-accent);
    box-shadow: 0 1px 2px rgba(59, 91, 219, 0.24), 0 6px 16px rgba(59, 91, 219, 0.18);
}
.btn-primary:hover { box-shadow: 0 2px 4px rgba(59, 91, 219, 0.28), 0 10px 22px rgba(59, 91, 219, 0.24); transform: translateY(-1px); }
.btn-success { --bs-btn-bg: var(--shody-status-success); --bs-btn-border-color: var(--shody-status-success); --bs-btn-hover-bg: #0e9f5c; --bs-btn-hover-border-color: #0e9f5c; }
.btn-danger  { --bs-btn-bg: var(--shody-status-error);   --bs-btn-border-color: var(--shody-status-error);   --bs-btn-hover-bg: #d92d20; --bs-btn-hover-border-color: #d92d20; }
.btn-warning { --bs-btn-bg: var(--shody-status-warning); --bs-btn-border-color: var(--shody-status-warning); --bs-btn-color: #fff; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #dd7a06; --bs-btn-hover-border-color: #dd7a06; }
.btn-info    { --bs-btn-bg: var(--shody-status-info);    --bs-btn-border-color: var(--shody-status-info);    --bs-btn-color: #fff; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: var(--shody-status-info-ink); --bs-btn-hover-border-color: var(--shody-status-info-ink); }
.btn-outline-primary   { --bs-btn-color: var(--shody-accent-strong); --bs-btn-border-color: var(--shody-accent); --bs-btn-hover-bg: var(--shody-accent); --bs-btn-hover-border-color: var(--shody-accent); --bs-btn-active-bg: var(--shody-accent-strong); }
.btn-outline-secondary { --bs-btn-color: var(--shody-text-muted); --bs-btn-border-color: var(--shody-border-strong); --bs-btn-hover-bg: var(--shody-surface-1); --bs-btn-hover-border-color: var(--shody-text-faint); --bs-btn-hover-color: var(--shody-text-strong); }
.btn-outline-danger    { --bs-btn-color: var(--shody-status-error-ink); --bs-btn-border-color: var(--shody-status-error-line); --bs-btn-hover-bg: var(--shody-status-error); --bs-btn-hover-border-color: var(--shody-status-error); --bs-btn-active-bg: var(--shody-status-error-ink); --bs-btn-active-border-color: var(--shody-status-error-ink); }
.btn-link { --bs-btn-color: var(--shody-accent-strong); --bs-btn-hover-color: var(--shody-accent); text-decoration: none; font-weight: 600; }
.btn-sm { font-size: 0.75rem; padding: 0.35rem 0.7rem; border-radius: var(--shody-r-xs); }
.btn-lg { font-size: 0.95rem; padding: 0.7rem 1.3rem; border-radius: var(--shody-r-md); }

/* Form controls */
.form-control, .form-select {
    border-radius: var(--shody-r-sm);
    border-color: var(--shody-border-strong);
    color: var(--shody-text);
    font-size: 0.85rem;
    transition: border-color var(--shody-dur-1) var(--shody-ease-standard),
                box-shadow var(--shody-dur-2) var(--shody-ease-out);
}
.form-control::placeholder { color: var(--shody-text-faint); }
.form-control:focus, .form-select:focus {
    border-color: var(--shody-accent);
    box-shadow: 0 0 0 3px var(--shody-accent-soft-2);
}
.form-control:disabled, .form-select:disabled { background: var(--shody-surface-2); color: var(--shody-text-faint); }
.form-label { font-size: 0.78rem; font-weight: 600; color: var(--shody-text-muted); margin-bottom: 0.35rem; }
.form-check-input:checked { background-color: var(--shody-accent); border-color: var(--shody-accent); }
.form-check-input:focus { border-color: var(--shody-accent); box-shadow: 0 0 0 3px var(--shody-accent-soft-2); }
.input-group-text { background: var(--shody-surface-1); border-color: var(--shody-border-strong); color: var(--shody-text-muted); border-radius: var(--shody-r-sm); }

/* Bootstrap badges */
.badge { font-weight: 600; letter-spacing: 0.01em; border-radius: var(--shody-r-pill); }
.badge.bg-primary   { background-color: var(--shody-accent) !important; }
.badge.bg-success   { background-color: var(--shody-status-success) !important; }
.badge.bg-danger    { background-color: var(--shody-status-error) !important; }
.badge.bg-warning   { background-color: var(--shody-status-warning) !important; color: #fff !important; }
.badge.bg-info      { background-color: var(--shody-status-info) !important; }
.badge.bg-secondary { background-color: var(--shody-status-muted) !important; }

/* Alerts — quiet, structured, left signal rail */
.alert {
    border-radius: var(--shody-r-md);
    border: 1px solid var(--shody-border);
    border-left-width: 3px;
    font-size: 0.85rem;
    padding: 0.8rem 1rem;
    background: var(--shody-surface-0);
    color: var(--shody-text);
    box-shadow: var(--shody-shadow-1);
}
.alert-success { border-left-color: var(--shody-status-success); background: var(--shody-status-success-soft); color: var(--shody-status-success-ink); border-color: var(--shody-status-success-line); }
.alert-danger, .alert-error { border-left-color: var(--shody-status-error); background: var(--shody-status-error-soft); color: var(--shody-status-error-ink); border-color: var(--shody-status-error-line); }
.alert-warning { border-left-color: var(--shody-status-warning); background: var(--shody-status-warning-soft); color: var(--shody-status-warning-ink); border-color: var(--shody-status-warning-line); }
.alert-info { border-left-color: var(--shody-status-info); background: var(--shody-status-info-soft); color: var(--shody-status-info-ink); border-color: var(--shody-status-info-line); }

/* Modals, dropdowns, tooltips, tabs, pagination */
.modal-content { border-radius: var(--shody-r-lg); border: 1px solid var(--shody-border); box-shadow: var(--shody-shadow-pop); overflow: hidden; }
.modal-header, .modal-footer { background: var(--shody-surface-1); border-color: var(--shody-border); }
.modal-title { font-weight: 700; color: var(--shody-text-strong); }
.dropdown-menu { border-radius: var(--shody-r-md); border: 1px solid var(--shody-border); box-shadow: var(--shody-shadow-3); padding: 0.35rem; font-size: 0.85rem; }
.dropdown-item { border-radius: var(--shody-r-xs); padding: 0.45rem 0.7rem; }
.dropdown-item:active { background: var(--shody-accent); }
.dropdown-item:hover, .dropdown-item:focus { background: var(--shody-surface-2); }
.tooltip-inner { border-radius: var(--shody-r-sm); background: var(--shody-ink-800); font-size: 0.75rem; padding: 0.4rem 0.6rem; box-shadow: var(--shody-shadow-3); }
.nav-tabs { border-bottom: 1px solid var(--shody-border); gap: 0.15rem; }
.nav-tabs .nav-link { border: none; border-bottom: 2px solid transparent; color: var(--shody-text-muted); font-weight: 600; font-size: 0.82rem; padding: 0.55rem 0.9rem; border-radius: var(--shody-r-xs) var(--shody-r-xs) 0 0; transition: color var(--shody-dur-1), border-color var(--shody-dur-1), background var(--shody-dur-1); }
.nav-tabs .nav-link:hover { color: var(--shody-text-strong); background: var(--shody-surface-1); border-bottom-color: var(--shody-border-strong); }
.nav-tabs .nav-link.active { color: var(--shody-accent-strong); background: transparent; border-bottom-color: var(--shody-accent); }
.nav-pills .nav-link.active { background: var(--shody-accent); }
.page-link { color: var(--shody-accent-strong); border-radius: var(--shody-r-xs) !important; border: none; }
.page-link:hover { background: var(--shody-accent-soft); color: var(--shody-accent-strong); }
.page-item.active .page-link { background: var(--shody-accent); border-color: var(--shody-accent); box-shadow: 0 2px 8px rgba(76,110,245,0.28); }

/* Links */
a { color: var(--shody-accent-strong); }
a:hover { color: var(--shody-accent); }

/* Scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--shody-border-strong) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--shody-border-strong); border-radius: var(--shody-r-pill); border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--shody-text-faint); background-clip: padding-box; }

/* ══════════════════════════════════════════════════════════════════════
   SHARED PARTIAL COMPONENTS
   ══════════════════════════════════════════════════════════════════════ */

/* ── Status badge (templates/_status_badge.html) ───────────────────── */
.shody-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    padding: 0.28em 0.7em;
    border-radius: var(--shody-r-pill);
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: 0.02em;
    white-space: nowrap;
    border: 1px solid transparent;
}
.shody-badge::before {
    content: "";
    width: 0.42em;
    height: 0.42em;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}
.shody-badge--success { color: var(--shody-status-success-ink); background: var(--shody-status-success-soft); border-color: var(--shody-status-success-line); }
.shody-badge--warning { color: var(--shody-status-warning-ink); background: var(--shody-status-warning-soft); border-color: var(--shody-status-warning-line); }
.shody-badge--error   { color: var(--shody-status-error-ink);   background: var(--shody-status-error-soft);   border-color: var(--shody-status-error-line); }
.shody-badge--info    { color: var(--shody-status-info-ink);    background: var(--shody-status-info-soft);    border-color: var(--shody-status-info-line); }
.shody-badge--muted   { color: var(--shody-status-muted-ink);   background: var(--shody-status-muted-soft);   border-color: var(--shody-status-muted-line); }
/* Running/info badges get a soft signal pulse on the dot. */
.shody-badge--info::before { animation: shody-pulse 1.6s ease-in-out infinite; }

/* ── Form field helper (templates/_form_field.html) ────────────────── */
.shody-field { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: var(--shody-gap-md); }
.shody-field__label { font-size: 0.8rem; font-weight: 600; color: var(--shody-text-muted); }
.shody-field__label--required::after { content: " *"; color: var(--shody-status-error); }
.shody-field__help { font-size: 0.75rem; color: var(--shody-text-faint); }
.shody-field__error { font-size: 0.78rem; color: var(--shody-status-error-ink); margin-top: 0.15rem; }
.shody-field input.is-invalid,
.shody-field select.is-invalid,
.shody-field textarea.is-invalid { border-color: var(--shody-status-error); box-shadow: 0 0 0 3px var(--shody-status-error-soft); }

/* ── Empty state (templates/_empty_state.html) ─────────────────────── */
.shody-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 3rem 1.5rem;
    border: 1px dashed var(--shody-border-strong);
    border-radius: var(--shody-r-lg);
    color: var(--shody-text-muted);
    gap: var(--shody-gap-sm);
    background:
        radial-gradient(circle at 20% 20%, var(--shody-accent-soft) 0, transparent 45%),
        radial-gradient(circle at 80% 80%, var(--shody-flow-soft) 0, transparent 45%),
        var(--shody-surface-1);
}
.shody-empty__icon {
    font-size: 1.5rem;
    color: var(--shody-accent);
    width: 3.4rem;
    height: 3.4rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--shody-r-lg);
    background: var(--shody-surface-0);
    border: 1px solid var(--shody-border);
    box-shadow: var(--shody-shadow-1);
    margin-bottom: 0.25rem;
}
.shody-empty__title { font-size: 1rem; font-weight: 700; color: var(--shody-text-strong); }
.shody-empty__message { font-size: 0.85rem; max-width: 42ch; line-height: 1.55; }
.shody-empty__cta { margin-top: 0.65rem; }

/* ── Async-action button busy indicator (static/js/shody-actions.js) ─ */
button.is-busy, .shody-btn.is-busy, .btn.is-busy {
    opacity: 0.7;
    cursor: progress;
    position: relative;
    pointer-events: none;
}
button.is-busy::after, .shody-btn.is-busy::after, .btn.is-busy::after {
    content: "";
    display: inline-block;
    margin-left: 0.5rem;
    width: 0.8em;
    height: 0.8em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    vertical-align: -0.1em;
    animation: shody-spin 0.7s linear infinite;
}

/* ── Skeleton loader ───────────────────────────────────────────────── */
.shody-skeleton {
    background: linear-gradient(90deg, var(--shody-surface-2) 25%, var(--shody-surface-3) 37%, var(--shody-surface-2) 63%);
    background-size: 400% 100%;
    animation: shody-shimmer 1.4s ease infinite;
    border-radius: var(--shody-r-xs);
    display: block;
}

/* ── Responsive table wrapper ──────────────────────────────────────── */
.shody-table-scroll {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--shody-r-sm);
}
@media (max-width: 640px) {
    /* Let content decide width on phones so column-hiding (.hide-sm) can bring
       a table within the viewport instead of a fixed floor forcing a scroll. */
    .shody-table-scroll table { min-width: 0; }
}

/* ── Mobile data-density helpers ───────────────────────────────────────
   Dense tables carry more columns than a phone can show. Tag low-priority
   cells with .hide-sm / .hide-md (on BOTH the <th> and every matching <td>)
   to drop them on small screens; wrap action-button labels in <span class="lbl">
   and add .act-iconify to the actions cell to collapse buttons to icon-only.
   Desktop is unaffected. */
@media (max-width: 576px) {
    .hide-sm { display: none !important; }
    /* Collapse action buttons to icon-only. .lbl is scoped to .act-iconify so
       it works for any button flavour (.btn as well as page-specific pills like
       .gso-edit-btn / .gso-del-btn). */
    .act-iconify .lbl { display: none; }
    .act-iconify .btn, .act-iconify .gso-edit-btn, .act-iconify .gso-del-btn { padding-left: 0.5rem; padding-right: 0.5rem; }
    .act-iconify a i, .act-iconify button i { margin-left: 0 !important; margin-right: 0 !important; }
    .act-iconify { white-space: nowrap; }
    /* tighter cells so the remaining columns fit comfortably */
    .shody-table-scroll table th, .shody-table-scroll table td,
    .table-responsive table th, .table-responsive table td,
    .am-table-wrap table th, .am-table-wrap table td,
    .as-table-wrap table th, .as-table-wrap table td { padding-left: 0.5rem; padding-right: 0.5rem; }
    /* Let long unbreakable values (emails, snake_case names) wrap instead of
       forcing the table wider than the phone. Action cells keep nowrap so the
       icon buttons stay on one line. */
    .shody-table-scroll td:not(.act-iconify), .table-responsive td:not(.act-iconify),
    .am-table-wrap td:not(.act-iconify), .as-table-wrap td:not(.act-iconify) { white-space: normal !important; overflow-wrap: anywhere; }
}
@media (max-width: 768px) {
    .hide-md { display: none !important; }
}

/* ── Refresh countdown chip ────────────────────────────────────────── */
.shody-refresh-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.18em 0.7em;
    border-radius: var(--shody-r-pill);
    background: var(--shody-flow-soft);
    color: var(--shody-flow);
    font-size: 0.72rem;
    font-weight: 600;
}
.shody-refresh-chip::before {
    content: "";
    width: 0.4em; height: 0.4em;
    border-radius: 50%;
    background: currentColor;
    animation: shody-pulse 1.6s ease-in-out infinite;
}

/* ── Section eyebrow / label ───────────────────────────────────────── */
.shody-eyebrow {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--shody-text-faint);
}
