/* =============================================================
   MAULBOT Dashboard - Custom Styles
   Supplements Tailwind CSS with animations, HTMX integration,
   and responsive layout helpers.
   ============================================================= */

/* ---- Gray-750: between gray-700 (#374151) and gray-800 (#1f2937) ---- */
.bg-gray-750   { background-color: #2b3544; }
.hover\:bg-gray-750:hover { background-color: #2b3544; }

/* ---- Gray-850: between gray-800 (#1f2937) and gray-900 (#111827) ---- */
.bg-gray-850   { background-color: #182030; }

/* ---- Trade day group header backgrounds (subtle P&L tint) ---- */
.day-header-positive { background-color: rgba(34, 197, 94, 0.08); }  /* green-500 @ 8% */
.day-header-negative { background-color: rgba(239, 68, 68, 0.08); }  /* red-500 @ 8% */
.day-header-neutral  { background-color: #1f2937; }                   /* gray-800 */

/* ---- Rotation utilities (chevrons in trade groups) ---- */
.rotate-0  { transform: rotate(0deg); }
.rotate-90 { transform: rotate(90deg); }

/* ---- Loading Spinner ---- */
.spinner {
    width: 2rem;
    height: 2rem;
    border: 3px solid rgba(255, 255, 255, 0.15);
    border-top-color: #3b82f6; /* blue-500 */
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

.spinner-sm {
    width: 1rem;
    height: 1rem;
    border-width: 2px;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* ---- HTMX Loading Indicator ---- */
.htmx-indicator {
    display: none;
    opacity: 0;
    transition: opacity 0.2s ease-in;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
    display: inline-block;
    opacity: 1;
}

/* Complement of .htmx-indicator: hide an element ONLY while its
   htmx-request element (self or ancestor) is in flight. Pairs with
   .htmx-indicator for button label <-> spinner swaps (e.g. the
   confirm_liquidate_modal.html "Working…" spinner on the destructive
   Cancel-All / Liquidate confirm button). */
.htmx-request .htmx-loading-hide,
.htmx-request.htmx-loading-hide {
    display: none;
}

/* Dim target element while loading */
.htmx-request.htmx-settling {
    opacity: 0.6;
}

/* ---- HTMX Swap Transitions ---- */
.htmx-swapping {
    opacity: 0;
    transition: opacity 0.15s ease-out;
}

.htmx-settling {
    transition: opacity 0.15s ease-in;
}

.htmx-added {
    opacity: 0;
    animation: fade-in 0.2s ease-in forwards;
}

@keyframes fade-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ---- Toast Notifications ---- */
#toast-container {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    pointer-events: none;
}

.toast {
    pointer-events: auto;
    min-width: 280px;
    max-width: 420px;
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    color: #f9fafb;
    font-size: 0.875rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
    animation: toast-in 0.3s ease-out forwards;
}

.toast-error {
    background-color: #991b1b; /* red-800 */
    border-left: 4px solid #ef4444;
}

.toast-success {
    background-color: #166534; /* green-800 */
    border-left: 4px solid #22c55e;
}

.toast-info {
    background-color: #1e3a5f;
    border-left: 4px solid #3b82f6;
}

.toast-dismiss {
    animation: toast-out 0.25s ease-in forwards;
}

@keyframes toast-in {
    from { opacity: 0; transform: translateX(100%); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes toast-out {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(100%); }
}

/* ---- Table Responsive Wrapper ---- */
.table-responsive {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: #4b5563 #1f2937;
}

.table-responsive::-webkit-scrollbar {
    height: 6px;
}

.table-responsive::-webkit-scrollbar-track {
    background: #1f2937;
}

.table-responsive::-webkit-scrollbar-thumb {
    background: #4b5563;
    border-radius: 3px;
}

/* ---- Chart Container ---- */
.chart-container {
    position: relative;
    width: 100%;
    min-height: 280px;
}

.chart-container canvas {
    width: 100% !important;
}

@media (min-width: 768px) {
    .chart-container {
        min-height: 360px;
    }
}

@media (min-width: 1280px) {
    .chart-container {
        min-height: 440px;
    }
}

/* ---- Live Page: Resize Handle ---- */
.resize-handle {
    cursor: col-resize;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    transition: background-color 0.15s;
}
.resize-handle:hover,
.resize-handle.dragging {
    background-color: #3b82f6;
}
body.resizing-panel {
    cursor: col-resize !important;
    user-select: none !important;
    -webkit-user-select: none !important;
}

/* ---- Live Page: Right Panel Tabs ---- */
.right-tab-btn {
    padding: 6px 12px;
    font-size: 12px;
    font-weight: 500;
    color: #9ca3af;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}
.right-tab-btn:hover {
    color: #e5e7eb;
}
.right-tab-btn.active {
    color: #60a5fa;
    border-bottom-color: #3b82f6;
}

/* ---- Active Navigation Link ---- */
.nav-link {
    padding: 0.5rem 0.75rem;
    border-radius: 0.375rem;
    color: #9ca3af; /* gray-400 */
    transition: color 0.15s, background-color 0.15s;
}

.nav-link:hover {
    color: #e5e7eb; /* gray-200 */
    background-color: rgba(55, 65, 81, 0.5);
}

.nav-link-active {
    color: #ffffff;
    background-color: #1e3a5f;
}

/* ---- Mobile Hamburger Menu ---- */
#mobile-menu {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease-out;
}

#mobile-menu.open {
    max-height: 500px;
}

#hamburger-btn .bar {
    display: block;
    width: 1.25rem;
    height: 2px;
    margin: 4px auto;
    background-color: #9ca3af;
    transition: transform 0.25s ease, opacity 0.25s ease;
}

#hamburger-btn.active .bar:nth-child(1) {
    transform: translateY(6px) rotate(45deg);
}

#hamburger-btn.active .bar:nth-child(2) {
    opacity: 0;
}

#hamburger-btn.active .bar:nth-child(3) {
    transform: translateY(-6px) rotate(-45deg);
}

/* ---- Misc Utility ---- */
.pnl-positive { color: #22c55e; }
.pnl-negative { color: #ef4444; }
.pnl-zero     { color: #9ca3af; }

/* Pulse dot for "connected" indicator */
.pulse-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #22c55e;
    animation: pulse-ring 1.5s ease-out infinite;
}

@keyframes pulse-ring {
    0%   { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.5); }
    70%  { box-shadow: 0 0 0 6px rgba(34, 197, 94, 0); }
    100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); }
}

/* Accessibility: respect user motion preferences */
@media (prefers-reduced-motion: reduce) {
    .animate-spin,
    .animate-pulse,
    [class*="animate-"] {
        animation: none !important;
        transition: none !important;
    }
    .status-dot::after {
        animation: none !important;
    }
}

/* =============================================================
   MOBILE FIXES — applies system-wide via media query
   ============================================================= */

/* iOS Safari auto-zooms any input with font-size < 16px on focus.
   Force 16px on all form controls for mobile to prevent the zoom. */
@media (max-width: 767px) {
    input,
    select,
    textarea {
        font-size: 16px !important;
    }
}

/* Use dynamic viewport height where supported. iOS Safari's 100vh
   includes the URL bar, causing the bottom 80px to be cut off.
   100dvh excludes the URL bar and reflows correctly when it appears.
   This applies to any element using h-screen or min-h-screen via
   Tailwind, plus the body and any explicit calc(100vh - X) layouts. */
@supports (height: 100dvh) {
    .h-screen        { height: 100dvh !important; }
    .min-h-screen    { min-height: 100dvh !important; }
}

/* Safe-area-inset-bottom: prevent iPhone home indicator overlap.
   Apply to body so all full-height pages clear the home bar. */
body {
    padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* Mobile chart overlay needs to clear the home indicator too,
   since it uses fixed inset-0 which ignores body padding. */
#mobile-chart-overlay {
    padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* Body scroll lock for modals/overlays.  Apply via JS by adding
   .body-scroll-lock to the body element. */
body.body-scroll-lock {
    overflow: hidden;
    touch-action: none;
}

/* Touch target helper: minimum 44x44px hit area per iOS HIG.
   Apply to any button or interactive element via class="touch-target". */
.touch-target {
    min-width: 44px;
    min-height: 44px;
}

/* Mobile: enlarge cramped chart range buttons so users can tap them
   without fat-fingering.  Desktop layout (text-[11px], px-2 py-0.5)
   is preserved by the `min-width: 768px` cutoff. */
@media (max-width: 767px) {
    .chart-range-btn {
        padding: 8px 12px !important;
        font-size: 12px !important;
        min-height: 36px;
    }
}

/* =============================================================
   MOBILE CARD PATTERN (Round 2 — replaces horizontal-scroll tables)

   Used by the dual-render pattern in live_positions.html,
   live_watchlist.html, signals_stream.html, and trades_table.html:

       <table class="w-full hidden md:table">...desktop...</table>
       <div class="md:hidden">
           <div class="mobile-card">...one card per row...</div>
       </div>

   Each `mobile-card` is a self-contained block with a header row
   (symbol + status badge + primary action) and a 2-column metric
   grid below.  The 16px font on inputs prevents iOS auto-zoom
   (already enforced globally for <input>/<select>/<textarea>).
   ============================================================= */
.mobile-card {
    display: block;
    padding: 14px 12px;                       /* slightly taller padding for breathing room */
    border-bottom: 1px solid rgb(55 65 81);   /* gray-700 */
    background: rgb(17 24 39);                /* gray-900 */
}
.mobile-card + .mobile-card {
    margin-top: 1px;                          /* micro-gap between cards for visual separation */
}
.mobile-card:hover { background: rgb(31 41 55); }   /* gray-800 */
.mobile-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 10px;                      /* slightly more separation between header and metrics */
}
.mobile-card-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 12px;                            /* 6→8px row gap for cleaner separation */
    font-size: 13px;
}
.mobile-card-grid .col-span-2 { grid-column: span 2 / span 2; }
.mobile-card-label {
    color: rgb(107 114 128);                  /* gray-500 */
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    line-height: 1;
    margin-bottom: 2px;
}
.mobile-card-value {
    color: rgb(229 231 235);                  /* gray-200 */
    font-variant-numeric: tabular-nums;
    font-size: 13px;
}
/* P&L is the hero metric on mobile — slightly larger for quick scanning */
.mobile-card-value.text-base { font-size: 15px; }

/* =============================================================
   MOBILE FILTER FORM GRID (Round 2)

   Replaces flex-wrap on filter forms.  Apply via:
       <div class="mobile-form-grid flex flex-wrap items-end gap-3">

   On desktop the original flex-wrap behavior is preserved.  On
   mobile (<768px), fields collapse into a 2-column grid and the
   submit/clear buttons span the full row at the bottom.  Mark
   any field that needs to span both columns (e.g. a wide select)
   with `col-span-2-mobile`.
   ============================================================= */
@media (max-width: 767px) {
    .mobile-form-grid {
        display: grid !important;
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: 8px !important;
    }
    .mobile-form-grid > .col-span-2-mobile { grid-column: span 2 / span 2; }
    .mobile-form-grid > button[type="submit"],
    .mobile-form-grid > a {
        grid-column: span 2 / span 2;
        min-height: 44px;
    }
    .mobile-form-grid input,
    .mobile-form-grid select,
    .mobile-form-grid textarea {
        width: 100% !important;
    }
    /* Inner field wrappers (label + input) — let them fill grid cell */
    .mobile-form-grid > div { width: 100%; }
}

/* Mobile tab bar and bottom sheet removed — mobile uses single-scroll layout
   with inline dropdown for account switching. */

/* =============================================================
   TOAST NOTIFICATIONS (Step 8)
   ============================================================= */
.toast-notification {
    background: #1f2937;
    border: 1px solid #374151;
    border-radius: 8px;
    padding: 10px 16px;
    color: #e5e7eb;
    font-size: 13px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.4);
    animation: toast-slide-in 0.3s ease-out;
    max-width: 360px;
    cursor: pointer;
    transition: opacity 0.3s;
}
.toast-notification:hover { opacity: 0.8; }
.toast-entry   { border-left: 3px solid #3b82f6; }
.toast-win     { border-left: 3px solid #22c55e; }
.toast-loss    { border-left: 3px solid #ef4444; }
.toast-info    { border-left: 3px solid #6b7280; }
@keyframes toast-slide-in {
    from { transform: translateY(20px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

/* =============================================================
   BAR TIMER (Step 9)
   ============================================================= */
.bar-timer-strip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 12px;
    background: #111827;
    border-bottom: 1px solid #1f2937;
    font-size: 13px;
    font-family: 'Courier New', monospace;
}
.bar-timer-progress {
    flex: 1;
    height: 4px;
    background: #374151;
    border-radius: 2px;
    overflow: hidden;
}
.bar-timer-fill {
    height: 100%;
    border-radius: 2px;
    transition: width 1s linear, background-color 0.5s;
}

/* =============================================================
   SPARKLINE (Step 10)
   ============================================================= */
.sparkline-container {
    display: inline-block;
    vertical-align: middle;
    margin: 0 4px;
}

/* =============================================================
   PORTFOLIO RISK BAR (Step 11)
   ============================================================= */
.risk-bar-outer {
    height: 6px;
    background: #374151;
    border-radius: 3px;
    overflow: hidden;
    width: 100%;
}
.risk-bar-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.5s ease, background-color 0.5s;
}

/* =============================================================
   POSITION HEAT INDICATOR (Step 12)
   ============================================================= */
.heat-bar {
    height: 4px;
    border-radius: 2px;
    background: linear-gradient(to right, #ef4444 0%, #eab308 40%, #22c55e 100%);
    position: relative;
    margin: 2px 0;
}
.heat-bar-mask {
    position: absolute;
    right: 0;
    top: 0;
    height: 100%;
    background: #1f2937;
    border-radius: 0 2px 2px 0;
    transition: width 0.5s;
}

/* Tailwind JIT gap fallback (2026-04-23) — `pointer-events-auto` is used in
   admin modal templates (scheduled_jobs, services) via the standard
   split-backdrop pattern (outer wrapper = `pointer-events-none` to let
   clicks pass through to the backdrop; inner modal = `pointer-events-auto`
   to catch clicks on modal content). The compiled `tailwind.min.css` ships
   the `-none` utility but NOT the `-auto` utility, so inner modal content
   inherits `pointer-events: none` from its wrapper and the backdrop wins
   hit-testing — clicking anywhere in the modal triggered close-on-backdrop.
   Define the utility here so the standard Tailwind class continues to
   work without a Tailwind rebuild step. Will be a no-op if a future
   rebuild emits the rule upstream. */
.pointer-events-auto { pointer-events: auto; }

/* ============================================================
   Responsive page-width utilities (Rule 41 §A)
   ------------------------------------------------------------
   `<main>` in base.html / controller/base.html now uses
   `max-w-full` so data/table pages can fill the content area.
   Pages that benefit from a tighter reading column (forms,
   help text, single-task wizards) opt in with `.form-container`.

   The clamp() formula scales the form width SEAMLESSLY with
   the viewport — no breakpoint jumps:
     - floor 40rem  (~640px) for readability on narrow viewports
     - preferred 60vw scales linearly with screen width
     - ceiling 87.5rem (~1400px) keeps line length scannable on 4K

   Resolved widths at common viewports:
     400px  phone  → 100%   (parent wins; width:100% beats max-w)
     768px  tablet → 640px  (floor)
     1280px laptop → 768px  (60vw)
     1440px desk   → 864px  (60vw)
     1920px HD     → 1152px (60vw)
     2560px+ 4K    → 1400px (ceiling)
   ============================================================ */
.form-container {
  width: 100%;
  max-width: clamp(40rem, 60vw, 87.5rem);
  margin-inline: auto;
}

/* Tighter variant for narrow single-column wizards / settings panels.
   Use sparingly — prefer `.form-container` unless a page is visibly
   too wide with the default ceiling. */
.form-container-narrow {
  width: 100%;
  max-width: clamp(36rem, 50vw, 64rem);
  margin-inline: auto;
}
