/*
 * TNT Trading Partners - Theme Stylesheet
 *
 * Extracted from base.html and restructured for theming. Appearance is driven
 * by two attributes on <html>:
 *     data-theme  = "dark" | "light"        (default: dark)
 *     data-color  = "tnt" | "ocean" | "emerald" | "violet"   (default: tnt)
 *
 * The default (dark + tnt) is pixel-identical to the previous hardcoded look.
 * Rules consume semantic tokens (--bg/--fg/--surface/--brand/--gradient/...),
 * so flipping theme or color recolors the whole app. The raw --tnt-* brand
 * palette is kept intact for any template that references it directly.
 */

:root {
    /* --- Fixed TNT brand palette (kept for back-compat with inline styles) --- */
    --tnt-red: #C92A2A;
    --tnt-orange: #E85D04;
    --tnt-yellow: #F59F00;
    --tnt-gold: #D4850D;
    --tnt-navy: #1A365D;
    --tnt-black: #0D0D0D;
    --tnt-charcoal: #1A1A1A;
    --tnt-dark: #141414;
    --tnt-gray: #2D2D2D;
    --tnt-gray-light: #9A9A9A;
    --tnt-white: #FFFFFF;
    --tnt-offwhite: #F5F5F5;
    --tnt-gradient: linear-gradient(135deg, var(--tnt-red), var(--tnt-orange), var(--tnt-yellow));

    /* --- Semantic surface/text tokens: default to dark --- */
    --bg: var(--tnt-black);
    --fg: var(--tnt-white);
    --surface: var(--tnt-charcoal);
    --surface-2: var(--tnt-gray);
    --border: var(--tnt-gray);
    --border-strong: var(--tnt-gray-light);
    --muted: #b0b0b0;   /* light gray — meets 4.5:1 on --surface-2 (#2d2d2d); was #9a9a9a (3.5:1) */
    --nav-bg: rgba(13, 13, 13, 0.95);
    --nav-bg-scrolled: rgba(13, 13, 13, 0.98);

    /* --- Semantic brand/accent tokens: default to TNT color theme --- */
    --brand: var(--tnt-orange);
    --brand-strong: var(--tnt-red);
    --gradient: var(--tnt-gradient);
    --brand-glow: rgba(232, 93, 4, 0.4);
    --brand-glow-soft: rgba(232, 93, 4, 0.3);
}

/* ===================== THEME: light ===================== */
/* Softer light mode (after p54 / tv2gemini): a gray page with white cards that
   pop, a slightly darker "frame" for navbar/footer, and low-contrast borders —
   not an offensively bright pure-white surface everywhere. */
[data-theme="light"] {
    --bg: #f5f5f5;          /* page background (soft gray) */
    --fg: #1a1a1a;
    --surface: #ffffff;     /* cards — white so they pop off the page */
    --surface-2: #e2e6ea;   /* frame: navbar / footer / secondary surfaces */
    --border: rgba(0, 0, 0, 0.10);
    --border-strong: rgba(0, 0, 0, 0.18);
    --muted: #5f5f5f;   /* slightly darker for 4.5:1 on the light --surface-2 frame */
    --nav-bg: rgba(226, 230, 234, 0.95);
    --nav-bg-scrolled: rgba(226, 230, 234, 0.98);
}

/* ===================== COLOR THEMES ===================== */
/* TNT is the default (declared in :root); listed here for completeness. */
[data-color="tnt"] {
    --brand: var(--tnt-orange);
    --brand-strong: var(--tnt-red);
    --gradient: var(--tnt-gradient);
    --brand-glow: rgba(232, 93, 4, 0.4);
    --brand-glow-soft: rgba(232, 93, 4, 0.3);
}
[data-color="ocean"] {
    --brand: #0EA5E9;
    --brand-strong: #2563EB;
    --gradient: linear-gradient(135deg, #2563EB, #0EA5E9, #22D3EE);
    --brand-glow: rgba(14, 165, 233, 0.4);
    --brand-glow-soft: rgba(14, 165, 233, 0.3);
}
[data-color="emerald"] {
    --brand: #10B981;
    --brand-strong: #059669;
    --gradient: linear-gradient(135deg, #059669, #10B981, #34D399);
    --brand-glow: rgba(16, 185, 129, 0.4);
    --brand-glow-soft: rgba(16, 185, 129, 0.3);
}
[data-color="violet"] {
    --brand: #8B5CF6;
    --brand-strong: #7C3AED;
    --gradient: linear-gradient(135deg, #7C3AED, #8B5CF6, #A78BFA);
    --brand-glow: rgba(139, 92, 246, 0.4);
    --brand-glow-soft: rgba(139, 92, 246, 0.3);
}

/* ===================== A11Y CONTRAST OVERRIDES (axe-verified) =====================
   Bootstrap's default semantic colors and brand-orange-as-text don't meet WCAG
   4.5:1 on our themed surfaces, so tune them per theme. --brand-ink is a
   contrast-safe brand text color; --link-ink a safe plain-link blue. */
/* Contrast-safe brand text ink + Bootstrap's link-color token, per theme. Setting
   --bs-link-color (rather than a high-specificity `a` rule) fixes plain links
   without clobbering components that set their own link color. */
:root {
    --brand-ink: #fb8b3c;                 /* dark default */
    --bs-link-color: #6ea8fe; --bs-link-color-rgb: 110, 168, 254;
    --bs-link-hover-color: #8bb9ff; --bs-link-hover-color-rgb: 139, 185, 255;
}
[data-theme="light"] {
    --brand-ink: #9a3d0a;
    --bs-link-color: #0a58ca; --bs-link-color-rgb: 10, 88, 202;
    --bs-link-hover-color: #084298; --bs-link-hover-color-rgb: 8, 66, 152;
}
.dropzone-link { color: var(--brand-ink); }
/* Bootstrap semantic text/inline-code — brighten on dark, deepen on light. */
[data-theme="dark"] .text-danger,
[data-theme="dark"] .btn-outline-danger { color: #f28b95 !important; }
[data-theme="dark"] .text-success { color: #45d68a !important; }
/* Badge utilities: darken so white text passes even on a dimmed/disabled card. */
.badge.bg-secondary { background-color: #4b5563 !important; }
.badge.bg-danger { background-color: #b02a37 !important; }
[data-theme="dark"] .text-secondary,
[data-theme="dark"] .btn-outline-secondary { color: #adb5bd; border-color: #6c757d; }
[data-theme="dark"] code { color: #f087c0; }
[data-theme="light"] code { color: #a3195b; }

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

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    background-color: var(--bg);
    color: var(--fg);
    line-height: 1.6;
    overflow-x: hidden;
    transition: background-color 0.3s ease, color 0.3s ease;
}

/* Scrollbar styling */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--surface); }
::-webkit-scrollbar-thumb { background: var(--brand); border-radius: 4px; }

/* Skip link for accessibility */
.skip-link {
    position: absolute;
    top: -50px;
    left: 0;
    background: var(--brand);
    color: var(--tnt-white);
    padding: 12px 24px;
    z-index: 9999;
    text-decoration: none;
    font-weight: 600;
    border-radius: 0 0 8px 0;
    transition: top 0.3s;
}
.skip-link:focus { top: 0; }

/* Navbar styling */
.navbar {
    background: var(--nav-bg);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--border-strong);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.12);
    transition: all 0.3s ease;
}
.navbar.scrolled {
    background: var(--nav-bg-scrolled);
    box-shadow: 0 4px 30px rgba(0, 0, 0, 0.25);
}
/* 3-class selectors so they override Bootstrap's .navbar-dark .navbar-nav
   .nav-link (otherwise links are white and invisible in light mode). */
.navbar .navbar-nav .nav-link {
    color: var(--fg);
    font-weight: 500;
    padding: 0.5rem 1rem;
    transition: color 0.3s ease;
    position: relative;
}
/* Dropdown toggles are native <button>s (for keyboard/role correctness); reset the
   UA button chrome so they match the <a> nav-links — otherwise the default
   light-gray button background makes the white nav text fail contrast (1.13:1). */
.navbar .navbar-nav button.nav-link {
    background: transparent;
    border: 0;
    cursor: pointer;
}
.navbar .navbar-nav .nav-link:hover,
.navbar .navbar-nav .nav-link:focus,
.navbar .navbar-nav .nav-link.active { color: var(--brand-ink); }
.navbar .navbar-nav .nav-link.active::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 1rem;
    right: 1rem;
    height: 2px;
    background: var(--gradient);
    border-radius: 2px;
}
.btn-nav {
    background: var(--gradient);
    border: none;
    border-radius: 6px;
    padding: 0.5rem 1.25rem !important;
    font-weight: 600;
    color: var(--tnt-white) !important;
    transition: transform 0.3s, box-shadow 0.3s;
}
.btn-nav:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 20px var(--brand-glow);
    color: var(--tnt-white) !important;
}

/* Themed form controls (selects, inputs, textareas, checks) */
/* Use the themed muted color for Bootstrap's .text-muted AND .form-text (both
   default to a fixed gray that's too dark on our dark surfaces - low contrast/
   invisible). Theming .form-text here fixes every help caption app-wide. */
.text-muted { color: var(--muted) !important; }
.form-text { color: var(--muted); }

.form-label { color: var(--fg); font-weight: 500; }
.form-control,
.form-select,
textarea.form-control {
    background-color: var(--surface);
    color: var(--fg);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
}
.form-control::placeholder { color: var(--muted); }
.form-control:focus,
.form-select:focus {
    background-color: var(--surface);
    color: var(--fg);
    border-color: var(--brand);
    box-shadow: 0 0 0 0.2rem var(--brand-glow-soft);
}
.form-select {
    /* dark-aware dropdown caret */
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239A9A9A' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
}

/* Password reveal toggle — small borderless eye inside the field, mirroring
   dash_mantine_components PasswordInput (not a full-height bordered button). */
.pw-field { position: relative; }
.pw-field > .form-control { padding-right: 2.2rem; }
.pw-toggle {
    position: absolute;
    top: 50%;
    right: 0.5rem;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    line-height: 0;
}
.pw-toggle:hover { color: var(--fg); }
.pw-toggle svg { width: 18px; height: 18px; }

/* Symbol autocomplete suggestions (universe page). */
.symbol-search { position: relative; }
/* Wrapper the reusable symbol_search.js injects around any [data-symbol-search]
   input so its dropdown anchors to the input (not the wider form field). */
.symbol-search-wrap { position: relative; display: block; }
.symbol-suggestions {
    position: absolute;
    z-index: 1080;
    top: calc(100% + 2px);
    left: 0;
    right: 0;
    max-height: 260px;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);  /* soft drop shadow */
}
.symbol-suggestion {
    display: flex;
    flex-direction: column;
    width: 100%;
    text-align: left;
    padding: 0.45rem 0.7rem;
    border: 0;
    background: transparent;
    color: var(--fg);
    cursor: pointer;
}
.symbol-suggestion:hover,
.symbol-suggestion:focus,
.symbol-suggestion.is-active { background: var(--brand-glow-soft); }
.symbol-suggestion .symbol-desc {
    font-size: 0.8rem;
    color: var(--muted);
}

/* Drag & drop file upload zone (universe bulk import). */
.dropzone {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    width: 100%;
    min-height: 84px;
    padding: 1rem;
    margin: 0;
    border: 2px dashed var(--border-strong);
    border-radius: 10px;
    color: var(--muted);
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.dropzone:hover { border-color: var(--brand); color: var(--fg); }
/* The file input is visually-hidden but focusable; show a ring when it has focus. */
.dropzone:focus-within {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(232, 93, 4, 0.35);  /* TNT orange focus ring */
    outline: none;
}
.dropzone.dragover {
    border-color: var(--brand);
    background: var(--brand-glow-soft);
    color: var(--fg);
}
.dropzone-link { color: var(--brand-ink); text-decoration: underline; }

/* Plan tier feature bullet lists (subscribe page). */
.tier-features { list-style: none; padding: 0; margin: 0 0 1rem; }
.tier-features li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.2rem 0;
    font-size: 0.92rem;
}
.tier-features .feature-yes > span { color: #22c55e; font-weight: 700; }  /* green check */
.tier-features .feature-no { color: var(--muted); }
.tier-features .feature-no > span { color: #ef4444; font-weight: 700; }  /* red x */

/* Tier badge (navbar + sidebar) — shows the user's subscription plan. */
.tier-badge { font-weight: 600; }
.tier-badge.tier-free { background: #4b5563; color: #fff; }    /* gray-600 (4.5:1 on white text) */
.tier-badge.tier-basic { background: #0369a1; color: #fff; }   /* sky-700 (white text passes) */
.tier-badge.tier-pro { background: #f59e0b; color: #1a1a1a; }  /* amber, dark text */
.form-select option { background-color: var(--surface); color: var(--fg); }
.form-check-input {
    background-color: var(--surface);
    border-color: var(--border-strong);
}
.form-check-input:checked {
    background-color: var(--brand);
    border-color: var(--brand);
}
.form-check-label { color: var(--fg); }

/* Form-switch knob: Bootstrap's default OFF-state circle is a dark SVG that is
   invisible on the dark theme (black on black). Use a neutral gray knob that
   reads in both modes; the ON-state keeps a white knob on the brand track. */
.form-switch .form-check-input {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23adb5bd'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:checked {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e");
}

/* Card section titles: icon + accent underline (matches sibling repos) */
.card-title {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--fg);
    margin-bottom: 1rem;
    padding-bottom: 0.6rem;
    border-bottom: 1px solid var(--border);
}
.card-title .card-icon {
    font-size: 1.15rem;
    line-height: 1;
}
.card-title .card-accent {
    margin-left: auto;
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--brand);
}

/* Page titles: emoji + gradient text with a gradient underline (skill-page-header) */
.page-title {
    position: relative;
    display: inline-block;
    padding-bottom: 0.5rem;
    margin-bottom: 1.5rem;
    font-weight: 700;
}
.page-title .title-text {
    background: var(--gradient);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
.page-title::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    height: 3px;
    width: 100%;
    background: var(--gradient);
    border-radius: 2px;
}

/* Navbar category dropdowns (top nav style) */
.navbar .dropdown-menu {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
}
.navbar .dropdown-item {
    color: var(--fg);
    font-weight: 500;
    padding: 0.5rem 1rem;
}
.navbar .dropdown-item:hover,
.navbar .dropdown-item:focus {
    background: var(--surface-2);
    color: var(--brand);
}
.navbar .dropdown-toggle { cursor: pointer; }
.navbar .dropdown-divider { border-color: var(--border); }

/* Theme toggle controls */
.theme-controls { display: flex; align-items: center; gap: 0.5rem; }
.theme-btn {
    background: transparent;
    border: 1px solid var(--border-strong);
    color: var(--fg);
    border-radius: 6px;
    padding: 0.35rem 0.6rem;
    cursor: pointer;
    font-size: 0.95rem;
    line-height: 1;
    transition: border-color 0.2s, color 0.2s;
}
.theme-btn:hover { border-color: var(--brand); color: var(--brand); }
.theme-select {
    background: var(--surface);
    color: var(--fg);
    border: 1px solid var(--border-strong);
    border-radius: 6px;
    padding: 0.35rem 0.5rem;
    cursor: pointer;
    font-size: 0.85rem;
}
/* Theme the dropdown OPTIONS too — the browser default is a white/light list that
   reads as dark-on-dark (or white-on-white) on our dark surfaces. */
.theme-select option {
    background: var(--surface);
    color: var(--fg);
}
/* Multi-select listbox (e.g. the Trade page account picker). Give each option room
   to breathe, theme the selected/hover rows to the brand instead of the OS blue,
   and drop the padding that squashes a native <select multiple>. */
.theme-multiselect {
    padding: 0.25rem;
    cursor: default;
}
.theme-multiselect option {
    padding: 0.4rem 0.55rem;
    border-radius: 5px;
    margin: 1px 0;
}
.theme-multiselect option:checked {
    background: var(--brand) linear-gradient(0deg, var(--brand), var(--brand));
    color: #ffffff;  /* white */
}
.theme-multiselect option:hover {
    background: var(--surface-2);
}

/* Mantine-style MultiSelect widget — a progressive enhancement of a native
   <select multiple class="theme-multiselect">. app.js hides the native element
   (kept in the DOM for form submit + change events) and builds this UI: chosen
   items as removable pills, a searchable dropdown of checkable options. */
.ms-widget { position: relative; }
.ms-native-hidden {
    position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.ms-control {
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    min-height: 46px; padding: 6px 34px 6px 8px; position: relative;
    background: var(--surface); color: var(--fg);
    border: 1px solid var(--border-strong); border-radius: 8px; cursor: text;
}
.ms-control.is-open {
    border-color: var(--brand);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 30%, transparent);
}
.ms-control.is-invalid { border-color: #dc3545; }  /* red */
.ms-pill {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--surface-2); color: var(--fg);
    border: 1px solid var(--border); border-radius: 6px;
    padding: 2px 6px 2px 9px; font-size: 0.82rem; line-height: 1.5;
}
.ms-pill-x {
    cursor: pointer; opacity: 0.65; font-weight: 700;
    background: none; border: 0; padding: 0 0 0 2px; color: inherit;
    font-size: 1em; line-height: 1;
}
.ms-pill-x:hover { opacity: 1; color: #dc3545; }  /* red */
.ms-pill-x:focus-visible {
    outline: 2px solid var(--brand); outline-offset: 1px; opacity: 1; border-radius: 3px;
}
.ms-search {
    flex: 1 1 70px; min-width: 70px; border: 0; outline: 0; background: transparent;
    color: var(--fg); font-size: 0.85rem; padding: 2px;
}
.ms-search::placeholder { color: var(--muted); }
/* Visible keyboard focus for the whole widget (the search input clears its own
   outline), and a strong roving-highlight for the arrow-key-active option. */
.ms-control:focus-within {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(232, 93, 4, 0.35);  /* TNT orange focus ring */
}
.ms-option.is-active {
    outline: 2px solid var(--brand); outline-offset: -2px;
}
.ms-caret {
    position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
    color: var(--muted); pointer-events: none; font-size: 0.8rem;
}
.ms-dropdown {
    position: absolute; z-index: 1000; left: 0; right: 0; top: calc(100% + 4px);
    background: var(--surface); border: 1px solid var(--border-strong);
    border-radius: 8px; padding: 4px; max-height: 240px; overflow-y: auto;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);  /* soft drop shadow */
}
.ms-option {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 10px; border-radius: 6px; cursor: pointer;
    font-size: 0.85rem; color: var(--fg);
}
.ms-option:hover, .ms-option.is-active { background: var(--surface-2); }
.ms-check {
    width: 16px; height: 16px; border-radius: 4px; flex: 0 0 auto;
    border: 1.5px solid var(--border-strong);
    display: inline-flex; align-items: center; justify-content: center; font-size: 11px;
}
.ms-option.is-selected .ms-check {
    background: var(--brand); border-color: var(--brand); color: #ffffff;  /* white */
}
.ms-empty { padding: 8px 10px; color: var(--muted); font-size: 0.82rem; }
/* While the menu is open, lift the widget — and the card that holds it — above
   sibling containers so the absolutely-positioned dropdown never renders behind a
   neighboring container. Card :hover uses transform, which creates a stacking
   context that would otherwise trap the dropdown; raising the card (and cancelling
   the hover lift while open) keeps the overlay on top and steady. */
.ms-widget.is-open { z-index: 1080; }
.card-modern.ms-open { position: relative; z-index: 1080; }
.card-modern.ms-open:hover { transform: none; }

/* Table styling */
.scroll {
    /* Global table rule: grow with content but never occupy more than 80% of
       the viewport; longer content scrolls inside the container. */
    max-height: 80vh;
    overflow-y: auto;
    border-radius: 12px;
}
/* The TABLE HEADER ROW (column names) stays pinned while the container
   scrolls. Solid background: a transparent stuck header lets rows show
   through and reads as if it scrolled away. */
.scroll thead th {
    position: sticky;
    top: 0;
    z-index: 10;
    background-color: var(--surface);
}
.table-dark {
    /* Point Bootstrap's table cell vars at theme tokens so cells follow
       light/dark mode instead of Bootstrap's hardcoded dark (else cells render
       dark on a light page). */
    --bs-table-color: var(--fg);
    --bs-table-bg: var(--surface);
    --bs-table-border-color: var(--border);
    --bs-table-striped-color: var(--fg);
    --bs-table-striped-bg: var(--surface-2);
    --bs-table-hover-color: var(--fg);
    --bs-table-hover-bg: var(--surface-2);
    color: var(--fg);
    background: var(--surface);
    border-radius: 12px;
    /* NO overflow:hidden here: any non-visible overflow on the TABLE makes the
       table itself the scrollport for its sticky th, so the header row pins to
       the (moving) table instead of the .scroll container and never sticks.
       The .scroll wrapper carries the rounded clipping instead. */
}
.table-dark th {
    background: var(--surface-2);
    border-color: var(--border-strong);
    color: var(--fg);   /* brand orange only hits 3.9:1 on the header bg — use --fg */
    font-weight: 600;
}
.table-dark td { border-color: var(--border); }

/* Button styling */
.btn-primary {
    background: var(--gradient);
    border: none;
    font-weight: 600;
    padding: 0.75rem 2rem;
    border-radius: 8px;
    transition: transform 0.3s, box-shadow 0.3s;
}
.btn-primary:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 30px var(--brand-glow);
    background: var(--gradient);
}

.btn-outline {
    background: transparent;
    border: 2px solid var(--brand-ink);
    color: var(--brand-ink) !important;   /* contrast-safe brand text (orange fails 4.5:1 on light) */
    font-weight: 600;
    padding: 0.75rem 2rem;
    border-radius: 8px;
    transition: all 0.3s;
    text-decoration: none;
    display: inline-block;
}
.btn-outline:hover {
    background: var(--brand);
    color: var(--tnt-white) !important;
    text-decoration: none;
}
/* Selected state for a btn-check radio/checkbox toggle (e.g. the Trade page's
   Buy/Sell + quantity/limit mode toggles) -- Bootstrap hides the input and shows
   the state on the label, so the custom .btn-outline needs its own checked rule.
   The ACTIVE button is a solid fill; hovering an INACTIVE one gets only a subtle
   tint (not the full fill), so it never looks like the selected one. Scoped to
   toggle labels (a .btn-outline right after a .btn-check) so standalone buttons
   keep their normal full-fill hover. */
.btn-check:checked + .btn-outline {
    background: var(--brand);
    color: var(--tnt-white) !important;
}
/* Hover on a toggle label must NOT change the hue (that made an inactive hover
   look like the active one). Each state keeps its OWN color; hover adds a clearly
   visible brand glow ring (works on dark mode) plus a light tint on the inactive
   one -- distinct from the solid-filled active state, and never a hue swap. */
.btn-check:not(:checked) + .btn-outline:hover {
    background: var(--brand-glow-soft);
    color: var(--brand) !important;
    box-shadow: 0 0 0 3px var(--brand-glow);
}
.btn-check:checked + .btn-outline:hover {
    background: var(--brand);
    color: var(--tnt-white) !important;
    box-shadow: 0 0 0 3px var(--brand-glow);
}
.btn-check:focus-visible + .btn-outline {
    outline: 3px solid var(--brand);
    outline-offset: 2px;
}

/* Card styling */
.card-modern {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    transition: transform 0.3s, box-shadow 0.3s;
}
.card-modern:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
    border-color: var(--brand);
}

/* Bot / strategy cards with a fixed per-strategy logo + accent.
   --accent is set inline from the strategy's spec.accent. */
.strat-logo {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.6rem;
    line-height: 1;
    background: var(--surface-2);  /* fallback when color-mix is unsupported */
    background: color-mix(in srgb, var(--accent, var(--brand)) 20%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent, var(--brand)) 45%, transparent);
    box-shadow: 0 0 18px color-mix(in srgb, var(--accent, var(--brand)) 28%, transparent);
}
.bot-card {
    padding: 1.25rem;
    border-top: 4px solid var(--accent, var(--brand));
}
.bot-card:hover { border-color: var(--accent, var(--brand)); }
.bot-card-head {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    margin-bottom: 1rem;
}
.bot-alloc {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.bot-card-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.min-w-0 { min-width: 0; }  /* let text-truncate work inside flex */

/* On/off toggle switch with a glowing "light" when active (p75/p83 style) */
.switch {
    position: relative;
    display: inline-block;
    width: 50px;
    height: 26px;
    flex: 0 0 auto;
    margin: 0;
}
.switch input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.switch .slider {
    position: absolute;
    inset: 0;
    cursor: pointer;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 999px;
    transition: background .25s, box-shadow .25s, border-color .25s;
}
.switch .slider::before {
    content: "";
    position: absolute;
    height: 18px;
    width: 18px;
    left: 3px;
    top: 3px;
    background: var(--muted);
    border-radius: 50%;
    transition: transform .25s, background .25s, box-shadow .25s;
}
.switch input:checked + .slider {
    background: color-mix(in srgb, #22C55E 28%, transparent);  /* green active fill */
    border-color: #22C55E;  /* green */
    box-shadow: 0 0 14px 1px rgba(34, 197, 94, 0.6);  /* green glow (the "light") */
}
.switch input:checked + .slider::before {
    transform: translateX(24px);
    background: #22C55E;  /* green knob */
    box-shadow: 0 0 10px rgba(34, 197, 94, 0.9);  /* knob light */
}
.switch input:focus-visible + .slider {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

/* Larger toggle for the prominent bot on/off control. */
.switch.switch-lg { width: 64px; height: 34px; }
.switch.switch-lg .slider::before { height: 26px; width: 26px; left: 3px; top: 3px; }
.switch.switch-lg input:checked + .slider::before { transform: translateX(30px); }

/* Prominent bot on/off row (Edit page). The single most important setting, so it
   gets its own boxed row that lights up green when the bot is live. */
.bot-power {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1.25rem;
    flex-wrap: wrap;
    padding: 0.9rem 1.15rem;
    border: 1px solid var(--border-strong);
    border-radius: 12px;
    background: var(--surface-2);
    transition: border-color .2s, box-shadow .2s;
}
.bot-power-info { display: flex; flex-direction: column; gap: 0.15rem; min-width: 12rem; flex: 1; }
.bot-power-title { font-weight: 700; font-size: 1.02rem; }
.bot-power.is-live {
    border-color: #22C55E;  /* green - bot is live */
    box-shadow: 0 0 0 1px #22C55E, 0 0 22px rgba(34, 197, 94, 0.18);  /* green live glow */
}

/* Icon buttons: compact square actions with a native tooltip (title attr) */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    font-size: 1.05rem;
    line-height: 1;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--fg);
    cursor: pointer;
    text-decoration: none;
    transition: border-color .2s, background .2s, transform .2s;
}
.btn-icon:hover {
    border-color: var(--brand);
    background: color-mix(in srgb, var(--brand) 12%, transparent);
    transform: translateY(-1px);
    text-decoration: none;
}
.btn-icon-danger:hover {
    border-color: #EF4444;  /* red */
    background: rgba(239, 68, 68, 0.12);  /* soft red */
}

/* Styled tooltips (replaces the browser's default title= tooltip) */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 9px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: var(--surface-2);
    color: var(--fg);
    border: 1px solid var(--border-strong);
    padding: 0.35rem 0.55rem;
    border-radius: 8px;
    font-size: 0.74rem;
    font-weight: 600;
    line-height: 1.3;
    /* Cap the width and wrap: a long tooltip must not sprawl sideways into the
       fixed sidebar (where a low-z pseudo-element would hide behind it). Short
       tooltips size to their content and stay one line. */
    white-space: normal;
    width: max-content;
    max-width: 240px;
    text-align: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s ease, transform .15s ease;
    z-index: 1200;   /* above the sidebar (1050) so tooltips never hide behind it */
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);  /* soft drop shadow */
}
[data-tooltip]::before {
    content: "";
    position: absolute;
    bottom: calc(100% + 4px);
    left: 50%;
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: var(--border-strong);
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s ease;
    z-index: 1200;
}
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
[data-tooltip]:hover::before,
[data-tooltip]:focus-visible::before { opacity: 1; }

/* Whole-card states: glowing when on, faded/grayscale when off, plus a
   one-time "light-up" pulse when a bot is switched on. */
.bot-card {
    transition: filter .5s ease, opacity .5s ease, box-shadow .5s ease,
                transform .3s, border-color .3s;
}
.bot-card.is-on {
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent, var(--brand)) 30%, transparent),
                0 8px 30px color-mix(in srgb, var(--accent, var(--brand)) 16%, transparent);
}
.bot-card.is-off {
    filter: grayscale(0.9) brightness(0.7);  /* fade to dark, desaturated */
    opacity: 0.85;
    box-shadow: none;
}
@keyframes card-lightup {
    0% {
        box-shadow: 0 0 0 2px var(--accent, var(--brand)),
                    0 0 48px 8px color-mix(in srgb, var(--accent, var(--brand)) 75%, transparent);
        transform: translateY(-4px);
    }
    100% {
        box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent, var(--brand)) 30%, transparent),
                    0 8px 30px color-mix(in srgb, var(--accent, var(--brand)) 16%, transparent);
        transform: translateY(0);
    }
}
.bot-card.lit { animation: card-lightup 0.6s ease-out; }
/* Power-down ("off") needs no keyframe: the .bot-card transition eases into the
   dim/desaturated .is-off state above - a smooth fade to dark. */

/* Deep-link focus (/bots?bot=<id>): the fixed navbar shouldn't cover the scrolled
   card, and a brief pulse draws the eye to the just-created bot. */
.bot-card { scroll-margin-top: 120px; }
@keyframes card-focus-flash {
    0%, 100% {
        box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent, var(--brand)) 30%, transparent),
                    0 8px 30px color-mix(in srgb, var(--accent, var(--brand)) 16%, transparent);
    }
    30% {
        box-shadow: 0 0 0 3px var(--accent, var(--brand)),
                    0 0 48px 8px color-mix(in srgb, var(--accent, var(--brand)) 70%, transparent);
    }
}
.bot-card.is-focused { animation: card-focus-flash 0.8s ease-in-out 3; }
@media (prefers-reduced-motion: reduce) {
    .bot-card.lit,
    .bot-card.is-focused { animation: none; }
}

/* Assistant-navigation highlight: when the AI assistant sends the user to a
   section/dropdown/container, it briefly glows so the eye lands on the right spot.
   Applied by app.js initAssistantFocus() to the URL's focus= element (or #hash). */
.assistant-focus {
    scroll-margin-top: 120px;   /* fixed navbar shouldn't cover the scrolled target */
    animation: assistant-glow 0.9s ease-in-out 3;
    border-radius: 12px;        /* keep the ring tidy on plain containers */
}
@keyframes assistant-glow {
    0%, 100% {
        box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 0%, transparent);
    }
    35% {
        box-shadow: 0 0 0 3px var(--brand),
                    0 0 34px 6px color-mix(in srgb, var(--brand) 60%, transparent);
    }
}
@media (prefers-reduced-motion: reduce) {
    .assistant-focus { animation: none; outline: 3px solid var(--brand); }
}

/* Themed number steppers (replace the browser's default spin arrows) */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}
.stepper {
    position: relative;
    display: inline-flex;
    align-items: stretch;
}
.stepper > input[type="number"] { padding-right: 1.5rem; }
.stepper-btns {
    position: absolute;
    right: 1px;
    top: 1px;
    bottom: 1px;
    width: 1.35rem;
    display: flex;
    flex-direction: column;
    border-left: 1px solid var(--border);
    overflow: hidden;
    border-radius: 0 7px 7px 0;
}
.stepper-btn {
    flex: 1 1 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    background: var(--surface-2);
    color: var(--muted);
    font-size: 0.5rem;
    line-height: 1;
    cursor: pointer;
    transition: background .15s, color .15s;
}
.stepper-btn + .stepper-btn { border-top: 1px solid var(--border); }
.stepper-btn:hover {
    background: var(--brand);
    color: var(--tnt-white);
}

/* Bootstrap's modal close (X) ships a dark SVG; invert it on the dark theme
   (the default) so it isn't black-on-dark. Light theme keeps the default. */
.btn-close { filter: invert(1) grayscale(100%) brightness(1.8); }
[data-theme="light"] .btn-close { filter: none; }
/* Bootstrap ALERTS keep a light background in either theme, so their close (×)
   must stay the DEFAULT dark glyph — the dark-surface invert above makes it
   white-on-light (invisible). Reset it for close buttons inside an alert. */
.alert .btn-close { filter: none; }

/* Inline "saved" feedback next to a control (no top-of-page flash) */
.alloc-msg {
    opacity: 0;
    transition: opacity .2s ease;
    white-space: nowrap;
}
.alloc-msg.show { opacity: 1; }

/* Gradient text */
.gradient-text {
    background: var(--gradient);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

/* Glow effect */
.glow-orange { box-shadow: 0 0 40px var(--brand-glow-soft); }

h1 { text-align: center; }

/* ===================== SIDEBAR (skill-navbar, persistent) ===================== */
/* In left/right mode the sidebar is always visible (collapsible to icons) and
   there is NO top bar; content is offset by the sidebar width and starts at the
   very top. */
:root { --sidebar-w: 248px; --sidebar-w-collapsed: 66px; }

.tnt-content { transition: margin 0.25s ease; }
/* Sticky footer: the main content fills at least the viewport so the footer
   stays below the fold on short pages (universe, subscribe, ...) instead of
   floating up into view. Mirrors the per-page fix on the pay pages. */
.tnt-content > main { min-height: 100vh; }
.content-with-sidebar-left { margin-left: var(--sidebar-w); }
.content-with-sidebar-right { margin-right: var(--sidebar-w); }
.content-with-sidebar-left.sidebar-collapsed { margin-left: var(--sidebar-w-collapsed); }
.content-with-sidebar-right.sidebar-collapsed { margin-right: var(--sidebar-w-collapsed); }

/* No top bar in sidebar mode -> drop the page padding meant to clear a navbar. */
body.nav-sidebar #main-content { padding-top: 2rem !important; }

.tnt-sidebar {
    position: fixed;
    top: 0; bottom: 0;
    width: var(--sidebar-w);
    background: var(--surface-2);
    z-index: 1050;
    overflow-y: auto;
    /* overflow-y:auto alone computes overflow-x to auto as well, so any inside
       horizontal overflow (nowrap labels, hidden data-tooltip bubbles) showed a
       horizontal scrollbar. The sidebar never scrolls sideways -- clamp it. */
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    transition: width 0.25s ease;
}
.tnt-sidebar-left { left: 0; border-right: 1px solid var(--border); }
.tnt-sidebar-right { right: 0; border-left: 1px solid var(--border); }
.tnt-sidebar.collapsed { width: var(--sidebar-w-collapsed); }
.tnt-sidebar.collapsed .sidebar-label,
.tnt-sidebar.collapsed .tnt-sidebar-logo,
.tnt-sidebar.collapsed .tnt-sidebar-group { display: none; }
.tnt-sidebar.collapsed .tnt-sidebar-logo-mini { display: inline-block; }
.tnt-sidebar-logo-mini { display: none; }

/* Header: logo on top, collapse/expand toggle centered BELOW it. */
.tnt-sidebar-header {
    padding: 1rem 0.75rem 0.65rem;
    border-bottom: 1px solid var(--border);
}
.tnt-sidebar-brand {
    display: flex; align-items: center; justify-content: center;
    padding-bottom: 0.65rem;
}
.tnt-sidebar-logo-link { display: flex; width: 100%; align-items: center; justify-content: center; text-decoration: none; }
/* Expanded wordmark fills the sidebar header (minimal side margin). */
.tnt-sidebar:not(.collapsed) .tnt-sidebar-logo { width: 100%; height: auto; }
.tnt-sidebar-toggle {
    display: block; margin: 0 auto;
    background: transparent; border: 1px solid var(--border-strong); color: var(--fg);
    border-radius: 6px; width: 40px; height: 28px; cursor: pointer; line-height: 1;
}
.tnt-sidebar-toggle:hover { border-color: var(--brand); color: var(--brand); }

.tnt-sidebar-user { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0.75rem 1rem; }
.tnt-sidebar-nav { padding: 0.5rem 0.6rem; flex: 1 1 auto; }
.tnt-sidebar-group {
    text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.06em;
    color: var(--muted); padding: 0.85rem 0.6rem 0.3rem;
}
.tnt-sidebar-link {
    display: flex; align-items: center; gap: 0.7rem;
    padding: 0.55rem 0.7rem; border-radius: 8px;
    color: var(--fg); text-decoration: none; font-weight: 500;
    white-space: nowrap; transition: background 0.2s, color 0.2s;
}
.tnt-sidebar-link .sidebar-icon { font-size: 1.1rem; width: 1.4rem; text-align: center; flex: 0 0 auto; }
.tnt-sidebar-link:hover { background: var(--surface); color: var(--brand); }
.tnt-sidebar-link.active { background: var(--surface); color: var(--brand); box-shadow: inset 3px 0 0 0 var(--brand); }
.tnt-sidebar-logout { padding: 0.5rem 0.6rem 1.25rem; border-top: 1px solid var(--border); }

.tnt-sidebar.collapsed .tnt-sidebar-link { justify-content: center; gap: 0; position: relative; }
.tnt-sidebar.collapsed .tnt-sidebar-brand,
.tnt-sidebar.collapsed .tnt-sidebar-user { justify-content: center; }

/* Styled hover tooltip for collapsed sidebar icons (p54). Rendered as a fixed
   element on <body> by nav.js so it isn't clipped by the sidebar overflow. */
.tnt-tooltip {
    position: fixed;
    transform: translateY(-50%);
    background: var(--surface);
    color: var(--fg);
    border: 1px solid var(--border-strong);
    padding: 0.35rem 0.7rem;
    border-radius: 8px;
    white-space: nowrap;
    font-size: 0.85rem;
    font-weight: 600;
    z-index: 2000;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
    pointer-events: none;
}
.tnt-tooltip[hidden] { display: none; }

/* Body-level [data-tooltip] bubble (promoted by app.js initTooltips). Unlike the
   sidebar tooltip it sits ABOVE (or, when flipped, below) its trigger and wraps
   long text. Being fixed at z-index 2000 it overlays the sidebar instead of
   hiding behind it. */
.tnt-tooltip.tnt-hint {
    transform: translate(-50%, -100%);
    white-space: normal;
    max-width: 260px;
    text-align: center;
    line-height: 1.3;
}
.tnt-tooltip.tnt-hint.below { transform: translate(-50%, 0); }
/* With the JS bubble active, suppress the CSS ::after fallback so tooltips don't
   double up. */
html.js-tt [data-tooltip]::after,
html.js-tt [data-tooltip]::before { content: none; }

@media (max-width: 768px) {
    .content-with-sidebar-left, .content-with-sidebar-right { margin-left: 0; margin-right: 0; }
}

/* ===================== LOGO CONTRAST PLATE ===================== */
/* The TNT wordmark has navy text that vanishes on dark surfaces (navbar/footer/
   sidebar). Place it on a light rounded plate so it stays legible in any theme. */
.navbar-brand img,
.tnt-sidebar-logo,
.tnt-sidebar-logo-mini,
.footer img {
    background: rgba(255, 255, 255, 0.92);
    padding: 4px 9px;
    border-radius: 8px;
}

/* ===================== BROKERS PAGE ===================== */
.broker-logo {
    width: 48px; height: 48px; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    background: #ffffff; border: 1px solid var(--border); border-radius: 10px;
    overflow: hidden;
}
.broker-logo img { max-width: 40px; max-height: 40px; object-fit: contain; }
.broker-logo-fallback { font-size: 1.6rem; line-height: 1; }
/* Dim, but keep opacity high enough that the card's text/badges still meet
   contrast (0.62 dropped them below 4.5:1); grayscale carries the "disabled" look. */
.broker-card.broker-disabled { opacity: 0.85; filter: grayscale(0.5); }

.chip {
    display: inline-block; font-size: 0.75rem; font-weight: 600;
    padding: 0.2rem 0.55rem; border-radius: 6px;
    background: var(--surface-2); color: var(--fg);
}
.chip-soft { background: transparent; border: 1px solid var(--border-strong); color: var(--muted); }

.broker-filter {
    border: 1px solid var(--border-strong); background: transparent; color: var(--fg);
    border-radius: 20px; padding: 0.25rem 0.85rem; transition: all 0.2s;
}
.broker-filter:hover { border-color: var(--brand); color: var(--brand); }
.broker-filter.active {
    background: var(--gradient); color: var(--tnt-white); border-color: transparent;
}

/* Swatches for the color-theme picker on the settings page */
.theme-swatch {
    width: 22px; height: 22px; border-radius: 50%;
    display: inline-block; vertical-align: middle; margin-right: 0.5rem;
    border: 2px solid var(--border-strong);
}
.swatch-tnt { background: linear-gradient(135deg, #C92A2A, #E85D04, #F59F00); }
.swatch-ocean { background: linear-gradient(135deg, #2563EB, #0EA5E9, #22D3EE); }
.swatch-emerald { background: linear-gradient(135deg, #059669, #10B981, #34D399); }
.swatch-violet { background: linear-gradient(135deg, #7C3AED, #8B5CF6, #A78BFA); }

/* Stylized dark/light mode toggle (segmented control) */
.mode-toggle {
    display: inline-flex;
    gap: 0.4rem;
    background: var(--surface-2);
    border-radius: 12px;
    padding: 0.3rem;
}
.mode-option {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    border: none;
    background: transparent;
    color: var(--fg);
    font-weight: 600;
    padding: 0.5rem 1.2rem;
    border-radius: 9px;
    cursor: pointer;
    transition: background 0.2s, color 0.2s, transform 0.15s;
}
.mode-option:hover { transform: translateY(-1px); }
.mode-option.selected {
    background: var(--gradient);
    color: var(--tnt-white);
    box-shadow: 0 4px 14px var(--brand-glow);
}
.mode-option .mode-emoji { font-size: 1.05rem; }

/* Bottom navbar leaves room at the page foot */
body.nav-bottom { padding-bottom: 90px; }

/* Clickable color-palette picker (settings page) */
.palette-grid { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.palette-option {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    background: var(--surface);
    border: 2px solid var(--border);
    border-radius: 12px;
    padding: 0.6rem 0.9rem;
    cursor: pointer;
    color: var(--fg);
    transition: border-color 0.2s, transform 0.15s;
}
.palette-option:hover { transform: translateY(-2px); border-color: var(--border-strong); }
.palette-option.selected { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-glow-soft); }
.palette-option .theme-swatch { width: 28px; height: 28px; margin: 0; }
.palette-label { font-weight: 500; font-size: 0.9rem; }

/* Webhook reference: theme-aware code blocks + inline code (readable both modes) */
.wh-code {
    background: var(--surface-2);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 14px;
    white-space: pre-wrap;
    overflow-x: auto;
    font-size: 0.85rem;
}
.wh-page code {
    color: var(--fg);
    background: var(--surface-2);
    padding: 0.1rem 0.35rem;
    border-radius: 4px;
}

/* Copy-to-clipboard button overlaid on .wh-code example blocks */
.wh-code-wrap { position: relative; }
.wh-code-wrap .wh-code { padding-top: 34px; }
.wh-copy {
    position: absolute;
    top: 6px;
    right: 6px;
    padding: 0.1rem 0.5rem;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--fg);   /* default btn gray (#6c757d) fails contrast on the frame */
}

/* Readonly inputs (e.g. webhook URL fields) must follow the theme, not Bootstrap's
   hardcoded light-grey readonly background (which left white text unreadable). */
.form-control[readonly] {
    background-color: var(--surface);
    color: var(--fg);
    opacity: 1;
}

/* Admin plan-tier drag-and-drop reordering */
.tier-drag-handle {
    cursor: grab;
    color: var(--muted);
    font-size: 1.3rem;
    line-height: 1;
    padding: 0.25rem 0.1rem;
    user-select: none;
}
.tier-row {
    background: var(--surface);
    transition: box-shadow 0.18s ease, opacity 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.tier-row.dragging {
    opacity: 0.65;
    border-color: var(--brand);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
    transform: scale(1.01);
    cursor: grabbing;
}
.tier-drag-handle:active { cursor: grabbing; }

/* Bootstrap modal -> follow the theme (set the --bs-* vars, don't fight elements) */
.modal-content {
    --bs-modal-bg: var(--surface);
    --bs-modal-color: var(--fg);
    --bs-modal-border-color: var(--border);
    --bs-modal-header-border-color: var(--border);
    --bs-modal-footer-border-color: var(--border);
}

/* Collapsible per-bot settings cards (progressive disclosure, p83 pattern). The
   <summary> is the clickable card header; advanced cards render without `open`. */
.settings-card > summary.settings-summary {
    cursor: pointer;
    margin-bottom: 0;
    list-style: none;               /* hide the default disclosure triangle */
    user-select: none;
}
.settings-card > summary.settings-summary::-webkit-details-marker { display: none; }
.settings-summary .settings-caret {
    margin-left: auto;
    color: var(--muted);
    font-size: 0.95rem;
    transition: transform 0.2s ease;
}
.settings-card[open] > summary .settings-caret { transform: rotate(180deg); }
.settings-summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 6px; }

/* Edit-bot settings grid: each field is a clean vertical stack — icon+label, then
   its description, then a full-width input — so titles, help, and inputs line up
   the same in every column instead of number inputs floating inline beside labels. */
.settings-grid .setting-switch { margin-top: 1.9rem; }
.settings-grid .form-text { min-height: 1.1rem; margin-top: 0.25rem; }
.settings-grid .form-label { font-weight: 500; margin-bottom: 0.35rem; display: block; }
/* Description sits on its own line between the label and the input. */
.settings-grid .field-help { display: block; margin: 0 0 0.5rem; line-height: 1.35; }
/* Number inputs are wrapped in a .stepper (inline-flex by default); force it to a
   full-width block so it matches text inputs/selects and never hugs the label. */
.settings-grid .stepper { display: flex; width: 100%; }
.settings-grid .stepper > input[type="number"] { flex: 1 1 auto; width: 100%; }

/* Vertical indentation line for conditional/subordinate settings (p54/p83 pattern):
   a revealed show_if field nests under its controlling toggle with a brand-colored
   line, like a threaded reply. The whole block is shifted right (margin-left), with
   max-width compensating so the full-width col never overflows the row. */
.settings-grid .setting-field.is-conditional {
    border-left: 3px solid var(--brand);
    margin-left: 1.75rem;
    max-width: calc(100% - 1.75rem);
    padding-left: 1rem;
    margin-top: 0.25rem;
}

/* ===================== OPTIONS PAYOFF BUILDER ===================== */
/* Interactive payoff diagram on the Edit-Bot page (static/js/option_payoff.js):
   an SVG chart with draggable strike/delta handles, a stats readout, and a
   legend, styled to sit inside the Strategy-parameters card. */
.option-payoff {
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-radius: 12px;
    padding: 0.75rem 0.75rem 0.5rem;
}
.option-payoff-svg {
    width: 100%;
    height: auto;
    display: block;
    touch-action: none;                 /* let pointer-drag own the gesture */
}
.option-handle {
    cursor: ew-resize;
    stroke: var(--surface-1);
    stroke-width: 1.5;
    transition: r 0.1s ease;
}
.option-handle:hover, .option-handle:focus {
    r: 10;
}
/* Distinct, high-contrast keyboard focus ring for the SVG slider handle (its
   value is exposed via aria-valuenow/valuetext; arrow keys move it). */
.option-handle:focus-visible {
    outline: none;
    stroke: var(--fg);
    stroke-width: 3;
}
.option-breakeven {
    cursor: help;
    stroke: var(--surface-1);
    stroke-width: 1;
    transition: r 0.1s ease;
}
.option-breakeven:hover, .option-breakeven:focus {
    r: 6;
    outline: none;
}
.option-payoff-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border-strong);
}
.opf-stat { display: flex; flex-direction: column; line-height: 1.2; }
.opf-stat-l { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.opf-stat-v { font-size: 0.95rem; font-weight: 700; }
.option-payoff-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    margin-top: 0.4rem;
    font-size: 0.72rem;
    color: var(--muted);
}
.option-payoff-legend span { display: inline-flex; align-items: center; gap: 0.35rem; }
.option-payoff-legend i { width: 12px; height: 3px; border-radius: 2px; display: inline-block; }

/* ===================== AI ASSISTANT CHAT WIDGET ===================== */
/* Floating customer-service-style chat (partials/_ai_chat.html): a launcher
   button pinned bottom-right on every page that expands into a chat panel.
   Sits above page content and the navbar but below Bootstrap modals feel-wise;
   fully theme-aware via the semantic tokens. */
.ai-chat {
    position: fixed;
    right: 24px;
    bottom: 24px;
    z-index: 1090;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 12px;
}
body.nav-bottom .ai-chat { bottom: 104px; }  /* clear the bottom navbar */

.ai-chat-launcher {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: none;
    background: var(--gradient);
    color: var(--tnt-white);
    font-size: 1.5rem;
    cursor: pointer;
    box-shadow: 0 6px 24px var(--brand-glow);
    transition: transform 0.15s ease, box-shadow 0.2s ease;
}
.ai-chat-launcher:hover { transform: translateY(-2px) scale(1.05); }
.ai-chat-launcher:focus-visible { outline: 3px solid var(--brand); outline-offset: 3px; }
.ai-chat.is-open .ai-chat-launcher { transform: none; }

.ai-chat-panel {
    width: 360px;
    max-width: calc(100vw - 32px);
    height: 480px;
    max-height: calc(100vh - 140px);
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45);  /* deep drop shadow */
    animation: ai-chat-pop 0.18s ease;
}
@keyframes ai-chat-pop {
    from { opacity: 0; transform: translateY(10px) scale(0.98); }
    to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .ai-chat-panel { animation: none; }
}

.ai-chat-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.7rem 1rem;
    background: var(--gradient);
    color: var(--tnt-white);
}
.ai-chat-title { font-weight: 600; }
.ai-chat-close {
    border: none;
    background: transparent;
    color: var(--tnt-white);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 0.2rem;
}
.ai-chat-close:focus-visible { outline: 2px solid var(--tnt-white); outline-offset: 2px; }

.ai-chat-log {
    flex: 1;
    overflow-y: auto;
    padding: 0.9rem;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    background: var(--bg);
}
.ai-chat-msg {
    max-width: 85%;
    padding: 0.5rem 0.75rem;
    border-radius: 14px;
    font-size: 0.88rem;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-word;
}
.ai-chat-msg.from-user {
    align-self: flex-end;
    background: var(--brand);
    color: var(--tnt-white);
    border-bottom-right-radius: 4px;
}
.ai-chat-msg.from-bot {
    align-self: flex-start;
    background: var(--surface-2);
    color: var(--fg);
    border: 1px solid var(--border);
    border-bottom-left-radius: 4px;
}
.ai-chat-msg.is-error { border-color: var(--tnt-red); color: var(--tnt-red); }

/* Per-action result rows inside an assistant bubble (✅ done / ⛔ refused) */
.ai-chat-action { display: flex; flex-direction: column; padding: 0.15rem 0; }
.ai-chat-action + .ai-chat-action { border-top: 1px solid var(--border); }
.ai-chat-action-name { font-weight: 600; }
.ai-chat-action-detail { font-size: 0.8rem; color: var(--muted); }
.ai-chat-action.refused .ai-chat-action-detail { color: var(--tnt-red); }

/* Typing indicator: three pulsing dots while the assistant works */
.ai-chat-typing { display: flex; gap: 5px; align-items: center; min-height: 30px; }
.ai-chat-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--muted);
    animation: ai-chat-blink 1.2s infinite both;
}
.ai-chat-dot:nth-child(2) { animation-delay: 0.2s; }
.ai-chat-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes ai-chat-blink {
    0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
    40% { opacity: 1; transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
    .ai-chat-dot { animation: none; opacity: 0.6; }
}

.ai-chat-form {
    display: flex;
    gap: 0.5rem;
    padding: 0.7rem;
    border-top: 1px solid var(--border);
    background: var(--surface);
}
.ai-chat-input {
    flex: 1;
    background: var(--bg);
    color: var(--fg);
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    padding: 0.45rem 0.7rem;
    font-size: 0.88rem;
}
.ai-chat-input:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-glow-soft);
}
.ai-chat-send {
    border: none;
    border-radius: 10px;
    background: var(--gradient);
    color: var(--tnt-white);
    font-size: 1rem;
    padding: 0 0.85rem;
    cursor: pointer;
}
.ai-chat-send:disabled, .ai-chat-input:disabled { opacity: 0.6; cursor: wait; }
.ai-chat-send:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }

/* Voice-dictation mic button (Web Speech API). Hidden unless the browser supports
   SpeechRecognition; pulses red while actively listening. */
.ai-chat-mic {
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    background: var(--bg);
    color: var(--fg);
    font-size: 1rem;
    padding: 0 0.7rem;
    cursor: pointer;
}
.ai-chat-mic:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }
.ai-chat-mic.is-listening {
    background: #DC2626;  /* red-600 */
    border-color: #DC2626;  /* red-600 */
    color: #FFFFFF;  /* white */
    animation: ai-mic-pulse 1.2s infinite;
}
@keyframes ai-mic-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.55); }  /* red-600 glow */
    50% { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0); }  /* red-600 glow fade */
}
@media (prefers-reduced-motion: reduce) {
    .ai-chat-mic.is-listening { animation: none; }
}

@media (max-width: 480px) {
    .ai-chat { right: 12px; bottom: 12px; }
    body.nav-bottom .ai-chat { bottom: 96px; }
    .ai-chat-panel { height: 70vh; }
}

/* Generic AI "thinking" status line (Build-with-AI generate, etc.): pulsing
   brand dots + a label, so an in-flight LLM call never looks like a freeze. */
.ai-thinking {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--muted);
    font-size: 0.9rem;
}
.ai-thinking .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--brand);
    animation: ai-chat-blink 1.2s infinite both;
}
.ai-thinking .dot:nth-child(2) { animation-delay: 0.2s; }
.ai-thinking .dot:nth-child(3) { animation-delay: 0.4s; }
@media (prefers-reduced-motion: reduce) {
    .ai-thinking .dot { animation: none; opacity: 0.6; }
}

/* AI chat widget: allowance strip (muted) + low-allowance warning (amber),
   shown between the header and the message log. */
.ai-chat-balance {
    padding: 0.4rem 1rem;
    font-size: 0.78rem;
    color: var(--muted);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}
.ai-chat-warn {
    padding: 0.45rem 1rem;
    font-size: 0.8rem;
    color: #B45309;  /* Amber-brown - readable on light surfaces */
    background: rgba(245, 159, 0, 0.14);  /* Translucent amber */
    border-bottom: 1px solid rgba(245, 159, 0, 0.35);  /* Amber */
}
[data-theme="dark"] .ai-chat-warn { color: #F5B84D; }  /* Light amber on dark */

/* Bootstrap progress bar -> follow the theme (set the --bs-* vars, don't fight
   the element): themed track under the traffic-light colored bar. */
.progress { --bs-progress-bg: var(--surface-2); }
