/* ════════════════════════════════════════════════════════════════
   DASHBOARD STYLES - изначально скопированы из прототипа market_report.html
   (ранний проект-предшественник, архивный, вне этого репо). Прототип больше
   не источник правды - этот файл редактируется напрямую.
   ════════════════════════════════════════════════════════════════ */

*{box-sizing:border-box;margin:0;padding:0}
:root{
  --warm-dark:   #40291a;
  --warm-accent: #e89a4d;
}
body{background:#060c18;color:#e6edf3;font-family:'Segoe UI',system-ui,sans-serif;font-size:14px;line-height:1.5}
a{color:#58a6ff;text-decoration:none}
code{background:#21262d;padding:1px 5px;border-radius:3px;font-size:12px}

/* ── Header ── */
.header{background:#0d182a;border-top:1px solid #202e44;border-bottom:1px solid #202e44;padding:14px 28px;
  display:flex;align-items:center;gap:16px;position:fixed;top:0;left:0;right:0;z-index:200}
.header h1{font-size:17px;font-weight:700}
.total-badge{background:#21262d;border:1px solid #30363d;border-radius:20px;
  padding:3px 13px;font-size:13px;color:#58a6ff;font-weight:600}
.header .sub{color:#8b949e;font-size:12px;margin-left:auto}

/* ── Filter bar ── */
.filter-bar{background:#0d1117;border-bottom:1px solid #21262d;
  padding:8px 28px;position:fixed;top:49px;left:0;right:0;z-index:190}
.filter-row{display:flex;align-items:center;gap:8px}
.filter-chips-wrap{display:none;flex-direction:column;gap:0;padding:8px 0 4px}
.filter-chips-wrap.open{display:flex}
.fchip-search-row{display:flex;align-items:center;width:100%;margin-bottom:7px}
.fchip-search{background:#161b22;border:1px solid #30363d;border-radius:6px;
  color:#c9d1d9;font-size:11px;padding:4px 26px 4px 28px;width:180px;outline:none;
  transition:border-color .15s}
.fchip-search:focus{border-color:#58a6ff55}
.fchip-search::placeholder{color:#484f58}
.fchip-search-icon{position:absolute;left:8px;color:#484f58;pointer-events:none;font-size:11px}
.fchip-search-wrap{position:relative;display:flex;align-items:center}
.fchip-search-clear{position:absolute;right:7px;background:none;border:none;color:#484f58;
  cursor:pointer;font-size:13px;line-height:1;padding:0;display:none;
  transition:color .15s}
.fchip-search-clear:hover{color:#c9d1d9}
.fchip-search-clear.visible{display:block}
.fchip-chips-row{display:flex;flex-wrap:wrap;gap:5px}
.fchip{background:#21262d;border:1px solid #30363d;border-radius:20px;
  padding:3px 10px;font-size:11px;color:#8b949e;cursor:pointer;
  display:flex;align-items:center;gap:5px;transition:all .15s;white-space:nowrap}
.fchip:hover{border-color:#58a6ff55;color:#e6edf3}
.fchip.active{background:#40291a;border-color:#30363d;color:#e89a4d;font-weight:600}
.fchip-n{background:#30363d;border-radius:10px;padding:0 5px;font-size:10px;color:#6e7681}
.fchip.active .fchip-n{background:#40291a;color:#e89a4d}
.mode-wrap{display:flex;border:1px solid #30363d;border-radius:6px;overflow:hidden}
.mode-btn{background:#21262d;border:none;padding:3px 10px;font-size:11px;color:#8b949e;
  cursor:pointer;transition:all .15s}
.mode-btn.active{background:#1f6feb;color:#fff;font-weight:600}
.filter-all-btn{background:#1f6feb22;border:1px solid #30363d;border-radius:6px;
  color:#58a6ff;cursor:pointer;font-size:11px;padding:3px 11px;
  transition:all .15s;white-space:nowrap;font-weight:600}
.filter-all-btn.inactive{background:#21262d;color:#8b949e;font-weight:normal}
.filter-all-btn:hover{border-color:#58a6ff55}
.skills-toggle-btn{background:#21262d;border:1px solid #30363d;border-radius:6px;
  padding:3px 11px;font-size:11px;color:#8b949e;cursor:pointer;
  display:flex;align-items:center;gap:5px;transition:all .15s;white-space:nowrap}
.skills-toggle-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.skills-toggle-btn.open{background:#40291a;border-color:#30363d;color:#e89a4d}
.skills-toggle-btn.has-filters{background:#40291a;border-color:#30363d;color:#e89a4d}
.skills-toggle-arr{font-size:9px;transition:transform .2s}
.skills-toggle-btn.open .skills-toggle-arr{transform:rotate(180deg)}
.ctx-toggle-btn{background:#21262d;border:1px solid #30363d;border-radius:6px;
  padding:3px 11px;font-size:11px;color:#8b949e;cursor:pointer;
  display:flex;align-items:center;gap:5px;transition:all .15s;white-space:nowrap}
.ctx-toggle-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.ctx-toggle-btn.open{background:#40291a;border-color:#30363d;color:#e89a4d}
.ctx-toggle-btn.has-filters{background:#40291a;border-color:#30363d;color:#e89a4d}
.ctx-toggle-arr{font-size:9px;transition:transform .2s}
.ctx-toggle-btn.open .ctx-toggle-arr{transform:rotate(180deg)}
.hide-unsel-btn{background:#21262d;border:1px solid #30363d;border-radius:6px;
  padding:3px 11px;font-size:11px;color:#8b949e;cursor:pointer;
  display:flex;align-items:center;gap:5px;transition:all .15s;white-space:nowrap}
.hide-unsel-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.hide-unsel-btn.active{background:#40291a;border-color:#30363d;color:#e89a4d}
.ctx-chips-wrap{display:none;padding:6px 0 4px}
.ctx-chips-wrap.open{display:block}
/* Unified Clear / Reset red — middle ground between the previous dim
   #9a4d4d and the bright Trend #f85149. No border thickening on hover —
   only text becomes MORE saturated red (NOT lighter / washed out).
   display:flex + padding 3px 11px matches Skills/Roles/Context toggle buttons
   so heights line up across the filter bar. */

/* The ✕ icon (U+2715 HEAVY MULTIPLICATION X) has wider font metrics in
   Arial which pushes button line-height up by 2-3px. Pinning its
   line-height + display:block inside an inline-block span keeps the
   character visually large but stops it from inflating the parent's
   line-height calculation. */
.clear-btn{background:none;border:1px solid #292f38;border-radius:6px;padding:3px 11px;
  font-size:11px;color:#494f5c;cursor:default;white-space:nowrap;
  display:flex;align-items:center;gap:4px;
  pointer-events:none;transition:color .2s}
.clear-btn.active{color:#c47373;border-color:#7a3a3a;cursor:pointer;pointer-events:auto}
.clear-btn.active:hover{color:#e04545}
.reset-btn{background:none;border:1px solid #292f38;border-radius:6px;padding:3px 11px;
  font-size:11px;color:#494f5c;cursor:default;white-space:nowrap;margin-left:auto;
  display:flex;align-items:center;
  pointer-events:none;transition:color .2s}
.reset-btn.active{color:#c47373;border-color:#7a3a3a;cursor:pointer;pointer-events:auto}
.reset-btn.active:hover{color:#e04545}
.filter-count{font-size:11px;color:#58a6ff}
/* Freshness toggle button + drawer chip. Default: "All Active" с ▼.
   Click → drawer открывается с "Last Week Posts" chip → click chip
   → button label меняется на "Last Week Posts" + orange highlight. */
.freshness-toggle-btn.has-filters{
  background:#40291a;border-color:#30363d;color:#e89a4d;font-weight:600
}
.freshness-toggle-btn.open .cflt-toggle-arr{transform:rotate(180deg)}
/* Exclude toggle buttons - same shape как Select, но с red accent для active */
.skills-toggle-btn.exclude-toggle-btn.has-filters,
.roles-toggle-btn.exclude-toggle-btn.has-filters{
  background:#2d1414;border-color:#7a3a3a;color:#c47373
}
/* Exclude drawer - same chip wrapper, distinct red border (light hint) */
.filter-chips-wrap.exclude-chips-wrap{display:none;padding:6px 0 4px}
.filter-chips-wrap.exclude-chips-wrap.open{display:flex;flex-direction:column}
/* Exclude chip active state - red вместо orange (Select) */
.exclude-chips-wrap .fchip.active{
  background:#2d1414;border-color:#7a3a3a;color:#c47373;font-weight:600
}
.exclude-chips-wrap .fchip.active .fchip-n{background:#2d1414;color:#c47373}
/* chip-mute - chip в одном drawer скрыт because он в другом drawer (mutual exclusion) */
.fchip.chip-mute{display:none !important}

/* ── Layout ── */
.main{display:flex;overflow:hidden;margin-top:93px}
.left{flex:1;padding:20px 18px;overflow-y:auto;min-width:280px;
  scrollbar-width:thin;scrollbar-color:#30363d #0d1117;direction:rtl;scrollbar-gutter:stable}
.left>*{direction:ltr}
.right{width:662px;flex-shrink:0;padding:20px 18px;overflow-y:auto;min-width:220px;
  scrollbar-width:thin;scrollbar-color:#30363d #0d1117;scrollbar-gutter:stable}
.left::-webkit-scrollbar,.right::-webkit-scrollbar{width:5px}
.left::-webkit-scrollbar-track,.right::-webkit-scrollbar-track{background:#0d1117}
.left::-webkit-scrollbar-thumb,.right::-webkit-scrollbar-thumb{background:#30363d;border-radius:3px}
.left::-webkit-scrollbar-thumb:hover,.right::-webkit-scrollbar-thumb:hover{background:#484f58}
.divider{width:2px;flex-shrink:0;background:#21262d;cursor:col-resize;
  transition:background .15s;position:relative}
.divider:hover,.divider.dragging{background:#388bfd55}
.divider::after{content:'';position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);width:1px;height:40px;
  background:#30363d;border-radius:1px}

/* ── Overview cards ── */
.ov-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:4px}
.ov-card{background:#161b22;border:1px solid #21262d;border-radius:8px;
  padding:10px 12px;cursor:default;transition:border-color .2s}
.ov-card:hover{border-color:#30363d}
.ov-card.ov-high{border-color:#1f6feb44}
.ov-top{display:flex;align-items:center;gap:6px;margin-bottom:6px}
.ov-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;line-height:1;color:#8b949e}
.ov-icon svg{width:16px;height:16px;display:block;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.ov-card.ov-high .ov-icon{color:#58a6ff}
.ov-card.ov-mid .ov-icon{color:#c9d1d9}
.ov-label{font-size:11px;font-weight:600;color:#8b949e;text-transform:uppercase;letter-spacing:.04em}
.ov-bar-wrap{background:#21262d;border-radius:2px;height:4px;margin-bottom:6px;overflow:hidden}
.ov-bar{height:100%;background:#1f6feb;border-radius:2px;transition:width .4s}
.ov-card.ov-high .ov-bar{background:#32c589}
.ov-card.ov-mid .ov-bar{background:#1f6feb}
.ov-card.ov-low .ov-bar{background:#6e7681}
.ov-bottom{display:flex;justify-content:space-between;align-items:baseline}
.ov-pct{font-size:16px;font-weight:700;color:#e6edf3}
.ov-card.ov-high .ov-pct{color:#32c589}
.ov-top-skill{font-size:10px;color:#8b949e;text-align:right;max-width:90px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ── Breakdown pills ── */
.breakdown-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.br-label{font-size:11px;color:#8b949e;min-width:76px}
.pill-wrap{display:flex;flex-wrap:wrap;gap:5px;padding:2px 0}
.pill{background:#21262d;border:1px solid #30363d;border-radius:20px;
  padding:3px 11px;font-size:13px}

/* ── Condition rows ── */
.cond-item .skill-name{cursor:pointer}
.cond-item .opt-tag{min-width:20px;text-align:center}
.cond-chips-row{display:flex;flex-wrap:wrap;gap:5px}
.pill b{color:#58a6ff}
.pill small{color:#8b949e;font-size:11px}

/* ── Country filter ── */
.country-filter-bar{border-bottom:1px solid #21262d;margin:-4px -8px 10px;padding:0 8px}
.cflt-row{display:flex;align-items:center;gap:6px;margin-bottom:0;min-height:36px}
.cflt-toggle-btn{background:#1f6feb22;border:1px solid #30363d;border-radius:6px;
  color:#58a6ff;cursor:pointer;font-size:11px;padding:4px 10px;
  display:flex;align-items:center;gap:5px;transition:all .15s;white-space:nowrap}
.cflt-toggle-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.cflt-toggle-btn.open{background:#1f6feb22;border-color:#30363d;color:#58a6ff}
.cflt-toggle-btn.has-filters{background:#40291a;border-color:#30363d;color:#e89a4d}
.cflt-toggle-arr{font-size:9px;transition:transform .2s}
.cflt-toggle-btn.open .cflt-toggle-arr{transform:rotate(180deg)}
.cflt-clear{background:none;border:1px solid #292f38;border-radius:6px;
  color:#494f5c;cursor:default;font-size:11px;padding:3px 11px;
  display:flex;align-items:center;gap:4px;
  pointer-events:none;transition:color .2s;white-space:nowrap}
.cflt-clear.active{color:#c47373;border-color:#7a3a3a;cursor:pointer;pointer-events:auto}
.cflt-clear.active:hover{color:#e04545}
.cflt-chips-wrap{display:none;flex-wrap:wrap;gap:5px;padding:8px 0 4px}
.cflt-chips-wrap.open{display:flex}
.cflt-btn{background:#21262d;border:1px solid #30363d;border-radius:16px;
  color:#8b949e;cursor:pointer;font-size:11px;padding:3px 10px;
  transition:all .15s;white-space:nowrap}
.cflt-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.cflt-btn.active{background:#40291a;border-color:#30363d;color:#e89a4d;font-weight:600}

/* ── Country blocks ── */
.country-block{border:1px solid #21262d;border-radius:8px;margin-bottom:8px;overflow:hidden}
.country-head{padding:9px 14px;cursor:pointer;display:flex;align-items:center;gap:10px;
  background:#161b22;user-select:none}
.country-head:hover{background:#1c2128}
.cflag{font-size:18px;line-height:1}
.cname{font-size:14px;font-weight:700;flex:1}
.ccount{font-size:11px;color:#8b949e}
.ctoggle{font-size:10px;color:#8b949e;transition:transform .2s;margin-left:4px}
.ctoggle.open{transform:rotate(180deg)}
.country-body{display:none;border-top:1px solid #21262d}
.country-body.open{display:block}

/* ── Studio blocks ── */
.studio-block{border-left:3px solid transparent;border-bottom:1px solid #21262d}
.studio-block:last-child{border-bottom:none}
.studio-block.watched-studio{border-left-color:#e89a4d}
.studio-head{padding:9px 16px;cursor:pointer;display:flex;align-items:flex-start;
  gap:10px;background:#0d1117;user-select:none}
.studio-head:hover{background:#161b22}
.studio-block.watched-studio .studio-head{background:rgba(232,154,77,0.06)}
.studio-block.watched-studio .studio-head:hover{background:rgba(232,154,77,0.12)}
.studio-left{flex:1;min-width:0;display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.studio-name{font-size:13px;font-weight:600;color:#8b949e}
.studio-city{font-size:11px;color:#6e7681}
.icon-btn{font-size:11px;text-decoration:none;padding:1px 6px;
  border:1px solid #30363d;border-radius:4px;color:#58a6ff}
.icon-btn:hover{background:#21262d}
.icon-btn.mail{color:#32c589;border-color:#16583d}
.studio-right{display:flex;align-items:center;gap:8px;flex-shrink:0;flex-wrap:nowrap;padding-top:1px}
.studio-cnt{font-size:11px;color:#58a6ff;white-space:nowrap}
.tags-btn{background:#21262d;border:1px solid #30363d;border-radius:12px;
  padding:2px 9px;font-size:10px;color:#8b949e;cursor:pointer;white-space:nowrap;
  transition:all .15s}
.tags-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.tags-btn.open{background:#1f6feb22;border-color:#1f6feb55;color:#58a6ff}
.stoggle{font-size:10px;color:#8b949e;transition:transform .2s;flex-shrink:0}
.stoggle.open{transform:rotate(180deg)}

/* ── Studio tags ── */
.studio-tags{display:none;padding:6px 16px 8px 16px;
  background:#161b22;border-top:1px solid #21262d;flex-wrap:wrap;gap:4px}
.studio-tags.open{display:flex}
.sskill{font-size:11px;border-radius:3px;padding:2px 7px;white-space:nowrap;transition:all .15s}
.sskill-req{background:#1f6feb18;color:#58a6ff;border:1px solid #1f6feb33}
.sskill-opt{background:#21262d;color:#8b949e;border:1px solid #30363d}
.sskill-match{background:#40291a !important;color:#e89a4d !important;border-color:#e89a4d55 !important;font-weight:600}
.skill-match-badge{display:none;font-size:10px;font-weight:700;color:#e89a4d;background:#40291a;
  border:1px solid #e89a4d55;border-radius:10px;padding:1px 7px;white-space:nowrap;flex-shrink:0}

.studio-body{display:none;padding:6px 14px 10px 28px}
.studio-body.open{display:block}

/* ── Posting cards ── */
.pcard{border:1px solid #21262d;border-radius:6px;margin-bottom:5px;overflow:hidden}
.pcard:hover{border-color:#30363d}
.pcard-head{padding:6px 10px;cursor:pointer;background:#161b22;
  display:flex;align-items:center;gap:6px}
.pcard-head:hover{background:#1c2128}
.pcard-left{display:flex;align-items:center;gap:7px;flex:1;min-width:0;overflow:hidden}
.ptitle{font-size:12px;font-weight:600;color:#e6edf3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex-shrink:1}
.pdate{font-size:10px;color:#6e7681;flex-shrink:0;white-space:nowrap}
.pcard-actions{display:flex;align-items:center;gap:5px;flex-shrink:0}
.pmatch{display:none;font-size:10px;font-weight:700;color:#e89a4d;background:#40291a;
  border:1px solid #e89a4d66;border-radius:10px;padding:1px 7px;white-space:nowrap}
.pskills-btn{background:#1f6feb18;color:#58a6ff;border:1px solid #1f6feb44;
  border-radius:4px;font-size:10px;font-weight:600;padding:2px 8px;
  cursor:pointer;white-space:nowrap;transition:background .15s}
.pskills-btn:hover{background:#1f6feb33}
.pskills-btn.open{background:#1f6feb33;border-color:#1f6feb88}
.pskills-panel{display:none;padding:6px 10px;background:#0d1117;
  border-top:1px solid #21262d;flex-wrap:wrap;gap:4px}
.pskills-panel.open{display:flex}
.pcard-body{display:none;padding:6px 10px 8px;background:#0d1117;border-top:1px solid #21262d}
.pcard-body.open{display:block}
.pcard-meta-row{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.pmeta{font-size:10px;background:#21262d;border:1px solid #30363d;
  border-radius:10px;padding:1px 6px;color:#8b949e}
.stag{font-size:11px;border-radius:3px;padding:1px 6px}
.stag.req{background:#1f6feb22;color:#58a6ff;border:1px solid #1f6feb55}
.stag.opt{background:#21262d;color:#8b949e;border:1px solid #30363d}
.stag-match{background:#40291a !important;color:#e89a4d !important;border-color:#e89a4d55 !important;font-weight:600}
.psnippet{font-size:11px;color:#6e7681;line-height:1.5;padding:4px 10px 5px;
  border-top:1px solid #21262d;background:#0d1117;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* ── Studio skill match dot ── */
.skill-match-star{display:none;min-width:16px;height:16px;border-radius:8px;flex-shrink:0;
  background:#40291a;border:1.5px solid #ba7c3e;
  font-size:9px;font-weight:700;color:#e89a4d;
  align-items:center;justify-content:center;padding:0 3px}

/* ── Pct filter buttons ── */
.pct-filter{display:flex;gap:4px;margin-bottom:10px;padding-top:8px}
.pct-btn{background:#21262d;border:1px solid #30363d;border-radius:5px;
  padding:3px 9px;font-size:11px;color:#8b949e;cursor:pointer;transition:all .15s}
.pct-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.pct-btn.active{background:#40291a;border-color:#30363d;color:#e89a4d;font-weight:600}
.pct-btn.pct-all.active{background:#1f6feb22;border-color:#30363d;color:#58a6ff}

/* ── Right panel filter boxes ── */
.filter-box{border:1px solid #2a3f4d;border-radius:7px;overflow:hidden;margin-bottom:8px}
.filter-label-bar{font-size:10px;font-weight:700;color:#8b949e;letter-spacing:.08em;
  text-transform:uppercase;padding:6px 11px;background:#1f2a33;
  display:flex;align-items:center;justify-content:space-between;
  cursor:pointer;user-select:none;transition:background .15s,color .15s}
.filter-label-bar:hover{background:#243340;color:#c9d1d9}
.filter-box-arr{font-size:9px;color:#6e7681;transition:transform .2s;flex-shrink:0}
.filter-box-arr.open{transform:rotate(0deg)}
.filter-box-arr:not(.open){transform:rotate(-90deg)}
.filter-box-body{padding:8px 10px}
.filter-box-body.closed{display:none}
.sd-controls-box .pct-filter{margin-bottom:7px;padding-top:0}
.sal-cflt-bar .cflt-chips-wrap{padding-top:0}
.bar-legend{display:flex;gap:14px;font-size:11px;color:#8b949e}
.bar-legend span{display:flex;align-items:center;gap:4px}
.leg-req{width:12px;height:7px;background:#1f6feb;border-radius:2px}
.leg-opt{width:12px;height:7px;background:#388bfd44;border:1px solid #388bfd55;border-radius:2px}

/* ── Cat-blocks (level 2) ── */
.cat-block{margin-bottom:6px;border:1px solid #2a3f4d;border-radius:7px;overflow:hidden}
.cat-title{font-size:10px;font-weight:700;color:#8b949e;letter-spacing:.08em;
  text-transform:uppercase;padding:7px 11px;background:#1f2a33;
  display:flex;align-items:center;justify-content:space-between;
  cursor:pointer;user-select:none;transition:background .15s,color .15s}
.cat-title:hover{background:#243340;color:#c9d1d9}
.cat-arr{font-size:9px;color:#6e7681;transition:transform .2s;flex-shrink:0}
.cat-arr.open{transform:rotate(0deg)}
.cat-arr:not(.open){transform:rotate(-90deg)}
.cat-body{padding:4px 8px 6px}
.cat-body:not(.open){display:none}
.skill-item{border-radius:3px}
.skill-item:hover>.skill-row{background:#161b22;border-radius:3px 3px 0 0}
.skill-row{display:grid;grid-template-columns:155px 1fr 38px 58px 22px;
  align-items:center;gap:7px;padding:3px 0}
.sk-btn-col{position:relative;width:22px;height:22px;flex-shrink:0}
.sk-exp-btn{width:22px;height:22px;background:#0d1117;
  border:1px solid #30363d;border-radius:4px;color:#6e7681;cursor:pointer;
  padding:0;font-size:9px;line-height:1;display:flex;align-items:center;
  justify-content:center;transition:color .15s,transform .2s}
.sk-exp-btn:hover{color:#c9d1d9}
.sk-exp-btn.open{transform:rotate(90deg);color:#58a6ff}
.sk-copy-btn{width:22px;height:22px;background:#21262d;
  border:1px solid #30363d;border-radius:4px;color:#6e7681;cursor:pointer;
  padding:0;display:none;align-items:center;justify-content:center;
  position:absolute;top:26px;left:0;z-index:2;
  transition:color .15s,border-color .15s,background .15s}
.sk-copy-btn.visible{display:flex}
.sk-copy-btn:hover{color:#c9d1d9;border-color:#8b949e;background:#2d333b}
.sk-copy-btn.copied{color:#32c589;border-color:#16583d;background:#0e1714}
.sk-exp-placeholder{width:22px}

/* ── Skill detail sub-panel ── */
.skill-detail{display:none;padding:5px 4px 7px 10px;
  border-left:2px solid #1f6feb33;margin:0 0 4px 4px}
.skill-detail.open{display:block}
.sm-item{display:flex;align-items:flex-start;gap:6px;padding:2px 0}
.sm-cnt{flex-shrink:0;font-size:10px;font-weight:700;min-width:14px;
  text-align:right;border-radius:8px;padding:0 4px;margin-top:1px}
.sm-cnt.mc-multi{color:#58a6ff;background:#1f6feb18;border:1px solid #1f6feb33}
.sm-cnt.mc-one{color:#6e7681;background:none;border:1px solid transparent}
.sm-body{display:flex;flex-direction:column;gap:1px;min-width:0}
.sm-text{font-size:11px;color:#8b949e;line-height:1.4}
.sm-studios{font-size:10px;color:#484f58;line-height:1.3}
.skill-name{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-left:3px;
  cursor:pointer;border-radius:3px;transition:color .15s}
.skill-name:hover{color:#79c0ff !important}
/* Все skill names одного цвета — bar и так показывает kто чаще. Только
   совсем низкая популярность (<20%) приглушается серым чтобы визуально
   не отвлекать от верхних позиций. */
.skill-name.high{color:#e6edf3}
.skill-name.mid{color:#e6edf3}
.skill-name.low{color:#8b949e}
.skill-name.flt-active{color:#e89a4d !important;font-weight:600}
.skill-name.flt-active::before{content:'✓';font-size:10px;color:#e89a4d;margin-right:4px}
.skill-bar{height:13px;background:#21262d;border-radius:2px;overflow:hidden}
.bar-wrap{display:flex;width:100%;height:100%}
.bar-req{background:#1f6feb;height:100%}
.bar-opt{background:#388bfd44;height:100%}
.skill-pct{text-align:right;font-size:11px;font-weight:600}
/* skill-pct тоже единый цвет — без зеленых акцентов на верхних строках */
.skill-pct.high{color:#e6edf3}
.skill-pct.mid{color:#e6edf3}
.skill-pct.low{color:#8b949e}
.skill-counts{display:flex;gap:3px;justify-content:flex-end}
.req-tag{font-size:10px;background:#1f6feb22;color:#58a6ff;
  border:1px solid #1f6feb44;border-radius:3px;padding:1px 3px}
.opt-tag{font-size:10px;background:#30363d;color:#8b949e;
  border:1px solid #30363d;border-radius:3px;padding:1px 4px}

/* ── Section titles (level 1) ── */
.section-title{font-size:12px;font-weight:700;color:#58a6ff;text-transform:uppercase;
  letter-spacing:.1em;margin:0;padding:10px 0;
  border-top:1px solid #30363d;display:flex;align-items:center;gap:8px;
  cursor:pointer;user-select:none}
.section-title:first-child{border-top:none;padding-top:0}
.section-title::before{content:'';display:inline-block;width:3px;height:13px;
  background:#58a6ff;border-radius:2px;flex-shrink:0}
.section-title:hover{color:#79c0ff}
.section-title:hover::before{background:#79c0ff}
.sec-tog{font-size:10px;transition:transform .2s;flex-shrink:0;margin-left:auto;color:#6e7681}
/* "?" tooltip button — unified style for all sections (page title, Demand
   Overview, Skill Demand, Salaries, Demand Trend, Studios & Postings).
   The literal "?" text inside the <button> is hidden (font-size:0) but kept
   in DOM for accessibility. The "?" shape comes from
   /graphics/brand/question_mark_01.svg used as a CSS mask on ::before —
   so the icon color tracks the pseudo-element's background-color and can
   change between muted (default) and accent (open/active) states. */
.sec-info-btn {
  position: relative;
  background: #0d1117;
  border: 1px solid #30363d;
  border-radius: 4px;
  width: 22px;
  height: 22px;
  padding: 0;
  font-size: 0;
  color: transparent;
  cursor: pointer;
  flex-shrink: 0;
  display: inline-flex;
  vertical-align: middle;
  transition: border-color .15s, background-color .15s;
}
.sec-info-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 8px;
  height: 12px;  /* SVG viewBox 59.41 x 90.61 → ratio ~0.656 */
  background-color: #6e7681;   /* muted default */
  mask: url('/graphics/brand/question_mark_01.svg') center/contain no-repeat;
  -webkit-mask: url('/graphics/brand/question_mark_01.svg') center/contain no-repeat;
  transition: background-color .15s;
}
.sec-info-btn:hover { border-color: #8b949e; background-color: #161b22; }
.sec-info-btn:hover::before { background-color: #c9d1d9; }
.sec-info-btn.open { border-color: #58a6ff77; background-color: #1f6feb18; }
.sec-info-btn.open::before { background-color: #58a6ff; }
.sec-desc{display:none;font-size:14px;color:#8b949e;line-height:1.6;
  background:#161b22;border:1px solid #21262d;border-radius:6px;
  padding:10px 14px;margin-bottom:6px}
/* Multi-block description: stack two or more semantic blocks inside one
   sec-desc with a small blue kicker label above each. The kicker reads
   as a section heading without taking a full line of body text. */
.sec-desc-block + .sec-desc-block { margin-top: 10px; }
.sec-desc-kicker { font-size: 9px; font-weight: 700; letter-spacing: 0.6px;
  color: #58a6ff; text-transform: uppercase; margin-bottom: 4px; }
/* Bulleted list inside a sec-desc-block - small blue dots, same style
   pattern as the issue-card bullets on landing/issue page (orange
   there, blue here to match the kicker palette). */
.sec-desc-bullets { margin: 0; padding-left: 16px; list-style: disc; }
.sec-desc-bullets li { margin-bottom: 4px; }
.sec-desc-bullets li:last-child { margin-bottom: 0; }
.sec-desc-bullets li::marker { color: #58a6ff; }
.desc-legend{display:flex;flex-direction:column;gap:3px;margin-top:7px}
/* align-items:flex-start so leading marker (square/badge) stays on the FIRST
   line when description text wraps to multiple lines — previously the marker
   was centered across all lines which looked off. Add a tiny top offset to
   visually align marker with text x-height. */
.desc-leg-row{display:flex;align-items:flex-start;gap:6px;font-size:12px;color:#8b949e}
.desc-leg-row > .desc-sq { margin-top: 3px; }
.desc-sq{display:inline-block;width:18px;height:14px;border-radius:3px;flex-shrink:0}
/* Inline icon for demand-overview legend rows (matches the icons used on the
   Overview cards themselves so legend pairs with content visually). */
.desc-leg-ic{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;flex-shrink:0;color:#8b949e;margin-top:1px}
.desc-leg-ic svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.req-sq{background:#1f6feb22;border:1px solid #1f6feb44}
.opt-sq{background:#30363d;border:1px solid #30363d}
/* Neutral grey marker — used in Demand Overview legend list to bullet
   each technical category without using emoji (per user feedback). */
.grey-sq{background:#21262d;border:1px solid #30363d}
.desc-arr-sq{display:inline-flex;align-items:center;justify-content:center;
  width:18px;height:14px;background:#0d1117;border:1px solid #30363d;
  border-radius:3px;font-size:7px;color:#6e7681;flex-shrink:0}
/* Studios & Postings legend: a fixed-width key column (sized to the widest
   marker) so every description starts at the same x - the markers stay left,
   no frame, spacing unchanged. Aligns the description starts the user asked for. */
.desc-legend.leg-aligned .desc-leg-row { display: grid; grid-template-columns: var(--leg-key-w, 54px) 1fr; column-gap: 6px; align-items: start; }
.desc-legend.leg-aligned .desc-leg-row > :first-child { justify-self: start; margin-top: 2px; }
.desc-legend.leg-aligned .leg-txt { min-width: 0; }
.desc-legend.leg-aligned .desc-leg-row.leg-note { display: block; }
.sec-tog.open{transform:rotate(180deg)}
.sec-body{overflow:hidden;transition:none;padding-bottom:14px}
.sec-body.closed{display:none}

/* ── Salary section ── */
.srch-bar{position:relative;display:flex;align-items:center;margin-bottom:6px}
.srch-full{flex:1;min-width:0}
.cflt-chips-row{display:flex;flex-wrap:wrap;gap:5px}
.sal-header-top{display:flex;align-items:center;gap:8px;margin-bottom:4px;flex-wrap:nowrap}
.sal-pct-row{display:flex;gap:4px}
.sal-btn-col{display:flex;justify-content:flex-end}
.sal-note-col{display:flex;justify-content:flex-start}
.sal-note{font-size:10px;color:#58a6ff;white-space:nowrap;
  background:#1f6feb22;border:1px solid #1f6feb55;border-radius:5px;
  padding:0 8px;height:22px;line-height:22px;display:inline-block}
.sal-toggle-btn{font-size:10px;background:#21262d;border:1px solid #30363d;
  border-radius:5px;padding:0 8px;height:22px;line-height:22px;
  color:#8b949e;cursor:pointer;white-space:nowrap;transition:all .15s}
.sal-toggle-btn:hover{border-color:#e89a4d55;color:#e89a4d}
.sal-toggle-btn:active{background:#e89a4d22;border-color:#e89a4d55;color:#e89a4d}
.sal-axis{display:grid;grid-template-columns:140px 1fr 100px;margin-bottom:1px}
.sal-axis-marks{position:relative;height:13px}
.sal-axis-marks span{position:absolute;font-size:9px;color:#6e7681;white-space:nowrap;
  transform:translateX(-50%)}
.sal-axis-marks span:first-child{transform:none}
.sal-axis-marks span:last-child{transform:translateX(-100%)}
.sal-country{margin-bottom:10px}
.sal-country-label{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:#8b949e;margin-bottom:4px;cursor:pointer;padding:5px 8px;border-radius:6px;user-select:none}
.sal-country-label:hover{background:#161b22;color:#c9d1d9}
.sal-co-arr{font-size:10px;color:#6e7681;transition:transform .15s ease;display:inline-block;flex:none}
.sal-country:not(.collapsed) .sal-co-arr{transform:rotate(90deg)}
.sal-co-name{flex:1}
.sal-co-count{font-size:12px;font-weight:600;color:#8b949e;background:#21262d;border-radius:10px;padding:1px 8px;min-width:22px;text-align:center;flex:none}
.sal-country.collapsed .sal-country-rows{display:none}
.sal-item{}
.sal-row{display:grid;grid-template-columns:140px 1fr 100px;
  align-items:center;gap:8px;padding:3px 0}
.sal-label{font-size:11px;color:#e6edf3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  display:flex;align-items:center;gap:4px}
.sal-arr{background:none;border:none;color:#6e7681;cursor:pointer;padding:0;
  font-size:8px;line-height:1;transition:transform .2s,color .15s;flex-shrink:0}
.sal-arr:hover{color:#58a6ff}
.sal-arr.open{transform:rotate(90deg);color:#58a6ff}
.sal-detail{display:none;font-size:10px;color:#6e7681;padding:1px 0 5px 4px;
  border-left:2px solid #30363d;margin-left:2px}
.sal-detail.open{display:block}
.sal-loc-row{display:flex;justify-content:space-between;align-items:baseline;padding:2px 0}
.sal-loc-name{font-size:10px;color:#8b949e;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sal-loc-sal{font-size:10px;color:#6e7681;flex-shrink:0;margin-left:8px;white-space:nowrap}
.sal-bar-bg{
  background:linear-gradient(90deg,#30363d 1px,transparent 1px) 0 0/25% 100%,#21262d;
  border-radius:3px;height:11px;overflow:hidden}
.sal-bar-fill{background:linear-gradient(90deg,#1f6feb,#388bfd);height:100%}
.sal-range{font-size:11px;color:#58a6ff;white-space:nowrap;font-weight:600}
/* Floating tooltip shown on hover over a salary bar - the row's $ range,
   so it's readable without tracking the eye up to the axis. Positioned by
   JS (initSalBarTip in dashboard.js); text matches the current currency mode. */
.sal-bar-tip{position:fixed;z-index:60;pointer-events:none;display:none;
  background:#0d1117;border:1px solid #30363d;border-radius:6px;
  padding:4px 9px;font-size:11px;font-weight:600;color:#e6edf3;
  white-space:nowrap;box-shadow:0 4px 12px rgba(0,0,0,.4)}

/* ── NEW badge ── */
.new-badge{background:transparent;color:#16bc8e;font-size:9px;font-weight:700;
  padding:1px 6px;border-radius:8px;border:1px solid #16bc8e55;letter-spacing:.06em;vertical-align:middle;
  margin-left:5px;flex-shrink:0}

/* ── Salary by experience ── */
.sal-exp-section{margin-top:16px;padding-top:12px;border-top:1px solid #21262d}
.sal-exp-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));
  gap:7px}
.sal-exp-card{background:#161b22;border:1px solid #21262d;border-radius:6px;padding:8px 10px}
.sal-exp-label{font-size:10px;color:#6e7681;text-transform:uppercase;
  letter-spacing:.06em;margin-bottom:4px}
.sal-exp-range{font-size:13px;font-weight:700;color:#58a6ff}
.sal-exp-avg{font-size:10px;color:#8b949e;margin-top:2px}
.sal-exp-n{font-size:10px;color:#6e7681;margin-top:1px}

/* ── Trend filter bar ── */
.trend-filter-bar{margin-bottom:0}
.trend-flt-row{display:flex;align-items:center;gap:6px;margin-bottom:0}
.tleg-toggle-btn{background:#1f6feb22;border:1px solid #30363d;border-radius:6px;
  color:#58a6ff;cursor:pointer;font-size:11px;padding:4px 10px;
  display:flex;align-items:center;gap:5px;transition:all .15s;white-space:nowrap}
.tleg-toggle-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.tleg-toggle-btn.open{background:#40291a;border-color:#30363d;color:#e89a4d}
.tleg-toggle-btn.has-filters{background:#40291a;border-color:#30363d;color:#e89a4d}
.tleg-toggle-arr{font-size:9px;transition:transform .2s}
.tleg-toggle-btn.open .tleg-toggle-arr{transform:rotate(180deg)}
/* Trend Clear — default dim grey (no filter to clear yet), turns red only
   when .active class is toggled by JS (trend filter chip selected).
   display:flex + padding 3px 11px so it lines up with the Roles/Skills
   Select sibling buttons in the same row. */
.tleg-clear-btn{background:none;border:1px solid #292f38;border-radius:6px;
  color:#494f5c;cursor:default;font-size:11px;padding:3px 11px;
  display:flex;align-items:center;gap:4px;
  pointer-events:none;transition:color .15s;white-space:nowrap}
.tleg-clear-btn.active{color:#c47373;border-color:#7a3a3a;cursor:pointer;pointer-events:auto}
.tleg-clear-btn.active:hover{color:#e04545}
.tleg-chips-wrap{display:none;flex-direction:column;gap:6px;padding:8px 0 4px}
.tleg-chips-wrap.open{display:flex}
.tleg-search-wrap{position:relative;display:flex;align-items:center;align-self:flex-start}
.tleg-search{background:#161b22;border:1px solid #30363d;border-radius:6px;
  color:#c9d1d9;font-size:11px;padding:4px 26px 4px 28px;width:180px;outline:none;
  transition:border-color .15s}
.tleg-search:focus{border-color:#58a6ff55}
.tleg-search::placeholder{color:#484f58}
.tleg-search-icon{position:absolute;left:8px;color:#484f58;pointer-events:none;font-size:11px}
.tleg-sclear{position:absolute;right:7px;background:none;border:none;color:#484f58;
  cursor:pointer;font-size:13px;line-height:1;padding:0;display:none;transition:color .15s}
.tleg-sclear.visible{display:inline-block}
.tleg-sclear:hover{color:#c9d1d9}
.tleg-sclear.visible{display:block}
.tleg-chips-row{display:flex;flex-wrap:wrap;gap:5px}
.tleg-btn.active{background:#40291a;border-color:#30363d;color:#e89a4d;font-weight:600}

/* ── Trend chart ── */
.trend-canvas-wrap{position:relative;background:#161b22;border:1px solid #21262d;
  border-radius:6px;overflow:hidden;padding:0;margin-top:8px}
.trend-canvas-wrap canvas{display:block;width:100%;height:200px}
.tleg-btn{display:flex;align-items:center;gap:5px;background:#21262d;border:1px solid #30363d;
  border-radius:12px;padding:2px 9px;font-size:11px;color:#8b949e;cursor:pointer;transition:all .15s}
.tleg-btn:hover{border-color:#58a6ff44;color:#e6edf3}
.tleg-btn.off{opacity:.35}
.tleg-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.trend-msg{font-size:12px;color:#6e7681;text-align:center;padding:60px 20px;line-height:1.6}
.trend-msg strong{color:#8b949e;display:block;margin-bottom:6px;font-size:13px}

/* ── Empty / footer ── */
.empty{color:#8b949e;padding:28px;text-align:center;font-size:13px}
.footer{text-align:center;padding:12px;font-size:11px;color:#6e7681;border-top:1px solid #21262d}

@media(max-width:860px){
  .header{position:static}
  .filter-bar{position:static}
  .main{flex-direction:column;height:auto !important;margin-top:0 !important;overflow:visible}
  .left{height:auto !important;overflow-y:visible}
  .right{width:100%;border-top:1px solid #21262d;height:auto !important;overflow-y:visible}
  .divider{display:none}
  .ov-grid{grid-template-columns:repeat(2,1fr)}
  /* Phone: "Updated … · Week …" wraps to its own row. Its desktop
     margin-left:auto pins it right (inline with the title); on the wrapped
     mobile row that detaches it to the far right, away from the left-aligned
     title. Reset so it sits left under H1. */
  .header .sub{margin-left:0}
  /* Phone: single-line button rows must WRAP instead of overflowing the
     screen (where the overflow-x guard would clip them out of reach). These
     rows fit on one line on desktop, so flex-wrap there never triggers —
     desktop layout stays exactly as-is. Covers: top Dashboard filter bar
     (.filter-row), Salary FILTER BY (.cflt-row), SALARY RANGES header
     (.sal-header-top — overrides its desktop flex-wrap:nowrap), and the
     trend-chart control rows (.trend-flt-row). row-gap keeps the wrapped
     lines from touching. */
  .filter-row{flex-wrap:wrap;row-gap:6px}
  .cflt-row{flex-wrap:wrap;row-gap:6px;min-height:0}
  .sal-header-top{flex-wrap:wrap !important;row-gap:6px}
  .trend-flt-row{flex-wrap:wrap;row-gap:6px}
}

/* ── Salary rows: stacked layout on phones ──────────────────────────
   Desktop renders each salary row as a tight 3-column grid
   `studio-name 140px | bar 1fr | range 100px`. On a narrow phone that
   math is fragile: the 1fr bar column collapses to a sliver and the
   140px name + 100px range can push the bar/range past the edge — on
   some mobile browsers (notably iOS Safari) the bar and the $ range end
   up invisible, leaving only the "Studio ?" name (the Chromium device
   emulator does NOT reproduce this, so it only shows on a real phone).

   Fix: below 560px restructure the row into two stacked lines via
   grid-template-areas — name + range on the first line (range guaranteed
   its own space, right-aligned), the bar full-width on the second line.
   No fragile fixed columns, so the bar is always wide and the salary
   number always visible. The scale axis ($0…$Nk) is widened to match.
   Desktop (>560px) keeps the original 3-column grid untouched. */
@media (max-width: 560px) {
  /* FLEX (not grid): an earlier grid `minmax(0,1fr) auto` made bars appear
     but iOS Safari sized the auto range-column to min-content, breaking
     "$399k – $457k" at the en-dash so the range overflowed right and got
     clipped (showed just "$399k"). Flex content-sizes the range to its full
     width and pins it right via margin-left:auto; the bar is forced to its
     own full-width line via flex-basis:100%. order: name(1) range(2) bar(3)
     even though the DOM order is name, bar, range. */
  .sal-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 3px 8px;
  }
  .sal-label    { order: 1; flex: 1 1 auto; min-width: 0; }
  .sal-range    { order: 2; flex: 0 0 auto; margin-left: auto; }
  .sal-bar-wrap { order: 3; flex: 1 0 100%; }
  /* Axis scale: drop the 140px/100px spacer cells so the $0…$Nk marks
     span the full width, aligning with the now full-width bars. */
  .sal-axis { grid-template-columns: 1fr; }
  .sal-axis > span { display: none; }
}


/* ════════════════════════════════════════════════════════════════
   NAVISCA POLISH LAYER — additions on top of the migrated prototype.
   Moved here from inline <style> in templates/dashboard.html so that
   CSS-only tweaks can ship without re-running the GitHub workflow
   (push.bat detects template changes as "needs workflow"; CSS file
   changes deploy via Cloudflare Pages alone).
   ════════════════════════════════════════════════════════════════ */

/* Защита от extensions / addons изменяющих цвета */
html { color-scheme: dark; }
body { background: #060c18 !important; color: #e6edf3 !important; }

/* Snippet — click to expand full text */
.psnippet { cursor: pointer; transition: color .15s; position: relative; }
.psnippet:hover { color: #c9d1d9; }
.psnippet.expanded {
  -webkit-line-clamp: unset !important;
  display: block !important;
  white-space: normal;
  overflow: visible;
  background: #0d1117;
  border-top: 1px solid #21262d;
  padding-bottom: 8px;
}
.psnippet::after {
  content: ' ▾';
  font-size: 9px;
  color: #58a6ff;
  opacity: .6;
}
.psnippet.expanded::after { content: ' ▴'; }

/* Copy snippet button — сдержанный серый, зелёный только на hover/copied */
.snippet-copy-btn {
  background: #21262d;
  border: 1px solid #30363d;
  border-radius: 4px;
  color: #8b949e;
  cursor: pointer;
  padding: 2px 8px;
  font-size: 10px;
  font-weight: 600;
  margin-left: 6px;
  transition: all .15s;
  vertical-align: middle;
}
.snippet-copy-btn:hover {
  border-color: rgba(50, 197, 137, 0.5);
  color: #32c589;
}
.snippet-copy-btn.copied {
  background: rgba(50, 197, 137, 0.15);
  border-color: #32c589;
  color: #5bd9a3;
}

/* Language toggle button — фиолетовый акцент */
.lang-toggle {
  background: rgba(191, 122, 240, 0.08);
  border: 1px solid rgba(191, 122, 240, 0.4);
  border-radius: 4px;
  padding: 1px 8px;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  cursor: pointer;
  margin-left: 6px;
  vertical-align: middle;
  color: #bf7af0;
  transition: all .15s;
}
.lang-toggle:hover {
  background: rgba(191, 122, 240, 0.18);
  border-color: rgba(191, 122, 240, 0.7);
  color: #d2a8ff;
}

/* Roles toggle button — same size/shape as Skills/Context, purple accent only on active state */
.roles-toggle-btn{background:#21262d;border:1px solid #30363d;border-radius:6px;
  padding:3px 11px;font-size:11px;color:#8b949e;cursor:pointer;display:flex;
  align-items:center;gap:5px;transition:all .15s;white-space:nowrap}
.roles-toggle-btn:hover{border-color:#58a6ff55;color:#e6edf3}
.roles-toggle-btn.open{background:#2d1a40;border-color:#30363d;color:#bf7af0}
.roles-toggle-btn.has-filters{background:#2d1a40;border-color:#30363d;color:#bf7af0}
.roles-toggle-arr{font-size:9px;transition:transform .2s}
.roles-toggle-btn.open .roles-toggle-arr{transform:rotate(180deg)}
/* Roles chip — фиолетовая активная подсветка */
.role-fchip.active{background:#2d1a40;border-color:#30363d;color:#bf7af0;font-weight:600}
.role-fchip.active .fchip-n{background:#2d1a40;color:#bf7af0}

/* ═══ UNIFIED COLOR SYSTEM (Phase 1) ═══════════════════════════════
   - All bars: BLUE gradient (Skills already blue; Roles changes to blue)
   - Category accent colors (chips/circles/✓/active row name):
       Skills      = orange   #e89a4d  bg #40291a
       Roles       = purple   #bf7af0  bg #2d1a40
       Job Context = teal     #39c5cf  bg #0f3a3d   ← new
*/

/* Roles bar changes from purple-gradient to blue (match Skills bars) */
.bar-role { height: 100%;
  background: linear-gradient(90deg, #1f6feb, #388bfd);
  border-radius: 3px; transition: width .25s; }

/* Job Context: teal toggle button + chips */
.ctx-toggle-btn.open{background:#0f3a3d !important;color:#39c5cf !important}
.ctx-toggle-btn.has-filters{background:#0f3a3d !important;color:#39c5cf !important}
.cond-fchip.active{background:#0f3a3d !important;border-color:#30363d !important;
  color:#39c5cf !important;font-weight:600}
.cond-fchip.active .fchip-n{background:#0f3a3d !important;color:#39c5cf !important}

/* Job Context: active row name in Industry/Experience tables — teal not orange.
   Only when data-type is wt|exp|remote (Industry / Experience / Remote rows).
   Skills section .flt-active stays orange. */
.skill-name[data-type="wt"].flt-active,
.skill-name[data-type="exp"].flt-active,
.skill-name[data-type="remote"].flt-active {
  color: #39c5cf !important;
}
.skill-name[data-type="wt"].flt-active::before,
.skill-name[data-type="exp"].flt-active::before,
.skill-name[data-type="remote"].flt-active::before {
  color: #39c5cf !important;
}

/* Job Context pmeta chips on pcards:
   - Default (any time): едва уловимый зеленоватый оттенок, остаётся
     приглушённым. Визуально читается "это Job Context category" без
     криков. Серый кастомизирован минимально.
   - Match (filter active): ярко-teal — пользователь сразу видит совпадение. */
.pmeta[data-mtype] {
  color: #88a09c;
  border-color: #313a39;
}
.pmeta-match { background: #0f3a3d !important; color: #39c5cf !important;
  border-color: #39c5cf55 !important; font-weight: 600; }

/* Period selector toolbar above the three trend charts */
.trend-period-bar { display: flex; align-items: center; gap: 6px;
  padding: 0; margin: 0; }
.trend-period-label { font-size: 10px; font-weight: 700; color: #8b949e;
  letter-spacing: .08em; text-transform: uppercase; margin-right: 4px; }
.trend-period-btn { background: #21262d; border: 1px solid #30363d;
  border-radius: 6px; padding: 3px 11px; font-size: 11px; color: #8b949e;
  cursor: pointer; transition: all .15s; white-space: nowrap; }
.trend-period-btn:hover { border-color: #58a6ff55; color: #e6edf3; }
.trend-period-btn.active { background: #1f6feb22; border-color: #30363d;
  color: #58a6ff; font-weight: 600; }
/* Salary view dropdown — green tint (money semantics) to distinguish the
   "which axis" dropdown from the blue series-select dropdown next to it. */
.tleg-toggle-btn.tleg-view-toggle { background: #1d2d2422; color: #3fb950; }
.tleg-toggle-btn.tleg-view-toggle:hover { border-color: #3fb95055; color: #56d971; }
.tleg-toggle-btn.tleg-view-toggle.open { background: #0f3a3d; color: #5fe0e8; }

/* ── "What's new" updates folder ── */
/* Hand-curated changelog entries (newest first). Visually distinct from
   the data axes above - blue info accent, no family color, so the eye
   reads it as meta-context, not another data dimension. */
.cat-block.cat-updates .cat-body { border-color: #1f6feb44; }
.cat-block.cat-updates .cat-body::before { border-color: #1f6feb44; }
.updates-list { display: flex; flex-direction: column; gap: 10px;
  padding: 10px 12px; }
.update-entry { display: grid; grid-template-columns: 84px 1fr; gap: 12px;
  align-items: baseline; }
.update-date { font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: 11px; color: #6e7681; letter-spacing: .02em; }
.update-body { min-width: 0; }
.update-title { font-size: 13px; font-weight: 600; color: #e6edf3;
  margin-bottom: 3px; }
.update-text { font-size: 12px; color: #8b949e; line-height: 1.45; }
.update-link { color: #58a6ff; text-decoration: none; font-size: 11px;
  font-weight: 500; margin-left: 6px; white-space: nowrap; }
.update-link:hover { color: #79c0ff; text-decoration: underline; }
@media (max-width: 600px) {
  .update-entry { grid-template-columns: 1fr; gap: 2px; }
  .update-date { font-size: 10px; }
}

/* ── Category folder accents — 1px coloured rim around the BODY only,
   not the title bar. The cat-title header keeps its own darker band
   intact; the coloured rim wraps just the data table below it. */
.cat-block.cat-skills .cat-body,
.cat-block.cat-roles  .cat-body,
.cat-block.cat-jc     .cat-body,
.filter-box.cat-skills .filter-box-body,
.filter-box.cat-roles  .filter-box-body,
.filter-box.cat-jc     .filter-box-body { position: relative; }

.cat-block.cat-skills .cat-body::before,
.cat-block.cat-roles  .cat-body::before,
.cat-block.cat-jc     .cat-body::before,
.filter-box.cat-skills .filter-box-body::before,
.filter-box.cat-roles  .filter-box-body::before,
.filter-box.cat-jc     .filter-box-body::before {
  content: '';
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  border: 1px solid;
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: 6px;
  box-sizing: border-box;
  pointer-events: none;
  z-index: 2;
}
.cat-block.cat-skills  .cat-body::before,
.filter-box.cat-skills .filter-box-body::before { border-color: #5a3a1f; }
.cat-block.cat-roles   .cat-body::before,
.filter-box.cat-roles  .filter-box-body::before { border-color: #3a1f5a; }
.cat-block.cat-jc      .cat-body::before,
.filter-box.cat-jc     .filter-box-body::before { border-color: #1a4d52; }

/* Row hover tint per category — barely a shift from the default #161b22
   gray, but enough to remind the user which folder they're inside. */
.cat-block.cat-skills .skill-item:hover > .skill-row { background: #1c1715; }
.cat-block.cat-roles  .skill-item:hover > .skill-row { background: #18151e; }
.cat-block.cat-jc     .skill-item:hover > .skill-row { background: #141d1e; }

.cat-block.cat-skills  .cat-title > span:first-child::before,
.cat-block.cat-roles   .cat-title > span:first-child::before,
.cat-block.cat-jc      .cat-title > span:first-child::before,
.cat-block.cat-salary  .cat-title > span:first-child::before,
.filter-box.cat-skills .filter-label-bar > span:first-child::before,
.filter-box.cat-roles  .filter-label-bar > span:first-child::before,
.filter-box.cat-jc     .filter-label-bar > span:first-child::before,
.filter-box.cat-salary .filter-label-bar > span:first-child::before {
  /* Ring: 7px box + 1px accent-coloured border + dark fill same hue. */
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid currentColor;
  margin-right: 6px;
  vertical-align: -1px;
}
.cat-block.cat-skills  .cat-title > span:first-child::before,
.filter-box.cat-skills .filter-label-bar > span:first-child::before { color: #e89a4d; background: #5a3a1f; }
.cat-block.cat-roles   .cat-title > span:first-child::before,
.filter-box.cat-roles  .filter-label-bar > span:first-child::before { color: #bf7af0; background: #3a1f5a; }
.cat-block.cat-jc      .cat-title > span:first-child::before,
.filter-box.cat-jc     .filter-label-bar > span:first-child::before { color: #39c5cf; background: #1a4d52; }
.cat-block.cat-salary  .cat-title > span:first-child::before,
.filter-box.cat-salary .filter-label-bar > span:first-child::before { color: #58a6ff; background: #0d2a4d; }

/* Job Context: studio circle + pcard dot (mirrors yellow/purple ones) */
.jc-match-circle { display: none; min-width: 16px; height: 16px;
  border-radius: 8px; flex-shrink: 0;
  background: #0f3a3d; border: 1.5px solid #39c5cf;
  font-size: 9px; font-weight: 700; color: #5fe0e8;
  align-items: center; justify-content: center; padding: 0 3px;
  margin-left: 4px; }
.jc-match-circle.visible { display: inline-flex; }
.jc-match-dot { display: none; width: 8px; height: 8px;
  border-radius: 50%; flex-shrink: 0;
  background: #39c5cf; box-shadow: 0 0 0 2px #0f3a3d55;
  margin-right: 6px; vertical-align: middle; }
.jc-match-dot.visible { display: inline-block; }

/* Purple role-match indicators (mirror yellow skill-match-star pattern):
   - .role-match-circle on studio-head: shows count of matching role postings
   - .role-match-dot on pcard-head: just a marker dot (no number) */
.role-match-circle { display: none; min-width: 16px; height: 16px;
  border-radius: 8px; flex-shrink: 0;
  background: #2d1a40; border: 1.5px solid #bf7af0;
  font-size: 9px; font-weight: 700; color: #d2a8ff;
  align-items: center; justify-content: center; padding: 0 3px;
  margin-left: 4px; }
.role-match-dot { display: none; width: 8px; height: 8px;
  border-radius: 50%; flex-shrink: 0;
  background: #bf7af0; box-shadow: 0 0 0 2px #2d1a4055;
  margin-right: 6px; vertical-align: middle; }
.role-match-dot.visible { display: inline-block; }
.role-match-circle.visible { display: inline-flex; }

/* Top Roles table в левой панели */
.role-name { cursor: pointer; color: #e6edf3; transition: color .15s; }
.role-name:hover { color: #d2a8ff; }
.role-item.role-active .role-name {
  color: #bf7af0 !important;
  font-weight: 600;
}
/* ✓ перед активной ролью — то же что и Skills (.flt-active::before),
   только фиолетового цвета чтобы держать роль-цветовую схему. */
.role-item.role-active .role-name::before {
  content: '✓';
  font-size: 10px;
  color: #bf7af0;
  margin-right: 4px;
}

/* Experience Level rows — split label into fixed-width "level" + "years" so
   "Senior 5+ Years", "Mid 3-5 Years", "Junior 1-3 Years" align вертикально
   (years колонка ровная независимо от длины level). */
.sen-level { display: inline-block; min-width: 56px; }
.sen-years { color: #6e7681; font-weight: normal; font-size: 11px; }

/* Salary label: только название студии + ? кнопка (позиция в popup).
   Сохраняем оригинальную ширину 140px и не смещаем шкалу. */
.sal-label { display: flex !important; align-items: center; gap: 4px; }
.sal-studio { color: #e6edf3; font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Match section-level "?" button style (.sec-info-btn) — squarish with
   rounded corners, not a circle. Keeps the whole dashboard's info-icons
   visually consistent. */
.sal-info-btn { background: #0d1117; border: 1px solid #30363d; border-radius: 4px;
  padding: 1px 5px; font-size: 10px; font-weight: 700; line-height: 1;
  color: #6e7681; cursor: pointer; transition: color .15s, border-color .15s;
  flex-shrink: 0; }
.sal-info-btn:hover { color: #c9d1d9; border-color: #8b949e; }
.sal-info-btn.open { color: #58a6ff; border-color: #58a6ff55; }
.sal-info-popup { display: none; grid-column: 1 / -1; padding: 4px 0 6px 6px;
  color: #8b949e; font-size: 11px; border-left: 2px solid #30363d;
  margin: 0 0 4px 0; }
.sal-info-popup.open { display: block; }

/* The ✕ icon (U+2715 HEAVY MULTIPLICATION X) has wider font metrics in
   Arial which pushes button line-height up by 2-3px. Pinning its
   line-height + display:block inside an inline-block span keeps the
   character visually large but stops it from inflating the parent's
   line-height calculation. */
.clear-x { display: inline-block; line-height: 1; font-size: 11px; }

/* X-Ray button on each trend chart — when active, drawTrend renders the
   previous window of equal length as dashed underlay curves. Style mirrors
   trend-period-btn sizing so it fits inline with siblings. */
.trend-xray-btn { background: #21262d; border: 1px solid #30363d;
  border-radius: 6px; padding: 3px 11px; font-size: 11px; color: #8b949e;
  cursor: pointer; transition: all .15s; white-space: nowrap; }
.trend-xray-btn:hover { border-color: #58a6ff55; color: #e6edf3; }
.trend-xray-btn.active { background: #1f6feb22; border-color: #30363d;
  color: #58a6ff; font-weight: 600; }

/* "All series" mode for each trend chart — toggles between the default
   top-12 (skills) / top-8 (roles, industries) view and a long-tail picker.
   The checkbox styling mirrors a small inline control; when ticked, JS
   adds .tleg-disabled to the default Select/All/Clear buttons (greys them
   out) and unhides the Pick-One button + its dropdown. */
/* Split into two adjacent boxes (.tleg-am-box for the checkbox +
   .tleg-am-text for the label) so the checkbox can keep its native
   size without inflating the row height vs the sibling buttons. Both
   sub-boxes stretch to the same height via align-items: stretch on
   the parent label. JS still toggles .checked on the parent label;
   the children read it from there. */
.tleg-allmode { display: inline-flex; align-items: stretch; gap: 4px;
  font-size: 11px; color: #8b949e; cursor: pointer; user-select: none; }
.tleg-am-box,
.tleg-am-text { display: inline-flex; align-items: center;
  border: 1px solid #30363d; border-radius: 6px; background: #21262d;
  height: 20px; line-height: 1;
  transition: all .15s; }
.tleg-am-box { padding: 0 6px; }
.tleg-am-text { padding: 0 10px; }
.tleg-am-box input { margin: 0; accent-color: #58a6ff; cursor: pointer;
  display: block; }
.tleg-allmode:hover .tleg-am-box,
.tleg-allmode:hover .tleg-am-text { border-color: #58a6ff55; }
.tleg-allmode:hover .tleg-am-text { color: #e6edf3; }
.tleg-allmode.checked .tleg-am-box,
.tleg-allmode.checked .tleg-am-text { background: #1f6feb22;
  border-color: #58a6ff55; }
.tleg-allmode.checked .tleg-am-text { color: #58a6ff; font-weight: 600; }
/* Hover on a checked control = intent to turn it off. Checkbox box
   warns in red (same palette as Clear/Reset elsewhere); text stays
   blue so the row still reads as the active selection. */
.tleg-allmode.checked:hover .tleg-am-box { border-color: #7a3a3a;
  background: #2d1414; }
.tleg-allmode.checked:hover .tleg-am-box input { accent-color: #c47373; }

/* When .tleg-disabled lands on default-mode controls (All / Select / Clear)
   they look greyed out and ignore pointer events. */
.filter-all-btn.tleg-disabled, .tleg-toggle-btn.tleg-disabled,
.tleg-clear-btn.tleg-disabled { opacity: .35; pointer-events: none; }

/* Pick-One button — same shape as tleg-toggle-btn but only present in
   show-all mode. Its label updates to the picked series name on selection.
   The :not([hidden]) guard keeps the HTML `hidden` attribute effective; a
   plain `display: inline-flex` rule would otherwise win over [hidden]. */
.tleg-pickone-btn:not([hidden]) { background: #1f6feb22; border: 1px solid #30363d;
  border-radius: 6px; padding: 3px 11px; font-size: 11px; color: #c9d1d9;
  cursor: pointer; transition: all .15s; display: inline-flex;
  align-items: center; gap: 5px; }
.tleg-pickone-btn:hover { border-color: #58a6ff55; color: #e6edf3; }
.tleg-pickone-btn.open .tleg-toggle-arr { transform: rotate(180deg); }
.tleg-pickone-btn.has-picked { background: #1f6feb22; color: #58a6ff;
  border-color: #58a6ff55; font-weight: 600; }

/* v4.2 — Integrate dashboard layout with shared site <nav>.
   Previously .header was position:fixed at top:0, overlapping the new nav
   (which is sticky at top:0 via styles.css). Make .header static — it scrolls
   with content. nav stays sticky at top:0. filter-bar sticky at top:63
   (right below nav).

   Why .header is NOT sticky: when both nav and .header are sticky, sticky's
   "flow position" differs from rendered position. .filter-bar's natural
   flow position used .header's pre-sticky-offset bottom (5px above its
   visible bottom), which caused .filter-bar to overlap into .header by 5px.
   Especially visible when tooltip expanded .header height. Making .header
   static eliminates that mismatch entirely. */
.header { position: static !important; }
.filter-bar { position: sticky !important; top: 63px !important; z-index: 180 !important; }

/* App-shell scroll containment. Body is non-scrolling (height:100vh + overflow:hidden)
   with nav/.header/.filter-bar at natural heights stacked via flex; .main takes the
   remainder. Without this, total flow height exceeded viewport by ~100px and wheel
   events inside .left/.right propagated to body scroll, pushing .header out of view
   (bug: scrolling right panel sniped the page title). overscroll-behavior:contain
   on .left/.right is belt-and-braces against propagation at scroll boundaries.
   Narrow viewport (<=860px) overrides below restore normal page scroll for mobile. */
html, body { height: 100vh !important; overflow: hidden !important; }
body { display: flex !important; flex-direction: column !important; }
nav, .header, .filter-bar { flex-shrink: 0 !important; }
.main { flex: 1 1 auto !important; min-height: 0 !important; height: auto !important;
        margin-top: 0 !important; }
.left, .right { overscroll-behavior: contain !important; }

@media (max-width: 860px) {
  html, body { height: auto !important; overflow: visible !important; }
  body { display: block !important; }
}

/* Page title: bigger + slightly muted (user feedback: increase + dim).
   line-height:1 removes inherent leading so the title sits at optical center
   of the row rather than appearing low because of caps + descender padding. */
.header h1 { font-size: 22px !important; font-weight: 700 !important;
  color: #c9d1d9 !important; line-height: 1 !important;
  display: inline-flex; align-items: center; gap: 8px; }

/* Page title "?" button uses the unified .sec-info-btn rule above (22x22 SVG).
   No override needed anymore. */

/* Page-level tooltip lives INSIDE .header as a wrapped flex item. When opened
   it adds a new row to the .header flex layout, growing the header box
   downward to reveal the description. Style is IDENTICAL to default .sec-desc
   (used by "Demand Overview" etc.) for visual consistency — same bg, border,
   color, padding. The border #21262d gives it definition inside .header
   even though bg matches .header's #161b22. */
.header { flex-wrap: wrap !important; row-gap: 7px !important; }
.sec-desc.page-desc {
  flex-basis: 100%;
  width: 100%;
  /* Halved spacing per user feedback. Above: tooltip almost flush with title
     (row-gap:4 on .header is the only thing above). Below: tooltip almost
     flush with .header edge (margin-bottom:0; .header padding-bottom 14px is
     the only thing below — overridden here to 7px to also halve). */
  margin: 0;
  padding: 10px 14px;
  background: #161b22;
  border: 1px solid #30363d;
  border-radius: 6px;
  font-size: 14px;
  color: #8b949e;
  line-height: 1.6;
}
/* When tooltip is open, set .header padding-bottom so the gap from
   tooltip bottom to filter-buttons top (above-buttons) matches the gap
   from filter-buttons bottom to next section box top (below-buttons).
   Below-buttons measured = 29px (filter-bar pad-bottom + border + .left
   padding-top). To match, above-buttons = .header padding-bottom (X) +
   .filter-bar padding-top (8px) should equal 29, so X = 21px. */
.header:has(.page-desc[style*="block"]) { padding-bottom: 11px !important; }

/* Location chip after ptitle — gray, smaller, so role title stands out.
   Renders deduped city ("Wellington" not "Wellington Wellington") for postings
   whose source put location in title text. */
.ploc { color: #8b949e; font-size: 11px; font-weight: normal;
  margin-left: 6px; white-space: nowrap; }

/* Studio name search input in Studios & Postings filter bar - mirrors the
   search-wrap pattern from /studios.html so the two pages look consistent. */
.studio-name-search { position: relative; display: inline-flex; align-items: center; }
.studio-name-search input {
  background: #0d1117; border: 1px solid #30363d; border-radius: 6px;
  padding: 5px 28px 5px 10px; color: #c9d1d9; font-size: 11px;
  outline: none; transition: border-color 0.15s; min-width: 220px;
}
.studio-name-search input:focus { border-color: #58a6ff55; }
.studio-name-search input::placeholder { color: #484f58; }
.studio-name-search-clear {
  position: absolute; right: 7px; background: none; border: none;
  color: #6e7681; font-size: 12px; cursor: pointer; padding: 0 4px;
  display: none; line-height: 1;
}
.studio-name-search-clear.visible { display: inline-block; }
.studio-name-search-clear:hover { color: #c9d1d9; }

/* ════════════════════════════════════════════════════════════════
   TIER GATING (Phase 2, 2026-05-23) — austere Free + Pro JS layer.
   See docs/LAUNCH_AND_GATING_PLAN.md.

   Default state (no data-tier on body) = Free / anonymous. CSS hides
   every .pro-only element. JS inline in dashboard.html fetches
   /api/me on load and sets body[data-tier="pro"] if the user is
   in a Pro tier (real sub OR active trial OR gift). At that point
   the rule chain inverts and Pro elements appear.

   Free user sees:
     - Header + total badge + page description (info on click stays)
     - Section title bars (Demand Overview, Skill Demand, Salaries,
       Demand Trend) as visible "proof of analysis", but section
       bodies are hidden and section togglers do nothing
     - Right panel: country folders open, studio cards open, postings
       as plain "title · location · date" with the studio "site" link
     - .free-only Pro-block at the bottom of the left column = upsell

   Pro user sees the full pre-2026-05-23 dashboard. No data difference
   between Free and Pro — only an interaction layer. The data IS in
   the HTML for the SEO benefit; Free just lacks the affordances.
   ════════════════════════════════════════════════════════════════ */

/* Generic utility: .pro-only hides for Free, .free-only hides for Pro.
   Use sparingly for one-off elements not covered by structural
   selectors below. */
body:not([data-tier="pro"]) .pro-only { display: none !important; }
body[data-tier="pro"] .free-only { display: none !important; }

/* ── Left panel sections (revised 2026-05-23 after first calibration):
      Demand Overview + Skill Demand stay OPEN with their bars + %
      visible for Free (proof of analysis, not just teaser titles).
      Salaries + Demand Trend stay LOCKED (sec-title-locked class on
      title; sec-body hidden). Within the open sections, internal
      Pro affordances (filter boxes, ▶ expand-row buttons, clickable
      skill names) are still hidden / inert. ── */

/* Locked sections: hide their body + description. */
body:not([data-tier="pro"]) #sec-sal,
body:not([data-tier="pro"]) #desc-sal,
body:not([data-tier="pro"]) #sec-tr,
body:not([data-tier="pro"]) #desc-tr {
  display: none !important;
}

/* Locked section title rows: dimmed + inert click + no toggler/info. */
body:not([data-tier="pro"]) .left .section-title.sec-title-locked {
  cursor: default;
  pointer-events: none;
  opacity: 0.55;
}

/* Open section title rows (ov, sd): full opacity, BUT toggler + info
   still hidden + click disabled so Free can't collapse the always-on
   content below. */
body:not([data-tier="pro"]) .left .section-title:not(.sec-title-locked) {
  cursor: default;
  pointer-events: none;
}

/* Hide section toggler arrow ▼ + ? info button on EVERY left section
   title for Free, regardless of locked/open state. */
body:not([data-tier="pro"]) .left .section-title .sec-tog,
body:not([data-tier="pro"]) .left .section-title .sec-info-btn {
  display: none;
}

/* Hide section descriptions for the OPEN sections too. They're info
   tooltips activated by the ? button, which is hidden. */
body:not([data-tier="pro"]) .left .sec-desc { display: none !important; }

/* Inside the open sections (sec-ov + sec-sd), Pro-only sub-elements: */

/* Filter boxes ("Skills — Select Percentages", "Roles — Select
   Percentages", "Job Context — Select Percentages"). Pure filter UI. */
body:not([data-tier="pro"]) .left .filter-box { display: none !important; }

/* Right-side per-row buttons (▶ expand + Copy text). Drilling into a
   row reveals the "exact phrases from job listings" - that's the kind
   of premium intelligence Pro pays for. */
body:not([data-tier="pro"]) .left .sk-btn-col { display: none !important; }

/* Skill name click → toggleFilterByName(). Filters don't exist for
   Free so this would just mutate state invisibly. Cursor stays text
   so it doesn't look interactive. */
body:not([data-tier="pro"]) .left .skill-name {
  pointer-events: none;
  cursor: default;
}

/* Category folder titles inside sec-sd ("SOFTWARE", "Top Roles — Art",
   etc.) - normally expand/collapse the cat-body below. For Free leave
   all cat-bodies expanded; disable cat-title click so they can't be
   collapsed. */
body:not([data-tier="pro"]) .left .cat-title {
  pointer-events: none;
  cursor: default;
}
body:not([data-tier="pro"]) .left .cat-arr { display: none; }

/* ── Top filter bar (mode + skills + roles + ctx + clear chips).
      The whole strip is Pro-only - filters ARE the Pro engine. ── */
body:not([data-tier="pro"]) .filter-bar { display: none !important; }

/* ── Right panel (Studios & Postings) is the live Free zone with
      ONE exception: the country-filter-bar at the top of the section
      body (All Countries dropdown, search studio name, Reset view,
      country chips) is filter UI = Pro-only. ── */
body:not([data-tier="pro"]) .country-filter-bar { display: none !important; }

/* Right panel section title stays interactive (country folders ARE
   the live data for Free). Explicit re-enable in case any later rule
   accidentally scopes broader. */
body:not([data-tier="pro"]) .right .section-title {
  pointer-events: auto;
  cursor: pointer;
  opacity: 1;
}
body:not([data-tier="pro"]) .right .section-title .sec-tog,
body:not([data-tier="pro"]) .right .section-title .sec-info-btn {
  display: inline-flex;
}

/* ── Studio cards: match indicator dots/stars only mean something
      when a filter is applied (Free has no filters). ── */
body:not([data-tier="pro"]) .skill-match-star,
body:not([data-tier="pro"]) .role-match-circle,
body:not([data-tier="pro"]) .jc-match-circle,
body:not([data-tier="pro"]) .role-match-dot,
body:not([data-tier="pro"]) .jc-match-dot {
  display: none !important;
}

/* ── Posting cards (.pcard) keep the head row title + location +
      date visible. Everything else inside the card - action buttons,
      skills popover trigger, meta chips, copy/lang/view buttons -
      is Pro-only. ── */
body:not([data-tier="pro"]) .pcard-actions,
body:not([data-tier="pro"]) .pskills-panel,
body:not([data-tier="pro"]) .pcard-meta-row {
  display: none !important;
}

/* Disable pcard expansion for Free since the expandable area is
   empty anyway (pcard-body contents are all Pro-only). Click on
   pcard-head does nothing instead of "open empty drawer". The
   studio "site" link stays clickable - it lives on studio-head,
   above the pcard. */
body:not([data-tier="pro"]) .pcard-head {
  cursor: default;
  pointer-events: none;
}

/* ── Pro-block upsell card lives at the bottom of the left panel
      with the .pro-block class. For Pro users it's redundant; for
      Free it's the call-to-action that anchors the whole austere
      view. ── */
body[data-tier="pro"] .pro-block { display: none !important; }

/* ── Right panel calibration (added 2026-05-23):
      Free should NOT see postings inside a studio. The row stays
      visible (name + city + site link) but the click no longer
      expands to reveal individual job postings. Also drop the NEW
      badge and the "N postings" counter from the row so it reads
      as a clean directory entry. The site link stays interactive
      via a pointer-events override. ── */
body:not([data-tier="pro"]) .studio-head {
  pointer-events: none;
  cursor: default;
}
body:not([data-tier="pro"]) .studio-head a.icon-btn {
  pointer-events: auto;
  cursor: pointer;
}
body:not([data-tier="pro"]) .studio-head .new-badge { display: none !important; }
body:not([data-tier="pro"]) .studio-right { display: none !important; }
body:not([data-tier="pro"]) .studio-body { display: none !important; }

/* ════════════════════════════════════════════════════════════════
   EMBEDDED MODE — Dashboard inside the Pro SPA shell.

   Standalone dashboard (default) uses an app-shell layout: body is a
   flex column locked to 100vh, `.main` takes the remainder and the
   inner `.left`/`.right` panes scroll independently with a sticky
   `.filter-bar` at top:63px. That's tuned for direct page loads where
   dashboard IS the whole app.

   When the same dashboard is injected into the Pro SPA shell (which
   already provides its own topbar and footer), those rules collide:
   doubled scrollbars, broken sticky offsets, body containment
   clipping the page below the fold.

   The Pro shell signals embedded mode by rendering `<body
   class="is-embedded">` (see workers/src/utils/proShell.ts +
   workers/src/routes/mainPages.ts). The rules below flip the layout
   to a normal scrollable page: body grows with content, page-level
   scroll, filter-bar becomes inline. Two-column .left/.right split
   is preserved horizontally (no narrow-viewport stacking unless the
   existing @media query kicks in) but the internal overflow on each
   pane is released so window scroll handles long content.

   Specificity: `body.is-embedded` (0,0,1,1) beats `html, body`
   (0,0,0,1 each) on its own — `!important` here just guards against
   the original rule being `!important` (it is).
   ════════════════════════════════════════════════════════════════ */

/* Preserve the standalone dashboard's two-pane UX inside the Pro shell:
   left + right panels each get their own scroll, the page itself does
   not. Layout has to be re-anchored against the shell chrome (shell
   .topbar above, shell .footer below) instead of the standalone <nav>. */
html:has(body.is-embedded) {
  height: 100vh !important;
  overflow: hidden !important;
}
body.is-embedded {
  height: 100vh !important;
  min-height: 100vh !important;
  overflow: hidden !important;
  display: flex !important;
  flex-direction: column !important;
}
/* Shell chrome rows (topbar + footer) keep their natural height. */
body.is-embedded > .topbar,
body.is-embedded > .footer {
  flex-shrink: 0 !important;
}
/* Shell <main> wraps the injected fragment. Take the remaining height
   and become a flex column itself so the inner .header / .filter-bar /
   .main chain can size against it. min-height:0 unlocks shrink. */
body.is-embedded > main {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  display: flex !important;
  flex-direction: column !important;
  overflow: hidden !important;
  margin-top: 0 !important;
}
body.is-embedded .header,
body.is-embedded .filter-bar {
  flex-shrink: 0 !important;
  position: static !important;
  top: auto !important;
  z-index: auto !important;
}
body.is-embedded .main {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  height: auto !important;
  display: flex !important;
  overflow: hidden !important;
  margin-top: 0 !important;
}
body.is-embedded .left,
body.is-embedded .right {
  overflow: auto !important;
  height: 100% !important;
  overscroll-behavior: contain !important;
}

/* ── Embedded mobile (≤860px) ──────────────────────────────────────
   The app-shell rules above lock the EMBEDDED dashboard (signed-in Pro
   shell) to a single 100vh viewport with two side-by-side scroll panes.
   That is correct on desktop but breaks on a phone: the page can't scroll
   and the two panes collapse to height 0 — the whole .left column
   (Demand Overview / Skill Demand / Salaries / Trend) vanishes.

   The standalone dashboard already has this override (see the
   `@media (max-width:860px) { html, body { height:auto; overflow:visible } }`
   block higher up), but those plain `html, body` / `.left` selectors lose
   on specificity to `body.is-embedded ...` (0,0,2,1), so the embedded
   branch needs its OWN narrow-viewport release. Mirror the standalone
   mobile behaviour: free the height + overflow so the window scrolls and
   stack .left over .right.

   ⚠ Pro shell is a permanent part of the system — fix mobile HERE, inside
   the embedded branch; never bypass/remove the shell. See
   docs/CLAUDE_RULES.md "Архитектурный инвариант: Pro shell".

   overflow-x is HIDDEN (not visible) on the page + wrapper: the filter bar
   (.filter-row) is an intentional horizontal-swipe strip (overflow-x:auto,
   nowrap) and a few left-panel boxes (salary filters) run wider than a
   phone. While the standalone app-shell clipped all that with its
   `overflow:hidden`, switching to `overflow:visible` to unlock vertical
   page scroll ALSO un-clipped that horizontal spill → the whole page
   scrolled sideways. Clipping only the X axis here keeps vertical scroll
   working while killing the sideways scroll; the filter strip still swipes
   on its own internal overflow-x:auto. (overflow-y:visible computes to auto
   alongside overflow-x:hidden — fine, content height is auto so nothing
   actually scrolls at that level; the page scrolls on <html>.) */
@media (max-width: 860px) {
  html:has(body.is-embedded) { height: auto !important; overflow-x: hidden !important; overflow-y: visible !important; }
  body.is-embedded {
    height: auto !important;
    min-height: 0 !important;
    overflow-x: hidden !important;
    overflow-y: visible !important;
  }
  body.is-embedded > main {
    overflow-x: hidden !important;
    overflow-y: visible !important;
    height: auto !important;
    min-height: 0 !important;
  }
  body.is-embedded .main {
    flex-direction: column !important;
    overflow: visible !important;
    height: auto !important;
  }
  body.is-embedded .left,
  body.is-embedded .right {
    overflow: visible !important;
    height: auto !important;
    width: 100% !important;
  }
}
