/* shell: generic detail-panel card/meta/pill/tool-detail base, used by
   every center-panel view (shell and ip-scanner tool alike) */
.v1-card {
  border: 0;
  background: var(--bg-elev);
  box-shadow: none;
  padding: 6px 12px 12px;
  position: relative;
  z-index: 1;
  flex: 1;
  min-width: 0;
  overflow: auto;
}

.v1-card h3 {
  margin: 0 0 8px;
  font-family: var(--font-head);
  font-size: 16px;
}

.v1-meta {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 10px;
}

.v1-pill {
  border: 0;
  padding: 7px;
  font-size: 11px;
  color: var(--txt-dim);
  background: #2b2b2e;
}

.v1-pill b {
  display: block;
  margin-top: 2px;
  color: var(--txt);
  font-size: 13px;
}

.tool-detail {
  border: 0;
  padding: 10px;
  min-width: 0;
  color: var(--txt-dim);
  font-size: 12px;
  line-height: 1.5;
  background: var(--bg-elev);
}

.tool-detail h4 {
  margin: 0 0 6px;
  color: var(--txt);
  font-size: 14px;
  font-family: var(--font-head);
}

.tool-detail ul {
  margin: 6px 0 0;
  padding-left: 18px;
}

/* shell: STYLELIST.md preview tab - one row per <input> type, label+desc on
   the left, the live element on the right. Two sections (Inputy / Inne
   style) sit side by side in a 2-column grid, with a single divider above
   both and a vertical divider between them, instead of each section having
   its own horizontal-only divider. */
.v1-stylelist-columns {
  display: grid;
  grid-template-columns: 400px 400px;
  gap: 20px;
  margin-top: 16px;
  border-top: 1px solid #3c3c3c;
  padding-top: 12px;
  align-items: start;
}

.v1-stylelist-columns-second {
  border-left: 1px solid #3c3c3c;
  padding-left: 20px;
}

.v1-stylelist-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 8px 0;
  border-bottom: 1px solid #2c2c2e;
}

.v1-stylelist-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 140px;
  min-width: 0;
}

.v1-stylelist-meta strong {
  color: var(--txt);
  font-size: 12px;
}

.v1-stylelist-meta span {
  color: var(--txt-dim);
  font-size: 11px;
}

.v1-stylelist-demo {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.v1-stylelist-demo input,
.v1-stylelist-demo select,
.v1-stylelist-demo textarea {
  font-family: var(--font-ui);
  font-size: 12px;
  color: var(--txt);
  background: #2b2b2e;
  border: 1px solid #3c3c3c;
  padding: 4px 6px;
}

.v1-stylelist-demo textarea {
  min-width: 180px;
  resize: vertical;
}

.v1-stylelist-hidden-note {
  color: var(--txt-dim);
  font-size: 11px;
  font-style: italic;
}

.v1-stylelist-scroll-v-demo {
  height: 70px;
  width: 180px;
  overflow-y: auto;
  overflow-x: hidden;
  background: #2b2b2e;
  border: 1px solid #3c3c3c;
  padding: 4px 6px;
  box-sizing: border-box;
}

.v1-stylelist-scroll-v-demo p {
  margin: 0 0 4px;
  color: var(--txt-dim);
  font-size: 11px;
}

.v1-stylelist-scroll-h-demo {
  width: 180px;
  overflow-x: auto;
  overflow-y: hidden;
  background: #2b2b2e;
  border: 1px solid #3c3c3c;
  box-sizing: border-box;
}

.v1-stylelist-scroll-h-track {
  display: flex;
  gap: 6px;
  padding: 6px;
  width: max-content;
}

.v1-stylelist-scroll-h-track span {
  flex: 0 0 auto;
  color: var(--txt-dim);
  font-size: 11px;
  background: #333337;
  border: 1px solid #3c3c3c;
  padding: 4px 8px;
  white-space: nowrap;
}

/* shell: Versions */
.v1-versions-list {
  display: grid;
  gap: 10px;
}

.v1-versions-shell {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 8px;
  min-height: 0;
  height: 100%;
}

.v1-versions-timeline-sticky {
  position: relative;
  z-index: 2;
  background: var(--bg-elev);
  padding: 2px 0 8px;
  border-bottom: 1px solid #2e323b;
}

#v1MainCard.is-versions-view {
  overflow: hidden;
}

#v1MainCard.is-versions-view #v1ToolDetail {
  min-height: 0;
  height: 100%;
}

.v1-detached-tool-card.is-versions-view .tool-detail {
  min-height: 0;
  height: 100%;
  overflow: hidden;
}

.v1-detached-tool-card.is-versions-view .v1-versions-shell {
  min-height: 0;
  height: 100%;
}

.v1-versions-list {
  min-height: 0;
  overflow: auto;
  padding-top: 6px;
}

.v1-version-track-wrap {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
}

.v1-version-scroll {
  border: 1px solid #3a3e47;
  background: #24262b;
  color: var(--txt-dim);
  width: 24px;
  height: 24px;
  cursor: pointer;
  font-size: 11px;
}

.v1-version-scroll:hover {
  color: #fff;
  border-color: #4e5562;
  background: #2f333a;
}

.v1-version-track {
  overflow-x: auto;
  overflow-y: hidden;
  padding: 6px 2px 2px;
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
}

.v1-version-track::-webkit-scrollbar,
.v1-version-track::-webkit-scrollbar-thumb,
.v1-version-track::-webkit-scrollbar-track,
.v1-version-track::-webkit-scrollbar-button,
.v1-version-track::-webkit-scrollbar-corner {
  width: 0 !important;
  height: 0 !important;
  display: none !important;
}

.v1-version-track.is-dragging {
  cursor: grabbing;
}

.v1-version-track-inner {
  position: relative;
  display: inline-flex;
  align-items: flex-start;
  gap: 20px;
  min-width: max-content;
  padding: 0 8px 4px;
}

.v1-version-track-inner::before {
  content: "";
  position: absolute;
  left: 8px;
  right: 8px;
  top: 9px;
  height: 2px;
  background: linear-gradient(90deg, #3f434d 0%, #5f6776 50%, #3f434d 100%);
  opacity: 0.9;
}

.v1-version-point {
  position: relative;
  border: 0;
  background: transparent;
  color: var(--txt-dim);
  display: inline-grid;
  gap: 6px;
  justify-items: center;
  cursor: pointer;
  padding: 0;
  min-width: 66px;
  z-index: 1;
}

.v1-version-dot {
  width: 10px;
  height: 10px;
  border-radius: 50% !important;
  border: 2px solid #737a88;
  background: #1a1b1f;
  box-shadow: 0 0 0 2px rgba(20, 20, 22, 0.75);
}

.v1-version-dot.is-published::after {
  content: "";
  position: absolute;
  width: 4px;
  height: 4px;
  margin-top: 1px;
  margin-left: 1px;
  border-radius: 50% !important;
  background: #8ec3ff;
}

.v1-version-point .v1-version-label {
  font-size: 11px;
  font-family: var(--font-mono);
  white-space: nowrap;
}

.v1-version-point:hover,
.v1-version-point.active {
  color: #ffffff;
}

.v1-version-point.active .v1-version-dot {
  border-color: #9fd0ff;
  box-shadow: 0 0 0 2px rgba(31, 62, 108, 0.45), 0 0 12px rgba(93, 162, 255, 0.35);
}

.v1-version-point.is-bumping .v1-version-dot {
  animation: v1-version-dot-spring 460ms cubic-bezier(0.2, 1.45, 0.45, 1);
}

.v1-version-physics {
  position: relative;
  height: 14px;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(85, 95, 112, 0.2) 0%, rgba(38, 42, 50, 0.75) 100%);
  overflow: hidden;
}

.v1-version-orb {
  position: absolute;
  top: 2px;
  left: calc(var(--v1-version-progress, 1) * 100%);
  transform: translateX(-50%);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #e2f2ff 0%, #7bc1ff 38%, #3e84d8 100%);
  box-shadow: 0 2px 8px rgba(65, 149, 247, 0.55);
  transition: left 520ms cubic-bezier(0.2, 1.35, 0.3, 1);
  animation: v1-orb-float 2.2s ease-in-out infinite;
}

.v1-version-orb::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 10px;
  height: 3px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.35);
}

@keyframes v1-version-dot-spring {
  0% { transform: scale(1); }
  40% { transform: scale(1.55); }
  68% { transform: scale(0.88); }
  100% { transform: scale(1); }
}

@keyframes v1-orb-float {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(-2px); }
}

.v1-version-entry {
  border: 1px solid #32343a;
  background: var(--bg-elev);
  padding: 10px;
  scroll-margin-top: 16px;
  transition: border-color 220ms ease, box-shadow 220ms ease, background-color 220ms ease;
}

.v1-version-entry.is-active {
  border-color: #5d9ffd;
  background: color-mix(in oklab, var(--bg-elev) 82%, #3169b5 18%);
  box-shadow: 0 0 0 1px rgba(93, 159, 253, 0.25);
}

.v1-version-entry h4 {
  margin: 0 0 6px;
  font-family: var(--font-head);
  font-size: 14px;
  color: #d9e3ff;
}

.v1-version-entry ul {
  margin: 0;
  padding-left: 18px;
  color: var(--txt-dim);
}

.v1-version-entry li {
  margin: 3px 0;
  line-height: 1.4;
}

/* shell: Language Manager - reuses the shared .v1-import-manager and
   .v1-catalog-item families below (styled to look like Import Tool, per
   request). Installed-language rows are a single horizontal line (flag +
   name + version + radio), so they get their own row class instead of
   .v1-import-item (a vertical id/name/version stack, wrong shape here). */
.v1-lang-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid #2f3238;
  background: #202228;
  cursor: pointer;
}

.v1-lang-item:hover {
  border-color: #4d535c;
}

.v1-lang-item input[type="radio"] {
  margin: 0;
  accent-color: var(--activity);
  flex: 0 0 auto;
}

.v1-lang-flag {
  font-size: 15px;
  line-height: 1;
  width: 20px;
  text-align: center;
}

.v1-catalog-installed-badge {
  color: var(--txt-dim);
  font-size: 12px;
  font-family: var(--font-ui);
  padding: 6px 4px;
  white-space: nowrap;
}

/* SHARED: base "v1-import-manager*" card/grid classes originally styled
   Import Tool (shell), reused by several other shell and ip-scanner tools
   (panel-content-runtime.js) for their own generic form layout. Do not
   treat as exclusively shell or tool - grep render*Tool() functions using
   "v1-import-manager" before moving. */
.v1-import-manager {
  display: grid;
  gap: 12px;
}

.v1-import-manager-note {
  color: var(--txt-dim);
  font-size: 12px;
}

.v1-import-manager-grid {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px 12px;
  align-items: start;
}

.v1-import-manager-grid label {
  color: var(--txt);
  font-size: 12px;
  padding-top: 8px;
}

.v1-import-manager-grid input,
.v1-import-manager-grid textarea {
  width: 100%;
  border: 1px solid #31333a;
  background: #1f2024;
  color: var(--txt);
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 8px 10px;
}

.v1-import-manager-grid textarea {
  min-height: 140px;
  resize: none;
}

.v1-import-manager-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* ip-scanner tool: Network Monitor - two stacked table sections
   (Connections, LAN Devices). Buttons live entirely in the LS panel now
   (tool-content-runtime.js's "network-monitor" entry) - CS is pure
   results: a visibility toolbar, sortable/groupable headers, and a
   collapsible per-section history log (also a table). */
.v1-netmon-shell {
  display: grid;
  gap: 20px;
}

.v1-netmon-toolbar {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.v1-netmon-toolbar-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--txt);
  cursor: pointer;
}

.v1-netmon-toolbar-radios {
  display: inline-flex;
  gap: 12px;
  align-items: center;
  font-size: 12px;
}

.v1-netmon-toolbar-radios label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--txt);
  cursor: pointer;
}

.v1-netmon-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.v1-netmon-view-select {
  border: 1px solid #3d424d;
  background: #22242a;
  color: var(--txt);
  font-size: 12px;
  padding: 4px 6px;
}

.v1-netmon-table th[data-netmon-sort-col] {
  cursor: pointer;
  user-select: none;
}

.v1-netmon-table th[data-netmon-sort-col]:hover {
  color: var(--accent, #d8973c);
}

.v1-netmon-sort-arrow {
  display: inline-block;
  font-size: 10px;
  margin-left: 2px;
}

.v1-netmon-group-row {
  cursor: pointer;
  background: #22242a;
}

.v1-netmon-group-row:hover {
  background: #2a2d34;
}

.v1-netmon-group-child td:first-child {
  padding-left: 22px;
}

/* Appeared/disappeared rows are mixed straight into the live table (flat
   or grouped alike) instead of a separate log - a disappeared row stays
   visible, greyed and struck through, for panel-interactions-runtime.js's
   grace window; a newly-appeared one gets a brief highlighted background.
   Both carry a leading +/- badge (netMonRowMark()) as a second, badge-only
   signal that doesn't depend on noticing the row styling itself. */
.v1-netmon-row-mark {
  font-weight: 700;
  display: inline-block;
  width: 10px;
}

.v1-netmon-row-mark.is-new {
  color: #2dcc71;
}

.v1-netmon-row-mark.is-gone {
  color: #e05d5d;
}

.v1-netmon-row-gone {
  opacity: 0.55;
  text-decoration: line-through;
}

.v1-netmon-row-new {
  background: rgba(45, 204, 113, 0.12);
}

/* shell: General settings screen (TBM Options -> General) - group headings
   inside the shared .v1-import-manager grid, extra breathing room above each
   new group beyond the grid's base 12px gap. First heading (Session) keeps
   the base gap only, so it doesn't float away from the intro note. */
.v1-general-settings-group {
  margin: 8px 0 0;
  color: var(--txt);
  font: 600 12px/1.3 var(--font-ui);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.v1-general-settings-group:first-of-type {
  margin-top: 0;
}

/* shell: General settings' "UI" test switch (Options -> General, hidden
   behind "Show unfinished tools") - deliberately not part of the
   .v1-results-columns-item checkbox grid above, since it's a radio pair
   and intentionally never persisted. */
.v1-general-settings-ui-switch {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 4px;
}

.v1-general-settings-ui-switch-label {
  color: var(--txt-dim);
  font-size: 12px;
}

.v1-general-settings-ui-switch-option {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--txt-dim);
  font-size: 12px;
  cursor: pointer;
}

.v1-general-settings-ui-switch-option input[type="radio"] {
  accent-color: var(--brand);
  cursor: pointer;
}

/* shell: AI Permissions' Profile picker - same radio-row markup as above,
   just stacked one-per-line instead of inline (easier to scan 4 options
   with full descriptive labels than a horizontal wrap). */
.v1-general-settings-ui-switch--stacked {
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

/* shell: AI Assistant provider block (Options -> General, below History) -
   one of these per provider (Anthropic/Google). Grid rather than flex so
   every label's colon lines up in a fixed-width column regardless of how
   long the value next to it is. */
.v1-ai-provider-block {
  display: grid;
  grid-template-columns: 64px 1fr;
  row-gap: 8px;
  column-gap: 10px;
  align-items: center;
  margin-top: 4px;
}

/* Divider only between the two blocks, not above the first one - :first-
   of-type would check "first <div> among ALL sibling divs" (this sits
   inside .v1-import-manager, which already has earlier divs like the
   intro-note header), not "first element with this class", so it never
   matched and both blocks got a leading border. The adjacent-sibling
   combinator targets exactly the second block instead. */
.v1-ai-provider-block + .v1-ai-provider-block {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid #2a2a2e;
}

.v1-ai-provider-field-label {
  color: var(--txt-dim);
  font-size: 12px;
  text-align: right;
}

.v1-ai-provider-field-value {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.v1-ai-provider-field-value select,
.v1-ai-provider-field-value input[type="text"],
.v1-ai-provider-field-value input[type="password"] {
  border: 1px solid #3d424d;
  background: #22242a;
  color: var(--txt);
  font-size: 12px;
  padding: 4px 6px;
  min-width: 220px;
}

.v1-ai-provider-radio {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--txt-dim);
  font-size: 12px;
  cursor: pointer;
}

.v1-ai-provider-radio input[type="radio"] {
  accent-color: var(--brand);
  cursor: pointer;
}

.v1-ai-provider-link {
  color: var(--brand);
  font-size: 11px;
  text-decoration: none;
}

.v1-ai-provider-link:hover {
  text-decoration: underline;
}

/* shell: AI Assistant's editable per-mode system prompts (below the two
   provider blocks) - same dark input styling as the provider block's
   fields above, just stacked (label/textarea/button) instead of a
   label+value grid row, since a multi-line prompt needs full width. */
.v1-ai-prompt-block {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid #2a2a2e;
}

.v1-ai-prompt-block label {
  display: block;
  color: var(--txt-dim);
  font-size: 12px;
  margin-bottom: 4px;
}

.v1-ai-prompt-block textarea {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid #3d424d;
  background: #22242a;
  color: var(--txt);
  font-size: 12px;
  font-family: var(--font-ui);
  padding: 6px 8px;
  resize: vertical;
}

.v1-ai-prompt-reset {
  margin-top: 6px;
}

/* ip-scanner tool: Presets */
.v1-presets-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
}

.v1-presets-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.v1-presets-actions button {
  border: 1px solid #3f3f46;
  border-radius: 8px;
  background: #2a2d31;
  color: var(--txt);
  font-size: 12px;
  font-family: var(--font-ui);
  padding: 6px 10px;
  cursor: pointer;
}

.v1-presets-actions button:hover {
  border-color: #555b66;
  background: #333845;
}

.v1-presets-table-wrap {
  max-height: 360px;
  overflow: auto;
}

.v1-results-table-scroll.v1-presets-table-wrap {
  overflow-y: auto;
}

.v1-presets-table {
  table-layout: auto;
  width: 100%;
  min-width: 0;
}

.v1-presets-table th,
.v1-presets-table td {
  padding: 6px 10px;
  vertical-align: middle;
}

.v1-presets-row.is-selected td {
  background: #2a2d31;
  color: var(--txt);
}

.v1-presets-table input[type="text"] {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid transparent;
  background: transparent;
  color: inherit;
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 1.2;
  padding: 0;
  border-radius: 0;
  min-height: 18px;
}

.v1-presets-table input[type="text"]:focus {
  background: #20242b;
  border-color: var(--brand);
  outline: none;
}

.v1-presets-table input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  width: 13px;
  height: 13px;
  margin: 0;
  border-radius: 50%;
  border: 1px solid #4a4f58;
  background: #1b1c20;
  display: inline-block;
  vertical-align: middle;
  cursor: pointer;
}

.v1-presets-table input[type="radio"]:checked {
  border-color: var(--brand);
  background: radial-gradient(circle at center, var(--brand) 0 48%, transparent 49% 100%), #1b1c20;
}

.v1-presets-table input[type="radio"]:focus-visible {
  outline: 1px solid var(--brand);
  outline-offset: 1px;
}

.v1-presets-col-default {
  width: 1%;
  min-width: 7ch;
  text-align: center;
  padding-left: 6px;
  padding-right: 6px;
  white-space: nowrap;
}

.v1-presets-col-emoji {
  width: 1%;
  min-width: 5ch;
  text-align: center;
  padding-left: 6px;
  padding-right: 6px;
  white-space: nowrap;
}

.v1-presets-col-emoji input {
  display: block;
  margin: 0 auto;
  width: 2.5ch;
  text-align: center;
}

.v1-presets-col-name {
  width: 180px;
  white-space: nowrap;
}

.v1-presets-col-ports {
  width: auto;
}

.v1-presets-hint {
  margin: 2px 0 0;
  color: var(--txt-dim);
  font-size: 12px;
}

@media (max-width: 980px) {
  .v1-presets-table {
    min-width: 520px;
  }
}

/* SHARED, see note near .v1-import-manager above */
.v1-import-manager-actions button {
  border: 0;
  background: #2f2f33;
  color: var(--txt);
  font-size: 12px;
  font-family: var(--font-ui);
  padding: 8px 11px;
  cursor: pointer;
}

.v1-import-manager-actions button:hover {
  background: color-mix(in oklab, var(--bg-soft) 70%, var(--brand) 30%);
  color: #ffffff;
}

/* shell: Import Tool's installed-extensions list display (not shared with
   IP Library, unlike the "-manager-" family above) */
.v1-import-output {
  display: grid;
  gap: 8px;
  margin: 0;
  min-height: 88px;
  padding: 10px;
  border: 1px solid #31333a;
  background: #18181b;
  color: var(--txt-dim);
  font-family: var(--font-mono);
  font-size: 12px;
  overflow: auto;
}

.v1-import-item {
  display: grid;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid #2f3238;
  background: #202228;
}

.v1-import-item strong {
  color: var(--txt);
}

.v1-import-item-uninstall {
  justify-self: start;
  margin-top: 4px;
}

/* shell: addon catalog list (Import Tool "Available addons"), fetched from
   the repo's own tools/ GitHub folder - see panels-runtime.js's
   fetchCatalog/renderCatalog */
.v1-catalog-list {
  display: grid;
  gap: 8px;
}

.v1-catalog-item {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid #2f3238;
  background: #202228;
}

.v1-ext-icon-img {
  width: 24px;
  height: 24px;
  object-fit: contain;
  border-radius: 4px;
}

.v1-extension-tool-item .v1-ext-icon-img {
  width: 16px;
  height: 16px;
  vertical-align: middle;
}

.v1-menu-dd-item .v1-ext-icon-img {
  width: 14px;
  height: 14px;
  vertical-align: middle;
  margin-right: 2px;
}

.v1-catalog-icon-cell {
  width: 32px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}

.v1-catalog-info strong {
  display: block;
  color: var(--txt);
}

.v1-catalog-version {
  color: #9db5ff;
  font-size: 11px;
}

.v1-catalog-install-btn {
  justify-self: end;
}

/* shell: generic action buttons + output box for extension-contributed
   tools whose manifest declares contributions.tools[key].actions (see
   renderDefaultTool/wireExtensionToolActions) */
.v1-ext-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 10px 0;
}

.v1-ext-action-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.v1-ext-action-output {
  display: block;
  margin: 0;
  min-height: 40px;
  padding: 10px;
  border: 1px solid #31333a;
  background: #18181b;
  color: var(--txt-dim);
  font-family: var(--font-mono);
  font-size: 12px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow: auto;
}

/* This class's own display:block always beats the [hidden] attribute's UA
   display:none (author style beats UA style at equal specificity) - without
   this override, toggling .hidden = true from JS (panels-runtime.js's
   wireExtensionToolActions, when a resultsTable is showing instead) has no
   visible effect. Same recurring gotcha as elsewhere in this codebase -
   confirmed by testing the actual addon end-to-end, not just checking the
   DOM property. */
.v1-ext-action-output[hidden],
.v1-ext-results-table-scroll[hidden] {
  display: none;
}

.v1-import-item span {
  color: #9db5ff;
  font-size: 11px;
}

.v1-import-empty {
  color: var(--txt-dim);
  font-style: italic;
}

/* ip-scanner tool: scanner action buttons (#v1ScanActions in index.html) */
.v1-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}

.v1-actions button {
  border: 0;
  background: #2f2f33;
  color: var(--txt);
  font-size: 12px;
  font-family: var(--font-ui);
  padding: 8px 11px;
  cursor: pointer;
}

.v1-actions button:hover {
  background: color-mix(in oklab, var(--bg-soft) 70%, var(--brand) 30%);
  color: #ffffff;
}

/* ip-scanner tool: Results views (Results IP + IP Library table styling) -
   rest of file */
.v1-results-meta-row {
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  position: relative;
  z-index: 8;
  font-size: 12px;
  color: var(--txt-dim);
  margin-bottom: 10px;
}

.v1-results-columns {
  position: relative;
  z-index: 20;
}

.v1-results-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  flex: 1 1 420px;
  min-width: 0;
}

.v1-results-controls [data-results-columns] {
  margin-left: auto;
}

.v1-results-columns-btn {
  border: 0;
  background: transparent;
  color: var(--txt);
  font-size: 12px;
  font-family: var(--font-ui);
  font-weight: 500;
  letter-spacing: 0;
  padding: 5px 11px;
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
}

.v1-results-columns-btn:hover,
.v1-results-columns-btn[aria-expanded="true"] {
  background: color-mix(in oklab, var(--bg-soft) 70%, var(--brand) 30%);
  color: #ffffff;
}

.v1-results-columns-menu {
  position: fixed;
  min-width: 320px;
  border: 1px solid var(--line);
  background: var(--bg-elev);
  color: var(--txt);
  padding: 6px 0;
  z-index: 10020;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
}

.v1-results-columns-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 16px;
  cursor: pointer;
  border: 0;
  color: inherit;
  font-size: 13px;
  line-height: 1.3;
}

.v1-results-columns-item:hover {
  background: color-mix(in oklab, var(--bg-soft) 70%, var(--brand) 30%);
  color: #ffffff;
}

.v1-results-columns-item input[type="checkbox"] {
  margin: 0;
  accent-color: var(--activity);
  flex: 0 0 auto;
}

.v1-results-columns-icon {
  width: 16px;
  text-align: center;
  opacity: 1;
}

/* Separates the "Columns" menu's port-level group (Banner Grabbing/HTTP
   Page Title/Access-Snapshot/SSL-TLS Cert Info) from its host/IP-level
   group (Hostname/Country Flag/ISP/AS/Device Identification) - mirrors the
   RS Config tab's Detect "Service Probing" vs "Host Enrichment" split. */
.v1-results-columns-separator {
  height: 1px;
  margin: 6px 16px;
  background: var(--line);
}

.v1-results-meta-row b {
  color: var(--txt);
}

.v1-results-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  color: var(--txt-dim);
}

.v1-results-table th {
  text-align: start;
  padding: 6px 10px;
  background: #1f1f23;
  color: var(--txt);
  font-weight: 600;
  border-bottom: 1px solid var(--line);
}

.v1-results-table td {
  padding: 6px 10px;
  border-bottom: 1px solid #2a2a2e;
}

.v1-results-table tr:hover td {
  background: #2a2d31;
  color: var(--txt);
}

.v1-iplib-table .v1-iplib-col-country {
  width: 120px;
  white-space: nowrap;
}

.v1-iplib-table .v1-iplib-col-address {
  white-space: nowrap;
}

.v1-iplib-empty {
  color: var(--txt-dim);
}
.v1-results-table-scroll {
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 2px;
}

.v1-results-table-scroll--ip {
  border: 1px solid #2a2a2e;
  border-radius: 6px;
  position: relative;
  z-index: 1;
}

.is-columns-menu-open .v1-results-table-scroll--ip {
  overflow-x: hidden;
}

.v1-ip-results-table {
  min-width: 980px;
}

/* Ensure horizontal overflow exists for IP Scan Results (detached/tab parity).
   Do not apply this to IP Library table (it also uses v1-ip-results-table class). */
.v1-ip-results-table:not(.v1-iplib-table) {
  width: max-content;
  min-width: 0;
}

.v1-ip-results-table th,
.v1-ip-results-table td {
  vertical-align: middle;
}

.v1-ip-results-table .v1-ip-col-check,
.v1-ip-results-table .v1-ip-col-star,
.v1-ip-results-table .v1-ip-col-status,
.v1-ip-results-table .v1-ip-col-expand {
  width: 28px;
  text-align: center;
  padding-left: 6px;
  padding-right: 6px;
}

.v1-ip-results-table .v1-ip-col-ping {
  width: 72px;
  color: #43d17e;
  font-weight: 700;
}

.v1-ip-results-table:not(.v1-iplib-table) .v1-ip-col-ip {
  min-width: 140px;
  white-space: nowrap;
}

.v1-ip-results-table .v1-ip-col-host,
.v1-ip-results-table .v1-ip-col-isp {
  max-width: 240px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.v1-ip-results-table:not(.v1-iplib-table) .v1-ip-col-host,
.v1-ip-results-table:not(.v1-iplib-table) .v1-ip-col-isp {
  min-width: 280px;
  max-width: none;
  overflow: visible;
  text-overflow: clip;
}

.v1-ip-results-table .v1-ip-col-as {
  min-width: 90px;
  white-space: nowrap;
}

.v1-ip-results-table .v1-ip-col-device {
  min-width: 180px;
  white-space: nowrap;
}

.v1-ip-results-table .v1-ip-col-location {
  min-width: 160px;
  white-space: nowrap;
}

.v1-ip-results-table .v1-ip-col-http {
  min-width: 200px;
  white-space: nowrap;
}

/* Not RTL-gated - applies in every language. IP addresses, ping ms, AS
   numbers, and HTTP status codes are inherently LTR data - force them to
   stay left-to-right and isolated from the surrounding bidi context,
   instead of letting the bidi algorithm reorder/misalign them under RTL
   languages (Arabic etc.). */
.v1-ip-col-ip,
.v1-ip-col-ping,
.v1-ip-col-as,
.v1-ip-col-http {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: left;
}

.v1-ip-results-table .v1-ip-col-access {
  min-width: 260px;
  white-space: nowrap;
}

.v1-ip-results-table .v1-ip-col-banner {
  min-width: 220px;
  white-space: nowrap;
}

.v1-ip-results-table .v1-ip-col-sslCert {
  min-width: 220px;
  white-space: nowrap;
}

.v1-ip-results-table .v1-ip-col-flag {
  width: 48px;
  text-align: center;
}

.v1-ip-status-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  display: inline-block;
  background: #6b7483;
}

.v1-ip-status-dot.is-up {
  background: #2dcc71;
  box-shadow: 0 0 0 2px rgba(45, 204, 113, 0.2);
}

/* Network Monitor: TCP connection-state dots, reusing the .is-up green for
   ESTABLISHED and adding a small palette for the rest of MIB_TCP_STATE. */
.v1-ip-status-dot.is-established {
  background: #2dcc71;
  box-shadow: 0 0 0 2px rgba(45, 204, 113, 0.2);
}

.v1-ip-status-dot.is-listening {
  background: #4a9eff;
  box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2);
}

.v1-ip-status-dot.is-pending {
  background: #e5c93e;
  box-shadow: 0 0 0 2px rgba(229, 201, 62, 0.2);
}

.v1-ip-status-dot.is-time-wait,
.v1-ip-status-dot.is-close-wait,
.v1-ip-status-dot.is-closing {
  background: #d8973c;
  box-shadow: 0 0 0 2px rgba(216, 151, 60, 0.2);
}

.v1-ip-status-dot.is-closed {
  background: #6b7483;
}

.v1-netmon-table .v1-ip-status-dot {
  margin-right: 6px;
  vertical-align: middle;
}

/* Email Recon: per-source lookup status dots, same .v1-ip-status-dot
   family as Network Monitor's TCP states above. */
.v1-ip-status-dot.is-found {
  background: #2dcc71;
  box-shadow: 0 0 0 2px rgba(45, 204, 113, 0.2);
}

.v1-ip-status-dot.is-not-found {
  background: #6b7483;
}

.v1-ip-status-dot.is-error {
  background: #e05d5d;
  box-shadow: 0 0 0 2px rgba(224, 93, 93, 0.2);
}

.v1-ip-status-dot.is-skipped {
  background: #3d424d;
}

.v1-emailrecon-table .v1-ip-status-dot {
  margin-right: 6px;
  vertical-align: middle;
}

.v1-emailrecon-shell {
  display: grid;
  gap: 16px;
}

.v1-emailrecon-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
}

.v1-emailrecon-summary-exists {
  font-weight: 600;
}

.v1-emailrecon-summary-count {
  color: var(--txt-dim);
  font-size: 12px;
}

.v1-emailrecon-attribution {
  color: var(--txt-dim);
  font-size: 11px;
  text-align: right;
}

.v1-emailrecon-attribution a {
  color: var(--txt-dim);
}

.v1-ip-expand-btn {
  width: 18px;
  height: 18px;
  border: 1px solid #3d424d;
  background: #20242b;
  color: #dce6f6;
  line-height: 1;
  font-size: 12px;
  cursor: pointer;
  padding: 0;
}

.v1-ip-expand-btn:hover {
  border-color: #5f94de;
  background: #273244;
}

.v1-ip-port-row .v1-ip-col-status,
.v1-ip-port-row .v1-ip-col-expand,
.v1-ip-port-row .v1-ip-col-flag,
.v1-ip-port-row .v1-ip-col-isp {
  color: transparent;
}

.v1-ip-port-row .v1-ip-col-ping {
  font-weight: 700;
}

.v1-ip-port-row .v1-ip-col-as,
.v1-ip-port-row .v1-ip-col-device,
.v1-ip-port-row .v1-ip-col-location {
  color: transparent;
}

.v1-ip-port-row .v1-ip-col-ip {
  color: #dce6f6;
}

.v1-ip-port-row .v1-ip-col-check,
.v1-ip-port-row .v1-ip-col-star {
  text-align: center;
}

.v1-ip-port-action-btn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 0;
  border-radius: 0;
  padding: 0;
  background: transparent;
  color: #dce6f6;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}

.v1-ip-port-action-btn:hover {
  color: #ffffff;
}

.v1-ip-port-action-btn.is-active[data-port-action="check"],
.v1-ip-port-action-btn.is-active[data-result-action="check"] {
  color: #43d17e;
}

.v1-ip-port-action-btn.is-active[data-port-action="favorite"],
.v1-ip-port-action-btn.is-active[data-result-action="favorite"] {
  color: #f0c85a;
}

.v1-ip-port-row td {
  padding-top: 2px;
  padding-bottom: 8px;
  border-bottom: 0;
  vertical-align: middle;
}

.v1-ip-port-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
}

.v1-ip-port-line-start {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.v1-ip-port-chip-emoji {
  font-size: 13px;
  line-height: 1;
  text-align: center;
}

.v1-ip-port-value {
  font-family: var(--font-mono);
  letter-spacing: 0.01em;
  min-width: 0;
  color: #dce6f6;
  word-break: break-word;
}

.v1-ip-port-badge {
  border: 0;
  padding: 3px 8px;
  font-size: 10px;
  font-family: var(--font-ui);
  letter-spacing: 0.02em;
  color: var(--txt-dim);
  background: #2f2f33;
  white-space: nowrap;
}

.v1-ip-port-badge--protocol.is-tcp {
  color: #bcd4ff;
  background: #22314d;
}

.v1-ip-port-badge--protocol.is-udp {
  color: #ffd9b3;
  background: #4d3822;
}

.v1-ip-port-badge--service {
  color: #c7e8c9;
  background: #253524;
}

/* UDP-only "no response at all" case - not a confirmed-open port, so a
   visually distinct (dashed/muted) treatment from the confident protocol
   badges above, matching the open|filtered ambiguity it represents. */
.v1-ip-port-badge--status.is-open-filtered {
  color: #d8c98a;
  background: transparent;
  border: 1px dashed #8a7a45;
}

.v1-ip-port-empty {
  color: var(--txt-dim);
  font-style: italic;
}

.v1-ip-port-link {
  color: #8fc0ff;
  text-decoration: underline;
  font-size: 12px;
  line-height: 1.3;
  word-break: break-all;
}

.v1-ip-port-link:hover {
  color: #c1deff;
}

/* IP blur toggle (top menu bar, [data-menu-action="blur-ip"]) - visual
   masking only (screen-share safety), not data redaction: the underlying
   text is still selectable in the DOM/devtools, just not on-screen. Covers
   every surface that renders a raw IP/hostname today; a future new surface
   (e.g. AI Assistant panel) just needs one of these selectors added, no new
   logic.

   Terminal/Console/PowerShell Console (#v1PsOutput) and the info log
   (#v1InfoLog) are blanket-blurred whole-pane rather than substring-matched:
   their content is free-form command output concatenated as plain text into
   one <pre> (no per-line/per-token DOM structure to target), so precise
   "blur just the IP" highlighting isn't feasible without a real rendering
   rewrite - see ROADMAP.md's "Selective IP-blur inside Terminal/Console
   output" entry. Blanket blur is the safe default here: better to over-blur
   unpredictable output than risk a missed IP. */
body.v1-blur-ip .v1-ip-result-row .v1-ip-col-ip,
body.v1-blur-ip .v1-ip-result-row .v1-ip-col-host,
body.v1-blur-ip #v1DetectExtIp,
body.v1-blur-ip #v1DetectLocalIp,
body.v1-blur-ip #v1DetectSubnets,
body.v1-blur-ip [data-ip-box] .v1-octet,
body.v1-blur-ip #v1ScanCidr,
body.v1-blur-ip #v1IpExtractorInput,
body.v1-blur-ip #v1IpExtractorOutput,
body.v1-blur-ip .v1-range-history-text,
body.v1-blur-ip #v1PsOutput,
body.v1-blur-ip #v1InfoLog,
body.v1-blur-ip [data-v1-console-pane="macro"] {
  filter: blur(5px);
  user-select: none;
}
