{"id":5,"date":"2026-07-27T17:09:04","date_gmt":"2026-07-27T17:09:04","guid":{"rendered":"https:\/\/insightmoves.com\/blog\/competitive-threat-score-calculator\/"},"modified":"2026-07-27T17:09:05","modified_gmt":"2026-07-27T17:09:05","slug":"competitive-threat-score-calculator","status":"publish","type":"page","link":"https:\/\/insightmoves.com\/blog\/competitive-threat-score-calculator\/","title":{"rendered":"Competitive Threat Score Calculator"},"content":{"rendered":"<p><!DOCTYPE html><br \/>\n<html lang=\"en\"><br \/>\n<head><br \/>\n<meta charset=\"UTF-8\"><br \/>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><br \/>\n<title>Competitive Threat Score Calculator: InsightMoves<\/title><br \/>\n<meta name=\"description\" content=\"Score how much of a competitive threat a company poses based on their current job postings. Free, no signup.\"><\/p>\n<style>\n  :root {\n    --bg: #f7f8fa;\n    --card: #ffffff;\n    --ink: #14202e;\n    --ink-soft: #4a5b6e;\n    --ink-mute: #7a8a9b;\n    --line: #e3e8ef;\n    --line-strong: #c9d3df;\n    --accent: #1f5fbf;\n    --accent-soft: #e8f0fc;\n    --low: #4f8a4f;\n    --med: #b78a17;\n    --high: #c25b1f;\n    --crit: #b21f2d;\n  }\n  * { box-sizing: border-box; }\n  html, body { margin: 0; padding: 0; }\n  body {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, \"Helvetica Neue\", Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.55;\n    color: var(--ink);\n    background: var(--bg);\n    -webkit-font-smoothing: antialiased;\n  }\n  main {\n    max-width: 880px;\n    margin: 0 auto;\n    padding: 28px 20px 64px;\n  }\n  .kicker {\n    text-transform: uppercase;\n    letter-spacing: 0.08em;\n    font-size: 12px;\n    color: var(--accent);\n    font-weight: 600;\n    margin: 0 0 8px;\n  }\n  h1 {\n    font-size: 30px;\n    line-height: 1.2;\n    margin: 0 0 8px;\n    letter-spacing: -0.01em;\n  }\n  .sub {\n    color: var(--ink-soft);\n    margin: 0 0 24px;\n    font-size: 16px;\n  }\n  .tool, .article-card {\n    background: var(--card);\n    border: 1px solid var(--line);\n    border-radius: 12px;\n    padding: 20px;\n    margin-bottom: 24px;\n  }\n  .grid {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 18px;\n  }\n  @media (max-width: 640px) {\n    .grid { grid-template-columns: 1fr; }\n    h1 { font-size: 24px; }\n    main { padding: 20px 16px 48px; }\n  }\n  label {\n    display: block;\n    font-weight: 600;\n    font-size: 14px;\n    color: var(--ink);\n    margin-bottom: 6px;\n  }\n  .hint {\n    font-size: 12px;\n    color: var(--ink-mute);\n    margin: 0 0 8px;\n  }\n  input[type=\"number\"] {\n    width: 100%;\n    padding: 10px 12px;\n    font-size: 16px;\n    border: 1px solid var(--line-strong);\n    border-radius: 8px;\n    background: #fff;\n    color: var(--ink);\n    font-family: inherit;\n  }\n  input[type=\"number\"]:focus {\n    outline: 2px solid var(--accent);\n    outline-offset: 1px;\n    border-color: var(--accent);\n  }\n  .slider-row {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n  }\n  input[type=\"range\"] {\n    flex: 1;\n    accent-color: var(--accent);\n  }\n  .slider-value {\n    min-width: 48px;\n    text-align: right;\n    font-variant-numeric: tabular-nums;\n    font-weight: 600;\n    color: var(--ink);\n  }\n  .toggle-row {\n    display: flex;\n    border: 1px solid var(--line-strong);\n    border-radius: 8px;\n    overflow: hidden;\n  }\n  .toggle-row label {\n    flex: 1;\n    text-align: center;\n    margin: 0;\n    padding: 10px 12px;\n    cursor: pointer;\n    font-weight: 500;\n    color: var(--ink-soft);\n    background: #fff;\n    border-right: 1px solid var(--line-strong);\n    transition: background 0.12s, color 0.12s;\n  }\n  .toggle-row label:last-child { border-right: none; }\n  .toggle-row input { display: none; }\n  .toggle-row input:checked + span {\n    color: #fff;\n  }\n  .toggle-row label:has(input:checked) {\n    background: var(--accent);\n    color: #fff;\n  }\n  .toggle-row label:has(input:checked) span { color: #fff; }\n  .output {\n    margin-top: 24px;\n    padding: 20px;\n    background: #f0f4fa;\n    border-radius: 10px;\n    border: 1px solid var(--line);\n  }\n  .score-row {\n    display: flex;\n    align-items: baseline;\n    gap: 14px;\n    flex-wrap: wrap;\n  }\n  .score-num {\n    font-size: 56px;\n    line-height: 1;\n    font-weight: 700;\n    font-variant-numeric: tabular-nums;\n    letter-spacing: -0.02em;\n  }\n  .score-num .denom {\n    font-size: 18px;\n    color: var(--ink-mute);\n    font-weight: 500;\n  }\n  .tier {\n    display: inline-block;\n    padding: 4px 12px;\n    border-radius: 999px;\n    font-size: 13px;\n    font-weight: 600;\n    text-transform: uppercase;\n    letter-spacing: 0.04em;\n    color: #fff;\n    background: var(--ink-mute);\n  }\n  .tier.low    { background: var(--low); }\n  .tier.med    { background: var(--med); }\n  .tier.high   { background: var(--high); }\n  .tier.crit   { background: var(--crit); }\n  .dominant {\n    margin: 12px 0 0;\n    font-size: 15px;\n    color: var(--ink-soft);\n  }\n  .breakdown {\n    margin-top: 18px;\n    border-top: 1px solid var(--line);\n    padding-top: 14px;\n  }\n  .breakdown h3 {\n    font-size: 12px;\n    text-transform: uppercase;\n    letter-spacing: 0.06em;\n    color: var(--ink-mute);\n    font-weight: 600;\n    margin: 0 0 10px;\n  }\n  .bar {\n    display: grid;\n    grid-template-columns: 140px 1fr 56px;\n    align-items: center;\n    gap: 10px;\n    margin-bottom: 8px;\n    font-size: 13px;\n  }\n  .bar-label { color: var(--ink-soft); }\n  .bar-track {\n    height: 8px;\n    background: #e1e7ef;\n    border-radius: 999px;\n    overflow: hidden;\n  }\n  .bar-fill {\n    height: 100%;\n    background: var(--accent);\n    border-radius: 999px;\n    transition: width 0.18s ease-out;\n  }\n  .bar-val {\n    text-align: right;\n    font-variant-numeric: tabular-nums;\n    color: var(--ink);\n    font-weight: 500;\n  }\n  .meta {\n    margin-top: 18px;\n    font-size: 12px;\n    color: var(--ink-mute);\n  }\n  .reset {\n    margin-top: 12px;\n    background: none;\n    border: 1px solid var(--line-strong);\n    border-radius: 8px;\n    padding: 8px 14px;\n    font-size: 13px;\n    color: var(--ink-soft);\n    cursor: pointer;\n    font-family: inherit;\n  }\n  .reset:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }\n  .article-card h2 {\n    font-size: 22px;\n    margin: 0 0 12px;\n    letter-spacing: -0.01em;\n  }\n  .article-card h3 {\n    font-size: 16px;\n    margin: 22px 0 8px;\n  }\n  .article-card p, .article-card li {\n    color: var(--ink);\n    font-size: 15px;\n  }\n  .article-card ul, .article-card ol {\n    padding-left: 22px;\n  }\n  .article-card li { margin-bottom: 4px; }\n  .figure {\n    margin: 18px 0;\n  }\n  .figure img, .figure iframe {\n    width: 100%;\n    border-radius: 10px;\n    border: 1px solid var(--line);\n    display: block;\n    background: #000;\n  }\n  .figure iframe {\n    aspect-ratio: 16 \/ 9;\n    height: auto;\n  }\n  .credit {\n    font-size: 12px;\n    color: var(--ink-mute);\n    margin: 6px 2px 0;\n  }\n  .credit a { color: var(--ink-mute); }\n  .formula {\n    background: #f0f4fa;\n    border-left: 3px solid var(--accent);\n    padding: 12px 14px;\n    border-radius: 0 8px 8px 0;\n    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n    font-size: 13px;\n    color: var(--ink);\n    overflow-x: auto;\n    white-space: pre;\n  }\n  .next {\n    margin-top: 24px;\n    padding: 16px 18px;\n    background: #f0f4fa;\n    border-radius: 10px;\n    font-size: 15px;\n    color: var(--ink-soft);\n  }\n  .next a { color: var(--accent); font-weight: 600; }\n  footer {\n    margin-top: 28px;\n    font-size: 12px;\n    color: var(--ink-mute);\n    text-align: center;\n  }\n  .sr-only {\n    position: absolute;\n    width: 1px; height: 1px;\n    padding: 0; margin: -1px;\n    overflow: hidden;\n    clip: rect(0,0,0,0);\n    white-space: nowrap;\n    border: 0;\n  }\n<\/style>\n<p><\/head><br \/>\n<body><br \/>\n<main><\/p>\n<p class=\"kicker\">InsightMoves free tool<\/p>\n<h1>Competitive Threat Score Calculator<\/h1>\n<p class=\"sub\">Score a competitor&#8217;s hiring posture from their job postings. Four inputs, one number, no signup.<\/p>\n<section class=\"tool\" aria-label=\"Calculator\">\n<form id=\"form\" onsubmit=\"return false;\">\n<div class=\"grid\">\n<div>\n          <label for=\"volume\">Total active job postings<\/label><\/p>\n<p class=\"hint\">Counted across the competitor&#8217;s careers page today.<\/p>\n<p>          <input id=\"volume\" type=\"number\" min=\"1\" max=\"2000\" step=\"1\" value=\"60\" inputmode=\"numeric\">\n        <\/div>\n<div>\n          <label for=\"seniority\">Senior \/ leadership share: <span id=\"seniorityVal\" class=\"slider-value\">20%<\/span><\/label><\/p>\n<p class=\"hint\">Role titles containing director, head, principal, staff, lead, VP, C-level.<\/p>\n<div class=\"slider-row\">\n            <input id=\"seniority\" type=\"range\" min=\"0\" max=\"100\" step=\"1\" value=\"20\">\n          <\/div>\n<\/p><\/div>\n<div>\n          <label for=\"departments\">Distinct departments hiring<\/label><\/p>\n<p class=\"hint\">For example: engineering, sales, marketing, ops, support, finance.<\/p>\n<p>          <input id=\"departments\" type=\"number\" min=\"1\" max=\"10\" step=\"1\" value=\"4\" inputmode=\"numeric\">\n        <\/div>\n<div>\n          <label>AI \/ ML hiring detected<\/label><\/p>\n<p class=\"hint\">Any posting mentions AI, ML, LLM, or model training in title or description.<\/p>\n<div class=\"toggle-row\" role=\"radiogroup\" aria-label=\"AI\/ML hiring\">\n            <label><input type=\"radio\" name=\"ai\" value=\"no\" checked><span>No<\/span><\/label><br \/>\n            <label><input type=\"radio\" name=\"ai\" value=\"yes\"><span>Yes<\/span><\/label>\n          <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div class=\"output\" aria-live=\"polite\" aria-atomic=\"true\">\n<div class=\"score-row\">\n<div class=\"score-num\"><span id=\"scoreNum\">&#8212;<\/span><span class=\"denom\"> \/ 100<\/span><\/div>\n<div id=\"tier\" class=\"tier\"><\/div>\n<\/p><\/div>\n<p class=\"dominant\" id=\"dominant\">Enter your inputs to see a score.<\/p>\n<div class=\"breakdown\">\n<h3>Signal contributions (weighted)<\/h3>\n<div class=\"bar\">\n            <span class=\"bar-label\">Posting volume (25%)<\/span><\/p>\n<div class=\"bar-track\">\n<div class=\"bar-fill\" id=\"fillVolume\" style=\"width:0%\"><\/div>\n<\/div>\n<p>            <span class=\"bar-val\" id=\"valVolume\">0<\/span>\n          <\/div>\n<div class=\"bar\">\n            <span class=\"bar-label\">Seniority share (30%)<\/span><\/p>\n<div class=\"bar-track\">\n<div class=\"bar-fill\" id=\"fillSenior\" style=\"width:0%\"><\/div>\n<\/div>\n<p>            <span class=\"bar-val\" id=\"valSenior\">0<\/span>\n          <\/div>\n<div class=\"bar\">\n            <span class=\"bar-label\">Department breadth (20%)<\/span><\/p>\n<div class=\"bar-track\">\n<div class=\"bar-fill\" id=\"fillDept\" style=\"width:0%\"><\/div>\n<\/div>\n<p>            <span class=\"bar-val\" id=\"valDept\">0<\/span>\n          <\/div>\n<div class=\"bar\">\n            <span class=\"bar-label\">AI\/ML signal (25%)<\/span><\/p>\n<div class=\"bar-track\">\n<div class=\"bar-fill\" id=\"fillAI\" style=\"width:0%\"><\/div>\n<\/div>\n<p>            <span class=\"bar-val\" id=\"valAI\">0<\/span>\n          <\/div>\n<\/p><\/div>\n<p>        <button type=\"button\" class=\"reset\" id=\"resetBtn\">Reset to defaults<\/button><\/p>\n<p class=\"meta\" id=\"metaLine\">Defaults: 60 postings, 20% senior, 4 departments, no AI\/ML.<\/p>\n<\/p><\/div>\n<\/p><\/form>\n<\/section>\n<article class=\"article-card\">\n<h2>How the score is calculated<\/h2>\n<p>The calculator combines four hiring signals into a single 0 to 100 score, with the weights the brief specifies:<\/p>\n<ul>\n<li><strong>Posting volume<\/strong>, 25%<\/li>\n<li><strong>Seniority share<\/strong>, 30%<\/li>\n<li><strong>Department breadth<\/strong>, 20%<\/li>\n<li><strong>AI \/ ML hiring<\/strong>, 25%<\/li>\n<\/ul>\n<p>Each input is first turned into a 0 to 100 <em>sub-score<\/em>, then the four sub-scores are combined with the weights above:<\/p>\n<pre class=\"formula\">score = 0.25 * volume + 0.30 * seniority + 0.20 * breadth + 0.25 * ai_ml<\/pre>\n<p>The sub-score transforms are:<\/p>\n<ul>\n<li><strong>Volume<\/strong>: a square-root curve that reaches 100 at 200 active postings. A small team hiring one person scores around 7; 50 postings scores 50; 200+ scores 100. Square-root scaling is used because doubling headcount is not the same as doubling threat: a competitor going from 10 to 20 openings is a much bigger signal than one going from 100 to 110.<\/li>\n<li><strong>Seniority<\/strong>: the slider value itself (0% = 0, 100% = 100).<\/li>\n<li><strong>Breadth<\/strong>: linear from 1 department (0) to 10 departments (100).<\/li>\n<li><strong>AI \/ ML<\/strong>: 100 if detected, 0 if not.<\/li>\n<\/ul>\n<h2>What the tiers mean<\/h2>\n<ul>\n<li><strong>0 to 25, Low.<\/strong> Light hiring activity, narrow team, no AI signal. The competitor is most likely maintaining, not expanding.<\/li>\n<li><strong>26 to 50, Medium.<\/strong> Real hiring motion, but contained. Worth a quarterly glance.<\/li>\n<li><strong>51 to 75, High.<\/strong> Aggressive build-out, leadership-heavy, or AI-focused. This is a competitor to watch this quarter.<\/li>\n<li><strong>76 to 100, Critical.<\/strong> Multiple signals firing at once. Treat as a direct competitive threat and revisit weekly.<\/li>\n<\/ul>\n<p>The single sentence under the score names whichever signal contributed the most weighted points, so you can see at a glance <em>why<\/em> the number is what it is.<\/p>\n<h2>Why these four signals, and not others<\/h2>\n<p>Job postings are a near-real-time footprint of a company&#8217;s strategy. They show up before press releases, before product launches, and before earnings calls. Four signals in particular carry most of the signal-to-noise:<\/p>\n<ol>\n<li><strong>Volume<\/strong> is the most basic. A 2026 analysis from Indeed&#8217;s Hiring Lab found that US software development postings had climbed roughly 15% since Claude Code launched in late February 2025, even as overall postings across the economy fell 7% over the same period (<a href=\"https:\/\/officechai.com\/ai\/us-software-job-postings-are-up-15-since-launch-of-claude-code-while-overall-job-postings-are-down-7-indeed-data\/\">OfficeChai, citing Indeed Hiring Lab<\/a>). Postings recover before revenue does.<\/li>\n<li><strong>Seniority share<\/strong> is what separates &#8220;growing&#8221; from &#8220;executing.&#8221; The same Indeed data found that 71% of the net increase in software development postings between May 2025 and May 2026 came from senior roles, and 37% of net new postings mentioned AI directly in the title. Harvard researchers Hosseini and Lichtinger have called this pattern (senior headcount up, entry-level headcount down at AI-adopting firms) &#8220;seniority-biased technological change&#8221; (cited in <a href=\"https:\/\/www.techtimes.com\/articles\/320986\/20260719\/ai-reshapes-entry-level-pipeline-across-law-finance-consulting.htm\">TechTimes on the FT analysis<\/a>). A spike in director and principal roles is a different story from a spike in junior roles.<\/li>\n<li><strong>Department breadth<\/strong> tells you whether hiring is focused or strategic. A company opening roles across engineering, sales, marketing, ops, and finance is in a different posture than one hiring only inside one team.<\/li>\n<li><strong>AI \/ ML<\/strong> is the signal that has changed fastest. A 2026 analysis of job postings found that 63% of roles requiring AI understanding are not in tech at all (<a href=\"https:\/\/www.msn.com\/en-us\/money\/general\/63-of-roles-requiring-ai-understanding-are-not-in-tech-at-all\/ar-AA27Oi5G\">MSN reporting<\/a>). McKinsey&#8217;s CEO Bob Sternfels disclosed at CES 2026 that the firm runs about 40,000 human employees alongside 25,000 AI agents, and that client-facing consulting roles are up roughly 25% while non-client-facing roles are down by a similar margin (<a href=\"https:\/\/www.techtimes.com\/articles\/320986\/20260719\/ai-reshapes-entry-level-pipeline-across-law-finance-consulting.htm\">TechTimes<\/a>). When a competitor starts hiring for AI roles, the assumption that they are reorganizing around automation is reasonable.<\/li>\n<\/ol>\n<h2>What this calculator does not do<\/h2>\n<p>It is a snapshot, not a trend. A competitor with 80 stable postings scores the same whether they have been flat for a year or doubling in three months. Direction matters as much as level, and direction is a separate input. It also does not account for:<\/p>\n<ul>\n<li>Whether postings are <em>net new<\/em> or have been open for months. A stale posting is a low-quality signal.<\/li>\n<li>Geography. A competitor opening 20 roles in your city is a different threat from 20 roles in a market you do not serve.<\/li>\n<li>What the postings say about <em>which products<\/em> they are building for. That is where the bigger analysis lives.<\/li>\n<\/ul>\n<p>Use this score to flag where to look. Treat it as a starting point, not a conclusion.<\/p>\n<figure class=\"figure\">\n      <img decoding=\"async\" width=\"1024\" height=\"1024\" class=\"wp-image-6\" src=\"https:\/\/insightmoves.com/blog\/wp-content\/uploads\/sites\/2\/2026\/07\/2136954043_5145b15312_b.jpg\" alt=\"3D bar graph blocks laid out in a meeting, used to compare options visually.\" loading=\"lazy\" srcset=\"https:\/\/insightmoves.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/07\/2136954043_5145b15312_b.jpg 1024w, https:\/\/insightmoves.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/07\/2136954043_5145b15312_b-300x300.jpg 300w, https:\/\/insightmoves.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/07\/2136954043_5145b15312_b-150x150.jpg 150w, https:\/\/insightmoves.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/07\/2136954043_5145b15312_b-768x768.jpg 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p class=\"credit\">Image: &#8220;3D Bar Graph Meeting&#8221; by Scott Maxwell, LuMaxArt, used under a Linkware Freebie licence (attribution link requested) via <a href=\"https:\/\/www.flickr.com\/photos\/22177648@N06\/2136954043\">Flickr<\/a>.<\/p>\n<\/figure>\n<h2>See the formula in action<\/h2>\n<p>This walkthrough by Nate B Jones shows what is possible when job postings are read as a competitive data source rather than a job board, including the kinds of signals a tool like this one is trying to surface:<\/p>\n<figure class=\"figure\">\n      <iframe src=\"https:\/\/www.youtube.com\/embed\/DHZgLzwWXfs\" title=\"I Used AI on Job Postings. It Exposed Billion-Dollar Company Secrets\" loading=\"lazy\" allowfullscreen><\/iframe><\/p>\n<p class=\"credit\">Video: <a href=\"https:\/\/www.youtube.com\/watch?v=DHZgLzwWXfs\">&#8220;I Used AI on Job Postings. It Exposed Billion-Dollar Company Secrets&#8221;<\/a>, Nate B Jones, YouTube.<\/p>\n<\/figure>\n<div class=\"next\">\n      Want this done automatically, every day, across a watchlist of competitors? <a href=\"https:\/\/insightmoves.com\/premium\">InsightMoves Premium<\/a> crawls careers pages daily, diffs the postings over time, and surfaces the new offices, new teams, and rising themes that a single-day score cannot.\n    <\/div>\n<\/article>\n<footer>\n    Calculator by <a href=\"https:\/\/insightmoves.com\/\">InsightMoves<\/a>. Inputs stay in your browser; nothing is sent to a server.<br \/>\n  <\/footer>\n<p><\/main><\/p>\n<p><script>\n(function () {\n  var volumeEl = document.getElementById('volume');\n  var seniorEl = document.getElementById('seniority');\n  var seniorVal = document.getElementById('seniorityVal');\n  var deptEl = document.getElementById('departments');\n  var aiEls = document.getElementsByName('ai');\n  var scoreNum = document.getElementById('scoreNum');\n  var tierEl = document.getElementById('tier');\n  var dominantEl = document.getElementById('dominant');\n  var fillVolume = document.getElementById('fillVolume');\n  var fillSenior = document.getElementById('fillSenior');\n  var fillDept = document.getElementById('fillDept');\n  var fillAI = document.getElementById('fillAI');\n  var valVolume = document.getElementById('valVolume');\n  var valSenior = document.getElementById('valSenior');\n  var valDept = document.getElementById('valDept');\n  var valAI = document.getElementById('valAI');\n  var resetBtn = document.getElementById('resetBtn');<\/p>\n<p>  var W_VOLUME = 0.25;\n  var W_SENIOR = 0.30;\n  var W_DEPT = 0.20;\n  var W_AI = 0.25;<\/p>\n<p>  function subVolume(v) {\n    if (v <= 0) return 0;\n    if (v >= 200) return 100;\n    return Math.round((Math.sqrt(v) \/ Math.sqrt(200)) * 100);\n  }\n  function subSenior(p) { return Math.max(0, Math.min(100, p)); }\n  function subDept(d) {\n    if (d <= 1) return 0;\n    if (d >= 10) return 100;\n    return Math.round(((d - 1) \/ 9) * 100);\n  }\n  function subAI(isAI) { return isAI ? 100 : 0; }<\/p>\n<p>  function tierFor(score) {\n    if (score <= 25) return { label: 'Low', cls: 'low' };\n    if (score <= 50) return { label: 'Medium', cls: 'med' };\n    if (score <= 75) return { label: 'High', cls: 'high' };\n    return { label: 'Critical', cls: 'crit' };\n  }\n\n  function dominantSentence(contribs, inputs) {\n    var entries = [\n      { name: 'posting volume',    points: contribs.volume, detail: inputs.volume + ' active postings' },\n      { name: 'seniority mix',     points: contribs.senior, detail: inputs.seniority + '% of roles are senior or leadership' },\n      { name: 'department breadth',points: contribs.dept,   detail: inputs.departments + ' distinct departments are hiring' },\n      { name: 'AI\/ML hiring',      points: contribs.ai,     detail: inputs.ai ? 'AI\/ML roles are present' : 'no AI\/ML roles detected' }\n    ];\n    entries.sort(function (a, b) { return b.points - a.points; });\n    var top = entries[0];\n    if (top.points === 0) {\n      return 'No signal is contributing yet. Try raising one of the inputs to see a meaningful score.';\n    }\n    return 'The dominant factor is ' + top.name + ' (' + top.detail + '), driving ' + top.points + ' of the ' + contribs.total + ' weighted points.';\n  }\n\n  function recalc() {\n    var vRaw = parseInt(volumeEl.value, 10);\n    var v = isNaN(vRaw) || vRaw < 1 ? 1 : Math.min(vRaw, 2000);\n    if (vRaw !== v) volumeEl.value = v;\n\n    var sRaw = parseInt(seniorEl.value, 10);\n    var s = isNaN(sRaw) ? 0 : Math.max(0, Math.min(100, sRaw));\n    seniorVal.textContent = s + '%';\n\n    var dRaw = parseInt(deptEl.value, 10);\n    var d = isNaN(dRaw) || dRaw < 1 ? 1 : Math.min(dRaw, 10);\n    if (dRaw !== d) deptEl.value = d;\n\n    var aiOn = false;\n    for (var i = 0; i < aiEls.length; i++) {\n      if (aiEls[i].checked &#038;&#038; aiEls[i].value === 'yes') { aiOn = true; break; }\n    }\n\n    var sv = subVolume(v);\n    var ss = subSenior(s);\n    var sd = subDept(d);\n    var sa = subAI(aiOn);\n\n    var cV = +(W_VOLUME * sv).toFixed(1);\n    var cS = +(W_SENIOR * ss).toFixed(1);\n    var cD = +(W_DEPT   * sd).toFixed(1);\n    var cA = +(W_AI     * sa).toFixed(1);\n    var total = +(cV + cS + cD + cA).toFixed(1);\n    var score = Math.round(total);\n\n    scoreNum.textContent = score;\n    var t = tierFor(score);\n    tierEl.textContent = t.label;\n    tierEl.className = 'tier ' + t.cls;\n\n    fillVolume.style.width = (W_VOLUME * sv) + '%';\n    fillSenior.style.width = (W_SENIOR * ss) + '%';\n    fillDept.style.width   = (W_DEPT   * sd) + '%';\n    fillAI.style.width     = (W_AI     * sa) + '%';\n    valVolume.textContent = cV;\n    valSenior.textContent = cS;\n    valDept.textContent   = cD;\n    valAI.textContent     = cA;\n\n    dominantEl.textContent = dominantSentence(\n      { volume: cV, senior: cS, dept: cD, ai: cA, total: total },\n      { volume: v, seniority: s, departments: d, ai: aiOn }\n    );\n  }\n\n  volumeEl.addEventListener('input', recalc);\n  seniorEl.addEventListener('input', recalc);\n  deptEl.addEventListener('input', recalc);\n  for (var i = 0; i < aiEls.length; i++) aiEls[i].addEventListener('change', recalc);\n\n  resetBtn.addEventListener('click', function () {\n    volumeEl.value = 60;\n    seniorEl.value = 20;\n    deptEl.value = 4;\n    for (var j = 0; j < aiEls.length; j++) aiEls[j].checked = (aiEls[j].value === 'no');\n    recalc();\n  });\n\n  recalc();\n})();\n<\/script><br \/>\n<\/body><br \/>\n<\/html><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Score how much of a competitive threat a company poses from their job postings, using four hiring signals (volume, seniority share, department breadth, AI\/ML) and the 25\/30\/20\/25 weights, with a 0-100 score, a Low\/Medium\/High\/Critical tier, a dominant-factor sentence, and a per-signal breakdown.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-tool.php","meta":{"footnotes":""},"class_list":["post-5","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/pages\/5","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/comments?post=5"}],"version-history":[{"count":1,"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/pages\/5\/revisions"}],"predecessor-version":[{"id":7,"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/pages\/5\/revisions\/7"}],"wp:attachment":[{"href":"https:\/\/insightmoves.com\/blog\/wp-json\/wp\/v2\/media?parent=5"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}