/* Space Grotesk. Must stay the first statement in this file — browsers drop
   @import if any rule precedes it. Loaded from CSS because we cannot edit the
   HTML <head>; the pages' existing preconnect to fonts.gstatic.com still
   applies, so the connection is already warm. */
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap');

/* ==========================================================================
   Palette B — Ink + Indigo
   Green and red belong to P&L data, so the brand stays out of both. Ink chrome
   lets the data be the only saturated thing on screen. Every value below is
   contrast-checked against white; ratios noted inline.
   ========================================================================== */

:root {
    /* --- Brand ---------------------------------------------------------- */
    --primary-color: #16181D;        /* ink      — white on it 17.76 AAA */
    --secondary-color: #4F46E5;      /* indigo   — as text on white 6.29 AA */

    /* Static fallbacks; the @supports block below re-derives these from
       --primary-color / --secondary-color so a re-theme is a one-line change.
       They are declared twice on purpose — a custom property holding an
       unsupported function stays "valid" at parse time and only fails at
       substitution, so a plain second declaration would not fall back. */
    --primary-color-dark: #121317;
    --primary-color-transparent: rgba(22, 24, 29, .5);
    --wl-focus-ring: rgba(79, 70, 229, .3);
    --wl-tint: rgba(79, 70, 229, .1);
    /* The login waves cross two grounds. Indigo at the light-panel strength is
       almost invisible on near-black, so the dark side carries ~4x the alpha to
       land at a comparable perceived weight. */
    --wl-wave-on-dark: rgba(79, 70, 229, .32);
    --wl-wave-on-light: rgba(79, 70, 229, .08);
    /* Drift speed: seconds for the pattern to travel one 220px tile. Lower is
       faster. 90s was ~2.4px/sec, below the threshold where the eye registers
       movement at all on a pattern this faint; 26s was still understated. */
    --wl-wave-drift: 16s;
    /* Buttons. Primary is the accent filled; secondary is the same accent as a
       border over a soft tint. Kept separate from --wl-table-head-bg even though
       they currently resolve alike, so the table band can move independently. */
    --wl-accent-dark: #433BC3;
    --wl-accent-soft: rgba(79, 70, 229, .08);
    /* Button heights. The app shipped nine distinct heights (30/33/34/36/40/42/
       44/46/52) driven by padding from 0 to 14px and five different
       line-heights. Two sizes cover every real case. */
    --wl-btn-h: 40px;
    --wl-btn-h-sm: 32px;
    /* Wave geometry. Two things vary together down the panel: the gap opens
       from ~9px at the top to ~125px at the bottom, and the stroke thickens
       from 1.2 to 4.4. Stroke-width is per-path rather than on the group, so
       the weight is baked into the geometry. preserveAspectRatio='none' lets
       it stretch to any viewport height. Held in a token because both the
       light and dark layers use it. */
    --wl-wave-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='1000' viewBox='0 0 220 1000' preserveAspectRatio='none'%3E%3Cg fill='none' stroke='%23fff'%3E%3Cpath d='M0 8.6 Q 27.5 -6.4 55 8.6 T 110 8.6 T 165 8.6 T 220 8.6' stroke-width='1.2'/%3E%3Cpath d='M0 30.1 Q 27.5 15.1 55 30.1 T 110 30.1 T 165 30.1 T 220 30.1' stroke-width='1.37'/%3E%3Cpath d='M0 62.5 Q 27.5 47.5 55 62.5 T 110 62.5 T 165 62.5 T 220 62.5' stroke-width='1.57'/%3E%3Cpath d='M0 104.9 Q 27.5 89.9 55 104.9 T 110 104.9 T 165 104.9 T 220 104.9' stroke-width='1.79'/%3E%3Cpath d='M0 156.7 Q 27.5 141.7 55 156.7 T 110 156.7 T 165 156.7 T 220 156.7' stroke-width='2.03'/%3E%3Cpath d='M0 217.6 Q 27.5 202.6 55 217.6 T 110 217.6 T 165 217.6 T 220 217.6' stroke-width='2.27'/%3E%3Cpath d='M0 287.2 Q 27.5 272.2 55 287.2 T 110 287.2 T 165 287.2 T 220 287.2' stroke-width='2.52'/%3E%3Cpath d='M0 365.2 Q 27.5 350.2 55 365.2 T 110 365.2 T 165 365.2 T 220 365.2' stroke-width='2.77'/%3E%3Cpath d='M0 451.4 Q 27.5 436.4 55 451.4 T 110 451.4 T 165 451.4 T 220 451.4' stroke-width='3.03'/%3E%3Cpath d='M0 545.7 Q 27.5 530.7 55 545.7 T 110 545.7 T 165 545.7 T 220 545.7' stroke-width='3.3'/%3E%3Cpath d='M0 647.9 Q 27.5 632.9 55 647.9 T 110 647.9 T 165 647.9 T 220 647.9' stroke-width='3.57'/%3E%3Cpath d='M0 757.7 Q 27.5 742.7 55 757.7 T 110 757.7 T 165 757.7 T 220 757.7' stroke-width='3.84'/%3E%3Cpath d='M0 875.1 Q 27.5 860.1 55 875.1 T 110 875.1 T 165 875.1 T 220 875.1' stroke-width='4.12'/%3E%3Cpath d='M0 1000.0 Q 27.5 985.0 55 1000.0 T 110 1000.0 T 165 1000.0 T 220 1000.0' stroke-width='4.4'/%3E%3C/g%3E%3C/svg%3E");

    /* --- Type ----------------------------------------------------------- */
    /* Nunito is still loaded by the pages' own <link>, so it is a real
       fallback rather than a theoretical one. */
    --primary-font: 'Space Grotesk', 'Nunito', sans-serif;

    /* --- Text and neutrals ---------------------------------------------- */
    --text-color: #16181D;
    --link-color: var(--secondary-color);
    --white: #ffffff;
    --black: #000000;
    --primary-table-heading-color: #6B7280;   /* 4.83 AA */
    --dropdown-icon-color: #6B7280;
    --bg-dark-login: var(--primary-color);

    /* --- Status --------------------------------------------------------- */
    /* Tradetron's originals failed contrast badly as text on white:
       green #01CA5D scored 2.19 and red #FF2A2A scored 3.74 — the two colours
       carrying every P&L figure were the least readable things on screen.
       These are used as text and as small indicator dots, never as a filled
       badge behind white text, so darkening them is safe. */
    --status-green: #0B8446;         /* was #01CA5D — now 4.77 AA */
    --status-red: #C81E1E;           /* was #FF2A2A — now 5.74 AA */
    --status-yellow: #B45309;        /* was #FFC704 — now 5.02 AA */
    --status-blue: #0369A1;          /* was #4062FF — now 5.93 AA, and no
                                        longer confusable with the indigo accent */
    --status-dark-green: #0F766E;    /* was #079697 — now 5.47 AA */

    /* --facebook/twitter/google/linkedin-color are deliberately left alone —
       those are other companies' brand colours, not ours to theme. */

    /* --- Ours ----------------------------------------------------------- */
    /* Two borders, because WCAG 1.4.11 only applies to one of them.
       Interactive control boundaries need 3:1 against the adjacent surface;
       decorative rules — table separators, card edges — do not. */
    --wl-border: #E5E7EB;            /* 1.24 on white — dividers only */
    --wl-border-control: #8A919C;    /* 3.18 on white — inputs, selects */
    --wl-muted: #6B7280;
    --wl-muted-strong: #4B5563;      /* 6.70 on the table head band */
    --wl-page: #FAFAFA;
    /* Indigo at 8% — enough to separate the header row from the body without
       becoming a coloured bar competing with the P&L figures below it. */
    --wl-table-head-bg: rgba(79, 70, 229, .08);
    /* Header and footer are the table's two caps and should read as a matched
       pair. The footer's height is set by its pagination buttons (31px) inside
       21px padding; this pins the header to the same figure rather than leaving
       the two to drift. */
    --wl-table-band: 73px;
    /* Body rows measured 53px on dashboard and reports but 51px on subscription,
       because row height was falling out of each row's tallest content rather
       than being stated. */
    --wl-table-row: 53px;

    /* Radius. style.css spreads 91 declarations across 30 distinct values;
       these three plus 50% for circles cover every real case. 6px and 10px are
       already the dominant values, so collapsing onto them changes the least. */
    --wl-radius-sm: 6px;             /* inputs, buttons, badges */
    --wl-radius-md: 10px;            /* cards, tables, dropdowns, modals */
    --wl-radius-pill: 200px;         /* pills, tabs */

    /* Elevation. Each step has a real y-offset — the incumbent
       `rgba(0,0,0,.1) 0 0 8px` has none, so it halos instead of lifting. */
    --wl-elev-1: 0 1px 2px rgba(0, 0, 0, .06), 0 1px 3px rgba(0, 0, 0, .08);
    --wl-elev-2: 0 2px 4px rgba(0, 0, 0, .06), 0 8px 20px rgba(0, 0, 0, .08);
    --wl-elev-3: 0 12px 28px rgba(0, 0, 0, .12)
}

@supports (color: color-mix(in srgb, red 50%, blue)) {
    :root {
        --primary-color-dark: color-mix(in srgb, var(--primary-color) 80%, #000);
        --primary-color-transparent: color-mix(in srgb, var(--primary-color) 50%, transparent);
        --wl-focus-ring: color-mix(in srgb, var(--secondary-color) 30%, transparent);
        --wl-tint: color-mix(in srgb, var(--secondary-color) 10%, transparent);
        --wl-wave-on-dark: color-mix(in srgb, var(--secondary-color) 32%, transparent);
        --wl-wave-on-light: color-mix(in srgb, var(--secondary-color) 8%, transparent);
        --wl-table-head-bg: color-mix(in srgb, var(--secondary-color) 8%, transparent);
        --wl-accent-dark: color-mix(in srgb, var(--secondary-color) 85%, #000);
        --wl-accent-soft: color-mix(in srgb, var(--secondary-color) 8%, transparent);
    }
}

/* ==========================================================================
   System compliance
   Audit of all 14 rendered pages found six places still outside the scales.
   ========================================================================== */

/* The last of the hardcoded #FF2A2A rules from the original audit. These are
   all semantic red — error, delete, sell, deploy-off — so they keep red, but
   the themed one: Tradetron's #FF2A2A scores 3.74 on white and fails AA,
   --status-red is 5.74. .switch-label is the "off" half of a toggle, where the
   old red on white text was the worst of them. */
.subscribe-btn.deploy-btn,
.subscribe-btn.deploy-btn:hover,
.deploye .fi-rr-cross-circle,
.alert-danger.cus-alert,
.item-unit .btn-item-del {
    color: var(--status-red);
}

.subscribe-btn.deploy-btn,
.subscribe-btn.deploy-btn:hover {
    border-color: var(--status-red);
}

.switch-label,
.cus-badge.red-bg {
    background: var(--status-red);
}

/* Several icon containers in style.css set a line-height that does not match
   their height, which pushes the glyph off centre — .rounded-white-icon is
   40px tall with line-height 45px, .btn-icon 20px with 12px. Flex centring
   ignores line-height, so the glyph sits true whatever the icon font's own
   metrics are. Same fix as .dashboard-table .arrow i below. */
.rounded-white-icon,
.btn-icon,
.btn-icon-text,
.btn-icon-text-outline {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

/* 5px radius survived on components the button rule did not name. */
.strategies-value,
.custom-dropdown .dropdown-item,
.custom-dropdown .dropdown-item.active,
.custom-checkbox[type=checkbox],
.pagination-row .page-link,
p.filter-description {
    border-radius: var(--wl-radius-sm);
}

/* Two greys were still failing AA as text on white. #9c9c9c on the S.No column
   scored 2.75 across 19 cells; #757990 is the pre-theme value of
   --primary-table-heading-color, hardcoded in four rules so the token override
   never reached them, at 4.29. */
.dashboard-table .serial-no,
.strategies-card .s-category,
.dash-prices p span,
.add-money .money-category,
#positonModal .modal-dialog .box-card label {
    color: var(--wl-muted);
}

/* Pure black rather than ink — off-palette, and the offcanvas is the mobile
   menu, so it is the first thing a phone user sees. */
.bb-offcanvas ul li a:hover,
.bb-offcanvas ul li.active > a,
.bb-offcanvas ul li > a,
.error-head,
.multiselect-container > li > a,
button.multiselect.dropdown-toggle.btn.btn-default {
    color: var(--text-color);
}

/* style.css uses `transition: all` in 24 rules — `a:hover` and `.btn` at .4s
   being the widest. Transitioning `all` animates layout properties too, so a
   hover can trigger reflow, and .4s is slow enough to feel laggy on a control.
   Naming the properties keeps it to compositable ones. */
a,
a:hover {
    transition: color .15s ease, border-color .15s ease;
}

.btn {
    transition: background-color .15s ease, border-color .15s ease,
                box-shadow .15s ease, color .15s ease;
}

/* ==========================================================================
   Numeric column alignment
   Every numeric column shipped left-aligned, so 931.5, 600 and 1,212.75 did not
   line up by place value and the tabular-nums applied in Typography bought
   nothing — tabular figures only pay off when the column is right-aligned.

   Headers are right-aligned with their cells; a right-aligned column under a
   left-aligned heading reads as a mistake.

   Markup cannot change and no numeric cell carries a class, so each table is
   addressed by the most specific hook it has: tab-pane id where one exists,
   otherwise a class unique to that table (th.arrow only ever appears on
   dashboard's table, .av-btn only in wallet's Balance column). Column indices
   differ per table, which is why these cannot be collapsed into one rule.
   Tables with no numeric columns — subscription, broker-exchanges — get no
   rule at all rather than an exclusion.
   ========================================================================== */

/* reports > Reports: PNL */
#reports .dashboard-table th:nth-child(3),
#reports .dashboard-table td:nth-child(3),
/* reports > Orderbook: Quantity, Price */
#order .dashboard-table th:nth-child(5),
#order .dashboard-table td:nth-child(5),
#order .dashboard-table th:nth-child(6),
#order .dashboard-table td:nth-child(6),
/* reports > Open Positions: Quantity, Price, Value */
#open .dashboard-table th:nth-child(5),
#open .dashboard-table td:nth-child(5),
#open .dashboard-table th:nth-child(6),
#open .dashboard-table td:nth-child(6),
#open .dashboard-table th:nth-child(7),
#open .dashboard-table td:nth-child(7),
/* dashboard: PNL */
.dashboard-table:has(th.arrow) th:nth-child(5),
.dashboard-table:has(th.arrow) td:nth-child(5),
/* wallet: Credit, Debit, Balance */
.dashboard-table:has(.av-btn) th:nth-child(5),
.dashboard-table:has(.av-btn) td:nth-child(5),
.dashboard-table:has(.av-btn) th:nth-child(6),
.dashboard-table:has(.av-btn) td:nth-child(6),
.dashboard-table:has(.av-btn) th:nth-child(7),
.dashboard-table:has(.av-btn) td:nth-child(7),
/* dashboard expanded rows: QTY, LTP, P&L, Val */
.nested-table th:nth-child(3),
.nested-table td:nth-child(3),
.nested-table th:nth-child(4),
.nested-table td:nth-child(4),
.nested-table th:nth-child(5),
.nested-table td:nth-child(5),
.nested-table th:nth-child(6),
.nested-table td:nth-child(6) {
    text-align: right;
}

/* ==========================================================================
   Table header
   A tinted band rather than a saturated bar: on a trading screen the header is
   structure, and the only saturated things should be the P&L figures under it.
   ========================================================================== */

/* Was keyed to .dashboard-table, which missed option-wizard's positions table —
   the only plain `<table class="table">` in the app, so it had no header band
   while every other table did. Keying off .table catches it. .nested-table is
   excluded: those are sub-tables inside an expanded row, where a second band
   would compete with the parent table's own header. */
/* The second selector is for option-wizard's positions table, which has no
   <thead> at all — its header row is a <tr> of <th> cells sitting inside
   <tbody>, so `thead th` can never match it. Restricted to the first row and to
   th cells, so data rows are untouched. */
.table:not(.nested-table) thead th,
.table:not(.nested-table) > tbody > tr:first-child > th {
    background-color: var(--wl-table-head-bg);
    /* The muted grey scores 4.29 on the band, just under AA. One step darker
       clears it at 6.70 and suits a header that now sits on its own surface. */
    color: var(--wl-muted-strong);
    /* Header was 46px against a 73px footer. `height` on a table cell acts as a
       minimum, and the vertical padding is zeroed so the token governs rather
       than fighting it. Bootstrap sets thead th to vertical-align:bottom, which
       would drop the labels to the floor of a band this tall. */
    height: var(--wl-table-band);
    padding-top: 0;
    padding-bottom: 0;
    vertical-align: middle;
}

/* Stated on the footer too, so the pair stays matched if its contents change. */
.pagination-row {
    min-height: var(--wl-table-band);
}

/* Body rows are stated rather than inferred from content, so dashboard,
   subscription and reports match. height on a table cell is a minimum, so a
   cell with wrapped text — broker-exchanges' Info column — still grows.
   Bootstrap aligns td to the top; middle suits rows mixing text with pills and
   buttons of differing heights. .nested-table is excluded, since sub-rows
   inside an expanded row should stay compact. */
.table:not(.nested-table) tbody td {
    height: var(--wl-table-row);
    padding-top: 0;
    padding-bottom: 0;
    vertical-align: middle;
}

/* The table's two caps match: the tfoot total row on reports takes the same
   height as the header, exactly as .pagination-row does on the pages that have
   one instead. */
.table:not(.nested-table) tfoot td,
.table:not(.nested-table) tfoot th {
    height: var(--wl-table-band);
    padding-top: 0;
    padding-bottom: 0;
    vertical-align: middle;
}

/* The band would otherwise square off the rounded top of .table-wrapper.
   Clipping the wrapper with overflow:hidden is not an option — style.css sets
   `.table thead, .table thead th { overflow: visible }` on purpose, and these
   pages open menus from inside the table. border-collapse is already
   `separate`, so per-cell radii render. */
.table:not(.nested-table) thead th:first-child,
.table:not(.nested-table) > tbody > tr:first-child > th:first-child {
    border-top-left-radius: var(--wl-radius-md);
}

.table:not(.nested-table) thead th:last-child,
.table:not(.nested-table) > tbody > tr:first-child > th:last-child {
    border-top-right-radius: var(--wl-radius-md);
}

/* ==========================================================================
   Brand leaks in style.css
   Eight rules hardcode Tradetron's #00C980 rather than reading --primary-color,
   so they survive any :root override. On reports.html the green "Details"
   buttons sat in the same table as the green P&L figures — in a trading UI a
   green control reading as a gain is actively confusing.
   ========================================================================== */

/* .act-btn and .edit-btn hardcode #00C980; their colour is set with the other
   secondary buttons in the Buttons section below. */

/* Positions row: five labelled selects plus an unlabelled Add button. The
   button was 40px against the selects' 36px, and sat 8px higher because its
   column has no label above it to push it down.

   The column is aligned to its bottom edge with padding-bottom of 1.5em —
   which is exactly `.form-group`'s own margin-bottom in style.css, so the two
   stay matched by construction rather than by a measured magic number. */
[class*="col-"]:has(> .add-btn) {
    display: flex;
    align-items: flex-end;
    padding-bottom: 1.5em;
}

/* Centred with line-height rather than flex: the markup carries Bootstrap's
   .d-inline-block, which is `display:inline-block!important` and overrides any
   display we set — so align-items never applies. line-height matching the
   height centres a single-line label without fighting the utility. */
.add-btn {
    height: 36px;
    min-height: 36px;
    padding-top: 0;
    padding-bottom: 0;
    line-height: 36px;
    text-align: center;
}

/* The wizard section divider was a 2px bar in #7c7979 — heavier and darker than
   any other line in the app, including the table borders it sits above. A
   divider is decorative, so it takes --wl-border rather than the 3:1 control
   border. */
.cus-wizard-border {
    height: 1px;
    background: var(--wl-border);
}

/* option-wizard's top row sits a button between two selects. The selects are
   36px; the button came to 42px (8px padding each side plus the 2px secondary
   border), so with the row top-aligned it hung 6px lower than its neighbours.
   Matching the input height rather than adjusting padding, so it stays 36px
   regardless of future border or padding changes. Scoped to .create-btn —
   standalone secondary buttons elsewhere are fine being taller. */
.create-btn {
    height: 36px;
    min-height: 36px;
    padding-top: 0;
    padding-bottom: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Strategy card stat tiles. #fff7ee is a peach belonging to no palette here;
   the soft accent tint matches the table header, secondary buttons and chevrons. */
.value-bg {
    background: var(--wl-accent-soft);
}

/* Tag pills were #eaeef6, a blue-grey near the accent tint but not it. */
.strategies-card .s-category {
    background: var(--wl-accent-soft);
    color: var(--wl-muted-strong);
}

/* Both were still on Tradetron's pre-theme values and bypassing the tokens —
   #ff2a2a scores 3.74 on white and fails AA, #4062ff is the old status blue
   that now clashes with the indigo accent. */
.red-clr {
    color: var(--status-red);
}

.blue-clr {
    color: var(--status-blue);
}

/* Wallet "add money" row. Three controls of different heights — input 36px,
   chips 33px, button 40px — in a Bootstrap .row, which defaults to
   align-items:stretch, so all three pinned to the same top edge and their
   centres landed 3px apart. Scoped to this card rather than .row generally,
   since Bootstrap rows do layout everywhere. */
.wallet-add-card .cus-card-body .row {
    align-items: center;
}

/* Header avatar. Was a 40px dark silhouette sitting flat in the bar. Now 32px
   on a soft tinted disc, with the icon itself recoloured to the accent in
   images/img-user.svg — CSS cannot reach inside an <img>, so the fill had to
   change in the asset. Padding insets the icon so the disc reads as a frame
   rather than a tight crop. */
.usr-st a.u-link img {
    width: 32px;
    height: 32px;
    padding: 3px;
    border-radius: 50%;
    background: var(--wl-accent-soft);
}

@media screen and (max-width: 767px) {
    .usr-st a.u-link img {
        width: 28px;
        height: 28px;
    }
}

/* ==========================================================================
   Ink -> accent sweep
   Principle: indigo means "selected or actionable"; ink is for text and
   structure. style.css used --primary-color for both jobs, so once the buttons
   moved to indigo every active state was left stranded in ink — the black
   pagination number and row chevrons next to indigo buttons.
   White on indigo is 6.29 AA, so anything that already had white text carries
   over unchanged.
   ========================================================================== */

/* Selected states. */
.pagination-row .page-item.active .page-link,
.dt-container .page-item.active .page-link,
.custom-checkbox[type=checkbox]:checked,
.rules-group-header .btn-toggle .btn.active {
    background-color: var(--secondary-color);
    border-color: var(--secondary-color);
}

/* Actions and brand accents. */
.btn-icon,
button.btn.exit-all-btn,
.ui-dialog-buttonset button,
.profile-img-upload,
.price-symbol span,
.cus-badge {
    background-color: var(--secondary-color);
}

.ui-dialog-buttonset button {
    border-color: var(--secondary-color);
}

/* The Actions dropdown chevron is `background: url(angle-down-white.svg)` — a
   literally white asset, which was fine on the old ink button and invisible on
   the pale secondary fill. Rather than add a dark twin of the asset, the same
   file becomes a mask over currentColor, so the chevron now takes the button's
   text colour and follows its hover and focus states. mask-size:contain also
   fixes the 12px artwork being clipped by the 10px box. */
.actions .custom-dropdown .dropdown-toggle::after {
    background: currentColor;
    -webkit-mask-image: url(../images/angle-down-white.svg);
    mask-image: url(../images/angle-down-white.svg);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
}

/* "Add Broker" is the only action on broker-exchanges, so it should read as the
   primary one. It shares `.btn.act-btn` with secondary controls like Back and
   Details, so the hook is its position: a button in .page-title is the page's
   primary action by definition. Currently the only such button in the app. */
.page-title .btn.act-btn {
    background: var(--secondary-color);
    border-color: var(--secondary-color);
    color: var(--white);
}

.page-title .btn.act-btn:not(:disabled):not(.disabled):hover,
.page-title .btn.act-btn:not(:disabled):not(.disabled):focus,
.page-title .btn.act-btn:not(:disabled):not(.disabled):active {
    background: var(--wl-accent-dark);
    border-color: var(--wl-accent-dark);
    color: var(--white);
}

/* Row expanders. Tertiary controls that repeat once per row — filled ink made
   three heavy dots of every table. Soft treatment keeps them clickable without
   the weight. */
.dashboard-table .arrow i {
    background: var(--wl-accent-soft);
    border: 1px solid var(--secondary-color);
    color: var(--text-color);
    /* style.css sets line-height:37px on a 26px box, which pushes the glyph
       about 5px below centre, and font-size:20px nearly fills the disc. Flex
       centring ignores line-height entirely, so the glyph sits true regardless
       of the icon font's own metrics. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    font-size: 15px;
}

/* Pagination's resting links: #e7e7e7 border is 1.3:1 and #b4b4b4 text is 2.2:1,
   which is why "3" reads as disabled when it is not. */
.pagination-row .page-link {
    border-color: var(--wl-border-control);
    color: var(--wl-muted);
}

/* Modal headers were full-width ink bars. Indigo would put a large saturated
   block atop every modal, so they take the same soft band as the table header —
   which means their white text has to come back to ink. */
.filterModal .modal-header,
.notificationModal .modal-header,
.subscribeModal .modal-header {
    background: var(--wl-accent-soft);
}

.filterModal .modal-header h4,
.filterModal .modal-header i,
.filterModal .modal-header .close,
.notificationModal .modal-header h4,
.notificationModal .modal-header i,
.subscribeModal .modal-header h4,
.subscribeModal .modal-header button {
    color: var(--text-color);
}

/* PT/Live toggle (dashboard). The track was white inside an ink border with an
   ink sliding pill. Recoloured to match the secondary buttons: soft tint track,
   accent pill. White on indigo is 6.29 AA for the active label; the inactive
   one stays ink on the tint.
   .switches-container.sell keeps --status-red — that variant is Buy/Sell, which
   is data semantics rather than brand. */
.switches-container {
    background: var(--wl-accent-soft);
    border-color: var(--secondary-color);
}

.switches-container .switch {
    background: var(--secondary-color);
}

/* Green here is semantic — on, subscribed — not brand. It stays green, but the
   themed, contrast-checked green instead of Tradetron's. */
.switch-green > .switch-input:checked ~ .switch-label {
    background: var(--status-green);
}

.subscribe-btn,
.subscribe-btn:hover {
    border-color: var(--status-green);
    color: var(--status-green);
}

.alert-success.cus-alert {
    color: var(--status-green);
}

/* The one leak carrying !important, so the override has to match it. It is a
   confirm action, so it follows the primary treatment. */
.sweet-alert button {
    background: var(--secondary-color) !important;
}

/* A coloured text-shadow on a close icon is decoration with no job. */
.filterModal .modal-header .close {
    text-shadow: none;
}

.dropdown-item.active,
.dropdown-item:active {
    background-color: var(--wl-tint);
    color: var(--text-color);
}

/* ==========================================================================
   Radius
   Buttons sat at 10px while the inputs above them sat at 6px — most visible on
   the login form, where the CTA is the same width as the fields and the
   mismatch reads as a mistake. Everything collapses onto sm / md / pill.
   ========================================================================== */

.btn,
.primaryBtn,
.btn.act-btn,
.btn.edit-btn,
.btn.cus-btn,
.btn-icon,
.btn-group-actions .btn,
.btn-outline-danger,
.btn-outline-success,
.cus-badge,
.filterModal .selectBox {
    border-radius: var(--wl-radius-sm);
}

.form-control,
.form-control.cus-form,
.form-control.filter-form {
    border-radius: var(--wl-radius-sm);
}

.cus-card,
.table-wrapper,
.modal-content,
.selectBox .dropdown-menu,
.status-dropdwon .dropdown-menu,
.dropdown.filter-dropdown .dropdown-menu,
.custom-dropdown .dropdown-menu,
.dt-container .table.table-rounded {
    border-radius: var(--wl-radius-md);
}

/* Top corners only — this table sits flush against the block beneath it. */
.table-rounded {
    border-radius: var(--wl-radius-md) var(--wl-radius-md) 0 0;
}

/* .btn-lg carried a 45px radius, which at that size is a pill in all but name. */
.btn.btn-lg,
.nav-pills.table-tab .nav-link,
.cus-card.strategies-card .cus-card-body .cus-badge {
    border-radius: var(--wl-radius-pill);
}

/* ==========================================================================
   Elevation
   style.css carries 27 box-shadows in 13 different values, 12 of them the same
   `rgba(0,0,0,.1) 0 0 8px` — zero y-offset, so surfaces halo rather than lift.
   Everything below maps onto the three-step scale, kept monotonic with stacking
   order: resting chrome < cards < overlays.
   ========================================================================== */

/* Resting — small chrome that sits on a surface rather than above it. */
.header,
.header.menu-shrink,
.btn-icon,
.rounded-white-icon,
.st-multiple .btn-group,
ul.sortable li.ui-state-default {
    box-shadow: var(--wl-elev-1);
}

/* Cards — primary surfaces floating on the page background. */
/* .cus-card covers 10 pages; dashboard and reports use .table-wrapper /
   .table-rounded / .dash-card instead, so all of them need naming here. */
.cus-card,
.table-rounded,
.table-wrapper,
.dash-card,
.alert-primary.cus-alert-btm {
    box-shadow: var(--wl-elev-2);
}

/* Overlays — anything that opens above the page and must read as detached. */
.top-bar .dropdown-menu,
.status-dropdwon .dropdown-menu,
.dropdown.filter-dropdown .dropdown-menu,
.custom-dropdown .dropdown-menu,
.selectBox .dropdown-menu,
.modal-content,
.modal.right.fade.show .modal-dialog,
.dd-dragel .dd-handle {
    box-shadow: var(--wl-elev-3);
}

/* style.css puts `rgba(0,0,0,.15) 0 12px 15px` under every button on
   hover/focus/active — a 15px blur with a 12px drop, heavier than the cards the
   buttons sit on, which inverts the stacking order. */
.btn:not(:disabled):not(.disabled):active,
.btn:not(:disabled):not(.disabled):focus,
.btn:not(:disabled):not(.disabled):hover {
    box-shadow: var(--wl-elev-2) !important;
}

/* ==========================================================================
   Inline SVG icons
   168 icons are pasted inline in the markup (a separate system from the
   Flaticon UIcons webfont and the images/*.svg files). They carry
   fill="#000000" from Flaticon's SVG export, so they render pure black and
   ignore the palette entirely.

   `fill` is a presentation attribute, which loses to any CSS rule — so this
   works without touching markup. Matching on the attribute rather than the
   element means only the 60 explicitly-black paths are affected; the 12
   fill="white" paths in .link-expand are left alone.
   ========================================================================== */

svg [fill="#000000"] {
    fill: currentColor;
}

/* The attribute selector above only reaches paths that actually carry
   fill="#000000". In the user dropdown, Wallet and Invoices do — but Profile,
   Broker & Exchanges, Help and Support and Logout have no fill attribute at
   all, so they fell back to SVG's default black and could not follow the label
   colour. Setting fill on the <svg> catches them: fill is an inherited SVG
   property, so paths with no attribute of their own pick it up, while paths
   that do carry one keep using the rule above. The nav and .link-expand icons
   already worked for this reason — their hover rules set fill on the <svg>. */
.dropdown-item svg {
    fill: currentColor;
}

/* ==========================================================================
   Typography
   ========================================================================== */

/* style.css sets `color: var(--text-color); background: var(--primary-color)`.
   Under Palette B both resolve to #16181D, so selected text was ink on ink —
   invisible rather than merely dark. The accent is the right colour for this
   anyway, and white on it clears AA at 6.29:1 on both the light surfaces and
   the ink login panel. */
::selection {
    background-color: var(--secondary-color);
    color: var(--white);
}

::-moz-selection {
    background-color: var(--secondary-color);
    color: var(--white);
}

/* style.css hardcodes Nunito here, bypassing --primary-font.
   8 uses across dashboard, reports, wallet, subscription, broker-exchanges. */
.dashboard-table {
    font-family: var(--primary-font);
}

/* Field labels were 15px/600 in ink while table headers are 15px/400 in grey —
   so the chrome outranked the data it was organising. Labels become the quiet
   thing; headers keep their weight as content structure.

   The markup has 11 different label class combinations plus 11 labels with no
   class at all, so keying off classes reached only a third of them. Of 82
   labels, 62 sit inside a .form-group and the 20 that do not are exactly the
   ones that must not change — .switch-green toggles and .form-check-label.
   So the container is the reliable hook, not the class. */
/* .checkbox labels are multiselect list items — things you read and click, not
   field captions. Their size is set in multiselect.css, but the !important on
   weight below was still reaching them. */
/* A few labels sit directly in a grid column rather than inside .form-group —
   "Profit MTM", "Stoploss MTM" and "Exit Time" in option-wizard's Exit Setting,
   which is why that section had 15px/700 labels next to 13px/500 ones. Adding
   the class catches them without reaching any toggle, since .switch-green and
   .form-check-label never carry it. */
.form-group label:not(.checkbox),
label.font-weight-bold,
.cus-label {
    font-size: 13px;
    /* Bootstrap's .font-weight-bold utility is `font-weight:700!important` and
       13 labels carry it; !important is the only thing that beats !important. */
    font-weight: 500 !important;
    color: var(--wl-muted);
}

/* Space Grotesk runs wider and more open than Nunito, so the inherited
   .02em body tracking reads loose. Reset to the font's own metrics. */
body {
    letter-spacing: 0;
}

/* Space Grotesk has a taller x-height than Nunito at the same px size;
   headings carry it better slightly tightened. */
h1, h2, h3, h4, h5, h6 {
    letter-spacing: -0.01em;
}

/* Align figures into columns. Proportional digits make numeric table columns
   and P&L values ragged, which matters more here than in a typical UI. */
.dashboard-table,
.dash-prices,
.strategies-value,
.subscribe-amnt,
table td,
table th {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}

/* ==========================================================================
   Form controls
   ========================================================================== */

/* style.css uses `1px solid #666` — a near-black hairline around every field,
   which reads like a wireframe. A field's border is its only boundary here
   (white input on a white card), so it has to clear WCAG 1.4.11's 3:1. */
/* The variants carry their own border at higher specificity — .filter-form sets
   #d6d6d6 and .cus-form sets none — so a bare .form-control rule misses both.
   Shorthand `border` so .cus-form gets one at all. */
.form-control,
.form-control.cus-form,
.form-control.filter-form {
    border: 1px solid var(--wl-border-control);
    font-size: 15px;
    /* Explicitly none, not merely omitted: style.css gives .cus-form
       `rgba(0,0,0,.1) 0 0 8px`, which would come back if this were dropped.
       A control defined by both a 3:1 border and a shadow is announcing itself
       twice — on a form like option-wizard, with ~20 fields, that compounds
       into noise. The border alone carries the boundary. */
    box-shadow: none;
    transition: border-color .15s ease, box-shadow .15s ease;
}

/* Hover was #8A919C -> #6B7280: technically applied, but one mid-grey shifting
   to a slightly darker mid-grey on a 1px border is imperceptible in use.

   The three states now read as a progression toward active rather than three
   shades of grey:
     rest   grey border
     hover  accent border, no ring
     focus  accent border + accent ring
   Hover borrows the focus colour but not its ring, so it clearly signals
   "this is interactive" without being mistaken for focus itself. */
.form-control:hover:not(:focus):not(:disabled):not([readonly]),
.form-control.flatpickr-input:hover:not(:focus) {
    border-color: var(--secondary-color);
}

/* A sweep of all 44 interactive elements found 16 with no hover feedback at
   all. These are the ones that are genuinely clickable; inputs that are hidden
   (.switch-input), already-active tabs, and real checkboxes are left alone
   because they either have their own visual or should not invite a click.

   Controls that behave like a field take the field's hover — accent border. */
.selectBox:hover,
button.multiselect.dropdown-toggle:hover,
.dropdown-select.status:hover {
    border-color: var(--secondary-color);
}

/* style.css sets `a:hover { color: var(--primary-color) }`. Under Palette B
   --primary-color and --text-color are both #16181D, so every plain link's
   hover recoloured it to exactly what it already was — a no-op app-wide. Same
   trap that made ::selection invisible. Links take the accent on hover instead.

   Excluded: anything that is a button (it has its own hover), and .u-link,
   which needs higher specificity to beat `.usr-st a.u-link` at (0,2,1). */
/* .nav-link and .active are excluded for the same reason as the button classes:
   they may sit on a filled background. The active pill is white-on-indigo, so
   recolouring its text to the accent put indigo on indigo and the label
   vanished. Nav links get their own rule below, which skips the active one. */
a:not(.btn):not(.primaryBtn):not(.subscribe-btn):not(.page-link):not(.nav-link):not(.active):hover,
.nav-link:not(.active):hover,
.usr-st a.u-link:hover,
.usr-st a.u-link:hover span {
    color: var(--secondary-color);
}

/* The status pill carries Bootstrap's .border-0, so a border-colour hover is
   invisible on it. Tint instead. */
.dropdown-select.status:hover {
    background: var(--wl-accent-soft);
}

/* Nav icons were hovering to --primary-color while their labels now hover to
   the accent, so the text turned indigo and the icon went ink beside it. An
   icon should track the label it belongs to — same root cause as the link
   hover, since --primary-color and --text-color are the same value here. */
/* :not(.active) on both the li and the a, matching the two ways style.css marks
   the current page. The active item's label is deliberately inert on hover — you
   are already there — so its icon must be too, or the icon turns indigo beside
   unchanged text. The active state keeps its own ink fill from style.css. */
.header nav ul li:not(.active) > a:not(.active):hover svg,
.bb-offcanvas ul li:not(.active) > a:not(.active):hover svg,
.sidebar ul li a:not(.active):hover svg,
.link-expand:hover svg {
    fill: var(--secondary-color);
}

/* The offcanvas mobile menu used literal `black` for its active state rather
   than a token. */
.bb-offcanvas ul li.active > a svg,
.bb-offcanvas ul li > a.active svg {
    fill: var(--text-color);
}

/* .subscribe-btn carries neither .btn nor .primaryBtn, so it was the last
   holdout from the button scale at style.css's explicit height:47px — 7px
   taller than every other button. These are card-level actions, the same tier
   as Filter and Save, so they take --wl-btn-h.

   Vertical padding is zeroed rather than kept: the wide variant holds a 30px
   .subscribe-amnt chip, which would not fit inside 40px once 7px of padding
   and the border are taken out. The element is already display:flex, so
   align-items centres both the chip and the plain-text variants. */
.subscribe-btn {
    height: var(--wl-btn-h);
    padding-top: 0;
    padding-bottom: 0;
    align-items: center;
}

/* Subscribe and Deploy keep their semantic green and red — the hover is a tint
   of the same colour rather than a shift to the brand, so the meaning holds. */
.subscribe-btn:hover {
    background: rgba(11, 132, 70, .07);
}

.subscribe-btn.deploy-btn:hover {
    background: rgba(200, 30, 30, .07);
}

/* Focus produced no visible ring anywhere in the app. Two separate rules in
   style.css suppress it:
     .form-control:focus                        (0,2,0)  box-shadow:none
     input[type=text]:focus:not([readonly])     (0,3,1)  box-shadow:none
   The second is an MDBootstrap leftover and outranks a plain .form-control:focus,
   so matching its specificity is what makes this land — !important is not needed
   for the shadow. border-color does need it, because style.css marks that one
   !important. */
/* Focus uses the indigo accent rather than the ink primary — an ink ring on an
   ink-chrome scheme would be nearly invisible. */
input.form-control:focus:not([readonly]),
select.form-control:focus,
textarea.form-control:focus {
    border-color: var(--secondary-color) !important;
    box-shadow: 0 0 0 3px var(--wl-focus-ring);
}

.form-control::placeholder {
    color: #9CA3AF;
    opacity: 1;
}

/* Disabled fields are legitimately disabled here — option-wizard greys out
   dependent inputs until their dropdown is set. But #e9ecef is heavier than the
   page background, so a disabled field read as darker and more prominent than an
   active one. Lighter fill, muted text, softened border: still unmistakably
   inert, no longer the loudest thing in the row. style.css marks the background
   !important, so this has to match. */
/* input.form-control:disabled rather than .form-control:disabled, because
   style.css also carries `input[type="text"]:disabled{background:#e9ecef!important}`
   at (0,2,1) — a plain (0,2,0) class rule loses to it even with !important. */
/* .flatpickr-input is excluded: flatpickr sets readonly on its field so it
   cannot be typed into, but the field is fully interactive — clicking it opens
   the calendar. Greying it made a working date picker look disabled. */
.form-control:disabled,
.form-control[readonly]:not(.flatpickr-input),
input.form-control:disabled,
select.form-control:disabled,
textarea.form-control:disabled {
    background-color: #F3F4F6 !important;
    border-color: var(--wl-border);
    color: var(--wl-muted);
    cursor: not-allowed;
}

@media (prefers-reduced-motion: reduce) {
    .form-control,
    .btn.btn-primary {
        transition: none;
    }
}

/* ==========================================================================
   Button sizing
   Height is set once and the vertical padding zeroed, so a button's height no
   longer depends on whichever padding rule happened to win. Centring is by flex
   rather than line-height because border width differs between the primary and
   secondary treatments, which would throw a line-height calculation off.
   ========================================================================== */

.btn,
.primaryBtn {
    height: var(--wl-btn-h);
    padding-top: 0;
    padding-bottom: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Buttons like "+ Add Broker" and "< Back" separate their icon from the
       label with a literal space in the markup. Making the button a flex
       container turns that label into an anonymous flex item, and leading
       whitespace in a flex item is stripped — so the space disappeared. gap
       restores it, and has no effect on text-only buttons, which have a single
       flex item and therefore no gap to apply. */
    gap: .4em;
}

/* Optical correction for the Flaticon glyphs. Box geometry says these are
   centred — the icon box and the label box sit within 0.4px of each other —
   but the glyph is drawn high inside its own em square: rendering both to a
   canvas puts the icon's ink centre 6.5px above its baseline against the
   label's 5.5px. Flex alignment cannot see inside a font, so this is the one
   place a 1px nudge is the correct tool rather than a workaround. */
.btn > i,
.primaryBtn > i {
    position: relative;
    top: 1px;
}

/* Small tier: explicit .btn-sm, plus anything inside a table cell. A 40px button
   in every row would add height to the densest screens, and these are row-scoped
   actions rather than page actions. */
.btn-sm,
td .btn,
.btn-icon {
    height: var(--wl-btn-h-sm);
}

/* Icon-only buttons should be square — height came from the scale above but
   width still fell out of the glyph plus its padding, so the edit pencils
   measured 35.5 x 32.

   Listed explicitly rather than detected. The obvious selector,
   :has(> i:only-child), does not work: :only-child counts element siblings,
   and a button's text label is a *text node*, so "+ Add Broker" matches it just
   as "<pencil>" does. CSS cannot test for a text node, so there is no way to
   tell an icon-only button from an icon+label one structurally. These are the
   only icon-only buttons in the app. */
.btn.edit-btn,
.btn-icon {
    width: var(--wl-btn-h-sm);
    padding-left: 0;
    padding-right: 0;
}

/* Two deliberate exceptions at the 36px input height: both sit inline in a row
   of form controls, where matching the inputs beside them matters more than
   matching buttons elsewhere. Neither carries .btn, so these beat .primaryBtn. */
.primaryBtn.create-btn,
.primaryBtn.add-btn {
    height: 36px;
    min-height: 36px;
}

/* Primary — the accent filled. Ink read as heavy once buttons multiplied on
   pages like option-wizard; indigo keeps the prominence a primary action needs
   while lifting the weight. White on it is 6.29, AA. */
.primaryBtn {
    background: var(--secondary-color) !important;
    border-color: var(--secondary-color) !important;
}

/* Secondary — the accent as a border over a soft tint, with ink text.
   Border is 2px rather than 4px: on a 36px control 4px is a fifth of its
   height, and .btn-sm ("Details") is smaller still. Change it in one place
   below if you want it heavier. */
.primaryBtn.reset-btn {
    background: var(--wl-accent-soft) !important;
    border: 2px solid var(--secondary-color) !important;
    color: var(--text-color) !important;
    -webkit-transition: all .2s ease;
    -moz-transition: all .2s ease;
    -o-transition: all .2s ease;
    transition: all .2s ease;
}

/* The 2px border is deliberate even though it is the same colour as the fill.
   Secondary buttons carry a 2px border and these have height:auto, so without a
   matching border the primary computed 4px shorter than the secondary beside it
   — Cancel 44px against Save 40px on broker-exchanges-add. Matching the box
   model here keeps the two treatments the same size everywhere by construction,
   rather than needing a height patch per page. */
.btn.btn-primary {
    background-color: var(--secondary-color);
    border: 2px solid var(--secondary-color);
    transition: background-color .15s ease, box-shadow .15s ease;
}

.primaryBtn:not(:disabled):not(.disabled):active,
.primaryBtn:not(:disabled):not(.disabled):focus,
.primaryBtn:not(:disabled):not(.disabled):hover {
    box-shadow: var(--wl-elev-2) !important;
}

.primaryBtn.reset-btn:not(:disabled):not(.disabled):active,
.primaryBtn.reset-btn:not(:disabled):not(.disabled):focus,
.primaryBtn.reset-btn:not(:disabled):not(.disabled):hover {
    box-shadow: var(--wl-elev-2) !important;
    -webkit-transition: all .2s ease;
    -moz-transition: all .2s ease;
    -o-transition: all .2s ease;
    transition: all .2s ease;
}

.btn.btn-primary:not(:disabled):not(.disabled):active,
.btn.btn-primary:not(:disabled):not(.disabled):focus,
.btn.btn-primary:not(:disabled):not(.disabled):hover {
    background: var(--wl-accent-dark);
    border-color: var(--wl-accent-dark);
    color: var(--white);
}

/* Secondary buttons: Cancel, Back, Add Broker, Details, Renewal, the Actions
   toggle. These were ink or mid-grey — the grey ones read as disabled. */
.btn.btn-secondary,
.btn.act-btn,
.btn.edit-btn {
    background: var(--wl-accent-soft);
    border: 2px solid var(--secondary-color);
    color: var(--text-color);
    transition: background-color .15s ease;
}

/* style.css forces `color: var(--white)` on every .btn in all three interaction
   states via `.btn:not(:disabled):not(.disabled):hover` — specificity (0,4,0),
   which outranks a plain `.btn.act-btn:hover` at (0,3,0). Rest was correct;
   hover, focus and active all flipped to white on the pale fill. Repeating the
   :not() guards takes these to (0,5,0). All three states are listed because
   the rule being beaten covers all three. */
.btn.btn-secondary:not(:disabled):not(.disabled):hover,
.btn.btn-secondary:not(:disabled):not(.disabled):focus,
.btn.btn-secondary:not(:disabled):not(.disabled):active,
.btn.act-btn:not(:disabled):not(.disabled):hover,
.btn.act-btn:not(:disabled):not(.disabled):focus,
.btn.act-btn:not(:disabled):not(.disabled):active,
.btn.edit-btn:not(:disabled):not(.disabled):hover,
.btn.edit-btn:not(:disabled):not(.disabled):focus,
.btn.edit-btn:not(:disabled):not(.disabled):active {
    background: var(--wl-tint);
    border-color: var(--wl-accent-dark);
    color: var(--text-color);
}

.btn.btn-primary:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--wl-focus-ring);
}

/* Was var(--success) — Bootstrap's #28A745, which scores 3.13 on white and is a
   different green from --status-green used by .decrease's counterpart. Gains and
   losses need to be a matched, legible pair. */
.increase {
    color: var(--status-green);
}

.wrapper_main {
    height: 100vh !important;
    padding: 0 !important;
    margin: 0 !important;
}

.content-block {
    width: 100%;
    height: calc(100vh - 155px);
    margin: 115px 0 0 0;
    padding: 20px;
    overflow-y: auto;
}

/* Wave texture on change-password, matching the login screens.

   change-password is the only page that puts .cus-login-box inside the app
   shell — login and signup nest it in .cus-login-2-col — so :has() identifies
   it without needing a class we cannot add. Anchored to .wrapper_main rather
   than .content-block because the latter scrolls, which would drag the texture
   with it. .header is fixed and opaque, so it covers the top of the layer. */
.wrapper_main:has(.cus-login-box)::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-color: var(--wl-wave-on-light);
    -webkit-mask-image: var(--wl-wave-mask), linear-gradient(to bottom, rgba(0, 0, 0, .15) 0%, #000 60%);
    mask-image: var(--wl-wave-mask), linear-gradient(to bottom, rgba(0, 0, 0, .15) 0%, #000 60%);
    -webkit-mask-size: 220px 100%, 100% 100%;
    mask-size: 220px 100%, 100% 100%;
    -webkit-mask-repeat: repeat-x, no-repeat;
    mask-repeat: repeat-x, no-repeat;
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
}

/* .content-block is not positioned, so it would otherwise paint below the
   absolutely-positioned layer above. */
.wrapper_main:has(.cus-login-box) .content-block {
    position: relative;
    z-index: 1;
}

@media (max-width: 767px) {
    .content-block {
        height: auto;
        margin-top: 65px;
        padding: 20px 0;
    }
}


/* 60px here forced the wordmark to 450px wide — 7.5:1 aspect against a 78px
   header row, so it read as the loudest thing on every page. style.css's own
   values were 34-40px across breakpoints; this returns to that scale.
   Login and signup are unaffected: they use .logo-login, not .header .logo. */
.header .logo img {
    max-height: 40px;
}

.header nav ul li > a:hover svg {
    transition: all .4s ease;
}

@media (max-width: 991px) {
    .header {
        padding: 0 !important;
    }
}

@media screen and (max-width: 767px) {
    .header .logo img {
        max-height: 32px;
    }

    .header .logo {
        padding-right: 15px;
    }

    .header nav ul li a svg {
        fill: rgba(0, 0, 0, 0.7);
    }

    .header nav ul > li > a {
        color: var(--dark);
    }

    .menu-toggle {
        margin-left: 8px;
    }
}

/* Was --primary-color, which under Palette B is the same ink the tab already
   is — so this hover did nothing. Third instance of that trap, after
   ::selection and the global a:hover. */
.nav-pills.table-tab a.nav-link:not(.active):hover {
    color: var(--secondary-color);
}

/* Active tab pill — a selected state, so it follows the accent.
   Also drops a stray `!important;` that sat on its own line here: invalid
   syntax, silently discarded by the parser. Flagged in plan.md since the
   original audit. */
.nav-pills.table-tab .nav-link.active,
.nav-pills .show > a.nav-link {
    background: var(--secondary-color);
    color: var(--white);
}

/* Strategies */
.strategy-title {
    display: flex;
    justify-content: space-between;
    align-items: start;
}

.cus-card.strategies-card .cus-card-body .cus-badge {
    font-size: 13px;
}

.btns {
    display: flex;
    gap: 10px;
}

.subscribe-btn {
    color: var(--status-green);
    border-color: var(--status-green);
    max-width: none;
    margin: 10px 0 0 0;
    display: flex;
    gap: 10px;
}

.subscribe-btn:hover,
.subscribe-btn {
    text-transform: capitalize;
    color: var(--status-green);
}

.subscribe-btn.deploy-btn,
.subscribe-btn.deploy-btn:hover {
    text-transform: capitalize;
    padding: 0 20px;
    color: var(--status-red);
}

.subscribe-btn:hover {
    text-transform: capitalize;
    color: var(--status-green);
}

.subscribe-amnt {
    color: var(--status-green);
    display: flex;
    align-items: center;
    border-radius: 5px;
    margin-right: 10px;
}

.subscribe-amnt img {
    max-width: 15px;
    margin-right: 5px;
}

.cus-card.strategies-card p {
    float: none;
    color: var(--wl-muted);
}

.strategies-card .s-category {
    font-size: 14px;
    padding: 3px 10px;
}

.st-detail-sec {
    margin-bottom: 10px;
    width: 100%;
    display: inline-block;
}

.strategies-detail {
    width: 100%;
    max-width: 100%;
    display: inline-block;
}

.strategies-value {
    width: auto;
    display: inline-block;
    min-width: 110px;
    margin: 0 7px 10px 0;
    padding: 5px 10px;
    border-radius: 5px;
}

.strategies-value h6 {
    font-size: 15px;
}

.strategies-value span {
    font-size: 12px;
    line-height: 1.3em;
    display: inline-block;
}

@media (min-width: 1366px) {
    .st-detail-sec {
        display: flex;
        margin-bottom: 0;
        align-items: end;
    }

    .strategies-detail {
        display: flex;
        align-items: end;
    }

    .strategies-value {
        margin: 0 7px 0 0;
    }

    .subscribe-btn {
        width: auto;
        margin-left: 10px;
    }
}


/* Login / Signup */
.cus-login-2-col {
    width: 100%;
    height: 100%;
    position: relative;
}

/* Wavy texture across the whole login screen.

   One full-width layer rather than one per panel: the mask tiles from a single
   origin, so the waves stay in phase across the seam instead of breaking at the
   panel edge. The two grounds get different strengths via a hard-stop gradient
   at 50%, which is also where .col-left ends.

   Drawn as a mask rather than a coloured background-image: a data-URI SVG cannot
   reference var(), so baking the indigo into it would create exactly the kind of
   hardcoded brand leak we spent this pass removing. Masking a token-coloured box
   keeps it deriving from --secondary-color. */
/* The drift. Shifting by exactly one tile width lands on an identical frame, so
   the loop is seamless with no fade or reset. transform is animated rather than
   mask-position because transform is composited — mask-position would repaint
   a full-viewport layer every frame.

   Each layer is one tile wider than its container and starts one tile to the
   left, so travelling +220px never exposes an empty edge. */
@keyframes wl-wave-drift {
    from { transform: translateX(0); }
    to   { transform: translateX(220px); }
}

.cus-login-2-col::after {
    content: "";
    position: fixed;
    top: 0;
    left: -220px;
    width: calc(100vw + 220px);
    animation: wl-wave-drift var(--wl-wave-drift) linear infinite;
    background-color: var(--wl-wave-on-light);
    /* Not height:100% — .cus-login-2-col collapses to zero height because both
       its children are out of flow (.col-left is fixed, .col-right floats), so a
       percentage would resolve against nothing. */
    height: 100vh;
    z-index: 0;
    pointer-events: none;
    /* Alpha lives in the gradient stops above, not here, so each side can be
       weighted independently. */
    /* One wave per 90px tile instead of three per 60px — about 10 lines down the
       panel rather than 45. Spacing comes from the tile, not from scaling the
       mask, so the stroke stays a crisp 1.5px instead of thickening. */
    /* Two mask layers intersected: the wave geometry, and a vertical fade that
       weakens them toward the top. Spacing already tightens upward, so the two
       together read as recession rather than a flat gradient. */
    -webkit-mask-image: var(--wl-wave-mask), linear-gradient(to bottom, rgba(0, 0, 0, .15) 0%, #000 60%);
    mask-image: var(--wl-wave-mask), linear-gradient(to bottom, rgba(0, 0, 0, .15) 0%, #000 60%);
    -webkit-mask-size: 220px 100%, 100% 100%;
    mask-size: 220px 100%, 100% 100%;
    -webkit-mask-repeat: repeat-x, no-repeat;
    mask-repeat: repeat-x, no-repeat;
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
}

/* The ::after is a later sibling in paint order, so both panels need lifting or
   the waves render on top of the artwork and the card. */
.cus-login-2-col .col-right,
.cus-login-2-col .col-left {
    z-index: 1;
}

/* .col-left's ink background is opaque, so lifting it above the ::after also
   hides the waves on that half. It needs its own layer, painted over its
   background but under its content.

   Both layers tile from viewport x=0 — .col-left is fixed at left:0 — so the
   waves stay in phase across the seam despite being two elements. Positioning it
   absolutely also keeps it out of .col-left's flex flow. */
.cus-login-2-col .col-left::before {
    content: "";
    position: absolute;
    inset: 0;
    /* Same offset-and-travel as the light layer, and the same duration, so the
       two stay in step across the seam. .col-left clips it below. */
    left: -220px;
    width: calc(100% + 220px);
    animation: wl-wave-drift var(--wl-wave-drift) linear infinite;
    pointer-events: none;
    background-color: var(--wl-wave-on-dark);
    /* Two mask layers intersected: the wave geometry, and a vertical fade that
       weakens them toward the top. Spacing already tightens upward, so the two
       together read as recession rather than a flat gradient. */
    -webkit-mask-image: var(--wl-wave-mask), linear-gradient(to bottom, rgba(0, 0, 0, .15) 0%, #000 60%);
    mask-image: var(--wl-wave-mask), linear-gradient(to bottom, rgba(0, 0, 0, .15) 0%, #000 60%);
    -webkit-mask-size: 220px 100%, 100% 100%;
    mask-size: 220px 100%, 100% 100%;
    -webkit-mask-repeat: repeat-x, no-repeat;
    mask-repeat: repeat-x, no-repeat;
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
}

/* Keep the artwork and tagline above the left-hand waves. */
.cus-login-2-col .slider-info {
    position: relative;
    z-index: 1;
}

.cus-login-2-col .slider-info {
    width: 100%;
    max-width: 500px;
    text-align: center;
}

/* Sized for the 4:3 landscape artwork (viewBox 330 x 247.5). The earlier caps
   were tuned for a 277x483 portrait asset, where max-width never bound; here it
   binds first and was rendering the art at two-thirds size. Width now roughly
   matches the tagline's measure so the two read as one block, and the height cap
   is the 4:3 equivalent so it still never dictates the size. */
.cus-login-2-col .slider-info figure img {
    width: 100%;
    max-width: 420px;
    max-height: 315px;
}

.cus-login-2-col .slider-info figure {
    margin-bottom: 32px;
}

/* The tagline has to carry the panel now that the artwork is smaller. */
.cus-login-2-col .slider-info h3 {
    color: var(--white);
    font-size: 26px;
    line-height: 1.35;
    letter-spacing: -0.01em;
}

.cus-login-2-col .col-left {
    width: 50%;
    height: 100vh;
    /* Clips the drifting wave layer, which is one tile wider than this panel. */
    overflow: hidden;
    /* Was #f3f3f3 against a #fafafa right panel — seven values apart, so the
       split-screen produced no contrast and the page carried no brand at all.
       --bg-dark-login exists for exactly this but is scoped to .cus-login,
       which this layout does not use. */
    background: var(--primary-color);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    position: fixed;
    top: 0;
    left: 0;
    padding: 0;
}

.cus-login-2-col .col-right {
    width: 50%;
    height: 100vh;
    float: right;
    position: relative;
    display: table;
    padding: 20px 35px;
    overflow: hidden;
}

.cus-login-2-col .cus-login-container {
    height: 100%;
    display: table-cell;
    vertical-align: middle;
    padding: 20px;
    text-align: center;
}

.cus-login-2-col .cus-login-box {
    display: inline-block;
    text-align: left;
}

.cus-login-box .logo-login img {
    max-height: 65px;
}

/* The card sat white-on-#fafafa with a directionless `0 0 8px` halo, so it did
   not read as a surface at all. */
.cus-login-box .cus-card {
    box-shadow: var(--wl-elev-2);
}

.cus-login-box .cus-card .cus-card-body {
    padding-bottom: 2rem;
}

/* A 140px centred pill under 354px fields left the form with no resolved width.
   Full-width ties the CTA to the fields it submits. */
/* Vertical padding is zero here, not 11px. This rule is (0,3,0) so it outranks
   the (0,1,0) .btn reset that zeroes padding for the height scale — leaving it
   at 11px meant 40px of button minus 22px padding and 4px borders left a 14px
   box holding a 36px line, and the label dropped to the floor of the button. */
.cus-login-box .btn.btn-primary {
    width: 100%;
    padding-top: 0;
    padding-bottom: 0;
    font-weight: 600;
}

/* The lowercase + ::first-letter trick that used to sentence-case "LOGIN" is
   gone. Two reasons: ::first-letter only applies to block containers, so it
   stopped working the moment buttons became inline-flex for centring — and it
   was silently lowercasing every other button in this box, which is how the
   404 page's CTA came out as "go to dashboard". On this branch the markup is
   editable, so the labels are sentence case at source instead. */

/* Centred, this sat directly between the password field and the CTA and competed
   with the primary action. Bootstrap's .text-center carries !important. */
.cus-login-box .form-group.text-center.my-1 {
    text-align: right !important;
}

.cus-login-box .form-group.text-center.my-1 p {
    margin-bottom: 0;
    font-size: 13px;
}

/* Links are wrapped in <u> in the markup, giving a default browser underline.
   We cannot remove the tag, but we can make it behave. */
.cus-login-box a u {
    text-decoration: none;
    border-bottom: 1px solid var(--wl-focus-ring);
    padding-bottom: 1px;
    transition: border-color .15s ease;
}

.cus-login-box a:hover u {
    border-bottom-color: var(--secondary-color);
}

/* :not(.btn) for the same reason the global link hover needs it — a filled
   button inside this box already has its own foreground. Without it, the 404
   page's indigo CTA got indigo text and the label disappeared. */
.cus-login-box a:not(.btn):not(.primaryBtn) {
    color: var(--secondary-color);
}


@media screen and (max-width: 991px) {
    .cus-login-2-col .col-left {
        display: none;
    }

    .cus-login-2-col .col-right {
        width: 100%;
        padding: 0;
    }

    /* The dark panel is hidden below this breakpoint, so the whole viewport is
       the light ground — the two-tone gradient would otherwise put the dark
       side's 32% indigo straight onto #fafafa. */
    .cus-login-2-col::after {
        background-image: none;
        background-color: var(--wl-wave-on-light);
    }
}

/* ==========================================================================
   Reduced motion
   Must come last: this only overrides the wave animation if it is declared
   after it. Placed earlier in the file, the later `animation` shorthand simply
   wins and the guard silently does nothing.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    .cus-login-2-col::after,
    .cus-login-2-col .col-left::before {
        animation: none;
    }
}
