diff --git a/app/assets/javascripts/api/vulnerability.js.coffee b/app/assets/javascripts/api/vulnerability.js.coffee
index ecd0bc5c7..6d0251f51 100644
--- a/app/assets/javascripts/api/vulnerability.js.coffee
+++ b/app/assets/javascripts/api/vulnerability.js.coffee
@@ -118,7 +118,6 @@ $(document).ready ->
$('.bdsa-search-clear').show()
else
$('.bdsa-search-clear').hide()
- $('.bdsa-search-error').hide()
$('.bdsa-search-clear').click () ->
$('.bdsa-search-input').val('').focus()
$(this).hide()
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 1c991246d..4cdcae0b5 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -31,6 +31,13 @@
#= require slick.min
+$(document).on 'click', '.flash-close', (e) ->
+ e.preventDefault()
+ $alert = $(e.currentTarget).closest('.alert')
+ $flashMsg = $alert.closest('#flash-msg')
+ $target = if $flashMsg.length then $flashMsg else $alert
+ $target.fadeOut 200, -> $target.remove()
+
$(document).on 'page:change', ->
StackShow.init()
Expander.init()
diff --git a/app/assets/javascripts/charts.js b/app/assets/javascripts/charts.js
index b6469f31b..4ec173d41 100644
--- a/app/assets/javascripts/charts.js
+++ b/app/assets/javascripts/charts.js
@@ -148,6 +148,12 @@ var Charts = {
width: 950,
lang: {
thousandsSep: ','
+ },
+ exporting: {
+ enabled: false
+ },
+ credits: {
+ enabled: false
}
})
@@ -182,6 +188,7 @@ var Charts = {
}
},
+
commit_volume_formatter: function() {
return '' + this.series.name + '
' + this.y + ' Commits (' + Math.floor(this.percentage) + '%)';
}
diff --git a/app/assets/javascripts/compare_accordion.js b/app/assets/javascripts/compare_accordion.js
new file mode 100644
index 000000000..f6896d33e
--- /dev/null
+++ b/app/assets/javascripts/compare_accordion.js
@@ -0,0 +1,30 @@
+// Mobile Compare Projects Accordion Functionality
+document.addEventListener('click', function(e) {
+ var accordionHeader = e.target.closest('.accordion-header');
+ if (accordionHeader) {
+ e.preventDefault();
+
+ var section = accordionHeader.parentElement;
+ var content = section.querySelector('.accordion-content');
+ var icon = accordionHeader.querySelector('i');
+ var isOpen = section.classList.contains('active');
+
+ if (isOpen) {
+ // Close this section
+ section.classList.remove('active');
+ content.style.maxHeight = null;
+ if (icon) {
+ icon.classList.remove('icon-chevron-up');
+ icon.classList.add('icon-chevron-down');
+ }
+ } else {
+ // Open this section
+ section.classList.add('active');
+ content.style.maxHeight = content.scrollHeight + 'px';
+ if (icon) {
+ icon.classList.remove('icon-chevron-down');
+ icon.classList.add('icon-chevron-up');
+ }
+ }
+ }
+});
diff --git a/app/assets/javascripts/contributors_cards.js b/app/assets/javascripts/contributors_cards.js
new file mode 100644
index 000000000..59e5bedd2
--- /dev/null
+++ b/app/assets/javascripts/contributors_cards.js
@@ -0,0 +1,33 @@
+document.addEventListener('click', function(e) {
+ // Handle contributor and enlistment card headers
+ var cardHeader = e.target.closest('.contributor-card-item .card-item-header, .enlistment-card-item .card-item-header');
+ if (cardHeader) {
+ // Skip if clicking a link
+ if (e.target.closest('a, .contributor-link')) {
+ return;
+ }
+ e.preventDefault();
+ cardHeader.closest('.contributor-card-item, .enlistment-card-item').classList.toggle('expanded');
+ return;
+ }
+
+ // Handle about code locations card header
+ var aboutHeader = e.target.closest('.about-code-locations-card .card-header');
+ if (aboutHeader) {
+ aboutHeader.closest('.about-code-locations-card').classList.toggle('expanded');
+ return;
+ }
+
+ // Handle about account basics card header
+ var basicsHeader = e.target.closest('.about-account-basics-card .card-header');
+ if (basicsHeader) {
+ basicsHeader.closest('.about-account-basics-card').classList.toggle('expanded');
+ return;
+ }
+
+ // Handle about project basics card header
+ var projectBasicsHeader = e.target.closest('.about-project-basics-card .card-header');
+ if (projectBasicsHeader) {
+ projectBasicsHeader.closest('.about-project-basics-card').classList.toggle('expanded');
+ }
+});
diff --git a/app/assets/javascripts/demographics.js.coffee b/app/assets/javascripts/demographics.js.coffee
index 69a951832..df770485c 100644
--- a/app/assets/javascripts/demographics.js.coffee
+++ b/app/assets/javascripts/demographics.js.coffee
@@ -1,21 +1,51 @@
ProjectDemographics =
+ chart: null
+
+ DESCRIPTIONS:
+ 'Inactive': 'No recent activity'
+ 'Very Low': 'Minimal activity'
+ 'Low': 'Low activity'
+ 'Moderate': 'Moderate activity'
+ 'High': 'High activity'
+ 'Very High': 'Very high activity'
+ 'New': 'Newly added project'
+
init: () ->
- return if $('#project_demographics').length == 0
+ return if $('#demographics_chart').length == 0
$.ajax
url: $('#demographics_chart').data('src')
cache: false
success: (data) ->
return if (data == null)
- chart = new Highcharts.Chart(data);
- ProjectDemographics.tooltip_formatter(chart)
+ data.tooltip ||= {}
+ data.tooltip.formatter = () ->
+ name = if @point?.name then @point.name else @series?.name or ''
+ pct = if @y? then @y else 0
+ desc = ProjectDemographics.DESCRIPTIONS[name] or ''
+ isMobile = window.innerWidth <= 768
+ if isMobile
+ "#{name}#{pct}%"
+ else
+ descHtml = if desc then "#{desc}" else ''
+ "#{name}#{descHtml}#{pct}%"
+
+ # On touch/mobile devices, disable allowPointSelect so tap shows tooltip
+ # instead of triggering slice selection animation
+ isTouch = 'ontouchstart' of window or navigator.maxTouchPoints > 0
+ if isTouch
+ data.plotOptions ||= {}
+ data.plotOptions.pie ||= {}
+ data.plotOptions.pie.allowPointSelect = false
+ data.plotOptions.pie.stickyTracking = true
- tooltip_formatter: (chart) ->
- chart.tooltip.options.formatter = () ->
- if this.point.name
- "#{this.point.name}: #{this.y}%"
- else
- "#{this.series.name}: #{this.y}%"
+ ProjectDemographics.chart = new Highcharts.Chart(data)
+
+ reflow: () ->
+ ProjectDemographics.chart.reflow() if ProjectDemographics.chart
$(document).on 'page:change', ->
ProjectDemographics.init()
+
+$(window).on 'resize', ->
+ ProjectDemographics.reflow()
diff --git a/app/assets/javascripts/dropdown_handler.js b/app/assets/javascripts/dropdown_handler.js
new file mode 100644
index 000000000..f9aea4967
--- /dev/null
+++ b/app/assets/javascripts/dropdown_handler.js
@@ -0,0 +1,71 @@
+// Dropdown menu handler for logged user menu
+(function($) {
+ 'use strict';
+
+ function initDropdown() {
+ var $dropdown = $('#logged_user_menu');
+
+ if ($dropdown.length === 0) {
+ return; // Dropdown not found (user not logged in)
+ }
+
+ var $toggle = $dropdown.find('.dropdown-toggle');
+ var $menu = $dropdown.find('.dropdown-menu');
+
+ // Remove any existing event handlers
+ $toggle.off('click.userDropdown');
+ $(document).off('click.userDropdown keydown.userDropdown');
+ $menu.find('a').off('click.userDropdown');
+
+ // Toggle dropdown on click
+ $toggle.on('click.userDropdown', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ var wasOpen = $dropdown.hasClass('open');
+
+ // Close all dropdowns first
+ $('.dropdown').removeClass('open');
+
+ // Toggle this dropdown
+ if (!wasOpen) {
+ $dropdown.addClass('open');
+ }
+
+ return false;
+ });
+
+ // Close dropdown when clicking outside
+ $(document).on('click.userDropdown', function(e) {
+ var $target = $(e.target);
+ if (!$dropdown.is($target) && $dropdown.has($target).length === 0) {
+ $dropdown.removeClass('open');
+ }
+ });
+
+ // Close dropdown when clicking a menu item
+ $menu.find('a').on('click.userDropdown', function() {
+ setTimeout(function() {
+ $dropdown.removeClass('open');
+ }, 150);
+ });
+
+ // Close dropdown on ESC key
+ $(document).on('keydown.userDropdown', function(e) {
+ if (e.keyCode === 27) {
+ $dropdown.removeClass('open');
+ }
+ });
+ }
+
+ // Initialize when DOM is ready
+ $(document).ready(function() {
+ initDropdown();
+ });
+
+ // Re-initialize on Turbolinks page change
+ $(document).on('page:change', function() {
+ initDropdown();
+ });
+
+})(jQuery);
diff --git a/app/assets/javascripts/enlistments.js.coffee b/app/assets/javascripts/enlistments.js.coffee
index 43df16d43..9dd71da81 100644
--- a/app/assets/javascripts/enlistments.js.coffee
+++ b/app/assets/javascripts/enlistments.js.coffee
@@ -14,7 +14,7 @@ class App.EnlistmentSelect
showSpinnerAndSubmit = ->
$(this).attr('disabled', 'disabled')
$('.enlistment .spinner').show()
- $('.well.enlistment form').submit()
+ $('.enlistment form').submit()
hideAllScmInfo = ->
$('.enlistment .scm_info').hide()
diff --git a/app/assets/javascripts/explore.js.coffee b/app/assets/javascripts/explore.js.coffee
index 10e85e195..7695531cf 100644
--- a/app/assets/javascripts/explore.js.coffee
+++ b/app/assets/javascripts/explore.js.coffee
@@ -1,6 +1,19 @@
+$(document).on 'click', '.tag-search-btn', ->
+ tag = $(this).siblings('.tag-input').val()
+ if tag.length > 0
+ window.location.href = '/tags?names=' + encodeURIComponent(tag)
+ return false
+
+$(document).on 'keydown', '.tag-input', (e) ->
+ if e.which == 13
+ e.preventDefault()
+ tag = $(this).val()
+ if tag.length > 0
+ window.location.href = '/tags?names=' + encodeURIComponent(tag)
+ return false
App.Explore =
init: () ->
- return if $('#explore_projects_page').length == 0
+ return if $('#explore_projects_page').length == 0 && $('.explore-projects-page').length == 0
$('#explore_search_form .icon-search').click (e) ->
e.preventDefault()
@@ -13,16 +26,16 @@ App.Explore =
$(this).siblings('.icon-search').trigger('click')
return false
- $('.similar_projects .icon-search').click (e) ->
+ $('.similar_projects .icon-search, .similar-card .search-icon-btn').click (e) ->
$(this).parents('form:first').trigger('submit')
$('form[rel=similar_project_jump]').submit (e) ->
- projectId = $("#project").val()
+ projectId = $(this).find('input[name="project"]').val()
if projectId != ''
e.preventDefault()
window.location.href = "/p/#{projectId.toLowerCase()}/similar"
else
- $('span.error').removeClass('hidden')
+ $(this).find('span.error').removeClass('hidden')
false
$('form[rel=sort_filter] select').change () ->
@@ -30,5 +43,76 @@ App.Explore =
$(this).attr('disabled', 'disabled')
$(this).parents('form').attr('action', document.location).submit()
+ # Discover More collapsible toggle (mobile/tablet)
+ $(document).on 'click', '.discover-toggle', (e) ->
+ content = $(this).siblings('.discover-content')
+ content.toggleClass('show')
+ chevron = $(this).find('.chevron')
+ chevron.text(if content.hasClass('show') then '▲' else '▼')
+
+ # Language filter dropdown toggle
+ $(document).on 'click', '.language-toggle', (e) ->
+ e.stopPropagation()
+ menu = $(this).siblings('.language-dropdown-menu')
+ menu.toggleClass('show')
+
+ $(document).on 'click', (e) ->
+ unless $(e.target).closest('.language-dropdown').length
+ $('.language-dropdown-menu').removeClass('show')
+
$(document).on 'page:change', ->
App.Explore.init()
+
+# ── PAI Tooltip ──────────────────────────────────────────────────────────────
+# Runs once at module level; uses event delegation so no re-binding needed.
+# position:fixed tooltip appended to
{y}
'} }], + series: [{data: [data], dataLabels: { format: '{y}
'} }], exporting: { enabled: false } @@ -86,18 +105,50 @@ var GaugeProgress = { var OrgsFilter = { init: function(){ - $('#explore_orgs_page .chzn-select').chosen().change(function(){ - $('.busy#commit_volume_loader').toggleClass('hidden') - $('#orgs_by_30_days_volume table').toggleClass('hidden') + var filterOrgs = function(filterValue) { + $('.busy#commit_volume_loader').removeClass('hidden') $.ajax({ - url: '/explore/orgs_by_thirty_day_commit_volume?format=js&filter='+ $(this).val(), + url: '/explore/orgs_by_thirty_day_commit_volume?format=js&org_type='+ filterValue, type: "GET", success: function(){ - $('#orgs_by_30_days_volume table').toggleClass('hidden') - $('.busy#commit_volume_loader').toggleClass('hidden') + $('.busy#commit_volume_loader').addClass('hidden') } }) - }) + }; + + // Legacy chosen dropdown support + $('#explore_orgs_page .chzn-select').chosen().change(function(){ + filterOrgs($(this).val()); + }); + + // Custom dropdown for org type filter - handle button toggle and aria-expanded + var $orgDropdown = $('#orgs_by_30_days_volume .custom-sort-dropdown'); + var $orgButton = $orgDropdown.find('.sort-dropdown-btn'); + + $orgButton.on('click', function() { + var isOpen = $orgDropdown.hasClass('open'); + $orgButton.attr('aria-expanded', !isOpen); + }); + + // Close dropdown when clicking outside + $(document).on('click', function(e) { + if (!$(e.target).closest('#orgs_by_30_days_volume .custom-sort-dropdown').length) { + $orgDropdown.removeClass('open'); + $orgButton.attr('aria-expanded', 'false'); + } + }); + + // Handle dropdown item clicks + $('#orgs_by_30_days_volume .sort-dropdown-item').on('click', function(e) { + e.preventDefault(); + var value = $(this).data('value'); + + // Close dropdown and update aria-expanded + $orgDropdown.removeClass('open'); + $orgButton.attr('aria-expanded', 'false'); + + filterOrgs(value); + }); } } @@ -120,5 +171,7 @@ var OrgClaimProject = { } } $(document).ready(function() { - OrgClaimProject.init() + GaugeProgress.init(); + OrgsFilter.init(); + OrgClaimProject.init(); }); diff --git a/app/assets/javascripts/page_loader.js b/app/assets/javascripts/page_loader.js new file mode 100644 index 000000000..d24cf0597 --- /dev/null +++ b/app/assets/javascripts/page_loader.js @@ -0,0 +1,64 @@ +// Show loader immediately when user clicks a link to a slow page. +// Hide it once the destination page's DOM is ready. + +(function() { + var SLOW_PAGE_PATTERNS = [ + /^\/people(\/|\?|$)/, + /^\/explore\/projects(\/|\?|$)/, + /^\/explore\/orgs(\/|\?|$)/, + /^\/committers(\/|\?|$)/, + /^\/accounts(\/|\?|$)/, + /^\/p\/[^/]+\/commits(\/|\?|$)/ + ]; + + function isSlowPage(url) { + try { + var path = new URL(url, window.location.origin).pathname; + return SLOW_PAGE_PATTERNS.some(function(pattern) { + return pattern.test(path); + }); + } catch (e) { + return false; + } + } + + function showLoader() { + var loader = document.getElementById('page-loader'); + if (loader) loader.classList.remove('hidden'); + } + + function hideLoader() { + var loader = document.getElementById('page-loader'); + if (loader) loader.classList.add('hidden'); + } + + // Show loader when clicking links to slow pages + document.addEventListener('click', function(e) { + // Skip if event was already prevented or not a left-click + if (e.defaultPrevented || e.button !== 0) return; + // Skip if modifier keys held (would open in new tab/window) + if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; + + var link = e.target.closest('a[href]'); + if (!link) return; + + // Skip if link targets something other than current window + if (link.target && link.target.toLowerCase() !== '_self') return; + + var href = link.getAttribute('href'); + // Skip hash-only links + if (!href || href.charAt(0) === '#') return; + + if (isSlowPage(href)) { + showLoader(); + } + }); + + // Hide loader once this page's DOM is ready + document.addEventListener('DOMContentLoaded', hideLoader); + + // Hide loader when page is restored from bfcache (browser back/forward) + window.addEventListener('pageshow', function(e) { + if (e.persisted) hideLoader(); + }); +})(); diff --git a/app/assets/javascripts/positions.js.coffee b/app/assets/javascripts/positions.js.coffee index c65a4b227..d677e8572 100644 --- a/app/assets/javascripts/positions.js.coffee +++ b/app/assets/javascripts/positions.js.coffee @@ -63,6 +63,14 @@ class SetupProjectAndLanguagesSections $(this).addClass('hidden') $('a.expanded').removeClass('hidden') $('#project-experience-form').find('input').autocomplete({ source: '/autocompletes/project' }) + # Defer chosen re-init until the browser has reflowed the now-visible section. + # Without setTimeout, chosen reads offsetWidth before layout and gets 0px. + $select = $('#position_languages .chzn-select') + setTimeout -> + $select.chosen('destroy') + $select.chosen() + $('#position_languages .chosen-container').css('width', '100%') + , 0 $('a.expanded').click -> $('#additional-fields').addClass('hidden') $(this).addClass('hidden') diff --git a/app/assets/javascripts/project_badges.js.coffee b/app/assets/javascripts/project_badges.js.coffee index 0f043bdc5..206c175de 100644 --- a/app/assets/javascripts/project_badges.js.coffee +++ b/app/assets/javascripts/project_badges.js.coffee @@ -7,6 +7,11 @@ ProjectNewBadge = initializeNewBadge: (_klass) -> $("#add_badge_btn").on 'click', (event) -> $('#add_badge_btn, #add_new_badge_form').toggle() + # Re-initialize chosen after showing the form row — it was first + # initialized on a display:none element, so width/position may be wrong. + if $('#add_new_badge_form').is(':visible') + $('#add_new_badge_form .chzn-select').chosen('destroy') + $('#add_new_badge_form .chzn-select').chosen() handleEvents: (_klass) -> $('#project_badges_page').on 'change', '#select_project_badge', (event) -> diff --git a/app/assets/javascripts/project_rating.js.coffee b/app/assets/javascripts/project_rating.js.coffee index a3a61a9e0..8f761fe9c 100644 --- a/app/assets/javascripts/project_rating.js.coffee +++ b/app/assets/javascripts/project_rating.js.coffee @@ -1,3 +1,88 @@ +STAR_COLOR_FILLED = '#ffb91a' +STAR_COLOR_EMPTY = '#d1d5db' + +getCsrfToken = -> + meta = document.querySelector('meta[name="csrf-token"]') + if meta then meta.getAttribute('content') else '' + +updateStarDisplay = (buttons, score) -> + buttons.each -> + svg = $(this).find('.star-svg') + rating = parseInt($(this).data('rating'), 10) + if rating <= score + svg.attr('fill', STAR_COLOR_FILLED).attr('stroke', STAR_COLOR_FILLED) + else + svg.attr('fill', 'none').attr('stroke', STAR_COLOR_EMPTY) + +ratingAjax = (method, url, ratingContent) -> + $.ajax + url: url + type: method + headers: + 'X-CSRF-Token': getCsrfToken() + dataType: 'html' + success: (html) -> + if ratingContent.length + ratingContent.replaceWith(html) + initInteractiveStars() + error: (xhr) -> + console.error('Rating request failed:', xhr.status, xhr.statusText) + +initInteractiveStars = -> + $('.interactive-stars').each -> + container = $(this) + return if container.data('bound') + container.data('bound', true) + + buttons = container.find('.star-btn') + rateUrl = container.data('rate-url') + unrateUrl = container.data('unrate-url') + loggedIn = container.data('logged-in') is true or container.data('logged-in') is 'true' + userScore = parseInt(container.data('user-score'), 10) or 0 + showParam = encodeURIComponent(container.data('show') or 'projects/show/community_rating') + + updateStarDisplay(buttons, userScore) + + buttons.each -> + btn = $(this) + rating = parseInt(btn.data('rating'), 10) + + btn.on 'mouseenter', -> + updateStarDisplay(buttons, rating) + + btn.on 'mouseleave', -> + updateStarDisplay(buttons, userScore) + + btn.on 'click', (e) -> + e.preventDefault() + e.stopPropagation() + + unless loggedIn + window.location.href = '/sessions/new?return_to=' + encodeURIComponent(window.location.href) + return + + newScore = if rating is userScore then 0 else rating + ratingContent = container.closest('.rating-content') + + if newScore is 0 + ratingAjax('DELETE', unrateUrl + '?show=' + showParam, ratingContent) + else + ratingAjax('POST', rateUrl + '?score=' + newScore + '&show=' + showParam, ratingContent) + + # Clear rating button + $('.clear-rating-btn').each -> + btn = $(this) + return if btn.data('bound') + btn.data('bound', true) + + btn.on 'click', (e) -> + e.preventDefault() + e.stopPropagation() + url = btn.data('url') + ratingContent = btn.closest('.rating-content') + ratingAjax('DELETE', url, ratingContent) + +# Old jrating-based rating system (used on non-redesigned pages) App.ProjectRating = init: -> $("#rating_spinner").hide() @@ -40,3 +125,4 @@ App.ProjectRating = $(document).on 'page:change', -> App.ProjectRating.init() + initInteractiveStars() diff --git a/app/assets/javascripts/project_swimlanes.js b/app/assets/javascripts/project_swimlanes.js new file mode 100644 index 000000000..270f4e96f --- /dev/null +++ b/app/assets/javascripts/project_swimlanes.js @@ -0,0 +1,30 @@ +// Project Swimlanes - Show More/Less functionality +document.addEventListener('DOMContentLoaded', function() { + var buttons = document.querySelectorAll('.show_more_btn'); + + for (var i = 0; i < buttons.length; i++) { + buttons[i].addEventListener('click', function() { + var swimlane = this.getAttribute('data-swimlane'); + var swimlaneContent = document.querySelector('.swimlane_content[data-swimlane="' + swimlane + '"]'); + var hiddenCards = swimlaneContent.querySelectorAll('.hidden_card'); + var isExpanded = this.textContent.trim() === 'Show Less'; + + // Toggle visibility of hidden cards + for (var j = 0; j < hiddenCards.length; j++) { + if (isExpanded) { + hiddenCards[j].style.display = 'none'; + } else { + hiddenCards[j].style.display = 'block'; + } + console.log('Card', j, 'classes:', hiddenCards[j].className, 'display:', window.getComputedStyle(hiddenCards[j]).display); + } + + // Toggle button text + if (isExpanded) { + this.textContent = 'Show More'; + } else { + this.textContent = 'Show Less'; + } + }); + } +}); diff --git a/app/assets/javascripts/projects.js.coffee b/app/assets/javascripts/projects.js.coffee index 4fb5fb2f4..f7ca1c34d 100644 --- a/app/assets/javascripts/projects.js.coffee +++ b/app/assets/javascripts/projects.js.coffee @@ -32,12 +32,20 @@ class App.ProjectForm class App.SimilarProjects constructor: -> return unless $('#projects_show_page').length - $('#similar_projects').html('') + $desktopDiv = $('#similar_projects') + $mobileDiv = $('#similar_projects_mobile') + return unless $desktopDiv.length || $mobileDiv.length + $desktopDiv.html('') + $mobileDiv.html('') $('#related_spinner').removeClass('hidden') - projectId = $('#similar_projects').data('projectId') + $('#related_spinner_mobile').removeClass('hidden') + projectId = ($desktopDiv.length && $desktopDiv.data('projectId')) || $mobileDiv.data('projectId') $.ajax url: "/p/#{ projectId }/similar_by_tags.js" + success: (data) -> + $mobileDiv.html($desktopDiv.html()) complete: -> $('#related_spinner').addClass('hidden') + $('#related_spinner_mobile').addClass('hidden') $(document).on 'page:change', -> new App.SimilarProjects() diff --git a/app/assets/javascripts/search_dingus.js b/app/assets/javascripts/search_dingus.js index f98d1251a..140dafccc 100644 --- a/app/assets/javascripts/search_dingus.js +++ b/app/assets/javascripts/search_dingus.js @@ -19,59 +19,118 @@ var ohloh = (function builder($) { ui: { init: function(){ var $scope = $('.ux-dropdown'); - var $search_text_field = $scope.find('.text'); - var dropdownHead = $('a span.selection', $scope); - var getSelectedValue = function() { - return dropdownHead.first().attr('val'); - }; - $('.dropdown-menu li a', $scope).click(function() { + var $search_text_field = $scope.find('.text').add($scope.siblings('.header-search-input')); + var dropdownHead = $('button span.selection, a span.selection', $scope); + $('.dropdown-menu .dropdown-item', $scope).click(function() { var selectedText = $(this).attr('val') dropdownHead.attr('val',selectedText) dropdownHead.html( $(this).html() ) - dropdownHead.parents('form').attr('action',selectedText) + // Do NOT set form action here; URL will be built on submit + // Update active class + $('.dropdown-menu .dropdown-item', $scope).removeClass('active') + $(this).addClass('active') if(selectedText != "//code.ohloh.net/search"){ dropdownHead.parents('form').removeAttr('target'); } }); - $('ul.dropdown-menu li a', $scope).on('click', 'a', function() { + $('.dropdown-menu .dropdown-item', $scope).on('click', function() { var $this = $(this); var section_name = $this.text(); - $('ul.dropdown-menu li a', $scope).removeClass('selected'); + $('.dropdown-menu .dropdown-item', $scope).removeClass('selected'); $this.addClass('selected'); - $('.ux-dropdown a span.selection', $scope).html(section_name); + $('.ux-dropdown button span.selection', $scope).html(section_name); }); $(document).ajaxStop($.unblockUI); if( (/\/p(\/|\?|$)/ig).test(window.location.href) ) { - $('a', $scope).removeClass('default'); - $('a[val="p"]', $scope).addClass('default'); + $('.dropdown-item', $scope).removeClass('default'); + $('.dropdown-item[val="p"]', $scope).addClass('default'); } if( (/\/orgs(\/|\?|$)/ig).test(window.location.href) ) { - $('a', $scope).removeClass('default'); - $('a[val="orgs"]', $scope).addClass('default'); + $('.dropdown-item', $scope).removeClass('default'); + $('.dropdown-item[val="orgs"]', $scope).addClass('default'); } if( (/\/(posts|forums)(\/|\?|$)/ig).test(window.location.href) ) { - $('a', $scope).removeClass('default'); - $('a[val="posts"]', $scope).addClass('default'); + $('.dropdown-item', $scope).removeClass('default'); + $('.dropdown-item[val="posts"]', $scope).addClass('default'); } if( (/\/(people|accounts|committers)(\/|\?|$)/ig).test(window.location.href) ) { - $('a', $scope).removeClass('default'); - $('a[val="people"]', $scope).addClass('default'); + $('.dropdown-item', $scope).removeClass('default'); + $('.dropdown-item[val="people"]', $scope).addClass('default'); } - $('a.default', $scope).trigger('click'); + $('.dropdown-item.default', $scope).trigger('click'); - $('.dropdown-menu li a', $scope).on('click', 'a', function(){ + $('.dropdown-menu .dropdown-item', $scope).on('click', function(){ $('input[name="query"].search').trigger('click').focus(); }); + // Toggle sort dropdown open/close on button click. + // NOTE: sort button intentionally has NO data-toggle="dropdown" so Bootstrap's + // dropdown plugin does not interfere — both would toggle .open on the same click + // and cancel each other out, keeping the menu permanently closed. + $(document).on('click', '.sort-dropdown-btn', function() { + var $dropdown = $(this).closest('.custom-sort-dropdown'); + $('.custom-sort-dropdown').not($dropdown).removeClass('open'); + $dropdown.toggleClass('open'); + }); + + // Close any open sort dropdown when clicking outside it + $(document).on('click', function(e) { + if (!$(e.target).closest('.custom-sort-dropdown').length) { + $('.custom-sort-dropdown.open').removeClass('open'); + } + }); + + // Handle custom sort dropdown + $('.custom-sort-dropdown .sort-dropdown-item').on('click', function(e) { + e.preventDefault(); + var $item = $(this); + var $dropdown = $item.closest('.custom-sort-dropdown'); + var selectedValue = $item.data('value'); + var selectedLabel = $item.text(); + + // Update button text + $dropdown.find('.selection').text(selectedLabel).data('value', selectedValue); + + // Update hidden input + $dropdown.find('.sort-value-input').val(selectedValue); + + // Update active class + $dropdown.find('.sort-dropdown-item').removeClass('active'); + $item.addClass('active'); + + // Submit form + $dropdown.closest('form').submit(); + }); + + // Handle search input with cancel button + $('#query').on('input', function() { + var $input = $(this); + var $cancelBtn = $input.siblings('.search-cancel-btn'); + + if ($input.val().length > 0) { + $cancelBtn.show(); + } else { + $cancelBtn.hide(); + } + }); + + // Handle search cancel button + $('.search-cancel-btn').on('click', function() { + var $input = $('#query'); + $input.val(''); + $(this).hide(); + $input.focus(); + }); + if( (/\?[query]=.{1,}/ig).test(window.location.href) ) { var q = window.location.href.split('?')[1].split('=')[1]; @@ -83,34 +142,33 @@ var ohloh = (function builder($) { $search_text_field.keydown(function(e){ if(e.which == 13) { e.preventDefault(); - $(this).siblings('.submit').trigger('click'); + $(this).siblings('.submit, .header-search-btn').trigger('click'); return false; } }); - $search_text_field.siblings('.submit').click(function(e) { - var search_term = $.trim($search_text_field.val()); + $search_text_field.siblings('.submit, .header-search-btn').click(function(e) { + var $btn = $(this); + var $field = $btn.siblings('.text, .header-search-input'); + var $local_scope = $btn.closest('form').find('.ux-dropdown'); + var localDropdownHead = $('button span.selection, a span.selection', $local_scope); + var search_term = $.trim($field.val()); if(search_term.length > 0) { e.preventDefault(); - var section = getSelectedValue(), - url_format = "/#{activator}?"+$search_text_field.attr('name')+"=#{query}"; - - var data = { - activator: section, - query: search_term - }; + var section = localDropdownHead.first().attr('val'); + var url = "/" + section + "?query=" + encodeURIComponent(search_term); - if($search_text_field.attr('name') == 's') - url_format += "&ref=Open%20Hub"; + if($field.attr('name') == 's') + url += "&ref=Open%20Hub"; if(window.location.href.indexOf("sort=") > -1) { sort_value = window.location.href.split('sort=')[1].split('&')[0]; - url_format += "&sort=" + sort_value; + url += "&sort=" + sort_value; } - window.location.href = url_format._f(data); + window.location.href = url; } return false; diff --git a/app/assets/javascripts/session_projects.js.coffee b/app/assets/javascripts/session_projects.js.coffee index a3c968661..0487d47d2 100644 --- a/app/assets/javascripts/session_projects.js.coffee +++ b/app/assets/javascripts/session_projects.js.coffee @@ -9,83 +9,128 @@ SessionProjects = url: "/session_projects?#{ timestamp }" success: SessionProjects.success + # Initialize compare checkboxes + SessionProjects.enable() + enable: -> - # Update all checkboxes on page to match those in the menu. + # Update all compare checkboxes on page to match those in the menu. # This is primarily so that state will be cleaned up after back button. - $('.sp_input').prop('checked', false) - $('.sp_form.styled').removeClass('selected') - $('#sp_menu .sp_input').each -> - $(".sp_input[project_id='#{ $(this).attr('project_id') }']").prop('checked', true) - $("#sp_form_#{ $(this).attr('project_id') }").addClass('selected') + $('.compare-checkbox').removeClass('selected') + $('.compare-checkbox i').removeClass('fa-check-square-o').addClass('fa-square-o') - if $('#sp_menu .sp_input').length < 3 + # Mark selected projects from menu + $('#sp_menu .remove-project').each -> + project_id = $(this).data('project-id') + $(".compare-checkbox[data-project-id='#{ project_id }']").addClass('selected') + $(".compare-checkbox[data-project-id='#{ project_id }'] i").removeClass('fa-square-o').addClass('fa-check-square-o') + + if $('#sp_menu .remove-project').length < 3 # All checkboxes are enabled. - $('.sp_input') - .unbind('change') - .bind('change', SessionProjects.change) - .prop('disabled', false) - .parent().removeClass('disabled') + $('.compare-checkbox') + .off('click') + .on('click', SessionProjects.change) + .removeClass('disabled') else # Project limit reached. Can only uncheck checkboxes. - $('.sp_input') - .filter(':checked') - .unbind('change') - .bind('change', SessionProjects.change) - .prop('disabled', false) - .parent().removeClass 'disabled' + $('.compare-checkbox.selected') + .off('click') + .on('click', SessionProjects.change) + .removeClass('disabled') SessionProjects.disableUnchecked() - # Activate the x icon. - $('#sp_menu .sp_input') - .unbind('click') - .bind('click', SessionProjects.change) + # Activate the remove icons in menu. + $('#sp_menu .remove-project') + .off('click') + .on('click', SessionProjects.remove) - # Animate the appearance/disappearance of menu. - height = '0' - height = '2.6em' if $('#sp_menu .sp_input').length - $('#sp_menu').animate { 'min-height': height }, duration: 300 + # Activate toggle button + $('#compare_toggle_btn') + .off('click') + .on('click', SessionProjects.toggleTray) + + # Show/hide the entire compare bar + if $('#sp_menu .remove-project').length > 0 + $('#sp_menu').fadeIn(200) + $('#projects_index_page').addClass('has-compare-tray') + else + $('#sp_menu').fadeOut(200) + $('#projects_index_page').removeClass('has-compare-tray') disableUnchecked: -> - $('.sp_input') - .not(':checked') - .unbind('change') - .prop('disabled', true) - .parent().addClass('disabled') + $('.compare-checkbox') + .not('.selected') + .off('click') + .addClass('disabled') - busy_span: " " - compare_span: "Compare" + toggleTray: -> + $tray = $('.compare-tray-content') + $icon = $('#compare_toggle_btn .toggle-icon') + + if $tray.hasClass('expanded') + $tray.removeClass('expanded') + $icon.removeClass('rotate') + else + $tray.addClass('expanded') + $icon.addClass('rotate') + false change: -> - checked = $(this).is(':checked') - checked = false if $(this).hasClass('icon-remove-sign') - # force false for remove-icons - project_id = $(this).attr('project_id') - sel = $('.sp_input[project_id="' + project_id + '"]') - sel.siblings('span').replaceWith SessionProjects.busy_span - sel.prop('checked', checked).prop 'disabled', true - SessionProjects.disableUnchecked() - if checked + $checkbox = $(this) + return false if $checkbox.hasClass('disabled') + + is_selected = $checkbox.hasClass('selected') + project_id = $checkbox.data('project-id') + + # Show loading state + $checkbox.addClass('disabled') + + if is_selected + # Uncheck $.ajax type: 'POST' - url: '/session_projects?project_id=' + project_id + url: '/session_projects/' + project_id + data: '_method': 'delete' success: SessionProjects.success + error: -> $checkbox.removeClass('disabled') else + # Check $.ajax type: 'POST' - url: '/session_projects/' + project_id - data: '_method': 'delete' + url: '/session_projects?project_id=' + project_id success: SessionProjects.success + error: (xhr) -> + if xhr.status == 403 + alert(xhr.responseText) + $checkbox.removeClass('disabled') + false + + remove: -> + project_id = $(this).data('project-id') + $.ajax + type: 'POST' + url: '/session_projects/' + project_id + data: '_method': 'delete' + success: SessionProjects.success false success: (data, textStatus, jqXHR) -> + # Remember if the tray was expanded + wasExpanded = $('.compare-tray-content').hasClass('expanded') + + # Replace the HTML $('#sp_menu').html(data) - if _(data).isEmpty() - $('#page').css('margin-top', '0px') - else - $('#page').css('margin-top', '52px') - $('.busy').replaceWith(SessionProjects.compare_span) SessionProjects.enable() + + # Restore expanded state if it was open + if wasExpanded + $('.compare-tray-content').addClass('expanded') + $('#compare_toggle_btn .toggle-icon').addClass('rotate') + false $(document).on 'page:change', -> SessionProjects.init() + +# Also initialize on regular page load +$ -> + SessionProjects.init() diff --git a/app/assets/javascripts/show.js.coffee b/app/assets/javascripts/show.js.coffee index b3011db7d..ffd726517 100644 --- a/app/assets/javascripts/show.js.coffee +++ b/app/assets/javascripts/show.js.coffee @@ -5,7 +5,7 @@ PersonSummaryAccountAbout = PersonSummaryAdminPanel = init: () -> - $('#close_admin_panel, #open_admin_panel').click -> + $('#close_admin_panel, #open_admin_panel, .admin_close_text_btn').click -> $('#admin_actions_opened, #admin_actions_closed').toggleClass('hidden') $(document).on 'page:change', -> PersonSummaryAccountAbout.init() diff --git a/app/assets/javascripts/steamgraph.js b/app/assets/javascripts/steamgraph.js index 108b470e1..6f17968b2 100644 --- a/app/assets/javascripts/steamgraph.js +++ b/app/assets/javascripts/steamgraph.js @@ -120,7 +120,9 @@ Streamgraph = { var svg = d3.select("#ohloh_streamgraph").append("svg") .attr("id", "ohloh_stream") - .attr("width", width) + .attr("viewBox", "0 0 " + width + " " + height) + .attr("preserveAspectRatio", "xMidYMid meet") + .attr("width", "100%") .attr("height", height) .attr('class', 'background-watermark'); @@ -181,11 +183,14 @@ Streamgraph = { }); }, populate_legends: function(legends, colors){ - legend_height = Math.min(legends.length * 18 + 5, 300); - $('#ohloh_streamgraph').after(''); - legends.map( function(l, i) { - div = ""+legends[i]+"
"; - $("#streamgraph_legend").append(div); + $('#streamgraph_legend').remove(); + $('#ohloh_streamgraph').after(''); + legends.map(function(l, i) { + var item = "" + + "" + + "" + l + "" + + ""; + $("#streamgraph_legend").append(item); }); }, diff --git a/app/assets/javascripts/theme_toggle.js b/app/assets/javascripts/theme_toggle.js new file mode 100644 index 000000000..7d6c196bd --- /dev/null +++ b/app/assets/javascripts/theme_toggle.js @@ -0,0 +1,183 @@ +// Theme Toggle Functionality +var ThemeToggle = { + COOKIE_NAME: 'theme_preference', + COOKIE_DAYS: 365, + + init: function() { + var self = this; + this.isAuthenticated = this.checkAuthentication(); + + if (this.isAuthenticated) { + this.loadServerThemePreference(function(theme) { + self.applyTheme(theme); + self.bindEvents(); + }); + } else { + var savedTheme = this.getSavedTheme(); + this.applyTheme(savedTheme); + this.bindEvents(); + } + }, + + checkAuthentication: function() { + var metaTag = document.querySelector('meta[name="current-user"]'); + return metaTag && metaTag.getAttribute('content'); + }, + + getCurrentUserId: function() { + var metaTag = document.querySelector('meta[name="current-user"]'); + return metaTag ? metaTag.getAttribute('content') : null; + }, + + loadServerThemePreference: function(callback) { + var userId = this.getCurrentUserId(); + if (!userId) { + callback(this.getSystemTheme()); + return; + } + + var self = this; + fetch('/accounts/' + userId + '/theme_preference.json', { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Accept': 'application/json' + } + }) + .then(function(response) { + if (!response.ok) { + return callback(self.getSystemTheme()); + } + return response.json(); + }) + .then(function(data) { + if (data && data.theme_preference) { + callback(data.theme_preference); + } else { + callback(self.getSystemTheme()); + } + }) + .catch(function(error) { + callback(self.getSystemTheme()); + }); + }, + + saveServerThemePreference: function(theme) { + if (!this.isAuthenticated) { + return; + } + + var userId = this.getCurrentUserId(); + if (!userId) { + return; + } + + fetch('/accounts/' + userId + '/set_theme_preference', { + method: 'POST', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-Token': this.getCsrfToken() + }, + body: JSON.stringify({ theme: theme }) + }) + .then(function(response) { + return response.json(); + }) + .catch(function(error) { + // Silent fail - cookie already set + }); + }, + + getCsrfToken: function() { + var token = document.querySelector('meta[name="csrf-token"]'); + return token ? token.getAttribute('content') : ''; + }, + + getCookie: function(name) { + var nameEQ = name + '='; + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i].trim(); + if (cookie.indexOf(nameEQ) === 0) { + return cookie.substring(nameEQ.length); + } + } + return null; + }, + + setCookie: function(name, value, days) { + var expires = ''; + if (days) { + var date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = '; expires=' + date.toUTCString(); + } + document.cookie = name + '=' + value + expires + '; path=/; SameSite=Lax'; + }, + + getSystemTheme: function() { + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + return 'dark'; + } + return 'light'; + }, + + getSavedTheme: function() { + var cookieTheme = this.getCookie(this.COOKIE_NAME); + if (cookieTheme && (cookieTheme === 'light' || cookieTheme === 'dark')) { + return cookieTheme; + } + return this.getSystemTheme(); + }, + + applyTheme: function(theme) { + var html = document.documentElement; + var moonIcon = document.getElementById('theme-icon-moon'); + var sunIcon = document.getElementById('theme-icon-sun'); + + if (theme === 'dark') { + html.classList.add('dark'); + if (moonIcon) moonIcon.classList.add('hidden'); + if (sunIcon) sunIcon.classList.remove('hidden'); + } else { + html.classList.remove('dark'); + if (moonIcon) moonIcon.classList.remove('hidden'); + if (sunIcon) sunIcon.classList.add('hidden'); + } + + this.setCookie(this.COOKIE_NAME, theme, this.COOKIE_DAYS); + }, + + toggleTheme: function() { + var currentTheme = this.getSavedTheme(); + var newTheme = currentTheme === 'light' ? 'dark' : 'light'; + this.applyTheme(newTheme); + if (this.isAuthenticated) { + this.saveServerThemePreference(newTheme); + } + }, + + bindEvents: function() { + var self = this; + var themeToggleBtn = document.getElementById('theme-toggle'); + + if (themeToggleBtn) { + themeToggleBtn.onclick = function(e) { + e.preventDefault(); + self.toggleTheme(); + return false; + }; + } + } +}; + +// Initialize on DOM ready +$(document).on('page:change', function() { + ThemeToggle.init(); +}); + +// Also initialize immediately if DOM is already loaded +$(document).ready(function() { + ThemeToggle.init(); +}); diff --git a/app/assets/javascripts/type_ahead.js.coffee b/app/assets/javascripts/type_ahead.js.coffee index b6ea3acb2..1d56c9e15 100644 --- a/app/assets/javascripts/type_ahead.js.coffee +++ b/app/assets/javascripts/type_ahead.js.coffee @@ -46,10 +46,12 @@ class App.TypeAhead class App.ChosenSelect constructor: () -> + $(document).on 'chosen:ready', (event, params) -> + $(params.chosen.container).find('.chosen-search-input').attr('aria-label', 'Search') $('.chzn-select').chosen() $('#sort_by .chzn-search').hide() $('.nav-select-container .chzn-search').show() - $('.value-select').chosen() + $('.value-select').not('.chzn-select').chosen() $(document).ready -> new App.ChosenSelect diff --git a/app/assets/javascripts/upload.js.coffee b/app/assets/javascripts/upload.js.coffee index a84e2d920..efde68f8b 100644 --- a/app/assets/javascripts/upload.js.coffee +++ b/app/assets/javascripts/upload.js.coffee @@ -13,6 +13,8 @@ FileUpload = $('input[type="submit"]').removeAttr('disabled') true + $('.ace-file-btn').attr('aria-label', 'Choose file') + $('.new_file_upload').on 'change', () -> if this.files[0].size > $(this).data('max_size') $('input[type="submit"]').attr('disabled', 'disabled') diff --git a/app/assets/stylesheets/account.sass b/app/assets/stylesheets/account.sass index cbdaa6d07..a7e7ab27b 100644 --- a/app/assets/stylesheets/account.sass +++ b/app/assets/stylesheets/account.sass @@ -1,88 +1,509 @@ -#accounts_index_page, #people_index_page - .account_details - width: 220px - margin-left: 15px +// ── People page max-width container ────────────────────────────────────────── +.people-page-container + max-width: 1280px + margin: 0 auto + padding: 32px 16px 0 + +.people-page-header + display: flex + flex-direction: column + gap: 16px + margin-bottom: 32px + @media only all and (min-width: 640px) + flex-direction: row + align-items: center + justify-content: space-between + .people-page-title + margin: 0 + +// ── People & Accounts page headings ────────────────────────────────────────── +.people-page-title + font-size: 24px + font-weight: 700 + color: #111827 + margin: 0 + @media only all and (min-width: 640px) + font-size: 30px + @media only all and (min-width: 1024px) + font-size: 36px + +.people-pagination + margin-bottom: 32px + +.people-section-title + font-size: 20px !important + font-weight: 700 !important + color: #111827 + margin: 0 0 16px + line-height: 1.3 !important + @media only all and (min-width: 640px) + font-size: 24px !important + margin-bottom: 24px + +.accounts-back-link + display: inline-flex + align-items: center + gap: 6px + color: #4b5563 + text-decoration: none + font-size: 14px + margin-bottom: 24px + transition: color 0.2s + &:hover + color: #111827 + text-decoration: none + +.people-more-btn + display: block + width: 100% + background-color: #5A2A82 + color: #ffffff + border: none + padding: 8px 16px + font-weight: 600 + border-radius: 4px + font-size: 14px + text-align: center + text-decoration: none + margin-top: 12px + margin-bottom: 12px + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23) + transition: background-color 0.2s, box-shadow 0.2s + &:hover + background-color: #4A1A72 + color: #ffffff + text-decoration: none + @media only all and (min-width: 640px) + display: inline-block + width: auto + padding: 8px 24px + font-size: 16px + margin-top: 12px + +// ── People Card ─────────────────────────────────────────────────────────────── +.people-card + background: #ffffff + border-radius: 16px + border: 1px solid rgba(229, 231, 235, 0.8) + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24) + transition: border-color 0.3s, box-shadow 0.3s + margin-bottom: 16px + overflow: hidden + cursor: pointer + &:hover + border-color: #5A2A82 + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23) + +.people-card__body + padding: 16px + +// Card row — mobile: column, desktop: row +.people-card__row + display: flex + flex-direction: column + gap: 12px + +// Avatar + info wrapper — on desktop becomes display:contents +// so avatar & info become direct flex children of .people-card__row +.people-card__avatar-info + display: flex + align-items: flex-start + gap: 16px + + img, .gravatar + width: 80px + height: 80px + border-radius: 4px + object-fit: cover + flex-shrink: 0 + +.people-card__info + flex: 1 + min-width: 0 + +.people-card__name + font-size: 20px + font-weight: 600 + margin: 0 0 4px + line-height: 1.4 + a + color: #5a2a82 !important + text-decoration: none + &:hover + text-decoration: underline + +.people-card__meta + font-size: 13px + color: #6b7280 + margin: 2px 0 + a + color: #6b7280 + text-decoration: none + &:hover + color: #5A2A82 + text-decoration: underline + +// Commits — mobile: top border, desktop: left border +.people-card__commits + display: flex + flex-direction: column + align-items: center + justify-content: center + padding: 8px 0 + border-top: 1px solid #e5e7eb + +.people-card__commits-count + font-size: 30px + font-weight: 700 + color: #111827 + line-height: 1.1 + text-align: center + +.people-card__commits-label + font-size: 11px + color: #6b7280 + text-transform: uppercase + letter-spacing: 0.05em + text-align: center + margin-top: 4px + a + color: #6b7280 + text-decoration: none + font-size: 11px + &:hover + color: #5A2A82 + +// Activity — languages + projects +.people-card__activity + flex: 1 + min-width: 0 + display: flex + flex-direction: column + gap: 15px + +.people-card__row-langs, +.people-card__row-projects + display: flex + align-items: flex-start + gap: 8px + flex-wrap: wrap + +.people-card__label + font-size: 12px + color: #6b7280 + white-space: nowrap + padding-top: 2px + flex-shrink: 0 + +.people-card__lang-tags + display: flex + align-items: center + flex-wrap: wrap + gap: 6px + +.people-card__lang-primary + display: inline-block + padding: 2px 10px + background: linear-gradient(to right, #5A2A82, #7F3FA0) + color: #ffffff + font-size: 12px + font-weight: 600 + border-radius: 4px + a + color: #ffffff !important + text-decoration: none + &:hover + text-decoration: underline + +.people-card__lang-secondary + font-size: 13px + color: #374151 + a + color: #374151 + text-decoration: none + &:hover + color: #5A2A82 + +.people-card__no-lang + font-size: 13px + color: #6b7280 + font-style: italic + +.people-card__project-list + display: flex + align-items: center + flex-wrap: wrap + gap: 8px + +.people-card__project-item + display: flex + align-items: center + gap: 4px + img, .people-card__project-icon + width: 20px + height: 20px + border-radius: 3px + flex-shrink: 0 + +.people-card__project-name + font-size: 13px + color: #5A2A82 + text-decoration: none + &:hover + text-decoration: underline + +.people-card__other-links + font-size: 12px + margin-top: 2px + .people-card__link + color: #5A2A82 + text-decoration: none + &:hover + text-decoration: underline + .people-card__link-dot + margin: 0 2px + &::before + content: '•' + color: #d1d5db + +.people-card__no-commits + font-size: 14px + color: #6b7280 + font-style: italic + text-align: center + padding: 20px 0 + +// Kudos — mobile: top border row, desktop: column no border +.people-card__kudos + display: flex + align-items: center + justify-content: center + gap: 12px + padding-top: 8px + border-top: 1px solid #e5e7eb + flex-shrink: 0 + +.people-card__kudos-rank + font-size: 28px + font-weight: 700 + color: #111827 + text-align: center + +.people-card__kudos-badge + display: flex + align-items: center + +// ── Unclaimed Card ──────────────────────────────────────────────────────────── +.unclaimed-card__header + display: flex + align-items: center + justify-content: space-between + gap: 12px + margin-bottom: 16px + flex-wrap: wrap + +.unclaimed-card__name + font-size: 20px + font-weight: 600 + color: #5A2A82 + margin: 0 + line-height: 1.4 + a + color: #5A2A82 + text-decoration: none + &:hover + text-decoration: underline + +.unclaimed-card__btn + background-color: #5A2A82 !important + color: #ffffff !important + border: none !important + padding: 6px 14px !important + font-weight: 600 !important + height: auto !important + line-height: normal !important + border-radius: 6px !important + font-size: 13px !important + white-space: nowrap + transition: background-color 0.2s + &:hover + background-color: #4A1A72 !important + color: #ffffff !important + +// Ensure inputs and buttons with this class inherit font family and weight +input.unclaimed-card__btn, +button.unclaimed-card__btn + font-weight: 600 !important + font-family: inherit !important + -webkit-font-smoothing: antialiased !important + height: auto !important + line-height: normal !important + +.unclaimed-card__grid + display: grid + grid-template-columns: repeat(2, 1fr) + gap: 16px + +.unclaimed-card__item + position: relative + + // Modern tile layout to match OpenHub design (image + absolute commit badge) + display: flex + flex-direction: column + align-items: center + gap: 8px + min-width: 0 + padding: 8px + +.unclaimed-card__more + grid-column: 1 / -1 + display: flex + align-items: center + justify-content: center + a + font-size: 13px + color: #5A2A82 + text-decoration: none + &:hover + text-decoration: underline + +// Unclaimed item inner elements: logo and commit badge +.unclaimed-card__item + .logo position: relative - height: 128px - .commits_summary - @include commits-summary-background-color - width: 470px - margin: 5px 0px - height: 118px - .in - padding: 49px 2px - .project_summary - padding: 5px 10px 0px 7px - width: auto - min-height: 99px - div - height: 23px - .project_name - @include projects-summary-projects-name-background-color - color: white - border: 1px dashed white + img, p + width: 48px !important + height: 48px !important + border-radius: 8px + object-fit: cover + border: 1px solid #e5e7eb !important + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) + @media only all and (min-width: 640px) + width: 64px !important + height: 64px !important + + p + // placeholder text inside logo (when no image available) + display: flex + align-items: center + justify-content: center + margin: 0 + font-size: 16px + font-weight: 600 + color: #6b7280 + background: #f3f4f6 + border-radius: 8px + @media only all and (min-width: 640px) font-size: 18px - line-height: 24px - width: 24px - height: 24px - text-align: center - float: left - margin-bottom: 0 - margin-top: 0 - margin-right: 2px - .language_summary - padding: 5px 7px 5px 9px - width: 129px - .language_name - width: 113px - margin-bottom: 5px - height: 28px - line-height: 28px - span - padding-left: 8px - a - color: inherit - .other_language - color: white - font-size: 10px - white-space: nowrap - line-height: 10px - margin-bottom: 0 - a - @include site-link-color - .more_commits_padding - padding-left: 10px - .no_commits - text-align: center - padding: 50px - font-size: 15px - color: black - .member_info + + .commits + // container for commit badge + label; keep in document flow so label sits below logo + font-size: 12px + display: inline-flex + flex-direction: column + align-items: center + justify-content: center + + a + color: #6a7282 !important + text-transform: uppercase + line-height: 1.3 + letter-spacing: 0.3px + + .logo .commit-count + // absolute badge overlayed on the project logo (positioned relative to .logo) position: absolute - bottom: 0px - left: 0px - .kudo_rank - margin-top: 0px - font-size: 30px - text-align: center - padding: 42px 5px 0px 5px - font-weight: 100 - width: 35px - color: #183867 - .commits_count - font-size: 27px - line-height: 30px - display: inline-block - padding: 31px 20px 20px + top: -6px + right: -6px + font-size: 12px + display: inline-flex + align-items: center + justify-content: center + background: linear-gradient(to right, #5A2A82, #7F3FA0) + color: #ffffff + padding: 2px 6px + border-radius: 4px + font-weight: 700 + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) + @media only all and (min-width: 640px) + top: -8px + right: -8px + padding: 4px 8px + + .project_link + font-size: 12px + line-height: 1.4 text-align: center - width: 115px - div - font-size: 12px - text-align: center !important + width: 100% + overflow-wrap: break-word + word-break: break-word + cursor: pointer + @media only all and (min-width: 640px) + font-size: 14px + a + color: #5A2A82 + &:hover + text-decoration: underline + +// ── Desktop overrides (sm: 576px+) ─────────────────────────────────────────── +@media only all and (min-width: 576px) + .people-card__body + padding: 24px + + .people-card__row + flex-direction: row + align-items: flex-start + gap: 24px + + // Make avatar+info transparent so children become direct row flex items + .people-card__avatar-info + display: contents + img, .gravatar + width: 96px + height: 96px + border-radius: 4px + + // Commits: remove top border, add left border + .people-card__commits + border-top: none + border-left: 1px solid #e5e7eb + padding: 16px 24px + + .people-card__commits-count + font-size: 40px + + // Kudos: remove top border, become a column + .people-card__kudos + flex-direction: column + border-top: none + padding-top: 0 + gap: 4px + + // Unclaimed grid: flex wrap on desktop + .unclaimed-card__grid + display: flex + flex-wrap: wrap + gap: 24px + +#account-settings-page + max-width: 1024px + margin: 0 auto + padding: 0 24px 32px + + @media (max-width: 639px) + padding: 0 16px 24px + + .settings-grid + @media (min-width: 640px) + grid-template-columns: repeat(2, 1fr) + @media (min-width: 1024px) + grid-template-columns: repeat(2, 1fr) + +// ── Account settings (unchanged) ───────────────────────────────────────────── #analysis_timestamp - @include analysis-timestamp-color margin-top: 0px + margin-left: 32px .account_settings_options margin-left: 20px @@ -127,6 +548,7 @@ .settings_specifications width: 380px length: 88px + .verification-buttons-container width: 100% margin-left: auto @@ -142,94 +564,35 @@ .grecaptcha-badge display: none -@media only all and (min-width: 768px) and (max-width: 1024px) - #accounts_index_page - h1 - font-size: 24px - margin-bottom: 0 - margin-top: 10px - h3 - font-size: 18px - margin-bottom: 0 - margin-top: 10px - .account_details - width: 142px - margin-left: 5px - .commits_summary - width: 379px - .commits_count - width: auto - font-size: 15px - padding: 31px 0px 12px - line-height: 20px - .well - min-height: 142px - .language_summary - width: 100px !important - .language_name - width: 85px !important - .kudo_rank - font-size: 18px - padding: 0 - font-weight: 500 - margin-top: 30px !important - width: auto - .kudo_badge - margin-top: 28px !important - padding: 0 - #search-dingus label.paginate - font-size: 10px !important - label - font-size: 10px - #search-dingus button.btn - font-size: 10px -@media only all and (min-width: 320px) and (max-width: 480px) - #accounts_index_page - h1 - font-size: 18px - margin-bottom: 0 - margin-top: 10px - h3 - font-size: 12px - margin-bottom: 0 - margin-top: 10px - .account_details - width: auto - .commits_summary - width: auto - .commits_count - width: auto - font-size: 15px - padding: 31px 0px 12px - line-height: 20px - .kudo_rank - font-size: 24px - padding: 0 - margin-top: 35px - .kudo_badge - margin-top: 28px !important - padding: 0 - .language_name - width: 90px !important - .unclaimed_committers_box .header_row h4 - font-size: 12px - .well - min-height: 142px - .unclaimed_committers_box .header_row .btn-mini - font-size: 8px - .language_summary - width: 100px !important - #more_account - font-size: 10px - #more_unclaimed - font-size: 10px - #search-dingus label.paginate - font-size: 8px !important - label - font-size: 8px - #search-dingus button.btn - font-size: 8px - #search-dingus input - width: auto - #search-dingus select - width: auto + +// Licenses index page — same container/header pattern as people page +.people-page-header__action + display: flex + align-items: center + +.licenses-list + display: flex + flex-direction: column + gap: 8px + margin-top: 8px + margin-bottom: 10px + + &__item + padding: 14px 20px !important + margin-bottom: 0 !important + + &__link + font-size: 15px + font-weight: 500 + color: #5A2A82 + text-decoration: none + + &:hover + color: #4a1f6e + text-decoration: underline + + html.dark & + color: #ffb91a + + &:hover + color: #ffcc4d diff --git a/app/assets/stylesheets/accounts/edit.sass b/app/assets/stylesheets/accounts/edit.sass index 985538472..4205c2c36 100644 --- a/app/assets/stylesheets/accounts/edit.sass +++ b/app/assets/stylesheets/accounts/edit.sass @@ -2,12 +2,541 @@ #settings a margin: 0 0 0.2em 0 +#accounts_edits + max-width: 1024px + margin: 0 auto + padding: 0 24px 32px + + @media (max-width: 639px) + padding: 0 16px 24px + + // Remove inherited margin-left so content aligns with the header + > .margin_left_15 + margin-left: 0 !important + margin-right: 0 !important + + .settings-page-header + margin-top: 16px + + .account-basics-sep + color: #9ca3af + font-weight: 400 + +// ── Form grid ────────────────────────────────────────────────────────────────── +.edit-form-grid + display: grid + grid-template-columns: 1fr + gap: 20px + margin-bottom: 20px + + @media (min-width: 768px) + grid-template-columns: 1fr 1fr + gap: 24px + +.edit-form-col + display: flex + flex-direction: column + gap: 20px + +// ── Section card ─────────────────────────────────────────────────────────────── +.edit-section + background: #ffffff + border-radius: 16px + border: 1px solid #e5e7eb + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06) + padding: 20px 24px + + html.dark & + background: #2D1548 + border-color: rgba(90, 42, 130, 0.35) + box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3) + + &.edit-section--full + grid-column: 1 / -1 + +.edit-section-header + display: flex + align-items: center + gap: 10px + margin-bottom: 18px + padding-bottom: 14px + border-bottom: 1px solid #f3f4f6 + + html.dark & + border-bottom-color: rgba(255, 255, 255, 0.08) + +.edit-section-icon + width: 32px + height: 32px + min-width: 32px + border-radius: 10px + background: linear-gradient(135deg, #5A2A82, #7B3FB5) + display: flex + align-items: center + justify-content: center + box-shadow: 0 2px 6px rgba(90, 42, 130, 0.3) + i + color: #ffffff + font-size: 14px + margin: 0 + line-height: 1 + +.edit-section-title + font-size: 14px !important + font-weight: 700 !important + color: #111827 !important + margin: 0 !important + letter-spacing: 0.01em + + html.dark & + color: #ffffff !important + +// ── Field groups ─────────────────────────────────────────────────────────────── +.edit-field-group + margin-bottom: 16px + + &:last-child + margin-bottom: 0 + +.edit-field-label + display: block + font-size: 13px + font-weight: 600 + color: #374151 + margin-bottom: 6px + + html.dark & + color: #d1d5db + +.edit-field-input-wrapper + position: relative + display: block + + .field_with_errors + display: block + + .edit-field-input + border-color: #ef4444 + background: #fff5f5 + + html.dark & + background: rgba(239, 68, 68, 0.1) + +.edit-field-icon + position: absolute + left: 14px + top: 50% + transform: translateY(-50%) + font-size: 14px + color: #666666 + pointer-events: none + z-index: 2 + + html.dark & + color: #a0a6b0 + +input.edit-field-input, +textarea.edit-field-input + display: block !important + width: 100% !important + padding: 12px 16px 12px 42px !important + border: 1px solid #e5e7eb !important + border-radius: 12px !important + -webkit-border-radius: 12px !important + -moz-border-radius: 12px !important + font-size: 14px !important + font-weight: 400 !important + background: #f9fafb !important + color: #111827 !important + line-height: 1.5 !important + height: auto !important + box-shadow: none !important + box-sizing: border-box !important + -webkit-appearance: none !important + appearance: none !important + outline: none !important + transition: border-color 0.2s, box-shadow 0.2s, background 0.2s + + &::placeholder + color: #767676 !important + font-weight: 400 !important + + &:focus, + &:focus-visible + border-color: #5A2A82 !important + box-shadow: 0 0 0 2px rgba(90, 42, 130, 0.25) !important + background: #ffffff !important + outline: none !important + + html.dark & + background: #1D0631 !important + border-color: rgba(90, 42, 130, 0.5) !important + color: #ffffff !important + + &::placeholder + color: #4b5563 !important + + &:focus, + &:focus-visible + border-color: #ffb91a !important + box-shadow: 0 0 0 2px rgba(255, 185, 26, 0.25) !important + background: #180529 !important + +.edit-field-textarea + display: block !important + width: 100% !important + padding: 12px 16px !important + border: 1px solid #e5e7eb !important + border-radius: 12px !important + font-size: 14px !important + background: #f9fafb !important + color: #111827 !important + line-height: 1.6 !important + resize: vertical + box-sizing: border-box !important + -webkit-appearance: none !important + appearance: none !important + outline: none !important + transition: border-color 0.2s, box-shadow 0.2s, background 0.2s + + &::placeholder + color: #767676 !important + + &:focus, + &:focus-visible + border-color: #5A2A82 !important + box-shadow: 0 0 0 2px rgba(90, 42, 130, 0.25) !important + background: #ffffff !important + outline: none !important + + html.dark & + background: #1D0631 !important + border-color: rgba(90, 42, 130, 0.5) !important + color: #ffffff !important + + &::placeholder + color: #4b5563 !important + + &:focus, + &:focus-visible + border-color: #ffb91a !important + box-shadow: 0 0 0 2px rgba(255, 185, 26, 0.25) !important + background: #180529 !important + +.edit-field-hint + font-size: 11px + color: #666666 + margin: 6px 0 0 + line-height: 1.5 + + html.dark & + color: #a0a6b0 + + a + color: #5A2A82 + text-decoration: underline + html.dark & + color: #ffb91a + +.edit-field-error + font-size: 12px + color: #ef4444 + margin: 6px 0 0 + +.edit-clear-link + display: inline-block + font-size: 12px + color: #5A2A82 + text-decoration: underline + margin-top: 6px + cursor: pointer + + html.dark & + color: #ffb91a + +// ── Map ──────────────────────────────────────────────────────────────────────── +#map + width: 100% + height: 200px + border-radius: 10px + overflow: hidden + margin-top: 12px + border: 1.5px solid #e5e7eb + + html.dark & + border-color: rgba(90, 42, 130, 0.4) + +// ── Affiliation chosen override ──────────────────────────────────────────────── #account-edit-form - .chzn-container, .chosen p - width: 347px !important + #value_select + .chosen-container-single .chosen-single + border: 1px solid #e5e7eb !important + border-radius: 12px !important + -webkit-border-radius: 12px !important + background: #f9fafb !important + background-image: none !important + height: auto !important + padding: 12px 16px !important + box-shadow: none !important + color: #111827 !important + line-height: 1.5 !important + font-size: 14px !important + &:hover + border-color: #d1d5db !important + .chosen-container-active > .chosen-single, + .chosen-container-active.chosen-with-drop .chosen-single + border-color: #5A2A82 !important + box-shadow: 0 0 0 2px rgba(90, 42, 130, 0.25) !important + .chosen-container .chosen-drop + border-radius: 0 0 12px 12px !important + border-left: 1px solid #5A2A82 !important + border-right: 1px solid #5A2A82 !important + border-bottom: 1px solid #5A2A82 !important + border-top: none !important + html.dark & + .chosen-container-single .chosen-single + background: #1D0631 !important + border-color: rgba(90, 42, 130, 0.5) !important + color: #ffffff !important + &:hover + border-color: #6b7280 !important + .chosen-container-active > .chosen-single, + .chosen-container-active.chosen-with-drop .chosen-single + border-color: #ffb91a !important + box-shadow: 0 0 0 2px rgba(255, 185, 26, 0.25) !important + .chosen-container .chosen-drop + border-left: 1px solid #ffb91a !important + border-right: 1px solid #ffb91a !important + border-bottom: 1px solid #ffb91a !important + +// ── Action buttons ───────────────────────────────────────────────────────────── +.edit-form-actions + display: flex + align-items: center + gap: 12px + padding-top: 8px + margin-bottom: 32px + +.edit-save-btn + display: inline-flex !important + align-items: center + padding: 11px 28px !important + background: linear-gradient(135deg, #5A2A82 0%, #7B3FB5 100%) !important + color: #ffffff !important + border: none !important + border-radius: 10px !important + font-size: 14px !important + font-weight: 700 !important + cursor: pointer !important + box-shadow: 0 2px 8px rgba(90, 42, 130, 0.35) !important + transition: background 0.15s, box-shadow 0.15s + -webkit-appearance: none !important + appearance: none !important + + &:hover + background: linear-gradient(135deg, #4a1f6e 0%, #6B35A0 100%) !important + box-shadow: 0 4px 14px rgba(90, 42, 130, 0.45) !important + color: #ffffff !important + +.edit-delete-btn + display: inline-flex !important + align-items: center + padding: 11px 20px !important + background: transparent !important + color: #dc2626 !important + border: 1.5px solid #fca5a5 !important + border-radius: 10px !important + font-size: 14px !important + font-weight: 600 !important + cursor: pointer !important + text-decoration: none !important + transition: background 0.15s, border-color 0.15s + + &:hover + background: #fef2f2 !important + border-color: #dc2626 !important + color: #dc2626 !important + text-decoration: none !important + + html.dark & + color: #f87171 !important + border-color: rgba(248, 113, 113, 0.4) !important + + &:hover + background: rgba(220, 38, 38, 0.1) !important + border-color: #f87171 !important + +@media (max-width: 767px) + #accounts_edits + .edit-form-grid + grid-template-columns: 1fr !important + + .edit-form-actions + flex-direction: column + align-items: stretch + + .edit-save-btn, + .edit-delete-btn + width: 100% !important + justify-content: center + +// ── About Account Basics card ────────────────────────────────────────────────── +.about-account-basics-card + max-width: 1024px + margin: 0 auto 32px + padding: 0 24px + + @media (max-width: 639px) + padding: 0 16px + + background: #fffbeb + border-radius: 16px + border: 1px solid rgba(251, 191, 36, 0.35) + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06) + overflow: hidden + + html.dark & + background: rgba(120, 53, 15, 0.12) + border-color: rgba(251, 191, 36, 0.25) + box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3) + + .card-header + display: flex + align-items: center + justify-content: space-between + padding: 14px 20px + cursor: pointer + user-select: none + transition: background-color 0.15s + + &:hover + background-color: rgba(251, 191, 36, 0.08) + + .card-header-left + display: flex + align-items: center + gap: 12px + flex: 1 + + .card-header-icon + width: 32px + height: 32px + min-width: 32px + border-radius: 10px + background: linear-gradient(135deg, #f59e0b, #d97706) + display: flex + align-items: center + justify-content: center + box-shadow: 0 2px 6px rgba(217, 119, 6, 0.3) + i + color: #ffffff + font-size: 14px + line-height: 1 + + .card-header-text + flex: 1 + + .card-title + margin: 0 0 1px + font-size: 14px !important + font-weight: 700 !important + color: #92400e !important + + html.dark & + color: #fbbf24 !important + + .card-subtitle + margin: 0 + font-size: 11px + color: #b45309 + line-height: 1.3 + + html.dark & + color: #d97706 + + .expand-toggle + background: none + border: none + padding: 4px 8px + cursor: pointer + color: #b45309 + transition: transform 0.2s + + html.dark & + color: #d97706 + + i + font-size: 13px + + .card-content + display: none + padding: 4px 20px 20px + + &.expanded + .expand-toggle + transform: rotate(180deg) + + .card-content + display: block + + .tips-grid + display: grid + grid-template-columns: 1fr + gap: 12px + + @media (min-width: 640px) + grid-template-columns: 1fr 1fr + gap: 14px + + .tip-item + display: flex + align-items: flex-start + gap: 10px + padding: 10px 12px + background: rgba(255, 255, 255, 0.7) + border-radius: 10px + border: 1px solid rgba(251, 191, 36, 0.2) + + html.dark & + background: rgba(255, 255, 255, 0.04) + border-color: rgba(251, 191, 36, 0.15) + + .tip-icon + width: 26px + height: 26px + min-width: 26px + border-radius: 8px + background: rgba(217, 119, 6, 0.12) + display: flex + align-items: center + justify-content: center + margin-top: 1px + + html.dark & + background: rgba(251, 191, 36, 0.12) + + i + font-size: 11px + color: #d97706 + + html.dark & + color: #fbbf24 + + .tip-body + flex: 1 + + .tip-text + margin: 0 + font-size: 12px + color: #555555 + line-height: 1.6 + + html.dark & + color: #d1d5db - #location - width: 85% + strong + color: #374151 + font-weight: 600 - .edit-description - width: 90% + html.dark & + color: #ffffff diff --git a/app/assets/stylesheets/accounts/languages.sass b/app/assets/stylesheets/accounts/languages.sass index f97f6bab5..2c652e471 100644 --- a/app/assets/stylesheets/accounts/languages.sass +++ b/app/assets/stylesheets/accounts/languages.sass @@ -1,3 +1,11 @@ +#accounts-languages-page + max-width: 1024px + margin: 0 auto + padding: 0 24px 32px + + @media (max-width: 639px) + padding: 0 16px 24px + #language_detail .lang_bg padding-top: 8px @@ -17,10 +25,45 @@ .chzn-select, .chzn-container :margin-top 2px +@media (max-width: 767px) + #language_detail + .table-responsive + border: none + table + font-size: 12px + td, th + padding: 4px 6px + white-space: nowrap + // Hide empty spacer column + tbody tr td:nth-child(7), + thead tr:first-child th:nth-child(6) + display: none + + .margin_top_10 + h2.col-md-2 + width: 100% !important + float: none !important + margin-bottom: 6px !important + + .pull-right + float: none !important + display: block !important + margin-bottom: 6px !important + + #sort_by.languages + float: none !important + margin-top: 0 !important + display: block !important + width: 100% !important + + .chzn-container, + select.chzn-select + width: 100% !important + #languages_index_page .projects background-color: #183867 !important .contributors background-color: #237b46 !important .commits - background-color: #8f908f !important \ No newline at end of file + background-color: #8f908f !important diff --git a/app/assets/stylesheets/accounts/new.sass b/app/assets/stylesheets/accounts/new.sass index 57b211c05..738f5df28 100644 --- a/app/assets/stylesheets/accounts/new.sass +++ b/app/assets/stylesheets/accounts/new.sass @@ -1,76 +1,645 @@ -@media(min-width: 320px) and (max-width: 480px) - #welcome-message-container - padding: 0px !important - margin-top: 1rem !important - display: contents - h2 - font-size: 18px !important - font-weight: 500 !important - #profile-description-1 - margin-top: -40px - #sign-up-git - margin-left: -30px - margin-bottom: 15px - #sign-up-email - margin-right: 170px +// ── Remove page_contents horizontal padding on sign-up / sign-in pages ──────── +#page-contents:has(.signup-page) + margin-left: 0 !important + margin-right: 0 !important + +// ── Signup page full layout ──────────────────────────────────────────────────── +.signup-page + display: flex + flex-direction: column + min-height: calc(100vh - 72px) + background: #ffffff + + @media (min-width: 768px) + flex-direction: row + +// ── Left panel ───────────────────────────────────────────────────────────────── +.signup-left-panel + position: relative + overflow: hidden + background: linear-gradient(135deg, #0D0019 0%, #1D0631 50%, #5A2A82 100%) + display: flex + flex-direction: column + justify-content: space-between + padding: 32px 24px + min-height: 280px + + @media (min-width: 768px) + width: 42% + flex-shrink: 0 + padding: 28px 20px + min-height: calc(100vh - 72px) + + @media (min-width: 1024px) + width: 46% + padding: 48px + + @media (min-width: 1280px) + padding: 64px + +.signup-orb + position: absolute + border-radius: 50% + pointer-events: none + +.signup-orb--top + top: -96px + right: -96px + width: 320px + height: 320px + background: rgba(255, 185, 26, 0.1) + filter: blur(48px) + +.signup-orb--bottom + bottom: -128px + left: -80px + width: 384px + height: 384px + background: rgba(90, 42, 130, 0.4) + filter: blur(48px) + +.signup-orb--mid + top: 33% + right: 0 + width: 256px + height: 256px + background: rgba(107, 33, 168, 0.2) + filter: blur(40px) + +.signup-left-content + position: relative + z-index: 1 + +.signup-badge + display: inline-flex + align-items: center + gap: 8px + padding: 6px 12px + background: rgba(255, 255, 255, 0.1) + backdrop-filter: blur(4px) + border: 1px solid rgba(255, 255, 255, 0.1) + border-radius: 999px + color: rgba(255, 255, 255, 0.8) + font-size: 12px + margin-bottom: 20px + +.signup-badge__dot + width: 6px + height: 6px + background: #ffb91a + border-radius: 50% + flex-shrink: 0 + +.signup-headline + font-size: 28px + font-weight: 700 + color: #ffffff + line-height: 1.2 + margin: 0 0 16px + letter-spacing: -0.02em + + @media (min-width: 768px) and (max-width: 1023px) + font-size: 26px margin-bottom: 10px - #sign-up-fields - display: contents - #sign-up-options - margin-top: -12px -.well .fa-exclamation-triangle - color: red -.well .fa-smile-o - color: green + @media (min-width: 1024px) + font-size: 36px -#sign-up-options - @include sign_buttons - .row-first - height: 100px + @media (min-width: 1280px) + font-size: 44px -#sign-up-fields +.signup-headline__accent + color: #ffb91a + +.signup-tagline + color: rgba(255, 255, 255, 0.7) + font-size: 14px + line-height: 1.7 + max-width: 340px + margin: 0 + + @media (min-width: 1024px) + font-size: 16px + +// ── Benefits list ────────────────────────────────────────────────────────────── +.signup-benefits + position: relative + z-index: 1 display: none + flex-direction: column + gap: 16px + margin-top: 32px + + @media (min-width: 768px) + display: flex + + @media (min-width: 768px) and (max-width: 1023px) + gap: 12px + margin-top: 20px + +.signup-benefit + display: flex + align-items: center + gap: 16px + +.signup-benefit__icon + width: 36px + height: 36px + border-radius: 12px + display: flex + align-items: center + justify-content: center + flex-shrink: 0 + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2) + color: #ffffff + font-size: 16px + +.signup-benefit__icon--amber + background: linear-gradient(135deg, #f59e0b, #f97316) + +.signup-benefit__icon--purple + background: linear-gradient(135deg, #5A2A82, #8b5cf6) + +.signup-benefit__icon--green + background: linear-gradient(135deg, #10b981, #0d9488) -#welcome-message-container - padding: 0px !important - margin-top: 1rem !important -#profile-description-2 - max-width: 400px +.signup-benefit__icon--blue + background: linear-gradient(135deg, #3b82f6, #6366f1) + +.signup-benefit__text + flex: 1 + +.signup-benefit__title + color: #ffffff + font-size: 13px + font-weight: 600 + margin: 0 0 2px + line-height: 1.3 + +.signup-benefit__desc + color: rgba(255, 255, 255, 0.55) + font-size: 11px + margin: 0 + line-height: 1.5 + +// ── Left footer disclaimer ───────────────────────────────────────────────────── +.signup-left-footer position: relative -#profile-description-2 .text-2 - position: relative; - display: block; -#profile-description-2 .show-more-2 - color: #1779dd; - position: relative; - font-size: 10px; - text-align: left; - cursor: pointer; -#profile-description-2 .show-more-2:hover - color: #1779dd; -#profile-description-2 .show-more-height-2 - height: 35px; - overflow: hidden; -#profile-description-1 - max-width: 400px; - position: relative; -#profile-description-1 .text-1 - position: relative; - display: block; -#profile-description-1 .show-more-1 - color: #1779dd; - position: relative; - font-size: 10px; - text-align: left; - cursor: pointer; -#profile-description-1 .show-more-1:hover - color: #1779dd; -#profile-description-1 .show-more-height-1 - height: 68px; - overflow: hidden; + z-index: 1 + display: none + margin-top: 40px + padding-top: 32px + border-top: 1px solid rgba(255, 255, 255, 0.1) + + @media (min-width: 768px) + display: block + + @media (min-width: 768px) and (max-width: 1023px) + margin-top: 20px + padding-top: 16px + +.signup-disclaimer + color: rgba(255, 255, 255, 0.45) + font-size: 11px + line-height: 1.7 + margin: 0 + +// ── Right panel ──────────────────────────────────────────────────────────────── +// Constrain #flash-msg to form card width inside auth right panels +.signup-right-panel + #flash-msg + width: 100% + max-width: 440px + margin: 0 0 16px + padding: 0 + +.signup-right-panel + flex: 1 + display: flex + flex-direction: column + align-items: center + justify-content: center + padding: 32px 16px + background: #f9fafb + + html.dark & + background: #1D0631 + + @media (min-width: 640px) + padding: 48px 24px + + @media (min-width: 768px) and (max-width: 1023px) + padding: 24px 16px + +// ── Form card ────────────────────────────────────────────────────────────────── +.signup-form-card + width: 100% + max-width: 440px + background: #ffffff + border-radius: 20px + box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08) + border: 1px solid #f3f4f6 + padding: 28px 24px + + html.dark & + background: #2D1548 + border-color: rgba(90, 42, 130, 0.4) + box-shadow: 0 4px 32px rgba(0, 0, 0, 0.5) + + @media (min-width: 640px) + padding: 36px 36px + + @media (min-width: 768px) and (max-width: 1023px) + padding: 24px 20px + +// ── GitHub button ────────────────────────────────────────────────────────────── +.btn-github + display: flex + align-items: center + justify-content: center + gap: 10px + width: 100% + padding: 14px 20px + background: #24292e + color: #ffffff !important + border-radius: 12px + font-size: 14px + font-weight: 600 + text-decoration: none !important + border: 1px solid transparent + transition: background 0.15s, box-shadow 0.15s + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) + margin-bottom: 8px + + &:hover + background: #1a1f24 + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) + color: #ffffff !important + text-decoration: none !important + + html.dark & + background: #0D0019 + border-color: rgba(255, 255, 255, 0.1) + + html.dark &:hover + background: #000000 + + .fa + font-size: 18px + +.signup-github-note + font-size: 11px + color: #666666 + text-align: center + margin: 0 0 20px + line-height: 1.5 + + html.dark & + color: #a0a6b0 + +// ── Divider ──────────────────────────────────────────────────────────────────── +.signup-divider + display: flex + align-items: center + gap: 12px + margin-bottom: 24px + +.signup-divider__line + flex: 1 + height: 1px + background: #e5e7eb + + html.dark & + background: rgba(255, 255, 255, 0.1) + +.signup-divider__text + font-size: 11px + color: #666666 + font-weight: 500 + text-transform: uppercase + letter-spacing: 0.05em + white-space: nowrap + + html.dark & + color: #a0a6b0 + +// ── Form header ──────────────────────────────────────────────────────────────── +.signup-form-header + margin-bottom: 24px + +.signup-form-title + font-size: 22px !important + font-weight: 800 !important + color: #111827 !important + margin: 0 0 6px !important + letter-spacing: -0.02em + + html.dark & + color: #ffffff !important + +.signup-form-subtitle + font-size: 13px + color: #555555 + margin: 0 + + html.dark & + color: #a0a6b0 + +.signup-signin-link + color: #5A2A82 + font-weight: 600 + text-decoration: none + transition: color 0.15s + + &:hover + text-decoration: underline + color: #5A2A82 + + html.dark & + color: #ffb91a + + html.dark &:hover + color: #ffb91a + +// ── Email toggle button ──────────────────────────────────────────────────────── +.btn-email-signup + display: flex + align-items: center + justify-content: center + gap: 10px + width: 100% + padding: 14px 20px + background: #f9fafb + color: #1f2937 !important + border-radius: 12px + font-size: 14px + font-weight: 600 + text-decoration: none !important + border: 1px solid #e5e7eb + transition: background 0.15s, border-color 0.15s + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) + margin-bottom: 20px + + &:hover + background: #f3f4f6 + border-color: rgba(90, 42, 130, 0.4) + text-decoration: none !important + + html.dark & + background: #1D0631 + color: #ffffff !important + border-color: rgba(90, 42, 130, 0.6) + + html.dark &:hover + background: #180529 + + .fa + color: #5A2A82 + font-size: 16px + + html.dark & + color: #ffb91a + +// ── Form fields — scoped under .signup-form-card for specificity over Bootstrap ─ +#sign-up-fields + display: none + +.signup-form-card + fieldset + border: none !important + padding: 0 !important + margin: 0 !important + + legend + display: none !important + + // Field group + .signup-field-group + margin-bottom: 18px + + // Label + .signup-field-label + display: block + font-size: 13px + font-weight: 600 + color: #374151 + margin-bottom: 6px + line-height: 1.4 + + html.dark & + color: #d1d5db + + // Icon wrapper — position: relative so icon sits inside + .signup-field-input-wrapper + position: relative + display: block + + // field_with_errors adds a wrapper div on validation failure + .field_with_errors + display: block + + .signup-field-input + border-color: #ef4444 + background: #fff5f5 + + html.dark & + background: rgba(239, 68, 68, 0.1) + + // Left icon — vertically centered, non-interactive + .signup-field-icon + position: absolute + left: 14px + top: 50% + transform: translateY(-50%) + font-size: 14px + color: #666666 + pointer-events: none + z-index: 2 + + html.dark & + color: #a0a6b0 + + // Inputs — scoped to #account_form (ID = specificity 100) beats Bootstrap's .form-control (010) + // Also keep !important on visual-critical properties as belt-and-suspenders + input.signup-field-input + display: block !important + width: 100% !important + padding: 12px 16px 12px 42px !important + border: 1px solid #e5e7eb !important + border-radius: 12px !important + font-size: 14px !important + font-weight: 400 !important + background: #f9fafb !important + color: #111827 !important + line-height: 1.5 !important + height: auto !important + box-shadow: none !important + box-sizing: border-box !important + -webkit-appearance: none !important + appearance: none !important + outline: none !important + transition: border-color 0.2s, box-shadow 0.2s, background 0.2s + + &::placeholder + color: #767676 !important + font-weight: 400 !important + + &:focus, + &:focus-visible + border-color: #5A2A82 !important + box-shadow: 0 0 0 2px rgba(90, 42, 130, 0.25) !important + background: #ffffff !important + outline: none !important + + html.dark & + background: #1D0631 !important + border-color: rgba(90, 42, 130, 0.5) !important + color: #ffffff !important + + &::placeholder + color: #4b5563 !important + + &:focus, + &:focus-visible + border-color: #ffb91a !important + box-shadow: 0 0 0 2px rgba(255, 185, 26, 0.25) !important + background: #180529 !important + + // Error text + .signup-field-group + .error, span.error + display: block + font-size: 11px + color: #ef4444 + margin: 5px 0 0 + + // Hint text + .signup-field-hint + font-size: 11px + color: #666666 + margin: 5px 0 0 + line-height: 1.5 + + html.dark & + color: #a0a6b0 + + // Submit button row + .signup-field-actions + margin-top: 4px + margin-bottom: 20px + + // Submit button + input.signup-submit-btn + display: block !important + width: 100% !important + padding: 13px 20px !important + background: linear-gradient(135deg, #5A2A82 0%, #7B3FB5 100%) !important + color: #ffffff !important + border: none !important + border-radius: 12px !important + font-size: 14px !important + font-weight: 700 !important + cursor: pointer !important + text-align: center !important + letter-spacing: 0.02em + -webkit-appearance: none !important + appearance: none !important + box-shadow: 0 2px 8px rgba(90, 42, 130, 0.3) !important + transition: background 0.15s, box-shadow 0.15s + + &:hover, + &:focus + background: linear-gradient(135deg, #4a1f6e 0%, #6B35A0 100%) !important + box-shadow: 0 4px 16px rgba(90, 42, 130, 0.45) !important + color: #ffffff !important + outline: none !important + +// ── Please Note card ─────────────────────────────────────────────────────────── +.signup-note-card + border: 1px solid rgba(251, 191, 36, 0.4) + background: #fffbeb + border-radius: 12px + padding: 14px 16px + margin-bottom: 16px + + html.dark & + background: rgba(120, 53, 15, 0.15) + border-color: rgba(251, 191, 36, 0.3) + +.signup-note-card__inner + display: flex + align-items: flex-start + gap: 10px + +.signup-note-card__icon + color: #d97706 + font-size: 14px + margin-top: 2px + flex-shrink: 0 + + html.dark & + color: #fbbf24 + +.signup-note-card__body + flex: 1 + +.signup-note-card__title + font-size: 12px + font-weight: 600 + color: #92400e + margin: 0 0 4px + + html.dark & + color: #fcd34d + +.signup-note-card__text + font-size: 11px + color: #78350f + margin: 0 + line-height: 1.6 + + html.dark & + color: rgba(252, 211, 77, 0.8) + + a + color: #92400e + text-decoration: underline + + html.dark & + color: #fcd34d + +// ── Terms note ───────────────────────────────────────────────────────────────── +.signup-terms-note + font-size: 11px + color: #666666 + text-align: center + line-height: 1.6 + margin: 0 + + html.dark & + color: #a0a6b0 +.signup-terms-link + color: #555555 + text-decoration: underline + transition: color 0.15s + &:hover + color: #5A2A82 + html.dark &:hover + color: #ffb91a +// ── Flash / invite ───────────────────────────────────────────────────────────── +.signup-flash, +.signup-invite-msg + font-size: 13px + color: #374151 + margin-bottom: 12px + padding: 10px 14px + background: #f3f4f6 + border-radius: 8px + html.dark & + background: rgba(255, 255, 255, 0.05) + color: #d1d5db diff --git a/app/assets/stylesheets/accounts/pai.sass b/app/assets/stylesheets/accounts/pai.sass index 43a52fa12..50afdd84a 100644 --- a/app/assets/stylesheets/accounts/pai.sass +++ b/app/assets/stylesheets/accounts/pai.sass @@ -1,10 +1,5 @@ @import oh-styles -#project_header_activity_indicator - width: 88px - margin-top: 1.4rem - margin-left: 2rem - .thirtyfive_project_activity_text font-size: 11px text-align: center @@ -29,26 +24,28 @@ text-align: left margin-left: 19px -#i_use_this_container - margin-bottom: 0.8rem - .btn.iusethis - font-size: 13px - height: 30px - margin-right: 10px - - .use_count - padding: 0 10px - font-size: 24px - height: 32px - line-height: 36px - display: block +// Redesigned header activity indicator wrapper +.activity-indicator-wrapper + display: flex + flex-direction: column + align-items: center + justify-content: center + gap: 8px + min-width: 80px + + [class^='thirtyfive_project_activity_level_'] + position: static + top: auto + margin-left: 0 + transform: scale(1.25) + transform-origin: center center + + .thirtyfive_project_activity_text + margin: 0 + width: auto + line-height: 1.2 + font-size: 12px + font-weight: 600 + color: white text-align: center - margin-top: 2px - a - @include site-link-color - -#project_container - #i_use_this_container - padding: 0 - .btn.iusethis - font-size: 2rem + white-space: nowrap diff --git a/app/assets/stylesheets/accounts/show.sass b/app/assets/stylesheets/accounts/show.sass index ecedde452..af676e571 100644 --- a/app/assets/stylesheets/accounts/show.sass +++ b/app/assets/stylesheets/accounts/show.sass @@ -1,98 +1,1414 @@ +// ═════════════════════════════════════════════════════════════════════ +// ACCOUNT SHOW PAGE - FIGMA DESIGN STYLING +// Palette: #5A2A82 primary, #1D0631 dark bg, #2D1548 dark card, +// #c084fc dark accent, #ffb91a yellow, #f97316 lang badge +// ═════════════════════════════════════════════════════════════════════ + #accounts_show_page - color: black - margin-top: -5px + background-color: #f9fafb + color: #111827 + margin: 0 !important + padding: 0 0 32px + min-height: 100vh + transition: background-color 0.3s ease, color 0.3s ease + + html.dark & + background-color: #1D0631 + color: #e5e7eb + .link_no_underline &:hover text-decoration: none !important - .primary_language_bg - text-align: center - width: 128px - line-height: 20px - .stacked_projects - img - margin-bottom: 10px !important - padding: 3px - p - margin-bottom: 10px !important -.dev_history - padding-top: 1em + +// ═════════════════════════════════════════════════════════════════════ +// HERO HEADER — full-width white section, inner content max-width constrained +// ═════════════════════════════════════════════════════════════════════ +.account_header + background: #ffffff + border-bottom: 1px solid #e5e7eb + padding: 0 !important + margin: 0 0 24px !important + max-width: none !important + width: 100% + position: static + + html.dark & + background: #1D0631 + border-bottom-color: rgba(42, 18, 69, 1) + +// ─── Inner constrained container ───────────────────────────────────── +.account_header_inner + max-width: 1024px + margin: 0 auto + padding: 24px 16px 20px + display: flex + flex-direction: column + gap: 16px + + @media (min-width: 640px) + padding: 24px 24px 20px + +// ─── Back link row ──────────────────────────────────────────────────── +.header_back_row + margin-bottom: -4px + +.header-back-link + display: inline-flex + align-items: center + gap: 4px + font-size: 12px + font-weight: 500 + color: #6b7280 + text-decoration: none + transition: color 0.15s + + &:hover + color: #5A2A82 + text-decoration: none + + html.dark & + color: #9ca3af + + html.dark &:hover + color: #ffb91a + + i + font-size: 11px + +// ─── Header Flex Container (Avatar + Name content) ────────────────── +.header_flex_container + display: flex + gap: 16px + align-items: flex-start + width: 100% + + @media (min-width: 768px) + gap: 20px + +// ─── Avatar Section (80px mobile / 96px sm+, rounded-2xl) ────────────────────────── #account_icon - width: 130px - margin-bottom: 18px - margin-top: 15px - margin-left: -15px + width: 80px !important + height: 80px !important + margin: 0 !important + padding: 0 !important + position: relative + flex-shrink: 0 + border-radius: 16px + overflow: hidden + border: 2px solid rgba(90, 42, 130, 0.3) + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05) + + html.dark & + border-color: rgba(192, 132, 252, 0.25) + a display: block + width: 100% + height: 100% + + img + width: 100% !important + height: 100% !important + object-fit: cover + display: block + padding: 0 !important + margin: 0 !important + + @media (min-width: 640px) + width: 96px !important + height: 96px !important + +// ─── Primary Language Badge (overlay on avatar — Figma: -bottom-2 -right-2) ───── +.primary_language_bg + position: absolute + bottom: -8px + right: -8px + width: 24px !important + height: 24px !important + border-radius: 6px + font-size: 10px !important + font-weight: 700 + border: 2px solid #ffffff + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15) + text-transform: uppercase + display: flex + align-items: center + justify-content: center + margin: 0 !important + padding: 0 !important + + html.dark & + border-color: #1D0631 + +// ═════════════════════════════════════════════════════════════════════ +// HEADER MAIN COLUMN (#account_header — name, info, kudos) +// ═════════════════════════════════════════════════════════════════════ #account_header - margin-top: -15px - margin-left: 20px - width: 790px - position: relative - min-height: 145px - .info - margin-top: 3px + flex: 1 + margin: 0 !important + padding: 0 !important + width: auto !important + min-height: 0 + position: static + display: flex + flex-direction: column + gap: 8px + +// ─── Name Block ────────────────────────────────────────────────── +#account_name + margin: 0 + padding: 0 + width: 100% + float: none !important + h1 - @include site-link-color - width: 350px - .social-connect - padding-top: 5px - font-size: 22px -#kudo_section - position: inherit - form - margin-bottom: 0px - display: inline -@media only all and (min-width: 320px) and (max-width: 480px) - #account_header - width: auto - .social-connect - .btn-info - font-size: 10px !important - #account_name - margin-top: -134px - margin-left: 64px - h1 + font-size: 20px !important + font-weight: 600 !important + color: #111827 !important + line-height: 1.25 !important + margin: 0 0 4px !important + width: auto !important + border: none !important + letter-spacing: 0 + word-break: break-word + + @media (min-width: 640px) + font-size: 30px !important + + html.dark & + color: #ffffff !important + + a + color: inherit !important + text-decoration: none !important + &:hover + text-decoration: none !important + +// ─── Info row wrapper (location + website — stacks mobile, row sm+) ─ +#account_header .info_row + display: flex + flex-direction: column + gap: 2px + margin: 4px 0 8px !important + + @media (min-width: 640px) + flex-direction: row + flex-wrap: wrap + align-items: center + column-gap: 12px + row-gap: 2px + +// ─── Individual info item (location / website / affiliation) ───────── +#account_header .info + font-size: 12px + color: #6b7280 + line-height: 1.4 + margin: 0 !important + padding: 0 + display: flex + align-items: center + gap: 4px + + @media (min-width: 640px) + font-size: 14px + + html.dark & + color: #9ca3af + + i + flex-shrink: 0 + font-size: 12px !important + color: inherit + + @media (min-width: 640px) + font-size: 14px !important + + a + color: #5A2A82 + text-decoration: none + display: inline-flex + align-items: center + gap: 4px + transition: color 0.15s ease + min-width: 0 + + &:hover + text-decoration: underline + + html.dark & + color: #c084fc + +// ─── Action Buttons + Analyzed Timestamp (Figma: mt-4 flex-col gap-2) ─ +.header_actions + display: flex + flex-direction: column + gap: 8px + margin: 0 + padding: 0 + width: 100% + +// ─── Buttons row (flex-wrap row) ───────────────────────────────────── +.header_buttons + display: flex + gap: 8px + flex-wrap: wrap + align-items: center + + .action_button + padding: 6px 12px !important + border-radius: 8px !important + border: 1px solid #e5e7eb !important + background: #f3f4f6 !important + font-size: 12px !important + font-weight: 500 !important + color: #374151 !important + text-decoration: none !important + display: inline-flex + align-items: center + gap: 6px + transition: all 0.2s ease + height: auto !important + line-height: 1.2 !important + margin: 0 !important + + @media (min-width: 640px) font-size: 14px !important - width: auto + padding: 6px 14px !important + + &:hover + background: #e5e7eb !important + border-color: #d1d5db !important + text-decoration: none !important + + html.dark & + background: rgba(255, 255, 255, 0.1) !important + border-color: rgba(255, 255, 255, 0.2) !important + color: #ffffff !important + + &:hover + background: rgba(255, 255, 255, 0.2) !important + border-color: rgba(255, 255, 255, 0.3) !important + + i + font-size: 14px + flex-shrink: 0 + + .kudo_button_wrapper + display: inline-flex + margin: 0 !important + padding: 0 !important + + button, .btn, a + padding: 6px 16px !important + border-radius: 9999px !important + border: 1px solid rgba(90, 42, 130, 0.5) !important + background: #ffffff !important + font-size: 14px !important + font-weight: 500 !important + color: #5A2A82 !important + text-decoration: none !important + display: inline-flex + align-items: center + gap: 8px + transition: all 0.2s ease + height: auto !important + line-height: 1 !important + margin: 0 !important + cursor: pointer + + &:hover + border-color: #5A2A82 !important + background: #ffffff !important + text-decoration: none !important + + &.active, &.given + background: #5A2A82 !important + border-color: #5A2A82 !important + color: #ffffff !important + + &:hover + background: #4a1f6e !important + border-color: #4a1f6e !important + + html.dark & + background: #2D1548 !important + border-color: rgba(192, 132, 252, 0.5) !important + color: #c084fc !important + + &:hover + border-color: #c084fc !important + + &.active, &.given + background: #5A2A82 !important + border-color: #5A2A82 !important + color: #ffffff !important + +// ─── Kudo badges — horizontal scrolling row between header info and action buttons +// ─── Badges row in account header (high specificity to override badges.sass) ── +.account_header_inner > .mini-badges-section + display: flex !important + flex-direction: row !important + flex-wrap: nowrap !important + align-items: flex-start !important + overflow-x: auto !important + overflow-y: visible !important + gap: 0 !important + padding: 8px 0 4px !important + margin: 0 !important + position: relative !important + top: auto !important + right: auto !important + height: auto !important + float: none !important + -webkit-overflow-scrolling: touch + scrollbar-width: none + &::-webkit-scrollbar + display: none + + @media (min-width: 640px) + flex-wrap: wrap !important + overflow-x: visible !important + + @media (min-width: 1025px) + flex-shrink: 0 !important + align-self: flex-start !important + margin: 0 0 0 auto !important + width: auto !important + padding: 0 !important + flex-wrap: wrap !important + overflow-x: visible !important + + .account-badge + display: inline-block !important + float: none !important + flex-shrink: 0 + height: 48px !important + width: 48px !important + margin: 0 8px 31px 0 !important + transition: transform 0.15s ease + background-size: auto 48px + + &:hover + transform: scale(1.05) + + &.last + margin-right: 0 !important + + .pips + margin: 53px 5px 0 6px !important + width: 37px !important + +// ─── Kudo Button Override (strong specificity to override Bootstrap) ────────────────────────── +.kudo_button_wrapper form, +.kudo_button_wrapper button, +.kudo_button_wrapper .btn, +.kudo_action_button + all: revert !important + border-radius: 9999px !important + border: 1px solid rgba(90, 42, 130, 0.5) !important + background: #ffffff !important + font-size: 14px !important + font-weight: 500 !important + color: #5A2A82 !important + text-decoration: none !important + display: inline-flex !important + align-items: center !important + gap: 8px !important + transition: all 0.2s ease !important + height: auto !important + line-height: 1 !important + margin: 0 !important + cursor: pointer !important + + &:hover + border-color: #5A2A82 !important + background: #ffffff !important + text-decoration: none !important + + html.dark & + background: #2D1548 !important + border-color: rgba(192, 132, 252, 0.5) !important + color: #c084fc !important + + &:hover + border-color: #c084fc !important + background: #2D1548 !important + + i + font-size: 14px !important + +// ═════════════════════════════════════════════════════════════════════ +// SECTION HEADING (Figma SectionHeading) — h2/h3 with horizontal divider +// ═════════════════════════════════════════════════════════════════════ +#accounts_show_page #accounts_show > h2 + font-size: 16px !important + font-weight: 600 !important + color: #111827 !important + line-height: 1.3 !important + margin: 0 0 16px !important + padding: 0 !important + letter-spacing: 0 + float: none !important + width: 100% !important + display: flex !important + align-items: center + gap: 12px + white-space: nowrap + + html.dark & + color: #ffffff !important + + &::after + content: '' + flex: 1 + height: 1px + background: #e5e7eb + min-width: 40px + + html.dark & + background: rgba(90, 42, 130, 0.2) + +#accounts_show_page .mezzo.padding_one_top > h3 + font-size: 16px !important + font-weight: 600 !important + color: #111827 !important + line-height: 1.3 !important + margin: 0 0 16px !important + padding: 0 !important + letter-spacing: 0 + float: none !important + width: 100% !important + display: flex !important + align-items: center + gap: 12px + white-space: nowrap + + html.dark & + color: #ffffff !important + + &::after + content: '' + flex: 1 + height: 1px + background: #e5e7eb + min-width: 40px + + html.dark & + background: rgba(90, 42, 130, 0.25) + +// ═════════════════════════════════════════════════════════════════════ +// ACCOUNT SUMMARY — single white card with proper layout +// ═════════════════════════════════════════════════════════════════════ +#accounts_show_page #accounts_show + background: transparent + border: none + box-shadow: none + padding: 0 16px + margin: 0 auto 24px + max-width: 1024px + width: 100% + + @media (min-width: 640px) + padding: 0 24px + +// Summary Card wrapper (white bg, rounded, border, shadow) +.summary_card_wrapper + background: #ffffff + border: 1px solid #e5e7eb + border-radius: 16px + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08) + overflow: hidden + width: 100% + + html.dark & + background: #2D1548 + border-color: rgba(90, 42, 130, 0.2) + +// Grid layout: stacks on mobile (1 column), 2 columns on md+ +.summary_grid + display: grid + grid-template-columns: 1fr + gap: 0 + width: 100% + + @media (min-width: 768px) + grid-template-columns: 1fr 1fr + +// Left column: Description + Projects Used +.summary_column_left + padding: 16px !important + border-bottom: 1px solid #f3f4f6 + margin: 0 !important + + @media (min-width: 640px) + padding: 24px !important + + @media (min-width: 768px) + border-bottom: none + border-right: 1px solid #f3f4f6 + padding: 24px !important + + html.dark & + border-bottom-color: rgba(90, 42, 130, 0.2) + + @media (min-width: 768px) + border-right-color: rgba(90, 42, 130, 0.2) + +// Right column: Baseball Card stats +.summary_column_right + padding: 16px !important + margin: 0 !important + + @media (min-width: 640px) + padding: 24px !important + +// Account analysis timestamp — now in header below action buttons +.header_actions #account_analysis_timestamp, +.header_actions #analysis_timestamp + float: none !important + color: #4b5563 !important + font-size: 12px + font-style: normal + margin: 0 !important + padding: 0 !important + display: flex + align-items: center + gap: 6px + + html.dark & + color: #9ca3af !important + + i + font-style: normal + color: inherit + font-size: 12px + + abbr + border-bottom: none + text-decoration: none + cursor: default + + abbr + border-bottom: none + text-decoration: none + cursor: default + +// Description body +#accounts_show_page #accounts_show .margin_bottom_10px + font-size: 14px + color: #4b5563 + line-height: 1.6 + margin-bottom: 16px !important + + html.dark & + color: #d1d5db + +// "Projects Used" subheading — purple uppercase tracked (Figma: mb-3 = 12px, no top margin) +#accounts_show_page #accounts_show .projects_used + font-size: 12px !important + font-weight: 600 !important + color: #5A2A82 !important + text-transform: uppercase + letter-spacing: 0.1em + margin: 0 0 12px !important + + html.dark & + color: #c084fc !important + + a + color: inherit !important + text-decoration: none + +// Stacked project icons +#accounts_show_page #accounts_show .stacked_projects + display: flex !important + flex-wrap: wrap + gap: 6px + margin-bottom: 16px + + a + border: 0 !important + display: inline-flex + + img + width: 36px !important + height: 36px !important + border-radius: 8px + border: 1px solid #e5e7eb + padding: 0 !important + margin: 0 !important + transition: transform 0.15s ease + object-fit: cover + + &:hover + transform: scale(1.05) + + html.dark & + border-color: rgba(90, 42, 130, 0.3) + + p + margin: 0 !important + display: inline-flex + color: #5A2A82 + font-size: 12px + align-items: center + padding-left: 4px + + a + color: inherit + text-decoration: none + +// ═════════════════════════════════════════════════════════════════════ +// BASEBALL CARD — clean stats list (label / value rows) +// ═════════════════════════════════════════════════════════════════════ +#accounts_show_page .baseball_card + width: 100% !important + float: none !important + display: flex + flex-direction: column + gap: 10px + + .col-md-3, .col-md-4, .col-md-7, + .col-xs-7, .col-sm-7, .col-xs-3, .col-sm-3, .col-xs-4, .col-sm-4 + padding: 0 !important + float: none !important + width: auto !important + + .statistic + width: 100% !important + min-height: auto + margin: 0 !important + padding: 0 !important + border-bottom: none !important + + .inner + width: 100% !important + line-height: 1.4 + display: flex + align-items: flex-start + justify-content: space-between + gap: 12px + + // Figma: flex-shrink-0 w-[42%] sm:w-44 text-xs sm:text-sm text-gray-500 + .name + width: 42% !important + font-size: 12px + font-weight: 400 + color: #6b7280 + text-align: left !important + margin: 0 !important + flex-shrink: 0 + line-height: 1.4 + + @media (min-width: 640px) + width: 176px !important + font-size: 14px + + html.dark & + color: #9ca3af + + // Figma: text-gray-700 text-right text-xs sm:text-sm + .value + font-size: 12px + font-weight: 500 + color: #374151 + margin: 0 !important + text-align: right + flex: 1 + line-height: 1.4 + min-width: 0 + + @media (min-width: 640px) + font-size: 14px + + html.dark & + color: #e5e7eb + + a + color: #5A2A82 + text-decoration: none + font-weight: 600 + + &:hover + text-decoration: underline + + html.dark & + color: #c084fc + + .language-box + font-size: 12px !important + font-weight: 700 !important + margin: 0 !important + padding: 2px 8px !important + border-radius: 4px !important + display: inline-block !important + min-width: auto !important + line-height: 1.4 !important + background-color: #f97316 !important + color: #ffffff !important + text-transform: none + + .right_sm + font-size: 11px + margin-left: 0 + margin-top: 2px + line-height: 1.4 + color: #4b5563 + display: block + width: 100% + font-weight: 400 + + html.dark & + color: #9ca3af + + // ─── Figma: commits count and org count are bold ────────────────── + .statistic--commits .value + font-weight: 700 !important + color: #111827 !important + + html.dark & + color: #ffffff !important + + .statistic--orgs .value + font-weight: 700 !important + color: #111827 !important + + html.dark & + color: #ffffff !important + + .right_sm + font-weight: 400 !important + color: #4b5563 !important + + html.dark & + color: #9ca3af !important + +// ═════════════════════════════════════════════════════════════════════ +// DEV HISTORY — section heading + chart cards +// ═════════════════════════════════════════════════════════════════════ +#accounts_show_page .mezzo.padding_one_top + border-top: none !important + margin: 24px auto 0 !important + padding: 0 16px !important + max-width: 1024px + + @media (min-width: 640px) + padding: 0 24px !important + + // ─── .dev_chart_section IS the card — wraps title + chart + JS-injected legend + .dev_chart_section + background: #ffffff + border: 1px solid #e5e7eb + border-radius: 16px + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08) + padding: 16px + margin-bottom: 24px + overflow: hidden + + @media (min-width: 640px) + padding: 20px + + html.dark & + background: #2D1548 + border-color: rgba(90, 42, 130, 0.2) + + &:last-child + margin-bottom: 0 + + // ─── Section headings (card header with horizontal divider) ───────────── + .dev_chart_section #commit_projects, + .dev_chart_section #commits_lang + float: none !important + clear: both + display: flex !important + align-items: center + gap: 12px + margin: 0 0 16px !important + padding: 0 0 12px !important + border-bottom: 1px solid #f3f4f6 !important + + html.dark & + border-bottom-color: rgba(90, 42, 130, 0.15) !important + + h4 + font-size: 15px !important + font-weight: 600 !important + color: #111827 !important + margin: 0 !important + padding: 0 + line-height: 1.3 !important + white-space: nowrap + border: none !important + + html.dark & + color: #ffffff !important + + a + color: inherit !important + text-decoration: none !important + + &:hover + text-decoration: underline !important + + // ─── Date range label ──────────────────────────────────────────────────── + .dev_chart_section .soft.margin_top_10.margin_left_20, + .dev_chart_section .soft.margin_left_20 + float: none !important + clear: both + color: #4b5563 !important + font-style: normal + font-size: 12px !important + margin: -4px 0 12px !important + display: block + + html.dark & + color: #9ca3af !important + + // ─── .margin_top_10 wrapper inside commits_by_language — reset margin ──── + .dev_chart_section > .margin_top_10 + margin-top: 0 !important + + // ─── Override fixed widths from streamgraph.sass ───────────────────────── + // #ohloh_streamgraph has width:715px float:left margin-left:15px + // #ohloh_stream (child SVG) has width:940px !important + // #streamgraph_legend is injected AFTER #ohloh_streamgraph by JS as a sibling + // Both end up inside .dev_chart_section, so card contains everything + .dev_chart_section #ohloh_streamgraph + width: 100% !important + float: none !important + margin-left: 0 !important + margin-right: 0 !important + overflow: visible + + svg, #ohloh_stream + width: 100% !important + max-width: 100% !important + + .dev_chart_section #streamgraph_legend + float: none !important + width: 100% !important + white-space: normal !important + margin-right: 0 !important + margin-top: 12px + border: none !important + overflow: visible + + // ─── Constrain all chart canvases to card width ────────────────────────── + .dev_chart_section .chart, + .dev_chart_section #project_contributions + max-width: 100% !important + width: 100% !important + margin-left: 0 !important + +// ═════════════════════════════════════════════════════════════════════ +// ADMIN PANEL — page wrapper aligns with summary card (same padding) +// ═════════════════════════════════════════════════════════════════════ +.admin_panel_page_wrapper + max-width: 1024px + margin: 0 auto 24px + padding: 0 16px + + @media (min-width: 640px) + padding: 0 24px + + // ── Development History section ─────────────────────────────────────── +.dev-history-section + padding: 0 + margin: 0 + + > h2 + font-size: 16px !important + font-weight: 600 !important + color: #111827 !important + line-height: 1.3 !important + margin: 0 0 16px !important + padding: 0 !important + letter-spacing: 0 + float: none !important + width: 100% !important + display: flex !important + align-items: center + gap: 12px + white-space: nowrap + + html.dark & + color: #ffffff !important + + &::after + content: '' + flex: 1 + height: 1px + background: #e5e7eb + min-width: 40px + + html.dark & + background: rgba(90, 42, 130, 0.2) + +// ── Admin card container (inside wrapper — full width within padding) ─ +#admin_actions_opened, #admin_actions_closed + border-radius: 16px !important + border: 1px solid rgba(251, 191, 36, 0.4) !important + background: #ffffff !important + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08) !important + padding: 0 !important + margin: 0 !important + overflow: hidden + width: 100% + + html.dark & + background: #1a0e2e !important + border-color: rgba(251, 191, 36, 0.3) !important + +// ─── Shared amber header bar (used in both open/closed states) ──── +.admin_panel_header + display: flex !important + align-items: center !important + justify-content: space-between !important + width: 100% !important + padding: 12px 16px !important + background: #fffbeb !important + border-bottom: 1px solid rgba(251, 191, 36, 0.3) !important + text-decoration: none !important + cursor: pointer + box-sizing: border-box + + html.dark & + background: rgba(120, 53, 15, 0.25) !important + border-bottom-color: rgba(251, 191, 36, 0.2) !important + + @media (min-width: 640px) + padding: 14px 20px !important + +// When collapsed, no border-bottom (nothing below the header) +#admin_actions_closed .admin_panel_header + border-bottom: none !important + +.admin_header_left + display: flex + align-items: center + gap: 10px + +.admin_lock_badge + width: 28px + height: 28px + border-radius: 8px + background: rgba(251, 191, 36, 0.2) + display: flex + align-items: center + justify-content: center + flex-shrink: 0 + + html.dark & + background: rgba(251, 191, 36, 0.3) + + i + font-size: 13px !important + color: #b45309 !important + margin: 0 !important + line-height: 1 + + html.dark & + color: #fbbf24 !important + +.admin_panel_title + font-size: 12px !important + font-weight: 700 !important + color: #92400e !important + text-transform: uppercase + letter-spacing: 0.08em + line-height: 1 + + html.dark & + color: #fcd34d !important + +.admin_chevron_btn + display: flex !important + align-items: center + color: #b45309 !important + text-decoration: none !important + background: transparent !important + border: none !important + box-shadow: none !important + padding: 2px 4px !important + margin: 0 !important + height: auto !important + line-height: 1 !important + cursor: pointer !important + + html.dark & + color: #fbbf24 !important + + i + font-size: 14px !important + margin: 0 !important + +// ─── Panel body (expanded content) ─────────────────────────────── +.admin_panel_body + background: #ffffff + display: flex + flex-direction: column + + html.dark & + background: #1a0e2e + +// ─── Info section (Figma: px-4 sm:px-5 py-4 space-y-4) ───────────── +.admin_info_section + padding: 16px !important + border-bottom: 1px solid #f3f4f6 + display: flex + flex-direction: column + gap: 16px + + html.dark & + border-bottom-color: rgba(90, 42, 130, 0.15) + + @media (min-width: 640px) + padding: 16px 20px !important + + p + margin: 0 !important + padding: 0 + color: #4b5563 + font-size: 13px + line-height: 1.5 + + html.dark & + color: #d1d5db + +// ─── Shared label with icon (Email Address / Open Hub Activity / Admin Actions) +.admin_info_label + display: flex + align-items: center + gap: 6px + margin: 0 0 8px !important + + i + font-size: 12px !important + color: #9ca3af !important + flex-shrink: 0 + + html.dark & + color: #6b7280 !important + + span + font-size: 11px !important + font-weight: 700 !important + color: #9ca3af !important + text-transform: uppercase + letter-spacing: 0.1em + line-height: 1.4 + + html.dark & + color: #6b7280 !important + +.admin_danger_label + i, span + color: #f87171 !important + + html.dark & + color: rgba(248, 113, 113, 0.8) !important + +// ─── Email link ────────────────────────────────────────────────────── +.admin_email_link + margin: 0 !important + + a + font-size: 13px !important + color: #5A2A82 !important + text-decoration: none + display: inline-flex + align-items: center + gap: 4px + word-break: break-all + + &:hover + text-decoration: underline + + html.dark & + color: #c084fc !important + +// ─── Activity mini-cards (Figma: grid grid-cols-1 sm:grid-cols-3) ──── +.admin_activity_cards + display: grid + grid-template-columns: 1fr + gap: 8px + + @media (min-width: 640px) + grid-template-columns: repeat(3, 1fr) + +.admin_activity_card + display: flex + align-items: center + gap: 10px + border: 1px solid #e5e7eb + border-radius: 12px + padding: 10px 12px + + html.dark & + background: #2D1548 + border-color: rgba(90, 42, 130, 0.2) + + > i + font-size: 16px !important + color: #5A2A82 !important + flex-shrink: 0 + + html.dark & + color: #c084fc !important + +.admin_activity_card_body + min-width: 0 + flex: 1 + + p.admin_activity_card_title + font-size: 11px !important + color: #9ca3af !important + margin: 0 0 2px !important + padding: 0 + + html.dark & + color: #6b7280 !important + + a + font-size: 13px !important + font-weight: 600 !important + color: #5A2A82 !important + text-decoration: none + display: block + + &:hover + text-decoration: underline + + html.dark & + color: #c084fc !important + +// ─── Actions section (Figma: px-4 sm:px-5 py-4 bg-red-50/40) ──────── +.admin_actions_section + padding: 16px !important + background: rgba(254, 242, 242, 0.4) + + html.dark & + background: rgba(127, 29, 29, 0.08) + + @media (min-width: 640px) + padding: 16px 20px !important + +// ─── Action buttons grid (Figma: grid-cols-2 sm:flex sm:flex-wrap) ── +.admin_btns_grid + display: grid + grid-template-columns: repeat(2, 1fr) + gap: 8px + + @media (min-width: 640px) + display: flex + flex-wrap: wrap + + .admin_disabled_btn + display: contents + +.admin_actions_section p + margin: 0 !important + padding: 0 + +// ─── Color-coded action buttons (inside grid/flex) ────────────────── +.admin_btns_grid .btn, +.admin_btns_grid a.btn, +.admin_btns_grid button.btn + border-radius: 10px !important + padding: 8px 12px !important + font-size: 12px !important + font-weight: 600 !important + margin: 0 !important + border: 1px solid !important + line-height: 1 !important + height: auto !important + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important + transition: all 0.15s ease + color: #ffffff !important + display: flex !important + align-items: center + justify-content: center + gap: 6px + text-align: center + + i + font-size: 12px + + &:hover + transform: scale(0.98) + text-decoration: none !important + color: #ffffff !important + + &.btn-primary + background-color: #5A2A82 !important + border-color: #5A2A82 !important + &:hover + background-color: #4a1f6e !important + + &.btn-warning + background-color: #f97316 !important + border-color: #ea580c !important + &:hover + background-color: #ea580c !important + + &.btn-success + background-color: #059669 !important + border-color: #047857 !important + &:hover + background-color: #047857 !important + + &.btn-danger + background-color: #dc2626 !important + border-color: #b91c1c !important + &:hover + background-color: #b91c1c !important + + &.btn-info + background-color: #1e3a8a !important + border-color: #1e40af !important + &:hover + background-color: #1e40af !important + + &.btn-default[disabled], &[disabled] + background-color: #e5e7eb !important + border-color: #d1d5db !important + color: #9ca3af !important + cursor: not-allowed + +// ─── Close admin panel text button (Figma: col-span-2 ghost button) ── +.admin_close_text_btn + grid-column: 1 / -1 + display: flex !important + align-items: center + justify-content: center + gap: 6px + padding: 8px 12px !important + border-radius: 10px !important + border: 1px solid transparent !important + background: transparent !important + font-size: 12px !important + font-weight: 500 !important + color: #6b7280 !important + text-decoration: none !important + cursor: pointer + transition: all 0.15s ease + box-shadow: none !important + height: auto !important + margin: 0 !important + line-height: 1 !important + + i + font-size: 11px !important + + &:hover + color: #374151 !important + border-color: #e5e7eb !important + background: transparent !important + text-decoration: none !important + + html.dark & + color: #9ca3af !important + + &:hover + color: #e5e7eb !important + border-color: rgba(90, 42, 130, 0.3) !important + +.dev_history + padding-top: 1em + +// ═════════════════════════════════════════════════════════════════════ +// RESPONSIVE OVERRIDES — Mobile & Tablet +// ═════════════════════════════════════════════════════════════════════ +@media only all and (min-width: 320px) and (max-width: 480px) + .account_header_inner + padding: 16px 12px 14px !important + gap: 12px + + .header_flex_container + gap: 12px + #account_icon - img - width: 90px - height: 90px + width: 64px !important + height: 64px !important + + #account_name h1 + font-size: 18px !important + + .header_buttons + gap: 6px + + .action_button + padding: 5px 10px !important + font-size: 11px !important + + #kudo_section + gap: 8px + + .social-connect + gap: 6px + + .btn-info, .btn-mini, .btn + padding: 5px 12px !important + font-size: 12px !important + #accounts_show_page - .primary_language_bg - width: 90px - #accounts_show - h2 - font-size: 15px !important - .projects_used - font-size: 14px !important - #admin_actions_opened + #accounts_show > h2 + font-size: 14px !important + + .baseball_card + .name + font-size: 11px + + .value + font-size: 12px + + .admin_actions_section + padding: 12px !important + .btn - font-size: 10px - .mezzo - h3 - font-size: 15px - #commit_projects - h4 - font-size: 13px - #commits_lang - h4 - font-size: 13px - #project_contributions - svg.highcharts-root - font-size: 10px !important - .highcharts-axis-labels - text + padding: 6px 10px !important + font-size: 11px !important + + .admin_btns_grid + grid-template-columns: 1fr !important + + .admin_close_text_btn + grid-column: 1 !important + + #accounts_show_page .mezzo.padding_one_top + > h3 + font-size: 14px !important + + > .col-sm-12, > .col-md-12 + padding: 14px !important + + #commit_projects h4, #commits_lang h4 + font-size: 13px !important + + #project_contributions + svg.highcharts-root + font-size: 10px !important + .highcharts-axis-labels text font-size: 10px !important - .highcharts-legend-item - text + .highcharts-legend-item text font-size: 6px !important + @media (min-width: 540px) and (max-width: 1024px) - #account_header - width: 83.33333333%; - margin-left: 8px - #account_name - h1 - font-size: 24px !important - width: auto - margin-top: 30px + .account_header_inner + padding: 20px 20px 18px !important + + #account_name h1 + font-size: 24px !important + +@media (min-width: 1025px) + .account_header_inner + flex-direction: row !important + flex-wrap: wrap !important + align-items: flex-start !important + + .account_header_inner > .header_flex_container + flex: 1 1 0% !important + min-width: 0 !important + + .account_header_inner > .header_actions + flex: 0 0 100% !important diff --git a/app/assets/stylesheets/ace-chosen-overrides.sass b/app/assets/stylesheets/ace-chosen-overrides.sass index 41b3bcda9..d018fbdc0 100644 --- a/app/assets/stylesheets/ace-chosen-overrides.sass +++ b/app/assets/stylesheets/ace-chosen-overrides.sass @@ -40,7 +40,7 @@ &.chosen-disabled .chosen-single abbr:hover:after color: #464646 -.chosen-single div b +.chosen-container-single .chosen-single div b background: none !important &:before content: "\f0d7" @@ -158,7 +158,7 @@ .chosen-container-active.chosen-with-drop .chosen-single @include chzn-container-border-color -@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx) .chosen-rtl .chosen-search input background-image: none !important background-repeat: no-repeat !important diff --git a/app/assets/stylesheets/alias.sass b/app/assets/stylesheets/alias.sass index c57bd86cb..518c0aa9a 100644 --- a/app/assets/stylesheets/alias.sass +++ b/app/assets/stylesheets/alias.sass @@ -1,16 +1,188 @@ +// Design System Variables +$purple-primary: #5A2A82 +$gray-500: #6b7280 +$gray-200: #e5e7eb +$yellow-accent: #FFB91A + +// System Font Stack +$font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif + .project_content_title - :height 50px + height: 72px + font-family: $font-family + .alias + font-family: $font-family + .undone - :text-decoration line-through - :color #808080 + text-decoration: line-through + color: $gray-500 + .pending - :color #8B0000 - :padding-left 18px - :background asset_url('icons/fact_warning.png') left center no-repeat + color: $purple-primary + padding-left: 18px + background: asset_url('icons/fact_warning.png') left center no-repeat + font-weight: 500 + li - :margin-left 25px - :margin-bottom 8px - :border-bottom 1px solid #ddd - :padding-bottom 5px + margin-left: 25px + margin-bottom: 12px + border-bottom: 1px solid $gray-200 + padding-bottom: 8px + font-weight: 400 + line-height: 1.6 + +// Dark Mode +html.dark, +body.dark + .alias + .undone + color: #94a3b8 + + .pending + color: $yellow-accent + + li + border-bottom-color: rgba(255, 255, 255, 0.1) + +// ────────────────────────────────────────────────────────────────────────────── +// Alias New Page (#alias-new-page) +// ────────────────────────────────────────────────────────────────────────────── + +#alias-new-page + padding: 24px 0 + + .alias-page-header + margin-bottom: 24px + + .alias-page-title + font-size: 22px + font-weight: 700 + color: #111827 + margin: 0 0 8px 0 + display: flex + align-items: center + gap: 8px + flex-wrap: wrap + + html.dark & + color: #ffffff + + a + color: #5A2A82 + text-decoration: none + + html.dark & + color: #ffb91a + + &:hover + text-decoration: underline + + &__sep + color: #9ca3af + font-weight: 400 + + // ── Form fields ── + + .alias-fields + padding: 4px 0 + + .alias-field-group + margin-bottom: 20px + + .alias-label + display: block + font-size: 13px + font-weight: 600 + color: #374151 + margin-bottom: 6px + + html.dark & + color: #d1d5db + + .alias-select-wrap + width: 100% + + select + box-sizing: border-box + width: 100% + border: 2px solid #e5e7eb !important + border-radius: 16px !important + padding: 10px 16px !important + font-size: 14px + height: auto !important + background: #ffffff !important + color: #111827 !important + transition: border-color 0.2s, box-shadow 0.2s + appearance: auto + + &:focus + border-color: #5A2A82 !important + outline: none !important + box-shadow: 0 0 0 3px rgba(90, 42, 130, 0.1) !important + + html.dark & + background: #1D0631 !important + color: #ffffff !important + border-color: #5A2A82 !important + + &:focus + border-color: #ffb91a !important + box-shadow: 0 0 0 3px rgba(255, 185, 26, 0.1) !important + + // chosen.js container + .chosen-container + width: 100% !important + + .chosen-single, + .chosen-choices + border: 2px solid #e5e7eb !important + border-radius: 16px !important + padding: 8px 16px !important + background: #ffffff !important + box-shadow: none !important + font-size: 14px !important + color: #111827 !important + + html.dark & + background: #1D0631 !important + border-color: #5A2A82 !important + color: #ffffff !important + + .chosen-container-active .chosen-single, + .chosen-container-active .chosen-choices + border-color: #5A2A82 !important + box-shadow: 0 0 0 3px rgba(90, 42, 130, 0.1) !important + + html.dark & + border-color: #ffb91a !important + box-shadow: 0 0 0 3px rgba(255, 185, 26, 0.1) !important + + .alias-actions + padding-top: 8px + display: flex + gap: 10px + + .alias-submit + height: 40px + padding: 0 24px + border-radius: 20px + font-size: 14px + font-weight: 600 + + // ── Responsive ── + + @media (max-width: 767px) + padding: 16px 0 + + .alias-page-title + font-size: 17px + + .alias-actions + flex-direction: column + + .alias-submit + width: 100% + @media (min-width: 768px) and (max-width: 1024px) + padding: 20px 0 diff --git a/app/assets/stylesheets/analyses.sass b/app/assets/stylesheets/analyses.sass index 902c4d18f..55372f3c4 100644 --- a/app/assets/stylesheets/analyses.sass +++ b/app/assets/stylesheets/analyses.sass @@ -12,3 +12,5 @@ #analyses_language_table .center text-align: center + .bar + min-width: 60px diff --git a/app/assets/stylesheets/api/custom.sass b/app/assets/stylesheets/api/custom.sass index e96b14288..11cce9759 100644 --- a/app/assets/stylesheets/api/custom.sass +++ b/app/assets/stylesheets/api/custom.sass @@ -1687,59 +1687,43 @@ padding: 6px #cve-cvss3, #cvss3, #cve-cvss3-mobile, #cvss3-mobile - background: asset-url("charts/watermark_340.png") no-repeat center - background-size: contain position: relative width: 100% height: 100% - html.dark & - background-image: none - - &::before - content: '' - position: absolute - top: 0 - left: 0 - right: 0 - bottom: 0 - background: asset-url("charts/watermark_340.png") no-repeat center - background-size: contain - filter: hue-rotate(260deg) saturate(1.2) brightness(0.3) - opacity: 0.2 - pointer-events: none - - .highcharts-axis-labels text, - .highcharts-axis-title text - fill: #d1d5db !important - stroke: none !important - stroke-width: 0 !important - -webkit-text-stroke: 0 !important - paint-order: stroke fill !important - - .highcharts-legend text - fill: #d1d5db !important - stroke: none !important - stroke-width: 0 !important - -webkit-text-stroke: 0 !important - paint-order: stroke fill !important - - svg text - stroke: none !important - stroke-width: 0 !important - -webkit-text-stroke: 0 !important - - text[stroke] - stroke: none !important - stroke-width: 0 !important - -webkit-text-stroke: 0 !important - - .highcharts-axis-line - stroke: #6b7280 !important - - .highcharts-grid-line - stroke: #374151 !important - opacity: 0.3 +html.dark + #cve-cvss3, #cvss3, #cve-cvss3-mobile, #cvss3-mobile + .highcharts-axis-labels text, + .highcharts-axis-title text + fill: #d1d5db !important + stroke: none !important + stroke-width: 0 !important + -webkit-text-stroke: 0 !important + paint-order: stroke fill !important + + .highcharts-legend text + fill: #d1d5db !important + stroke: none !important + stroke-width: 0 !important + -webkit-text-stroke: 0 !important + paint-order: stroke fill !important + + svg text + stroke: none !important + stroke-width: 0 !important + -webkit-text-stroke: 0 !important + + text[stroke] + stroke: none !important + stroke-width: 0 !important + -webkit-text-stroke: 0 !important + + .highcharts-axis-line + stroke: #6b7280 !important + + .highcharts-grid-line + stroke: #374151 !important + opacity: 0.3 .search-container display: flex @@ -1810,4 +1794,4 @@ color: #d1d5db .search-result-hint - color: #9ca3af + color: #9ca3af \ No newline at end of file diff --git a/app/assets/stylesheets/api_keys.sass b/app/assets/stylesheets/api_keys.sass index a57b7846e..7395c36e2 100644 --- a/app/assets/stylesheets/api_keys.sass +++ b/app/assets/stylesheets/api_keys.sass @@ -1,5 +1,68 @@ +.limit-label + color: #111827 + html.dark & + color: #e5e7eb + +#api-key-form + .help-block + color: #595959 !important + html.dark & + color: #9ca3af !important + + html.dark & + legend + color: #e5e7eb !important + border-bottom-color: #4b5563 !important + + .form-control + width: 85% !important + box-sizing: border-box !important + border: 2px solid #e5e7eb !important + border-radius: 16px !important + -webkit-border-radius: 16px !important + -moz-border-radius: 16px !important + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05) !important + background: #ffffff !important + color: #111827 !important + padding: 10px 16px !important + height: auto !important + transition: border-color 0.3s ease, box-shadow 0.3s ease + &::placeholder + color: #9ca3af !important + opacity: 1 + &:hover + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important + border-color: #d1d5db !important + &:focus, &:focus-visible + border-color: #5A2A82 !important + outline: none !important + box-shadow: 0 0 0 4px rgba(14, 75, 122, 0.1) !important + background: #ffffff !important + html.dark & + background: #1D0631 !important + color: #ffffff !important + border-color: #5A2A82 !important + &::placeholder + color: #6b7280 !important + opacity: 1 + &:hover + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.2), 0 2px 4px -1px rgba(0, 0, 0, 0.1) !important + border-color: #6b7280 !important + &:focus, &:focus-visible + border-color: #ffb91a !important + background: #1D0631 !important + box-shadow: 0 0 0 4px rgba(255, 185, 26, 0.1) !important + outline: none !important + label#request_limit font-size: 13px + display: flex + align-items: flex-start + gap: 8px + font-weight: normal + input[type="checkbox"] + margin-top: 3px + flex-shrink: 0 .api_keys .padding_20 @@ -9,6 +72,8 @@ label#request_limit color: #666 font-size: 12px font-weight: normal + html.dark & + color: #9ca3af #api_key_request_info .inline diff --git a/app/assets/stylesheets/autocomplete.sass b/app/assets/stylesheets/autocomplete.sass index 9cb5f06e2..317784611 100644 --- a/app/assets/stylesheets/autocomplete.sass +++ b/app/assets/stylesheets/autocomplete.sass @@ -1,58 +1,70 @@ .ui-autocomplete - :padding 0px - :border 1px solid #0082C6 - :background-color white - :overflow-y auto - :overflow-x hidden - :max-height 16.0em - :z-index 99999 - - :width 15.0em - :list-style-position outside - :list-style none - :padding 0 - :margin 0 + width: 160px + padding: 0 + margin: 0 + background-color: #ffffff + border: 1px solid #d1d5db + border-radius: 8px + overflow: hidden + overflow-y: auto + overflow-x: hidden + max-height: 16.0em + z-index: 99999 + list-style-position: outside + list-style: none + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23) + transition: all 0.2s ease + + html.dark & + background-color: #1D0631 + border-color: #5A2A82 + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.38), 0 6px 6px rgba(0, 0, 0, 0.46) li - :margin 0px - :padding 2px 5px - :cursor default - :display block - // COMMENT - if width will be 100% horizontal scrollbar will apear - when scroll mode will be used - width 100% - :font menu - :font-size 12px - // COMMENT - it is very important, if line-height not setted or setted - in relative units scroll will be broken in firefox - :line-height 16px - :overflow hidden + margin: 0 + padding: 8px 16px + cursor: default + display: block + font-size: 14px + font-weight: 400 + line-height: 20px + overflow: hidden + background: transparent + transition: background 0.15s ease, color 0.15s ease + + &:hover + background-color: #f3f4f6 + cursor: pointer + + html.dark & + background: #374151 a - :color black - :text-decoration none - :border 0 - :display block + color: #111827 + text-decoration: none + border: 0 + display: block - li:hover - :background-color $c2_light - :cursor pointer + html.dark & + color: #ffffff .ui-state-hover - :background-color $c2_light + background-color: #5A2A82 !important + color: #ffffff + + html.dark & + background-color: #ffb91a !important + color: #5A2A82 .ui-autocomplete-loading - :background Window asset_url('icons/auto_complete_spinner.gif') right center no-repeat + background: window asset_url('icons/auto_complete_spinner.gif') right center no-repeat .ui-autocomplete-moreItems - :text-align center - :margin 0px - :padding 0px 5px - :cursor default - :display block - :width 100% - :overflow hidden - :-moz-user-select none - :-khtml-user-select none + text-align: center + margin: 0 + padding: 8px 16px + cursor: default + display: block + width: 100% + overflow: hidden + user-select: none diff --git a/app/assets/stylesheets/badges.sass b/app/assets/stylesheets/badges.sass index 0eeafc679..fa3bd0de8 100644 --- a/app/assets/stylesheets/badges.sass +++ b/app/assets/stylesheets/badges.sass @@ -1,3 +1,20 @@ +.describer-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -48px 0 +.repo-person-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -288px 0 +.project-manager-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -240px 0 +.stacker-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -336px 0 +.org-manager-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -192px 0 +.fos-ser-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -96px 0 +.taxonomist-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat 0 0 +.kudo-rank-badge + background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -144px 0 + .mini-badges-section position: absolute height: 62px @@ -22,38 +39,39 @@ .kudo-rank-badge background: asset_url('badges/48-pixel-badge-sprite.png') no-repeat -144px 0 - .pip-0000 - background: asset_url('badges/pips-7-high.png') no-repeat 0 0 - .pip-0001 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -7px - .pip-0010 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -14px - .pip-0011 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -21px - .pip-0100 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -28px - .pip-0101 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -35px - .pip-0110 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -42px - .pip-0111 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -49px - .pip-1000 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -56px - .pip-1001 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -63px - .pip-1010 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -70px - .pip-1011 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -77px - .pip-1100 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -84px - .pip-1101 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -91px - .pip-1110 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -98px - .pip-1111 - background: asset_url('badges/pips-7-high.png') no-repeat 0 -105px + +.pip-0000 + background: asset_url('badges/pips-7-high.png') no-repeat 0 0 +.pip-0001 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -7px +.pip-0010 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -14px +.pip-0011 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -21px +.pip-0100 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -28px +.pip-0101 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -35px +.pip-0110 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -42px +.pip-0111 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -49px +.pip-1000 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -56px +.pip-1001 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -63px +.pip-1010 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -70px +.pip-1011 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -77px +.pip-1100 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -84px +.pip-1101 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -91px +.pip-1110 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -98px +.pip-1111 + background: asset_url('badges/pips-7-high.png') no-repeat 0 -105px .pips width: 37px @@ -90,9 +108,9 @@ #account_header .mini-badges-section position: relative - margin: 27px 4px 0 0 + margin: 0 .account-badge - margin: 0 20px 31px 0 + margin: 0 8px 31px 0 height: 48px width: 48px &.last @@ -100,9 +118,21 @@ @media only all and (min-width: 320px) and (max-width: 480px) #account_header .mini-badges-section - margin: 5px 43px 0 0 + margin: 0 + .account-badge + margin: 0 4px 20px 0 + height: 32px + width: 32px + background-size: auto 32px !important +@media only all and (min-width: 481px) and (max-width: 767px) + #account_header + .mini-badges-section + margin: 0 .account-badge - margin: 0 20px 20px 0 + margin: 0 6px 26px 0 + height: 40px + width: 40px + background-size: auto 40px !important #outside_committers_list .pips, #orgs_affiliated_list .pips margin: 0px 0px 0px 22px !important diff --git a/app/assets/stylesheets/base.sass b/app/assets/stylesheets/base.sass index 2e50269cc..664c6be75 100644 --- a/app/assets/stylesheets/base.sass +++ b/app/assets/stylesheets/base.sass @@ -1,14 +1,6 @@ @import oh-styles // base mixins -=sans_font - font-family: 'Roboto' -=serif_font - font-family: 'Roboto' -=arial_font - font-family: 'Roboto' -=lucida_font - font-family: 'Roboto' =small_font font-size: .91667em =tiny_font @@ -16,15 +8,9 @@ =link_blue @include site-link-color -// font awesome custom styles -#commits_index_page, -#commits_summary_page, -#mini_account_row - [class^="icon-"], [class*=" icon-"] - font-family: Roboto !important - body text-rendering: optimizeLegibility + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important a @include site-link-color @@ -162,7 +148,21 @@ ul.unstyled, ol.unstyled font-size: 12px thead th - border-bottom: 1px solid #ddd !important + color: #000 !important + background-color: #5b5d6237 !important + border-bottom: 1px solid #888 !important + + html.dark & + background-color: #3A1D58 !important + border-bottom-color: #5A2A82 !important + +.table.table-striped.table-condensed + tbody + tr:nth-child(odd) td, + tr:nth-child(even) td + html.dark & + background-color: #2D1548 !important + color: #ffffff !important .pre-line white-space: pre-line @@ -174,5 +174,61 @@ ul.unstyled, ol.unstyled .pagination @include site-pagination-colors +.modern-pagination + @include modern-pagination-styles + .font-1em font-size: 1em + +// Override any third-party CSS that sets display: inline on icon elements +a [class^="icon-"], +a [class*=" icon-"] + &:not(.icon-letter) + display: inline-flex !important + +// Icon Container - Global Baseline Styling +.icon-container + display: inline-flex !important + align-items: center + justify-content: center + width: 48px + height: 48px + border-radius: 12px + overflow: hidden + background-color: #f9fafb + border: 1px solid rgba(229, 231, 235, 0.8) + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) + flex-shrink: 0 + + html.dark & + background-color: #1D0631 + border-color: rgba(255, 255, 255, 0.1) + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.24) + + &.has-logo + background-color: transparent + border: none + box-shadow: none + + img + width: 100% + height: 100% + object-fit: contain + display: block + + @media (min-width: 640px) + width: 56px + height: 56px + .icon-letter + font-size: 26px + +// Icon Letter Fallback - Global Styling +.icon-letter + font-size: 22px + font-weight: 700 + color: #5A2A82 + text-transform: uppercase + user-select: none + + html.dark & + color: #ffb91a diff --git a/app/assets/stylesheets/bootstrap.sass b/app/assets/stylesheets/bootstrap.sass index 9804cfce4..e37c97869 100644 --- a/app/assets/stylesheets/bootstrap.sass +++ b/app/assets/stylesheets/bootstrap.sass @@ -7,8 +7,10 @@ @include bootstrap-default-alert-colors .alert h4 border: 0px !important + background-color: #fff !important .alert - padding: 8px 35px 8px 14px + border-radius: 16px + padding: 8px 14px 8px 14px margin-bottom: 20px font-size: 15px .alert h4 diff --git a/app/assets/stylesheets/buttons.sass b/app/assets/stylesheets/buttons.sass index 276577616..833adb3f9 100644 --- a/app/assets/stylesheets/buttons.sass +++ b/app/assets/stylesheets/buttons.sass @@ -1,284 +1,786 @@ -/** buttons **/ +/** buttons - Updated to match Black Duck / OpenHub redesign system **/ .btn - font-family: 'Roboto' !important - font-weight: bold !important - display: inline-block - color: #FFF !important + font-family: 'Roboto', sans-serif !important + font-weight: 500 !important + display: inline-flex !important + align-items: center !important + justify-content: center !important + gap: 8px !important + color: #374151 !important background-image: none !important - border: 5px solid - border-radius: 0 - box-shadow: none !important - -webkit-transition: all ease .15s - -moz-transition: all ease .15s - -o-transition: all ease .15s - transition: all ease .15s - cursor: pointer - vertical-align: middle - margin: 0 - position: relative - padding: 0 12px 1px - line-height: 32px - font-size: 14px - -.btn-large - padding: 0 14px 1px - line-height: 38px - border-width: 6px - font-size: 16px - -.btn-small - padding: 0 5.5px - line-height: 24px - border-width: 4px - font-size: 15px - /*margin: 2.5px; + border: 1px solid !important + border-radius: 6px !important + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important + transition: all 0.2s ease !important + cursor: pointer !important + vertical-align: middle !important + margin: 0 !important + position: relative !important + padding: 8px 16px !important + line-height: normal !important + font-size: 14px !important + text-decoration: none !important + white-space: nowrap !important + +.btn-large, .btn-lg + padding: 10px 24px !important + font-size: 16px !important + +.btn-small, .btn-sm + padding: 6px 12px !important + font-size: 13px !important .btn-mini - padding: 0 5px - line-height: 22px - border-width: 2px - font-size: 12px + padding: 4px 8px !important + font-size: 12px !important .btn-minier - padding: 0 4px - line-height: 18px - border-width: 1px - font-size: 11px + padding: 2px 6px !important + font-size: 11px !important -button.btn:active - top: 1px - left: 1px +button.btn:active, a.btn:active + top: 0 !important + left: 0 !important .btn, .btn-default - @include default-button-colors + background-color: white !important + border-color: #e5e7eb !important + color: #374151 !important -.btn.active, .btn-default.active - background-color: #9baab3 !important - border-color: #8a9ba6 + &:hover + border-color: #d1d5db !important + background-color: #f9fafb !important -.btn.no-border.active, .btn-default.no-border.active - background-color: #92a3ac !important - border-color: #92a3ac + &:active + outline: none !important + box-shadow: none !important + border-color: #e5e7eb !important -.btn.disabled, .btn-default.disabled, .btn[disabled], .btn-default[disabled] - background-color: #abbac3 !important + &:focus:not(:focus-visible) + outline: none !important + box-shadow: none !important -.btn-header - width: 100px + &:focus-visible + outline: 2px solid #5A2A82 !important + outline-offset: 2px !important + box-shadow: 0 0 0 3px rgba(90, 42, 130, 0.25) !important + border-color: #5A2A82 !important -.i_use_this_btn - @include secondary-button-colors - width: 100% + &.active + background-color: #f3f4f6 !important + border-color: #d1d5db !important -.btn-info - @include info-button-colors - &.no-hover:hover - background-color: #0082C6 !important - &.active, &.no-border.active - background-color: #66B7E8 !important - border-color: #66B7E8 &.disabled, &[disabled] - background-color: #66CEF6 !important + background-color: #f9fafb !important + color: #9ca3af !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #2D1548 !important + border-color: #5A2A82 !important + color: #d1d5db !important + + &:hover + border-color: #ffb91a !important + background-color: #2D1548 !important + + &.active + background-color: #1D0631 !important + border-color: #ffb91a !important + + &.disabled, &[disabled] + background-color: #1D0631 !important + color: #6b7280 !important + opacity: 0.6 !important .btn-primary - @include primary-button-colors - &.no-hover:hover - background-color: #005481 !important - &.active, &.no-border.active - background-color: #0082C6 !important - border-color: #005481 + background-color: #5A2A82 !important + border-color: #5A2A82 !important + color: white !important + font-weight: 600 !important + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23) !important + + &:hover + opacity: 0.9 !important + background-color: #5A2A82 !important + border-color: #5A2A82 !important + color: white !important + + &:active, &:focus + background-color: #4A1A72 !important + border-color: #4A1A72 !important + color: white !important + + &.active + background-color: #4A1A72 !important + border-color: #4A1A72 !important + + &.disabled, &[disabled] + background-color: #8A5AAA !important + border-color: #8A5AAA !important + color: white !important + opacity: 1 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #ffb91a !important + border-color: #ffb91a !important + color: #1D0631 !important + box-shadow: 0 3px 6px rgba(0,0,0,0.32), 0 3px 6px rgba(0,0,0,0.46) !important + + &:hover + opacity: 0.9 !important + background-color: #ffb91a !important + border-color: #ffb91a !important + color: #1D0631 !important + + &:active, &:focus + background-color: #e6a617 !important + border-color: #e6a617 !important + color: #1D0631 !important + + &.active + background-color: #e6a617 !important + border-color: #e6a617 !important + + &.disabled, &[disabled] + background-color: #ffb91a !important + border-color: #ffb91a !important + color: #1D0631 !important + opacity: 0.7 !important + +.btn-secondary + background-color: white !important + border-color: #e5e7eb !important + color: #374151 !important + font-weight: 500 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important + + &:hover + border-color: #5A2A82 !important + background-color: white !important + color: #374151 !important + + &:active, &:focus + background-color: white !important + border-color: #5A2A82 !important + color: #374151 !important + + &.active + background-color: #f9fafb !important + border-color: #5A2A82 !important + + &.disabled, &[disabled] + background-color: #f9fafb !important + color: #9ca3af !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #2D1548 !important + border-color: #5A2A82 !important + color: #d1d5db !important + box-shadow: 0 1px 3px rgba(0,0,0,0.24), 0 1px 2px rgba(0,0,0,0.48) !important + + &:hover + border-color: #ffb91a !important + background-color: #2D1548 !important + color: #d1d5db !important + + &:active, &:focus + background-color: #2D1548 !important + border-color: #ffb91a !important + + &.active + background-color: #1D0631 !important + border-color: #ffb91a !important + + &.disabled, &[disabled] + background-color: #1D0631 !important + color: #6b7280 !important + opacity: 0.6 !important + +.btn-outline + background-color: transparent !important + border-color: #e5e7eb !important + color: #374151 !important + font-weight: 500 !important + + &:hover + background-color: #f9fafb !important + border-color: #d1d5db !important + + &:active, &:focus + background-color: #f3f4f6 !important + + &.disabled, &[disabled] + background-color: transparent !important + color: #9ca3af !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: transparent !important + border-color: #5A2A82 !important + color: #d1d5db !important + + &:hover + background-color: rgba(90, 42, 130, 0.15) !important + border-color: #ffb91a !important + + &:active, &:focus + background-color: rgba(90, 42, 130, 0.25) !important + + &.disabled, &[disabled] + background-color: transparent !important + color: #6b7280 !important + opacity: 0.6 !important .btn-refresh - @include secondary-button-colors + color: white !important + background-color: #5A2A82 !important + border-color: #5A2A82 !important + border-radius: 0 12px 12px 0 + margin-left: -1px + padding: 10px 18px + transition: all 0.15s ease-in-out + + &:hover + background-color: rgba(90, 42, 130, 0.9) !important + border-color: #5A2A82 !important + transform: none + + &:active + background-color: #4A1A72 !important + border-color: #4A1A72 !important + &.no-hover:hover - background-color: #0082C6 !important + background-color: #5A2A82 !important + &.active, &.no-border.active - background-color: #66B7E8 !important - border-color: #66B7E8 + background-color: #4A1A72 !important + border-color: #4A1A72 + &.disabled, &[disabled] - background-color: #66CEF6 !important + background-color: #8A5AAA !important + border-color: #8A5AAA !important + opacity: 0.6 + cursor: not-allowed + + i + font-size: 16px + line-height: 1 + + // Dark mode + .dark & + background-color: #ffb91a !important + border-color: #ffb91a !important + color: #1D0631 !important + + &:hover + background-color: rgba(255, 185, 26, 0.9) !important + border-color: #ffb91a !important + + &:active + background-color: #e6a617 !important + border-color: #e6a617 !important + + &.active, &.no-border.active + background-color: #e6a617 !important + border-color: #e6a617 + + &.disabled, &[disabled] + background-color: #ffb91a !important + border-color: #ffb91a !important + opacity: 0.4 + +// Modern "I Use This" Button Design - All variants +.i_use_this_btn, +.i-use-this-btn, +.i-use-this-btn-mobile, +.btn-use-this + padding: 6px 16px !important + background-color: #5A2A82 !important + color: #ffffff !important + border: none !important + border-radius: 8px !important + font-size: 12px !important + font-weight: 600 !important + cursor: pointer !important + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important + transition: background-color 0.2s ease !important + display: inline-flex !important + align-items: center !important + justify-content: center !important + + &:hover + background-color: rgba(90, 42, 130, 0.9) !important + color: #ffffff !important + + &:active, &:focus + background-color: rgba(90, 42, 130, 0.9) !important + color: #ffffff !important + + &.disabled, &[disabled] + background-color: #9ca3af !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + html.dark & + background-color: #ffb91a !important + color: #1D0631 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.24), 0 1px 2px rgba(0,0,0,0.48) !important + + &:hover + background-color: rgba(255, 185, 26, 0.9) !important + color: #1D0631 !important + + &:active, &:focus + background-color: rgba(255, 185, 26, 0.9) !important + + &.disabled, &[disabled] + background-color: #6b7280 !important + opacity: 0.6 !important + +// State variants for redesigned button +.i-use-this-btn, +.i-use-this-btn-mobile + &.using + background-color: #5A2A82 !important + color: #ffffff !important + + &:hover + background-color: #4a1f6e !important + + html.dark & + background-color: #5A2A82 !important + color: #ffffff !important + + &:hover + background-color: #4a1f6e !important + + &.not-using + background-color: #ffb91a !important + color: #1D0631 !important + + &:hover + background-color: #ffcc4d !important + + html.dark & + background-color: #ffb91a !important + color: #1D0631 !important + + &:hover + background-color: #ffcc4d !important + +.btn-header + width: 100px + +.btn-info + background-color: #5A2A82 !important + border-color: #5A2A82 !important + color: white !important + font-weight: 600 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important + + &:hover + opacity: 0.9 !important + background-color: #5A2A82 !important + border-color: #5A2A82 !important + color: white !important + + &:active, &:focus + background-color: #4A1A72 !important + color: white !important + border-color: #4A1A72 !important + + &.active + background-color: #4A1A72 !important + border-color: #4A1A72 !important -.btn-success - @include join-now-button-colors - &.no-border:hover - border-color: #659965 - &.no-hover:hover - background-color: #437417 !important - &.active, &.no-border.active - background-color: #79B247 !important - border-color: #79B247 &.disabled, &[disabled] - background-color: #79B247 !important - background-color: #FFB819 !important + background-color: #8A5AAA !important + border-color: #8A5AAA !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #ffb91a !important + border-color: #ffb91a !important + color: #1D0631 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.24), 0 1px 2px rgba(0,0,0,0.48) !important + + &:hover + background-color: #e6a617 !important + border-color: #e6a617 !important + color: #1D0631 !important + + &.disabled, &[disabled] + background-color: #ffb91a !important + opacity: 0.4 !important + +.btn-success + background-color: #10b981 !important + border-color: #10b981 !important + color: white !important + font-weight: 600 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important + &:hover - background-color: #E07C05 !important - border-color: #E07C05 !important + opacity: 0.9 !important + background-color: #10b981 !important + border-color: #10b981 !important + color: white !important + + &:active, &:focus + background-color: #059669 !important + border-color: #059669 !important + + &.active + background-color: #059669 !important + border-color: #059669 !important + + &.disabled, &[disabled] + background-color: #6ee7b7 !important + border-color: #6ee7b7 !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #10b981 !important + border-color: #10b981 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.24), 0 1px 2px rgba(0,0,0,0.48) !important + + &:hover + background-color: #059669 !important + border-color: #059669 !important + + &.disabled, &[disabled] + background-color: #10b981 !important + opacity: 0.4 !important + .btn-warning - @include warning-button-colors - &.no-hover:hover - background-color: #9F4F0A !important - &.active, &.no-border.active - background-color: #F58220 !important - border-color: #F58220 + background-color: #f59e0b !important + border-color: #f59e0b !important + color: #1D0631 !important + font-weight: 600 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important + + &:hover + opacity: 0.9 !important + background-color: #f59e0b !important + border-color: #f59e0b !important + color: #1D0631 !important + + &:active, &:focus + background-color: #d97706 !important + border-color: #d97706 !important + color: #1D0631 !important + + &.active + background-color: #d97706 !important + border-color: #d97706 !important + + &.disabled, &[disabled] + background-color: #fbbf24 !important + border-color: #fbbf24 !important + color: #1D0631 !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #f59e0b !important + border-color: #f59e0b !important + color: #1D0631 !important + box-shadow: 0 1px 3px rgba(0,0,0,0.24), 0 1px 2px rgba(0,0,0,0.48) !important + + &:hover + background-color: #d97706 !important + border-color: #d97706 !important + color: #1D0631 !important + + &.disabled, &[disabled] + background-color: #f59e0b !important + color: #1D0631 !important + opacity: 0.4 !important .btn-danger - @include danger-button-colors - &.no-hover:hover - background-color: #9F2609 !important - &.active, &.no-border.active - background-color: #F5471D !important - border-color: #F5471D + background-color: #dc2626 !important + border-color: #dc2626 !important + color: white !important + font-weight: 600 !important + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23) !important + + &:hover + opacity: 0.9 !important + background-color: #dc2626 !important + border-color: #dc2626 !important + color: white !important + + &:active, &:focus + background-color: #b91c1c !important + border-color: #b91c1c !important + + &.active + background-color: #dc2626 !important + border-color: #dc2626 !important + &.disabled, &[disabled] - background-color: #F5471D !important + background-color: #fca5a5 !important + border-color: #fca5a5 !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #b91c1c !important + border-color: #b91c1c !important + box-shadow: 0 1px 3px rgba(0,0,0,0.24), 0 1px 2px rgba(0,0,0,0.48) !important + + &:hover + background-color: #991b1b !important + border-color: #991b1b !important + &.disabled, &[disabled] + background-color: #ef4444 !important + opacity: 0.4 !important + +// Dark neutral (unchanged - still works with branding) .btn-inverse background-color: #575757 !important - border-color: #575757 + border-color: #575757 !important + color: white !important + font-weight: 600 !important + &:hover background-color: #303030 !important - &.no-border:hover - border-color: #303030 - &.no-hover:hover - background-color: #555555 !important - &.active + border-color: #303030 !important + + &.active, &.no-border.active background-color: #434343 !important border-color: #333333 - &.no-border.active - background-color: #3b3b3b !important - border-color: #3b3b3b + &.disabled, &[disabled] background-color: #555555 !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #4b5563 !important + border-color: #4b5563 !important + color: white !important + &:hover + background-color: #374151 !important + border-color: #374151 !important + + &.disabled, &[disabled] + opacity: 0.4 !important + +// Muted purple accent (renamed intent: subtle brand accent) .btn-pink background-color: #7E7392 !important - border-color: #7E7392 + border-color: #7E7392 !important + color: white !important + font-weight: 600 !important + &:hover background-color: #53456D !important - &.no-border:hover - border-color: #b73766 - &.no-hover:hover - background-color: #d6487e !important - &.active - background-color: #c74072 !important - border-color: #b33564 - &.no-border.active - background-color: #be386a !important - border-color: #be386a + border-color: #53456D !important + + &.active, &.no-border.active + background-color: #53456D !important + border-color: #53456D + &.disabled, &[disabled] - background-color: #d6487e !important + background-color: #7E7392 !important + opacity: 0.6 !important + cursor: not-allowed !important + // Dark mode + .dark & + background-color: #7E7392 !important + border-color: #7E7392 !important + color: white !important + + &:hover + background-color: #53456D !important + border-color: #53456D !important + + &.disabled, &[disabled] + opacity: 0.4 !important + +// Teal accent (renamed intent: secondary brand color) .btn-purple background-color: #45867A !important - border-color: #45867A + border-color: #45867A !important + color: white !important + font-weight: 600 !important + &:hover background-color: #166859 !important - &.no-border:hover - border-color: #281649 - &.no-hover:hover - background-color: #281649 !important + border-color: #166859 !important + &.active, &.no-border.active - background-color: #7865A4 !important - border-color: #7865A4 + background-color: #166859 !important + border-color: #166859 + &.disabled, &[disabled] - background-color: #7865A4 !important + background-color: #45867A !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #45867A !important + border-color: #45867A !important + color: white !important + &:hover + background-color: #166859 !important + border-color: #166859 !important + + &.disabled, &[disabled] + opacity: 0.4 !important + +// Neutral grey .btn-grey background-color: #797979 !important - border-color: #797979 + border-color: #797979 !important + color: white !important + font-weight: 600 !important + &:hover background-color: #575757 !important - &.no-border:hover - border-color: #575757 - &.no-hover:hover - background-color: #575757 !important + border-color: #575757 !important + &.active, &.no-border.active - background-color: #797979 !important - border-color: #797979 + background-color: #575757 !important + border-color: #575757 + &.disabled, &[disabled] background-color: #9A9A9A !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #6b7280 !important + border-color: #6b7280 !important + color: white !important + + &:hover + background-color: #4b5563 !important + border-color: #4b5563 !important + &.disabled, &[disabled] + opacity: 0.4 !important + +// Soft accent (green-ish, used for subtle highlights) .btn-yellow background-color: #B3D084 !important - border-color: #B3D084 - color: #996633 !important + border-color: #B3D084 !important + color: #374151 !important + font-weight: 600 !important + &:hover background-color: #A0C465 !important - &.no-border:hover - border-color: #A0C465 - &.no-hover:hover - background-color: #A0C465 !important + border-color: #A0C465 !important + &.active, &.no-border.active - background-color: #B3D084 !important - border-color: #B3D084 + background-color: #A0C465 !important + border-color: #A0C465 + &.disabled, &[disabled] background-color: #B3D084 !important + opacity: 0.6 !important + cursor: not-allowed !important + + // Dark mode + .dark & + background-color: #B3D084 !important + border-color: #B3D084 !important + color: #1D0631 !important + &:hover + background-color: #A0C465 !important + border-color: #A0C465 !important + + &.disabled, &[disabled] + opacity: 0.4 !important + +// Light / muted (used for de-emphasized actions) .btn-light background-color: #DDD !important - border-color: #DDD + border-color: #DDD !important color: #888888 !important + font-weight: 500 !important + &:hover background-color: #BCBCBC !important - &.no-border:hover - border-color: #BCBCBC - &.no-hover:hover - background-color: #BCBCBC !important + border-color: #BCBCBC !important + &.active, &.no-border.active - background-color: #DDD !important - border-color: #DDD + background-color: #BCBCBC !important + border-color: #BCBCBC + &.disabled, &[disabled] background-color: #DDD !important + opacity: 0.6 !important + cursor: not-allowed !important + &.btn-mini:after left: -2px right: -2px top: -2px bottom: -2px + &.btn-small:after left: -4px right: -4px top: -4px bottom: -4px + &.btn-large:after left: -6px right: -6px top: -6px bottom: -6px + // Dark mode + .dark & + background-color: #374151 !important + border-color: #374151 !important + color: #9ca3af !important + + &:hover + background-color: #4b5563 !important + border-color: #4b5563 !important + + &.disabled, &[disabled] + opacity: 0.4 !important + .btn &.disabled.active, &[disabled].active, &.disabled:focus, &[disabled]:focus, &.disabled:active, &[disabled]:active - outline: none + outline: none !important + top: 0 !important + left: 0 !important + &.disabled:active, &[disabled]:active - top: 0 - left: 0 - &.active - color: #efe5b5 - &:after - display: inline-block - content: "" - position: absolute - border-bottom: 1px solid #efe5b5 - left: -4px - right: -4px - bottom: -4px - &.btn-small:after - left: -3px - right: -3px - bottom: -3px - border-bottom-width: 1px - &.btn-large:after - left: -5px - right: -5px - bottom: -5px - border-bottom-width: 1px - &.btn-mini:after, &.btn-minier:after - left: -1px - right: -1px - bottom: -1px - border-bottom-width: 1px - &.btn-yellow:after - border-bottom-color: #c96338 - &.btn-light - color: #515151 - &:after - border-bottom-color: #B5B5B5 + top: 0 !important + left: 0 !important + + &:hover + top: 0 !important + left: 0 !important diff --git a/app/assets/stylesheets/charts.sass b/app/assets/stylesheets/charts.sass index 9de5968b6..4702fda0f 100644 --- a/app/assets/stylesheets/charts.sass +++ b/app/assets/stylesheets/charts.sass @@ -1,26 +1,3 @@ -.watermark340 .highcharts-container - background: asset-url("charts/watermark_340.png") no-repeat center - background-size: contain - -.watermark440 .highcharts-container - background: asset-url("charts/watermark_440.png") no-repeat center - background-size: contain - -.watermark692 .highcharts-container - background: asset-url("charts/watermark_692.png") no-repeat center - background-size: contain - -.watermark860 .highcharts-container - background: asset-url("charts/watermark_860.png") no-repeat center - background-size: contain - -.watermark900white .highcharts-container - background: asset-url("charts/watermark_white_900.png") no-repeat center - background-size: contain - -.watermark914 .highcharts-container - background: asset-url("charts/watermark_914.png") no-repeat center - background-size: contain #vulnerabilities_index_page, #vulnerability_version_chart @@ -197,133 +174,182 @@ fill: none stroke-width: 2px - /* Tooltip */ - .highcharts-tooltip - cursor: default - pointer-events: none - white-space: nowrap - transition: stroke 150ms - /* font-size: 11pt - /* font-weight: normal - background: rgba(255,255,255,0.85) - border: 1px solid #000 - border-radius: 3px - box-shadow: 1px 1px 2px #888 - padding: 8px - tspan - stroke: black - stroke-width: 0px - opacity: 1.0 - z-index: 3 - - .highcharts-tooltip text - fill: #333333 - - .highcharts-tooltip .highcharts-header - font-size: 0.85em - - .highcharts-tooltip-box - stroke-width: 1px - fill: #f7f7f7 - fill-opacity: 0.85 - - .highcharts-tooltip-box .highcharts-label-box - fill: #f7f7f7 - fill-opacity: 0.85 - - div.highcharts-tooltip - filter: none - .highcharts-point-inactive opacity: 1.0 + .highcharts-series .highcharts-point + stroke: rgba(255, 255, 255, 0.6) + + .highcharts-legend-item .highcharts-point + stroke-width: 0 + .highcharts-point.highcharts-color-0, .highcharts-legend-item.highcharts-color-0 .highcharts-point, .highcharts-tooltip .highcharts-color-0 .highcharts-color-0, .highcharts-pointhighcharts-color-0 - @include projects-demographics-inactive-fill + fill: #64748b .highcharts-tooltip.highcharts-color-0, .highcharts-data-label-connector.highcharts-color-0 - @include projects-demographics-inactive-stroke + stroke: #64748b .highcharts-point.highcharts-color-1, .highcharts-legend-item.highcharts-color-1 .highcharts-point, .highcharts-tooltip .highcharts-color-1 - @include projects-demographics-very-low-fill - - .highcharts-halo.highcharts-color-1 - @include projects-demographics-very-low-fill - opacity: 0.3 + fill: #06b6d4 .highcharts-tooltip.highcharts-color-1, .highcharts-data-label-connector.highcharts-color-1 - @include projects-demographics-very-low-stroke + stroke: #06b6d4 .highcharts-point.highcharts-color-2, .highcharts-legend-item.highcharts-color-2 .highcharts-point, .highcharts-tooltip .highcharts-color-2 - @include projects-demographics-low-fill - - .highcharts-halo.highcharts-color-2 - @include projects-demographics-low-fill - opacity: 0.3 + fill: #3b82f6 .highcharts-tooltip.highcharts-color-2, .highcharts-data-label-connector.highcharts-color-2 - @include projects-demographics-low-stroke + stroke: #3b82f6 .highcharts-point.highcharts-color-3, .highcharts-legend-item.highcharts-color-3 .highcharts-point, .highcharts-tooltip .highcharts-color-3 - @include projects-demographics-moderate-fill - - .highcharts-halo.highcharts-color-3 - @include projects-demographics-moderate-fill - opacity: 0.3 + fill: #10b981 .highcharts-tooltip.highcharts-color-3, .highcharts-data-label-connector.highcharts-color-3 - @include projects-demographics-moderate-stroke + stroke: #10b981 .highcharts-point.highcharts-color-4, .highcharts-legend-item.highcharts-color-4 .highcharts-point, .highcharts-tooltip .highcharts-color-4 - @include projects-demographics-high-fill - - .highcharts-halo.highcharts-color-4 - @include projects-demographics-high-fill - opacity: 0.3 + fill: #f59e0b .highcharts-tooltip.highcharts-color-4, .highcharts-data-label-connector.highcharts-color-4 - @include projects-demographics-high-stroke + stroke: #f59e0b .highcharts-point.highcharts-color-5, .highcharts-legend-item.highcharts-color-5 .highcharts-point, .highcharts-tooltip .highcharts-color-5 - @include projects-demographics-very-high-fill - - .highcharts-halo.highcharts-color-5 - @include projects-demographics-very-high-fill - opacity: 0.3 + fill: #ef4444 .highcharts-tooltip.highcharts-color-5, .highcharts-data-label-connector.highcharts-color-5 - @include projects-demographics-very-high-stroke + stroke: #ef4444 .highcharts-point.highcharts-color-6, .highcharts-legend-item.highcharts-color-6 .highcharts-point, .highcharts-tooltip .highcharts-color-6 - @include projects-demographics-new-fill - - .highcharts-halo.highcharts-color-6 - @include projects-demographics-new-fill - opacity: 0.3 + fill: #a855f7 .highcharts-tooltip.highcharts-color-6, .highcharts-data-label-connector.highcharts-color-6 - @include projects-demographics-new-stroke + stroke: #a855f7 + +// styledMode: true means all label/legend styling must come from CSS, +// not from Highcharts JS options (itemStyle, color, etc. are ignored). +#demographics_chart + .highcharts-data-label text + fill: #1a202c + + @media (max-width: 768px) + .highcharts-legend-item text + font-size: 11px !important + + @media (max-width: 640px) + .highcharts-legend-item text + font-size: 10px !important + +html.dark #demographics_chart + .highcharts-data-label text + fill: #e2e8f0 !important + + .highcharts-data-label-connector + stroke: #94a3b8 !important + + .highcharts-legend-item text + fill: #e2e8f0 !important + + .highcharts-background + fill: #2D1548 + +// Demographics tooltip — rendered outside #demographics_chart via outside: true. +// All visual styling targets the HTML span rendered by useHTML: true. +// The SVG rect must be fully hidden to prevent double-layer background. +.highcharts-tooltip-container + z-index: 9999 !important + +// Kill every possible SVG background layer Highcharts injects for the demographics tooltip. +// With styledMode: true + outside: true, Highcharts creates a