/* ==========================================================================
   theme.css — Insights design tokens + base UI layer
   --------------------------------------------------------------------------
   Skin-safe by design: the customer's white-label brand colour (exposed by
   /white_label/custom.css as --wl-primary / --wl-secondary / --wl-accent) is
   confined to ACCENT roles only — buttons, active nav, links, chart series.
   Surfaces, text and the UI font are FIXED neutrals, so a bold brand colour
   can never recolour the whole UI or clash. New components use the .ins-*
   namespace so they layer on top of the existing pages without clobbering them.
   ========================================================================== */

:root {
    /* --- Brand accent (driven by white-label; falls back to Insights defaults) --- */
    --ins-brand:      var(--wl-primary, #002245);
    --ins-brand-2:    var(--wl-secondary, #0066cc);
    --ins-accent:     var(--wl-accent, #ff6b35);
    --ins-on-brand:   var(--wl-btn-text, #ffffff);

    /* --- Neutral surfaces & text (FIXED — never skinned, so they can't clash) --- */
    --ins-bg:          #f4f6f9;   /* app background          */
    --ins-surface:     #ffffff;   /* cards / panels          */
    --ins-surface-2:   #f8fafc;   /* subtle alt rows / wells */
    --ins-border:      #e4e8ee;
    --ins-border-strong: #c3ccd8;   /* clearer card/panel outline */
    --ins-text:        #1f2733;   /* primary text (AA on white) */
    --ins-text-muted:  #5b6675;
    --ins-text-subtle: #8a94a3;

    /* --- Semantic status palette (fixed) --- */
    --ins-success: #1f9d57;
    --ins-warning: #d98a00;
    --ins-danger:  #d23f3f;
    --ins-info:    #2b7cd3;

    /* Hyperlink colour (paler in dark mode — see the dark block) */
    --ins-link:    #0a58ca;

    /* --- Chart series palette (brand-led, recolours with the skin) --- */
    --ins-chart-1: var(--ins-brand-2);
    --ins-chart-2: var(--ins-accent);
    --ins-chart-3: #1f9d57;
    --ins-chart-4: #8b5cf6;
    --ins-chart-5: #d98a00;
    --ins-chart-6: #0ea5b7;

    /* --- Typography: IBM Plex (refined, open-source; a deliberate nod to RedHat/IBM)
       for all UI; brand font reserved for the wordmark only. System stack as fallback. --- */
    --ins-font-ui:    "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", sans-serif;
    --ins-font-brand: var(--font-family, var(--ins-font-ui));
    --ins-font-mono:  "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* --- Shape & elevation --- */
    --ins-radius:    10px;
    --ins-radius-sm: 6px;
    --ins-shadow-sm: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .10);
    --ins-shadow:    0 4px 14px rgba(16, 24, 40, .08);
    --ins-space:     1rem;

    /* --- Muted palette (IN-1145, from Jira Agile's IN-1084): mid-tone colours
       drawn see-through so they read as pale, with a crisp edge in the full
       colour and the page's own text on top. Shared so every plugin uses one
       palette. Colours are r, g, b so they work in rgb()/rgba(). Never brown,
       ochre or olive. Risk colours are the Platform Security gauge's. --- */
    --ins-muted-alpha:  0.55;             /* fills: paler in light mode     */
    --ins-pill-alpha:   0.22;             /* pills and headers: paler still */
    --ins-muted-blue:   110, 155, 209;
    --ins-muted-green:  111, 175, 131;
    --ins-muted-purple: 156, 139, 201;
    --ins-muted-teal:   95, 175, 174;
    --ins-muted-rose:   208, 112, 122;
    --ins-muted-slate:  148, 163, 184;
    --ins-risk-high:    240, 62, 62;      /* #F03E3E */
    --ins-risk-review:  254, 182, 49;     /* #FEB631 */
    --ins-risk-safe:    48, 179, 45;      /* #30B32D */
}

/* --------------------------------------------------------------------------
   Dark mode — flips ONLY the neutral tokens (surfaces/text/border). Brand
   accent tokens stay (driven by white-label), so the skin still owns accents
   and dark mode can't clash. Toggled via [data-theme="dark"] on <html> by the
   navbar sun/moon switch (persisted in localStorage; applied before paint).
   -------------------------------------------------------------------------- */
:root[data-theme="dark"] {
    --ins-bg:          #0f141a;
    --ins-surface:     #1a212b;
    --ins-surface-2:   #232c38;
    --ins-border:      #2c3743;
    --ins-border-strong: #45525f;   /* clearer card/panel outline */
    --ins-text:        #e7ecf2;
    --ins-text-muted:  #9fb0c0;
    --ins-text-subtle: #74859a;
    --ins-link:        #6cb2ff;   /* paler so links read easily on the dark surface */
    --ins-shadow-sm:   0 1px 2px rgba(0, 0, 0, .35);
    --ins-shadow:      0 6px 18px rgba(0, 0, 0, .45);
    /* More see-through on dark, so light text on a muted fill keeps 5:1+ */
    --ins-muted-alpha: 0.4;
    --ins-pill-alpha:  0.28;
}
/* Higher specificity than default.css `body { background:#fafafa }`. */
:root[data-theme="dark"] body {
    background-color: var(--ins-bg);
    color: var(--ins-text);
}
/* The white-label CSS forces `#content h1,h2,h3 { color: <primary navy> }` with
   ID specificity — fine on white, unreadable navy-on-dark. Beat it in dark mode. */
:root[data-theme="dark"] #content h1,
:root[data-theme="dark"] #content h2,
:root[data-theme="dark"] #content h3 {
    color: var(--ins-text);
}

/* Legacy/shared components that hardcode light colours — flip them in dark mode
   so pages built before the token system still look coherent. */
:root[data-theme="dark"] .card,
:root[data-theme="dark"] .modal-content,
:root[data-theme="dark"] .dropdown-menu,
:root[data-theme="dark"] .list-group-item {
    background-color: var(--ins-surface);
    color: var(--ins-text);
    border-color: var(--ins-border);
}
:root[data-theme="dark"] .modal-header,
:root[data-theme="dark"] .modal-footer { border-color: var(--ins-border); }

:root[data-theme="dark"] .table,
:root[data-theme="dark"] .table td,
:root[data-theme="dark"] .table th {
    color: var(--ins-text);
    border-color: var(--ins-border) !important;
    background-color: transparent;
}
:root[data-theme="dark"] .table th { background-color: var(--ins-surface-2) !important; }
:root[data-theme="dark"] .table tbody tr:hover,
:root[data-theme="dark"] .table tr:hover { background-color: var(--ins-surface-2) !important; }

:root[data-theme="dark"] .form-control,
:root[data-theme="dark"] .form-select,
:root[data-theme="dark"] select,
:root[data-theme="dark"] textarea,
:root[data-theme="dark"] input[type="text"],
:root[data-theme="dark"] input[type="email"],
:root[data-theme="dark"] input[type="password"],
:root[data-theme="dark"] input[type="search"],
:root[data-theme="dark"] input[type="number"] {
    background-color: var(--ins-surface-2);
    color: var(--ins-text);
    border-color: var(--ins-border);
}
:root[data-theme="dark"] .form-control::placeholder { color: var(--ins-text-subtle); }
:root[data-theme="dark"] .form-control:focus,
:root[data-theme="dark"] select:focus,
:root[data-theme="dark"] textarea:focus { background-color: var(--ins-surface-2); color: var(--ins-text); }

:root[data-theme="dark"] .dropdown-item { color: var(--ins-text); }
:root[data-theme="dark"] .dropdown-item:hover,
:root[data-theme="dark"] .dropdown-item:focus { background-color: var(--ins-surface-2); color: var(--ins-text); }

:root[data-theme="dark"] hr { border-color: var(--ins-border); }
:root[data-theme="dark"] .text-muted { color: var(--ins-text-muted) !important; }

/* Plugins' loading overlays hardcode a near-white box (inline rgba(250,250,250))
   around loading.gif. :has() lets us re-skin those boxes in dark mode centrally,
   without touching each plugin's template. */
:root[data-theme="dark"] div:has(> img[src*="loading.gif"]) {
    background: var(--ins-surface) !important;
    box-shadow: var(--ins-shadow) !important;
}

/* DataTables controls + pagination. Plugins' data tables (AWS, Jira, …) render
   pagination via DataTables, which ships light-theme styling (blue links on a
   white box) that ignores our tokens — so re-skin it centrally in dark mode.
   Covers both the DataTables-default markup (.paginate_button) and the
   Bootstrap-paginated markup (.page-link / .page-item). */
:root[data-theme="dark"] .dataTables_wrapper,
:root[data-theme="dark"] .dataTables_length,
:root[data-theme="dark"] .dataTables_filter,
:root[data-theme="dark"] .dataTables_info,
:root[data-theme="dark"] .dataTables_paginate { color: var(--ins-text); }

:root[data-theme="dark"] .paginate_button,
:root[data-theme="dark"] .dataTables_paginate .paginate_button,
:root[data-theme="dark"] .page-link {
    background-color: var(--ins-surface) !important;
    color: var(--ins-text) !important;
    border-color: var(--ins-border) !important;
}
:root[data-theme="dark"] .page-item { background-color: transparent; }
:root[data-theme="dark"] .paginate_button:hover,
:root[data-theme="dark"] .page-link:hover {
    background-color: var(--ins-surface-2) !important;
    color: var(--ins-text) !important;
}
:root[data-theme="dark"] .paginate_button.current,
:root[data-theme="dark"] .paginate_button.active,
:root[data-theme="dark"] .page-item.active .page-link {
    background-color: var(--ins-brand-2) !important;
    color: var(--ins-on-brand) !important;
    border-color: var(--ins-brand-2) !important;
}
:root[data-theme="dark"] .paginate_button.disabled,
:root[data-theme="dark"] .paginate_button.disabled:hover,
:root[data-theme="dark"] .page-item.disabled .page-link {
    color: var(--ins-text-subtle) !important;
    background-color: var(--ins-surface) !important;
}

/* Outline buttons (table length/filter controls, etc.) — Bootstrap's defaults
   sit on a light assumption; give them token text/border so they read on dark. */
:root[data-theme="dark"] .btn-outline-secondary {
    color: var(--ins-text);
    border-color: var(--ins-border);
}
:root[data-theme="dark"] .btn-outline-secondary:hover {
    background-color: var(--ins-surface-2);
    color: var(--ins-text);
    border-color: var(--ins-border);
}

/* Nav-pills / nav-tabs used as in-page view switchers (e.g. AWS Security /
   Services / EC2 / S3). The app mixes Bootstrap 3 (.nav-pills > li > a) and
   Bootstrap 4/5 (.nav-link), and neither themes the INACTIVE pill in dark mode
   (it stays white with blue link text), so cover both markups explicitly. */
:root[data-theme="dark"] .nav-pills .nav-link,
:root[data-theme="dark"] .nav-pills > li > a,
:root[data-theme="dark"] .nav-tabs .nav-link {
    color: var(--ins-text) !important;
    background-color: var(--ins-surface) !important;
}
:root[data-theme="dark"] .nav-pills .nav-link:hover,
:root[data-theme="dark"] .nav-pills > li > a:hover,
:root[data-theme="dark"] .nav-tabs .nav-link:hover {
    background-color: var(--ins-surface-2) !important;
    color: var(--ins-text) !important;
}
:root[data-theme="dark"] .nav-pills .nav-link.active,
:root[data-theme="dark"] .nav-pills > li.active > a,
:root[data-theme="dark"] .nav-pills > li > a.active {
    background-color: var(--ins-brand-2) !important;
    color: var(--ins-on-brand) !important;
}
:root[data-theme="dark"] .nav-item.border { border-color: var(--ins-border) !important; }

/* --------------------------------------------------------------------------
   Base typography — replaces the global decorator font on body text.
   (The brand/display font stays on .matura-font / the wordmark only.)
   -------------------------------------------------------------------------- */
body {
    font-family: var(--ins-font-ui);
    color: var(--ins-text);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--ins-font-ui);
    color: var(--ins-text);
    font-weight: 600;
    letter-spacing: -0.01em;
}

code, pre, kbd, samp {
    font-family: var(--ins-font-mono);
}

/* --------------------------------------------------------------------------
   Reusable .ins-* component primitives (used by the new dashboard + can be
   adopted by existing pages incrementally).
   -------------------------------------------------------------------------- */

/* Card */
.ins-card {
    background: var(--ins-surface);
    border: 1px solid var(--ins-border);
    border-radius: var(--ins-radius);
    box-shadow: var(--ins-shadow-sm);
    padding: 1.25rem 1.25rem;
}
.ins-card__title {
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ins-text-muted);
    margin: 0 0 0.5rem;
}

/* Metric / stat */
.ins-metric__value {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--ins-text);
}
.ins-metric__delta {
    font-size: 0.85rem;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}
.ins-metric__delta--up   { color: var(--ins-success); }
.ins-metric__delta--down { color: var(--ins-danger); }
.ins-metric__delta--flat { color: var(--ins-text-subtle); }

/* Empty / loading states (graceful, not bare) */
.ins-empty,
.ins-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    text-align: center;
    color: var(--ins-text-subtle);
    padding: 2rem 1rem;
}
.ins-empty .fa,
.ins-empty .fas { font-size: 1.75rem; opacity: 0.5; }

.ins-spinner {
    width: 1.5rem;
    height: 1.5rem;
    border: 3px solid var(--ins-border);
    border-top-color: var(--ins-brand-2);
    border-radius: 50%;
    animation: ins-spin 0.7s linear infinite;
}
@keyframes ins-spin { to { transform: rotate(360deg); } }

/* Shared loading spinner for the app AND every plugin — one source of truth, so
   any change here propagates everywhere (token-driven, so it's automatically
   theme- and skin-aware). Replaces the per-plugin loading.gif boxes. Markup:
       <div class="ins-loading-overlay"><div class="ins-spinner"></div></div>
   Add .ins-loading-overlay--fixed for a centred, full-view overlay. */
.ins-loading-overlay {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .75rem;
    padding: 1.5rem;
    background: var(--ins-surface);
    border: 1px solid var(--ins-border);
    border-radius: var(--ins-radius);
    box-shadow: var(--ins-shadow-sm);
}
.ins-loading-overlay--fixed {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 9999;
}
.ins-loading-overlay--lg .ins-spinner { width: 2.75rem; height: 2.75rem; border-width: 4px; }

/* Dark mode: a few plugin logos are near-black monochrome (the GitHub mark; the
   LangSmith filled pill), so they disappear against the dark background. Invert
   just those to light — targeted by icon filename so coloured plugin logos are
   untouched. Applies wherever the icon renders (home page + plugins page). */
:root[data-theme="dark"] img[src*="github_insight_icon"],
:root[data-theme="dark"] img[src*="langsmith_insight_icon"] {
    filter: invert(1);
}

/* Dark mode: AWS + SonarQube logos are coloured but include near-black elements
   (the "aws" wordmark; the "Sonar" text) that vanish on dark. Inverting would
   wreck the brand colours, so sit them on a subtle light chip instead — keeps the
   colours and makes the dark parts legible. */
:root[data-theme="dark"] img[src*="aws_insight_icon"],
:root[data-theme="dark"] img[src*="sonarqube_insight_icon"] {
    background: #f6f7f9;
    border-radius: 6px;
    padding: 4px 6px;
}

/* Dark mode: lighten plain text links (default link blue is too dark to read on
   the dark surface). Only links WITHOUT a class: a styled link (badge, button,
   chip, nav item, card) carries its own colours, which this must not override
   (IN-1023 — it turned clickable badges pale blue on red/amber). */
:root[data-theme="dark"] a:not([class]) {
    color: var(--ins-link);
}
:root[data-theme="dark"] a:not([class]):hover {
    color: #93c5ff;
}

/* --------------------------------------------------------------------------
   Tables on a phone (IN-1140). Add `ins-table-stack` to a wide table and a
   `data-label` to each cell: below 768px each row becomes a card with every
   value labelled, instead of a grid that scrolls sideways. Desktop is
   untouched. A cell with `ins-stack-title` heads its card (no label).
   `ins-hide-sm` / `ins-show-sm` swap in a shorter version of a busy cell.
   `ins-stack-lead` moves a cell up to just under the title (the value that
   matters most); `ins-stack-end` moves one to the foot (an expand button).
   Rules reach only the table's own rows (`>`), so a table nested in a detail
   row keeps its own layout. The !important beats DataTables' and the
   templates' inline widths.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
    table.ins-table-stack,
    table.ins-table-stack > tbody,
    table.ins-table-stack > tbody > tr > td {
        display: block;
        width: 100% !important;
    }
    table.ins-table-stack > tbody > tr {
        display: flex;
        flex-direction: column;
        width: 100% !important;
        background: var(--ins-surface) !important;
        border: 1px solid var(--ins-border);
        border-radius: var(--ins-radius, 8px);
        margin-bottom: 12px;
        padding: 10px 12px;
    }
    table.ins-table-stack > thead {
        display: none;
    }
    table.ins-table-stack,
    table.ins-table-stack > tbody > tr > td {
        border: none !important;
    }
    table.ins-table-stack > tbody > tr > td {
        padding: 4px 0 !important;
        text-align: left !important;
        background: transparent !important;
        overflow-wrap: anywhere;
        /* A desktop column cap (max-width) would leave the cell short of the
           card's edge; DataTables also stripes and hovers each cell with an
           inset shadow, so a short cell left a bite out of the shading.
           Cells span the card and the card carries the stripe instead. */
        max-width: none !important;
        box-shadow: none !important;
    }
    table.ins-table-stack.table-striped:not(.dataTable) > tbody > tr:nth-of-type(odd),
    table.ins-table-stack.dataTable.table-striped > tbody > tr.odd {
        box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-stripe, 0, 0, 0), 0.05);
    }
    /* The label sits on the left and the value on the right (IN-1141):
       table-stack.js gathers each cell's contents into one .ins-stack-value
       box, so a value of several pieces (bars, badges, a list) still lines up
       as one column. Without the box (script not run) the label sits above. */
    table.ins-table-stack > tbody > tr > td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: 0.8rem;
        font-weight: 600;
        color: var(--ins-text-muted);
    }
    table.ins-table-stack > tbody > tr > td[data-label]:has(> .ins-stack-value) {
        display: flex;
        align-items: baseline;
        gap: 12px;
    }
    table.ins-table-stack > tbody > tr > td[data-label]:has(> .ins-stack-value)::before {
        flex: 0 0 38%;
        max-width: 9.5rem;
    }
    table.ins-table-stack > tbody > tr > td > .ins-stack-value {
        display: block;
        flex: 1 1 auto;
        min-width: 0;
    }
    table.ins-table-stack > tbody > tr > td:empty {
        display: none;
    }
    table.ins-table-stack > tbody > tr > td.ins-stack-title {
        order: -2;
        font-size: 1.05rem;
        font-weight: 600;
        padding-bottom: 8px !important;
    }
    table.ins-table-stack > tbody > tr > td.ins-stack-lead {
        order: -1;
    }
    table.ins-table-stack > tbody > tr > td.ins-stack-end {
        order: 99;
    }
    .ins-hide-sm {
        display: none !important;
    }
}
@media (min-width: 768px) {
    .ins-show-sm {
        display: none !important;
    }
}
/* Above phone width the value box is invisible to layout: cells render exactly
   as they would without it. */
.ins-stack-value {
    display: contents;
}

/* --------------------------------------------------------------------------
   Muted pills (IN-1145): a pale see-through fill, a crisp edge in the full
   colour and the page's own text, so they read in both themes. Pick the
   colour with a modifier; ins-pill alone is neutral slate.
   -------------------------------------------------------------------------- */
.ins-pill {
    --ins-pill-rgb: var(--ins-muted-slate);
    display: inline-block;
    padding: 1px 10px;
    border: 1px solid rgb(var(--ins-pill-rgb));
    border-radius: 999px;
    background: rgba(var(--ins-pill-rgb), var(--ins-pill-alpha));
    color: var(--ins-text);
    font-size: 0.8rem;
    font-weight: 500;
    line-height: 1.5;
    white-space: nowrap;
}
.ins-pill--high   { --ins-pill-rgb: var(--ins-risk-high); }
.ins-pill--review { --ins-pill-rgb: var(--ins-risk-review); }
.ins-pill--safe   { --ins-pill-rgb: var(--ins-risk-safe); }
.ins-pill--blue   { --ins-pill-rgb: var(--ins-muted-blue); }
.ins-pill--purple { --ins-pill-rgb: var(--ins-muted-purple); }
.ins-pill--teal   { --ins-pill-rgb: var(--ins-muted-teal); }
