
/* ===========================================================================
   FIX LAYER - table integrity + phone layout
   Rendered after the page body, so it is the last stylesheet in the document.
   Problem 1: rows bleeding through the header band.
     A sticky <th> that paints no background of its own is transparent, so the
     rows scroll straight through it and the header and the data underneath
     read as one smeared line. Two things cause it and both are handled here:
     transparent header cells, and headers pinned against the page instead of
     against a scroll box (a table wrapped in a box with no height cap has
     nothing to pin to, so the header travels down the page over the rows).
   Problem 2: phones.
     Wide data tables become stacked cards, every page reserves the strip the
     hamburger floats in, and the dashboard header stops fighting its button.
   ========================================================================== */
/* -- 1 - table integrity: no transparency anywhere ----------------------- */
/* One solid palette for every table in the app. These are flat hex values on
   purpose: the old table colours were rgba() and color-mix(..., transparent)
   tints, which let the page background read through the cells and through the
   header band. Nothing below has an alpha channel, so nothing shows through. */
:root {
  --tbl-bg:    #141613;   /* row surface            */
  --tbl-alt:   #191c17;   /* zebra row              */
  --tbl-head:  #20241b;   /* header band            */
  --tbl-hover: #262a20;   /* row under the cursor   */
  --tbl-sel:   #2e2f18;   /* selected / active row  */
  --tbl-line:  #33362d;   /* cell rule              */
  --tbl-line2: #4a4e40;   /* header rule            */
}
:root[data-theme="light"] {
  --tbl-bg:    #ffffff;
  --tbl-alt:   #f7f7f7;
  --tbl-head:  #ececec;
  --tbl-hover: #f0f2f5;
  --tbl-sel:   #fbeed2;
  --tbl-line:  #dcdcdc;
  --tbl-line2: #c9ccd2;
}
/* sticky cells need separate borders: under border-collapse:collapse the
   header's bottom edge belongs to the table rather than the cell, so it
   scrolls away and the pinned row looks merged into the body. Every table in
   this app draws with border-bottom only, so nothing doubles up. */
table { border-collapse: separate; border-spacing: 0; }
/* the box the table scrolls in is solid, so the page can't show through the
   gaps between cells either */
.tscroll, .hist-scroll, .fl-wrap, .mt-table-wrap, .vi-table-wrap,
.scrollbox, .ys-tbox {
  background-color: var(--tbl-bg) !important;
  background-image: none !important;
}
table { background-color: var(--tbl-bg) !important; background-image: none !important; }
/* the header band - opaque, and painting its own bottom rule so the edge
   travels with it while it is pinned */
table > thead > tr > th {
  background-color: var(--tbl-head) !important;
  background-image: none !important;
  background-clip: padding-box;
  border-bottom: 1px solid var(--tbl-line2) !important;
}
/* body cells - opaque, including the zebra and the hover state, which used to
   be rgba() tints over whatever happened to be behind them */
table > tbody > tr > td,
table > tbody > tr > th {
  background-color: var(--tbl-bg) !important;
  background-image: none !important;
  background-clip: padding-box;
  border-bottom-color: var(--tbl-line) !important;
}
table > tbody > tr:nth-child(even) > td { background-color: var(--tbl-alt) !important; }
table > tbody > tr:hover > td          { background-color: var(--tbl-hover) !important; }
/* rows that mean something keep their own solid tone */
.vi-asset-grp > td,
.fl-drawer > td                 { background-color: var(--tbl-head) !important; }
.vi-asset-grp:hover > td        { background-color: var(--tbl-hover) !important; }
table.fl tr.sel > td,
.hist-active > td,
.mt-row.is-active > td          { background-color: var(--tbl-sel) !important; }
.mt-row:focus-within > td       { background-color: var(--tbl-hover) !important; }
/* position:sticky on <thead> or <tr> is ignored by several engines, so the
   cells are the single source of truth for pinning - and nothing is pinned
   unless it sits in a box that actually scrolls vertically. */
table > thead,
table > thead > tr { position: static !important; }
table > thead > tr > th { position: static !important; }
/* the boxes that do cap their height keep a pinned header */
.hist-scroll thead th,
.fl-wrap thead th,
.mt-table-wrap thead th,
.vi-table-wrap thead th,
.scrollbox thead th,
.ys-tbox thead th {
  position: sticky !important;
  top: 0 !important;
  z-index: 30 !important;
  box-shadow: 0 1px 0 var(--tbl-line2);
}
/* the feeds table scrolled the whole page, which is exactly why its header
   had nothing to pin to - give it the bounded box the other tables have */
.vi-table-wrap {
  max-height: min(70vh,620px);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
/* each scroll box is its own stacking context, so a chip or a hover state
   inside a cell can never paint over the pinned header */
.tscroll, .hist-scroll, .fl-wrap, .mt-table-wrap, .vi-table-wrap,
.scrollbox, .ys-tbox { isolation: isolate; }
/* -- 1b - form fields: solid, legible, predictably sized ----------------- */
/* The filter inputs were inheriting size and alignment from four different
   layers, and their background was color-mix(var(--bg3) 70%, transparent), so
   the page read through the field and the value sat wherever the last rule
   left it. Everything a text field needs is pinned here instead. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
textarea {
  font-family: var(--fm) !important;
  font-size: 14px !important;
  line-height: 20px !important;
  height: auto !important;
  min-height: 40px;
  padding: 9px 13px !important;
  box-sizing: border-box !important;
  color: var(--text) !important;
  -webkit-text-fill-color: var(--text) !important;
  caret-color: var(--acc,#ffd400);
  background-color: var(--bg3) !important;
  background-image: none !important;
  vertical-align: middle;
  text-align: left;
}
textarea { min-height: 88px; line-height: 1.5 !important; }
/* selects keep their own arrow, so only colour and size are pinned */
select {
  font-family: var(--fm) !important;
  font-size: 14px !important;
  line-height: 20px !important;
  min-height: 40px;
  box-sizing: border-box !important;
  color: var(--text) !important;
  background-color: var(--bg3) !important;
}
::placeholder { color: var(--muted) !important; opacity: 1; }
/* search fields render a UA clear button that overlaps the value in some
   browsers, and the focus ring was thick enough to eat into the field */
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
input:focus, select:focus, textarea:focus {
  box-shadow: 0 0 0 2px var(--acc,#ffd400) !important;
  border-color: var(--acc,#ffd400) !important;
}
/* The sign-in fields are white boxes with dark text. The rule above carries a
   five-deep :not() chain, which out-specifies a plain ".auth-box input", so
   its -webkit-text-fill-color was painting the typed credentials white on
   white. The same chain is repeated here to win the comparison. */
.auth-box input, .field input,
.auth-box input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
.field input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]) {
  background-color: #ffffff !important;
  background-image: none !important;
  color: #0d1426 !important;
  -webkit-text-fill-color: #0d1426 !important;
  caret-color: #0d1426 !important;
  opacity: 1 !important;
}
.auth-box input::placeholder, .field input::placeholder {
  color: #94a3b8 !important;
  -webkit-text-fill-color: #94a3b8 !important;
  opacity: 1 !important;
}
/* the browser's own autofill styling paints over both of the above */
.auth-box input:-webkit-autofill, .field input:-webkit-autofill,
.auth-box input:-webkit-autofill:hover, .field input:-webkit-autofill:hover,
.auth-box input:-webkit-autofill:focus, .field input:-webkit-autofill:focus,
.auth-box input:-webkit-autofill:active, .field input:-webkit-autofill:active {
  -webkit-text-fill-color: #0d1426 !important;
  -webkit-box-shadow: 0 0 0 1000px #ffffff inset !important;
  caret-color: #0d1426 !important;
}
/* 16px is the threshold below which iOS Safari zooms the page on focus */
@media (max-width: 620px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
  select, textarea {
    font-size: 16px !important;
    line-height: 22px !important;
    min-height: 44px;
  }
}
/* -- 1c - cells hold their own column ----------------------------------- */
/* .vi-chip is white-space:nowrap, which is what CVSS / EPSS / KEV want and
   the opposite of what a long product name wants. Under table-layout:fixed
   the cell cannot grow to fit it, so the chip ran across SEVERITY and
   DESCRIPTION. The severity chips keep nowrap; the product chip wraps. */
.vi-table td.vi-prod { vertical-align: top; }
.vi-table td.vi-prod .vi-chip {
  display: inline-block;
  max-width: 100%;
  white-space: normal !important;
  overflow-wrap: anywhere;
  word-break: break-word;
  line-height: 1.45;
  text-align: left;
  border-radius: 8px;
  padding: 3px 9px;
}
.vi-table .vi-sev-cell .vi-chip { white-space: nowrap; }
/* A <td> declared display:flex stops being a table cell. The table then wraps
   it in an anonymous cell, and the row background - which lives on the td -
   only covers the flex box's own content height instead of the full row. That
   is the mismatched block behind the severity column. Cells stay cells; the
   chips inside lay out inline. */
table > tbody > tr > td,
table > thead > tr > th { display: table-cell !important; }
.vi-table td.vi-sev-cell { vertical-align: top; }
.vi-table td.vi-sev-cell .vi-sev-chips { display: inline !important; }
.vi-table td.vi-sev-cell .vi-sev,
.vi-table td.vi-sev-cell .vi-chip {
  display: inline-block;
  vertical-align: middle;
  margin: 0 4px 4px 0;
}
/* nothing may paint outside its own cell */
.vi-table td, .vi-table th { overflow: hidden; }
.vi-table td { vertical-align: top; }
.vi-table td > *, .vi-table td span, .vi-table td a { max-width: 100%; }
.vi-desc { overflow-wrap: anywhere; }
/* the description column carries the weight, so give it the room and take it
   back off the two columns that only ever hold short values */
.vi-table th:nth-child(2) { width: 16%; }
.vi-table th:nth-child(3) { width: 17%; }
.vi-table th:nth-child(4) { width: 34%; }
/* -- 1d - the filter field's own text ------------------------------------ */
/* the value and the placeholder were both inheriting a colour that lost
   against the field background */
.vf-search, #vf-q, input[type="search"] {
  color: var(--text) !important;
  -webkit-text-fill-color: var(--text) !important;
  opacity: 1 !important;
  text-overflow: ellipsis;
}
.vf-search::placeholder, #vf-q::placeholder, input::placeholder, textarea::placeholder {
  color: var(--muted) !important;
  -webkit-text-fill-color: var(--muted) !important;
  opacity: 1 !important;
}
/* -- 2 - phone: the hamburger strip -------------------------------------- */
@media (max-width: 1000px) {
  /* the burger floats top-left over the content. Only .wrap / .fpage pages
     reserved room for it, so pages built from a bare div - the dashboard
     among them - had their title sitting underneath the button. */
  .has-sb { padding-top: 54px; padding-bottom: env(safe-area-inset-bottom,0px); }
  .has-sb .wrap, .has-sb .fpage { padding-top: 0; }
}
/* -- 3 - phone: page furniture ------------------------------------------- */
@media (max-width: 820px) {
  /* FINDINGS ▸ filter rows: the findings template already sends .fl-flabel
     full-width at this breakpoint, but the row it lives in was never allowed
     to wrap - the label took the whole line and the chips row was squeezed
     to zero width. Wrapping is a no-op on desktop, where the 96px label and
     the chips fit on one line anyway. */
  .fl-fbox { flex-wrap: wrap; }
  .fl-fbtns { flex: 0 0 auto; }
  .fl-chips { flex: 1 1 100%; min-width: 0; }
}
@media (max-width: 760px) {
  .ys-pagehead { flex-wrap: wrap; gap: 10px; padding: 12px 14px 10px !important; }
  .ys-pagehead > div:last-child { width: 100%; }
  .ys-pagehead > div:last-child > a,
  .ys-pagehead > div:last-child > button { flex: 1; justify-content: center; text-align: center; }
  .ys-dashbody { padding-left: 12px !important; padding-right: 12px !important; }
  /* headline blocks are letterspaced for a wide screen and shred on a phone */
  .ys-pagehead [style*="letter-spacing:.1em"] { letter-spacing: .04em !important; line-height: 1.45; }
  .vi-tabs { overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; padding: 4px; }
  .vi-tabs::-webkit-scrollbar { display: none; }
  .vi-tab { padding: 9px 13px; white-space: nowrap; font-size: 12px; }
  .vi-head, .vf-bar, .fnd-controls, .rw-filters { flex-wrap: wrap; }
  .vf-search { flex: 1 1 100%; min-width: 0; }
  .vf-sel { flex: 1 1 46%; min-width: 0; }
  .vf-clear { flex: 1 1 46%; }
  .vf-count { flex: 1 1 100%; }
  .vi-views { gap: 6px; }
  .vi-view { flex: 1 1 46%; min-width: 0; text-align: center; }
  .vi-view-note, .vi-scope { flex: 1 1 100%; font-size: 10.5px; }
  .vi-kpis { grid-template-columns: repeat(2,minmax(0,1fr)) !important; gap: 8px; }
  .vi-srcs { gap: 5px; }
  .card, .vi-table-wrap { border-radius: 10px; }
  /* charts are drawn at a desktop size and overflow their card */
  .chc, .dash-card, .fpanel, .sf-card { min-width: 0; }
  canvas { max-width: 100%; }
  .donut { justify-content: center; }
  .donut svg { max-width: 100%; height: auto; }
  /* ATTACK PATHS ▸ node chips ellipsize the value behind a title tooltip on
     desktop, which a phone user can't hover. Let the value wrap instead. */
  .ap-chip strong {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    max-width: 100%;
    overflow-wrap: anywhere;
  }
  /* Reports ▸ hero: 26px paddings eat a third of a phone's width and
     the gradient headline can shed a few pixels off its last word */
  .ev-hero { padding: 18px 16px !important; }
  .ev-hero-title, .ev-hero-sub { overflow-wrap: anywhere; }
}
/* -- 4 - phone: wide tables become stacked cards ------------------------- */
/* Swiping a 1180px-wide table sideways through a 380px window is unusable, so
   each row is redrawn as a card with the column name in front of its value.
   The script below tags the cells. Tables that merge cells are left
   scrollable, because a card view of them would file values under the wrong
   labels. */
@media (max-width: 900px) {
  .ys-cards {
    max-height: none !important;
    height: auto !important;
    overflow: visible !important;
    border: 0 !important;
    background: transparent !important;
  }
  .ys-cards table {
    display: block;
    width: 100% !important;
    min-width: 0 !important;
    table-layout: auto !important;
  }
  .ys-cards thead { display: none; }
  .ys-cards tbody { display: block; }
  .ys-cards tbody tr {
    display: block;
    margin: 0 0 10px;
    overflow: hidden;
    border: 1px solid var(--tbl-line2);
    border-radius: 10px;
    background-color: var(--tbl-bg);
  }
  .ys-cards tbody td { border-top-color: var(--tbl-line) !important; }
  .ys-cards tbody td {
    display: flex !important;
    /* Without wrapping, every chip in a cell becomes a flex item sharing one
       line and gets shrunk to a single character column. The label keeps its
       own fixed share; the values wrap underneath it when there are many. */
    flex-wrap: wrap;
    gap: 6px 10px;
    align-items: flex-start;
    width: auto !important;
    padding: 8px 12px !important;
    border: 0 !important;
    border-top: 1px solid var(--border,#26262c) !important;
    white-space: normal !important;
    overflow-wrap: anywhere;
  }
  .ys-cards tbody tr > td:first-child { border-top: 0 !important; }
  .ys-cards tbody td > * { flex: 0 0 auto; max-width: 100%; }
  .ys-cards tbody td::before {
    content: attr(data-th);
    flex: 0 0 38%;
    max-width: 38%;
    padding-top: 3px;
    font-family: var(--fm);
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: .09em;
    text-transform: uppercase;
    line-height: 1.35;
    color: var(--muted,#8a8a95);
  }
  /* spanning cells - group headers, empty states - stay full width */
  .ys-cards tbody td:not([data-th]) { display: block !important; }
  .ys-cards tbody td[data-th=""]::before { display: none; }
  .ys-cards .vi-sev-chips, .ys-cards .fl-attrs { flex-wrap: wrap; }
  /* the target view hides collapsed rows with display:none and reopens
     them as display:table-row, which would break out of the card flow */
  .ys-cards .vi-asset-tb.open .vf-row { display: block; }
  .ys-cards .vi-table td.vi-prod .vi-chip { max-width: 100%; }
  .ys-cards .vi-table td, .ys-cards .vi-table th { overflow: visible; }
  .ys-cards .vi-table td.vi-sev-cell { display: flex !important; }
  .ys-cards .fl-fam, .ys-cards .fl-loc, .ys-cards .fl-attrs,
  .ys-cards .ap-td-path { max-width: none; }
  /* tables that stay scrollable get a visible edge so the swipe is findable */
  .tscroll:not(.ys-cards), .hist-scroll:not(.ys-cards),
  .fl-wrap:not(.ys-cards), .mt-table-wrap:not(.ys-cards),
  .vi-table-wrap:not(.ys-cards), .ys-tbox:not(.ys-cards) {
    -webkit-overflow-scrolling: touch;
    border-right: 2px solid var(--acc,#ffd400);
  }
}
/* ===========================================================================
   MOBILE READABILITY - the shell pins body to 13px globally, which is
   cramped on a phone. From here down, phones get a real reading size,
   proportionate headings and tighter cards so more content fits per screen.
   Rendered last, so these !important rules win the cascade. */
@media (max-width: 620px) {
  body, :root[data-theme="light"] body {
    font-size: 16px !important;
    line-height: 1.55 !important;
  }
  h1, .fhead { font-size: 23px !important; }
  h2 { font-size: 19px !important; }
  h3 { font-size: 16px !important; }
  h4 { font-size: 15px !important; }
  /* denser cards: less chrome, more data per screen */
  .fpanel, .panel, .card {
    padding: 12px !important;
    margin-bottom: 12px !important;
  }
  .fhead, .panel-label, .card-title { letter-spacing: .04em !important; }
  /* panel intros and helper text stay legible */
  .fsub, .chc-s, .pm-drv, .hbar-h span {
    font-size: 12.5px !important;
  }
  /* KPI numbers keep their weight but fit narrower cards */
  .fc3d .v, .chc-v { overflow-wrap: anywhere; }
}
