/* ════════════════════════════════════════════════════════════════════
   HIVE DESIGN SYSTEM — modern fintech premium
   Shared token layer + universal primitives, linked by every page
   (agents.html, dashboard.html, admin.html). Page-specific components
   live in each page's own <style>. Every component color references a
   token here, so theming + cross-page consistency are single-sourced.

   NOTE: each page must also include, in <head> BEFORE this stylesheet:
     1. the anti-FOUC inline script that sets <html data-theme="…">
     2. the Inter font <link> (display=swap)
   and in the header markup: the #theme-toggle button (wired by a tiny
   per-page wireThemeToggle()).
   ════════════════════════════════════════════════════════════════════ */

:root,[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0A0B0D; --surface:#14161A; --surface-raised:#1B1E23;
  --text:#EBEDF0; --text-muted:#99A0A8; --text-subtle:#868D96; /* subtle bumped to AA ~4.7:1 on --bg (was #646B73, 3.6:1) — still a step below muted */
  /* AMBER BEE-YELLOW (2026-07-10). --accent = text/link accent (theme-aware); --accent-fill = universal
     bee-yellow for FILLS (buttons/badges/bee), always yellow with near-black --accent-contrast on it. */
  --accent:#f5c800; --accent-hover:#F8D747; --accent-contrast:#0A0B0D; --accent-soft:rgba(245,200,0,.11);
  --accent-fill:#f5c800; --accent-fill-strong:#EAB900; --amber:var(--accent);
  --success:#3FBE82; --success-soft:rgba(63,190,130,.14);
  --danger:#E96A60;  --danger-soft:rgba(233,106,96,.14);
  --border:#24272D; --border-strong:#313640;
  --shadow-card:0 1px 2px rgba(0,0,0,.45), 0 6px 20px -4px rgba(0,0,0,.40);
  --shadow-raised:0 10px 30px -6px rgba(0,0,0,.55);
}
[data-theme="light"]{
  color-scheme:light;
  --bg:#F4F6F8; --surface:#FFFFFF; --surface-raised:#FBFCFE;
  --text:#161A1F; --text-muted:#586069; --text-subtle:#616870; /* subtle bumped to AA ~5.3:1 on --bg (was #8B929B, 2.7:1) — still a step below muted */
  /* light theme: text/link accent darkens to a deep honey for readability on the light ground (#7A5A00 =
     5.89:1 AA); FILLS stay bee-yellow (--accent-fill) with near-black text, so buttons/bee remain yellow. */
  --accent:#7A5A00; --accent-hover:#6E5200; --accent-contrast:#0A0B0D; --accent-soft:rgba(122,90,0,.10);
  --accent-fill:#f5c800; --accent-fill-strong:#EAB900; --amber:var(--accent);
  --success:#1F9D63; --success-soft:rgba(31,157,99,.12);
  --danger:#D64A42;  --danger-soft:rgba(214,74,66,.10);
  --border:#E4E7EC; --border-strong:#D2D7DE;
  --shadow-card:0 1px 2px rgba(17,24,39,.05), 0 6px 20px -6px rgba(17,24,39,.10);
  --shadow-raised:0 12px 28px -8px rgba(17,24,39,.16);
}
:root{
  --font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --font-mono:ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --radius-card:14px; --radius-btn:10px; --radius-pill:999px;
}

*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--text);font-family:var(--font-sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;transition:background-color .2s ease,color .2s ease}
.wrap{max-width:1160px;margin:0 auto;padding:0 20px}

/* header */
header{border-bottom:1px solid var(--border);position:sticky;top:0;background:var(--bg);z-index:10;transition:background-color .2s ease,border-color .2s ease}
@supports (backdrop-filter:blur(1px)){ header{background:color-mix(in srgb,var(--bg) 82%,transparent);backdrop-filter:blur(10px)} }
.bar{display:flex;align-items:center;justify-content:space-between;height:60px}
.brand{display:flex;align-items:center;gap:10px;font-weight:700;font-size:15px;letter-spacing:.14em;text-transform:uppercase;color:var(--text);text-decoration:none}
.brand svg{display:block}
.brand svg polygon,.brand svg rect{fill:var(--accent-fill)}
.brand svg ellipse,.brand svg circle{fill:var(--bg)}
.bar-right{display:flex;align-items:center;gap:8px}
.navlink{font-family:var(--font-sans);font-size:13px;font-weight:500;color:var(--text-muted);text-decoration:none;border-radius:var(--radius-btn);padding:7px 12px;background:transparent;border:none;cursor:pointer;transition:color .15s,background-color .15s}
.navlink:hover{color:var(--text);background:var(--surface)}
.signout{font-family:var(--font-sans);font-size:13px;font-weight:500;cursor:pointer;color:var(--text-muted);background:transparent;border:1px solid var(--border);border-radius:var(--radius-btn);padding:7px 12px;transition:color .15s,border-color .15s}
.signout:hover{color:var(--text);border-color:var(--border-strong)}
.theme-toggle{display:grid;place-items:center;width:36px;height:36px;cursor:pointer;color:var(--text-muted);background:transparent;border:1px solid var(--border);border-radius:var(--radius-btn);transition:color .15s,border-color .15s,background-color .15s}
.theme-toggle:hover{color:var(--text);border-color:var(--border-strong);background:var(--surface)}
.theme-toggle .ic{display:none}
[data-theme="dark"] .theme-toggle .ic-sun{display:block}
[data-theme="light"] .theme-toggle .ic-moon{display:block}

/* section titles */
.section-title{font-family:var(--font-sans);font-size:13px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);margin:28px 0 12px}

/* buttons — primary (filled gold) + ghost + small secondary */
.btn{font-family:var(--font-sans);font-size:13px;font-weight:600;letter-spacing:.01em;cursor:pointer;background:var(--accent-fill);color:var(--accent-contrast);border:1px solid transparent;border-radius:var(--radius-btn);padding:10px 18px;box-shadow:0 1px 2px rgba(0,0,0,.12);transition:background-color .15s,transform .12s,box-shadow .15s}
.btn:hover{background:var(--accent-fill-strong);transform:translateY(-1px)}
.btn:disabled{background:var(--surface-raised);color:var(--text-subtle);border-color:var(--border);cursor:not-allowed;transform:none;box-shadow:none}
.btn.ghost{background:transparent;color:var(--text);border-color:var(--border);box-shadow:none}
.btn.ghost:hover{background:var(--surface-raised);border-color:var(--border-strong)}
.btn-sm{font-family:var(--font-sans);font-size:12px;font-weight:600;cursor:pointer;background:var(--surface-raised);color:var(--text);border:1px solid var(--border);border-radius:var(--radius-btn);padding:8px 14px;transition:background-color .15s,border-color .15s}
.btn-sm:hover{background:var(--surface);border-color:var(--border-strong)}
.btn-sm:disabled{color:var(--text-subtle);cursor:not-allowed}

/* form fields */
.field{display:flex;flex-direction:column;gap:6px}
.field label{font-size:11px;font-weight:500;text-transform:uppercase;letter-spacing:.07em;color:var(--text-muted)}
.field input,.field select{font-family:var(--font-sans);font-size:13px;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:var(--radius-btn);padding:9px 11px;min-width:200px;outline:none;transition:border-color .15s}
.field input:focus,.field select:focus{border-color:var(--accent)}

/* modal — overlay scrim + fade/slide animation (animate in/out of display:none;
   handlers only toggle [hidden]). Pages may override layout (alignment/padding/
   max-width) in their own <style>; this is the shared base. */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;z-index:50;padding:20px;opacity:1;transition:opacity .18s ease, display .18s allow-discrete}
.modal-overlay[hidden]{display:none;opacity:0}
@starting-style{ .modal-overlay:not([hidden]){opacity:0} }
.modal{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-card);max-width:480px;width:100%;padding:22px;max-height:90vh;overflow:auto;box-shadow:var(--shadow-raised);transition:transform .18s ease, opacity .18s ease}
.modal-overlay[hidden] .modal{transform:translateY(8px);opacity:0}
@starting-style{ .modal-overlay:not([hidden]) .modal{transform:translateY(8px);opacity:0} }
@media (prefers-reduced-motion: reduce){ .modal-overlay,.modal-overlay .modal{transition:none} }
.modal-head{font-family:var(--font-sans);font-size:14px;font-weight:600;letter-spacing:.02em;color:var(--text);margin-bottom:18px}
.modal .field{margin-bottom:12px}
.modal .field input,.modal .field select{width:100%}
.modal-actions{display:flex;gap:10px;justify-content:flex-end;margin:18px 0 4px}

/* tooltips (body-level fixed so modal overflow can't clip them) */
.tip{display:inline-block;margin-left:4px;font-size:11px;color:var(--text-subtle);cursor:help;user-select:none}
.tip:hover,.tip:focus{color:var(--accent);outline:none}
#tooltip{position:fixed;max-width:260px;background:var(--surface);border:1px solid var(--border);border-radius:10px;color:var(--text);font-family:var(--font-sans);font-size:11px;line-height:1.5;padding:8px 10px;z-index:100;pointer-events:none;box-shadow:var(--shadow-raised)}
#tooltip[hidden]{display:none}

/* status pills (badges + tags) + lifecycle led */
.badge,.tag{font-family:var(--font-sans);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:3px 10px;border-radius:var(--radius-pill);white-space:nowrap}
.badge.running,.tag.running{background:var(--success-soft);color:var(--success)}
.badge.paused,.tag.paused{background:var(--surface-raised);color:var(--text-muted);border:1px solid var(--border)}
.badge.grounded,.tag.grounded{background:transparent;color:var(--text-subtle);border:1px solid var(--border)}
/* idle = enabled lifecycle but no verified live-execution signal (neutral, not green) */
.badge.idle,.tag.idle{background:var(--surface-raised);color:var(--text-muted);border:1px solid var(--border)}
/* active = the owner explicitly STARTED it (lifecycle intent) — amber outline, deliberately NOT
   green: green stays reserved for a future runtime heartbeat that proves live execution. */
.badge.active,.tag.active{background:transparent;color:var(--accent);border:1px solid var(--accent)}
.led{color:var(--success);font-size:9px;line-height:1}
.led.active{color:var(--accent)}
.led.paused,.led.grounded,.led.off,.led.idle{color:var(--text-subtle)}

/* shared states */
.empty{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-card);box-shadow:var(--shadow-card);padding:32px;text-align:center;color:var(--text-muted);margin-bottom:24px}
.err{border:1px solid var(--danger);background:var(--danger-soft);color:var(--danger);border-radius:var(--radius-card);padding:14px 16px;margin-bottom:20px;font-size:13px}
footer{color:var(--text-subtle);font-size:12px;text-align:center;padding:40px 0 24px;letter-spacing:.03em}

/* ══════════════════════════════════════════════════════════════════════════════════════════════════
   HIVE PULSE — the live "what she's doing right now" status line. SHARED (owner 2026-07-17).
   ══════════════════════════════════════════════════════════════════════════════════════════════════
   THE SINGLE SOURCE for every surface that renders a status line: the agent DETAIL page header, the
   portfolio CARDS, and anything added later. It lives here because two independent copies had already
   drifted — the detail page had the full treatment (ping tempo + animated ellipsis + shimmer) while
   the cards had only a lone ping, with a separate `acpulsering` keyframe nobody remembered to update.
   A shared component is the only thing that stops that recurring. Do NOT re-declare these rules in a
   page's <style>; add page-specific LAYOUT (margin/size) against .hive-pulse instead.

   Contract — the markup a page must render:
     <div class="hive-pulse [is-live] [pulse-STATE]">
       <span class="hp-dot"></span>
       <span class="hp-text" role="status" aria-live="polite">Scanning markets</span>
       <span class="hp-ell" aria-hidden="true"><i>.</i><i>.</i><i>.</i></span>   (only if the state text ended in an ellipsis)
     </div>
   STATE ∈ scanning | watching | analyzing | checking | placing | reconnecting | paused | resting.
   `is-live` = a real, fresh signal. Never decorate a stale one — a frozen fake is worse than nothing.
*/
.hive-pulse{display:flex;align-items:center;gap:8px;min-height:16px;font-size:12px;color:var(--text-muted);transition:color .4s ease}
.hive-pulse[hidden]{display:none}                    /* explicit: beats display:flex so [hidden] hides */
.hive-pulse .hp-dot{flex:0 0 auto;width:7px;height:7px;border-radius:50%;background:var(--text-subtle);position:relative;transition:background .4s ease}
.hive-pulse .hp-text{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;transition:opacity .3s ease}
/* LIVE — amber dot with a soft expanding sonar ring. Calm base; TEMPO below is the only state coupling. */
.hive-pulse.is-live{color:var(--text)}
.hive-pulse.is-live .hp-dot{background:var(--accent)}
.hive-pulse.is-live .hp-dot::after{content:"";position:absolute;inset:0;border-radius:50%;background:var(--accent);opacity:.5;animation:hpRing 2.5s ease-out infinite}
@keyframes hpRing{0%{transform:scale(1);opacity:.5}70%{transform:scale(2.6);opacity:0}100%{transform:scale(2.6);opacity:0}}
/* TEMPO — real work beats faster than calm observation. Same states, different pace. No new states. */
.hive-pulse.pulse-analyzing .hp-dot::after,.hive-pulse.pulse-checking .hp-dot::after{animation-duration:1.7s}
.hive-pulse.pulse-placing .hp-dot::after{animation-duration:1.3s}
/* RECONNECTING — amber-muted fade: data is stale and says so. No fake liveness. */
.hive-pulse.pulse-reconnecting{color:var(--text-muted)}
.hive-pulse.pulse-reconnecting .hp-dot{background:var(--accent);opacity:.55;animation:hpFade 1.6s ease-in-out infinite}
@keyframes hpFade{0%,100%{opacity:.3}50%{opacity:.7}}
/* PAUSED / RESTING — still, muted dot. An agent that isn't hunting must not look like it is. */
.hive-pulse.pulse-paused .hp-dot,.hive-pulse.pulse-resting .hp-dot{background:var(--text-subtle)}
/* ANIMATED ELLIPSIS — the state text carries a literal '…'; JS strips it and these three dots pulse in
   sequence. OUTSIDE .hp-text so aria-live reads clean prose and the shimmer needn't cross it. */
.hive-pulse .hp-ell{flex:0 0 auto;margin-left:-3px;letter-spacing:.05em;color:inherit}
.hive-pulse .hp-ell i{font-style:normal;opacity:.22;animation:hpEll 1.4s ease-in-out infinite}
.hive-pulse .hp-ell i:nth-child(2){animation-delay:.18s}
.hive-pulse .hp-ell i:nth-child(3){animation-delay:.36s}
@keyframes hpEll{0%,62%,100%{opacity:.22}30%{opacity:1}}
.hive-pulse.pulse-analyzing .hp-ell i,.hive-pulse.pulse-checking .hp-ell i{animation-duration:1.1s}
.hive-pulse.pulse-placing .hp-ell i{animation-duration:.85s}
/* SHIMMER — one amber glint travels the text ~every 6s (sweep ~1.7s, then rests). LIVE states only.
   FAIL-SAFE: every var() carries a literal fallback. If a token failed to resolve, the gradient would
   be invalid, background-image would drop, and -webkit-text-fill-color:transparent would SURVIVE —
   leaving the status line INVISIBLE. The line reporting what a live money agent is doing must never be
   able to vanish for a cosmetic effect, so the gradient is always valid by construction. */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .hive-pulse.is-live .hp-text{
    background-image:linear-gradient(100deg,var(--text,#7A7F87) 0%,var(--text,#7A7F87) 40%,var(--accent,#f5c800) 50%,var(--text,#7A7F87) 60%,var(--text,#7A7F87) 100%);
    background-size:280% 100%;-webkit-background-clip:text;background-clip:text;
    -webkit-text-fill-color:transparent;animation:hpShimmer 6s ease-in-out infinite}
}
@keyframes hpShimmer{0%,72%{background-position:130% 0}100%{background-position:-30% 0}}
/* REDUCED MOTION — collapse to the honest static dot. The shimmer MUST hand the text its solid colour
   back, or it renders invisible. */
@media (prefers-reduced-motion:reduce){
  .hive-pulse .hp-dot::after,.hive-pulse.pulse-reconnecting .hp-dot,.hive-pulse .hp-ell i{animation:none}
  .hive-pulse.pulse-reconnecting .hp-dot{opacity:.7}
  .hive-pulse .hp-ell i{opacity:.55}
  .hive-pulse.is-live .hp-text{animation:none;background-image:none;-webkit-text-fill-color:currentColor;color:var(--text)}
}

/* ── Keyboard focus ring — site-wide a11y (2026-07-18). :focus-visible fires ONLY on keyboard nav,
   never on mouse click, so this gives keyboard users a clear ring without affecting pointer users.
   Bare pseudo-class → covers every focusable element (buttons, links, inputs, tabs, [tabindex]). ── */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
