From 00c692e76dc3f4ec55f85cdc049bd43122574f9d Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Thu, 9 Apr 2026 06:29:06 -0400 Subject: [PATCH 01/11] fix: accessibility and theming improvements - Add visually-hidden labels for search inputs (CC, FIPS, PP search pages, CVE/CPE vuln search) - Fix heading hierarchy: change "Search" subheading from h3 to h2 on all search pages - Add empty table header label "Actions" in FIPS MIP and IUT index tables - Refactor status badge colors: replace Bootstrap text-success/warning/danger with custom CSS classes (status-active, status-archived, status-historical, status-revoked) supporting separate light/dark mode colors via data-bs-theme selectors in base.css - Split btn-outline-primary color overrides into light (#0060F0) and dark (#85B6FF) themes - Add alert-primary link color override for light mode (#0a58ca) - Fix research link color in index page analysis section using CSS custom property override --- page/sec_certs_page/static/base.css | 1116 +++++++++++++++++ .../templates/cc/include.html.jinja2 | 171 +++ .../templates/cc/search/base.html.jinja2 | 227 ++++ .../templates/fips/include.html.jinja2 | 139 ++ .../templates/fips/iut/iut_index.html.jinja2 | 55 + .../templates/fips/mip/mip_index.html.jinja2 | 55 + .../templates/fips/search/base.html.jinja2 | 217 ++++ .../templates/index.html.jinja2 | 265 ++++ .../templates/pp/search/base.html.jinja2 | 211 ++++ .../templates/vuln/search.html.jinja2 | 82 ++ 10 files changed, 2538 insertions(+) create mode 100644 page/sec_certs_page/static/base.css create mode 100644 page/sec_certs_page/templates/cc/include.html.jinja2 create mode 100644 page/sec_certs_page/templates/cc/search/base.html.jinja2 create mode 100644 page/sec_certs_page/templates/fips/include.html.jinja2 create mode 100644 page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 create mode 100644 page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 create mode 100644 page/sec_certs_page/templates/fips/search/base.html.jinja2 create mode 100644 page/sec_certs_page/templates/index.html.jinja2 create mode 100644 page/sec_certs_page/templates/pp/search/base.html.jinja2 create mode 100644 page/sec_certs_page/templates/vuln/search.html.jinja2 diff --git a/page/sec_certs_page/static/base.css b/page/sec_certs_page/static/base.css new file mode 100644 index 00000000..85008f28 --- /dev/null +++ b/page/sec_certs_page/static/base.css @@ -0,0 +1,1116 @@ +:root { + --sidebar-width: 250px; +} + +/* Skip to main content link - accessible but visually hidden until focused */ +.skip-link { + position: absolute; + top: -40px; + left: 0; + background: #000; + color: white; + padding: 8px; + text-decoration: none; + z-index: 100; +} + +.skip-link:focus { + top: 0; +} + +.nav-button { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; +} + +.show .nav-button, +.collapsing .nav-button { + margin-right: 0 !important; + margin-top: 0.5rem !important; + margin-left: 0 !important; +} + +.nav-current { + background-color: var(--bs-gray-800); +} + +[data-bs-theme="dark"] #navbar { + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); +} + +.part-logo { + filter: drop-shadow(0px 8px 16px rgba(0, 0, 0, 0.15)); +} + +[data-bs-theme="dark"] .part-logo { + filter: invert(100%) drop-shadow(0px 8px 16px rgba(0, 0, 0, 0.15)); +} + +#wrapper { + overflow-x: hidden; +} + +#page-content-wrapper { + margin-top: 51px; + /* padding-left: 50px; + padding-right: 50px; */ +} + +#up-top-icon { + font-size: small !important; + position: fixed; + bottom: 0.7rem; + right: 0.7rem; +} + +#chat { + font-size: small !important; + position: fixed; + bottom: 0.7rem; + right: 3.7rem; +} + +#chat-icon { + padding: 0.175rem 0.5rem; +} + +#chat-modal .modal-lg, #chat-modal .modal-xl { + height: 90vh; +} + +#chat-modal .modal-content { + height: 100%; +} + +#chat-body { + display: flex; + flex-direction: column; + height: 100%; + min-height: 0; +} + +#chat-skeleton { + display: flex; + flex-direction: column; + flex: 1 1 auto; + min-height: 0; +} + +#chat-window { + flex: 1 1 auto; + min-height: 0; + overflow-y: auto; + border: 1px solid #ccc; + border-radius: 0.5em; + padding: 1em; + background: #f8f9fa; + margin-bottom: 1em; +} + +.chat-message-user { + text-align: right; + background: #d1e7dd; + color: #003d1a; + border-radius: 1em 1em 0 1em; + margin: 0.5em 0 0.5em auto; + max-width: 75%; + padding: 0.5em 1em; +} + +.chat-message-assistant { + text-align: left; + background: #d1dce7; + color: #001529; + border-radius: 1em 1em 1em 0; + margin: 0.5em auto 0.5em 0; + max-width: 75%; + padding: 0.5em 1em; +} + +.chat-message-assistant p:last-child { + margin-bottom: 0; +} + +.chat-message-assistant table>:not(caption)>*>* { + background: #d1dce7; +} + +[aria-expanded="false"] .fa-chevron-up, +[aria-expanded="false"] .fa-minus, +[aria-expanded="true"] .fa-chevron-down, +[aria-expanded="true"] .fa-plus { + display: none; +} + +#feedback { + position: fixed; + right: 0; + top: 15%; + margin-right: -3px; +} + +@media screen and (max-width: 768px) { + #feedback { + display: none; + } +} + +#feedback .card { + float: right; + width: 300px; + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + background-color: #fafafa; + transition: margin 0.25s ease; +} + +[data-bs-theme="dark"] #feedback .card { + background-color: #101010; +} + +#feedback .card.collapsed { + margin-right: -300px; +} + +#feedback .btn-secondary { + float: left; + font-size: 1.5rem; + margin-top: 120px; + margin-right: -3.9rem; + padding-left: 1rem; + padding-right: 1rem; + border-radius: 0 0 0.25rem 0.25rem; + background-color: #6c757d; + transform: rotate(90deg); +} + +#feedback .btn-secondary:hover { + background-color: #505050; +} + +.signin-wrapper { + display: flex; + align-items: center; + flex-direction: column; + padding-top: 40px; + padding-bottom: 40px; + min-height: 100vh; +} + +.form-signin { + width: 100%; + max-width: 330px; + padding: 15px; + margin: auto; +} + +.form-signin .checkbox { + font-weight: 400; +} + +.form-signin .form-floating:focus-within { + z-index: 2; +} + +/* +.form-signin input[type="email"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.form-signin input[type="password"] { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +*/ + +.feature-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 4rem; + height: 4rem; + margin-bottom: 1rem; + font-size: 2rem; + color: #fff; + border-radius: 0.75rem; +} + +.anchor { + padding-top: 57px; + margin-top: -57px; +} + +.outgoing-list { + list-style: none; +} + +.outgoing-list li:before { + font: var(--fa-font-solid); + content: "\f061"; + margin: 0 10px 0 -25px; + color: var(--bs-body-color); +} + +.incoming-list { + list-style: none; +} + +.incoming-list li:before { + font: var(--fa-font-solid); + content: "\f060"; + margin: 0 10px 0 -25px; + color: var(--bs-body-color); +} + +#content .listing { + padding: 1em; + border-radius: 0.5em; + border: 1px solid rgba(0, 0, 0, 0.2); + background-color: rgba(0, 0, 0, 0.03); +} + +#search-categories div { + display: flex; + flex-direction: column; +} + +body { + font-family: "IBM Plex Sans", + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, + "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; +} + +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: 600; +} + +.callout { + padding: 1.25rem; + margin-top: 1.25rem; + margin-bottom: 1.25rem; + color: inherit; + background-color: var(--bs-gray-100); + border-left: 0.25rem solid var(--bs-gray-300); +} + +[data-bs-theme="dark"] .callout { + background-color: var(--bs-gray-800); + border-left: 0.25rem solid var(--bs-gray-700); +} + +.callout-primary { + background-color: var(--bs-primary-bg-subtle); + border-left: 0.25rem solid var(--bs-primary-border-subtle); +} + +.callout-secondary { + background-color: var(--bs-secondary-bg-subtle); + border-left: 0.25rem solid var(--bs-secondary-border-subtle); +} + +.callout-success { + background-color: var(--bs-success-bg-subtle); + border-left: 0.25rem solid var(--bs-success-border-subtle); +} + +.callout-danger { + background-color: var(--bs-danger-bg-subtle); + border-left: 0.25rem solid var(--bs-danger-border-subtle); +} + +.callout-warning { + background-color: var(--bs-warning-bg-subtle); + border-left: 0.25rem solid var(--bs-warning-border-subtle); +} + +.callout-info { + background-color: var(--bs-info-bg-subtle); + border-left: 0.25rem solid var(--bs-info-border-subtle); +} + +.callout-light { + background-color: var(--bs-light-bg-subtle); + border-left: 0.25rem solid var(--bs-light-border-subtle); +} + +.callout-dark { + background-color: var(--bs-dark-bg-subtle); + border-left: 0.25rem solid var(--bs-dark-border-subtle); +} + +[data-bs-theme="dark"] .row.bg-dark { + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19), + 0 -4px 8px 0 rgba(0, 0, 0, 0.2), 0 -6px 20px 0 rgba(0, 0, 0, 0.19); +} + +.hide-light { + display: none; +} + +[data-bs-theme="dark"] .hide-light { + display: initial; +} + +.hide-dark { + display: initial; +} + +[data-bs-theme="dark"] .hide-dark { + display: none; +} + +/* New UX design */ + +.dropdown .dropbtn { + font-size: 16px; + border: none; + color: white; + padding: 14px 16px; + background-color: inherit; + font-family: inherit; /* Important for vertical align on mobile phones */ + margin: 0; /* Important for vertical align on mobile phones */ +} + +.dropdown .dropbtn:focus-visible { + outline: 3px solid #ffc107; + outline-offset: 2px; +} + +#left-navigation { + position: fixed; + left: 0px; + /* background-color: white; */ + width: var(--sidebar-width); + height: 100vh; + padding: 10px; + padding-top: 30px; +} + +#left-navigation .active { + background-color: var(--bs-secondary); + border-color: var(--bs-secondary); +} + +[data-bs-theme="light"] #left-navigation { + background-color: var(--bs-white); +} + +[data-bs-theme="dark"] #left-navigation { + background-color: var(--bs-dark); +} + + +.shifted-section { + margin-left: var(--sidebar-width); +} + +@media (max-width: 767.98px) { + .shifted-section { + margin-left: 10px; + } +} + + +.spaced-table { + border-collapse: separate; + border-spacing: 0 40px; +} + +#content { + display: flex; + flex-direction: column; + min-height: 100vh; + justify-content: space-between; +} + +#network-skeleton { + height: 300px; + overflow: auto; + position: relative; +} + +#network-skeleton::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: -1; + + display: block; + height: 100%; + width: 100%; + background-image: url('/static/img/references_background.png'); + background-size: contain; + filter: blur(10px); +} + +[data-bs-theme="light"] .bg-darker-light { + background-color: #f0f0f0; +} + +[data-bs-theme="dark"] .bg-darker-light { + background-color: #454545; +} + +.flex-basis-0 { + flex-basis: 0px; +} + +/* ============================================ + Dashboard Styles + ============================================ */ + +/* Dashed border utility for empty state cards */ +.border-dashed { + border-style: dashed !important; +} + +/* Collection card hover effect */ +.collection-card { + transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; +} + +.collection-card:hover { + transform: translateY(-4px); + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +/* ============================================ + Dash Dropdown Bootstrap Integration + ============================================ */ +.dash-bootstrap .Select-control { + border-radius: 0.375rem; + border: 1px solid var(--bs-border-color); + background-color: var(--bs-body-bg); + min-height: 38px; +} + +/* Vertically center single-select values */ +.dash-bootstrap .Select-control .Select-value, +.dash-dropdown .Select-control .Select-value { + display: flex !important; + align-items: center; + height: 100%; + padding-top: 0; + padding-bottom: 0; +} + +.dash-bootstrap .Select-control .Select-value-label, +.dash-dropdown .Select-control .Select-value-label { + line-height: 36px; +} + +.dash-bootstrap .Select-placeholder, +.dash-dropdown .Select-placeholder { + line-height: 36px; +} + +.dash-bootstrap .Select-control:hover { + border-color: var(--bs-primary); +} + +.dash-bootstrap .Select-menu-outer { + background-color: var(--bs-body-bg); + border: 1px solid var(--bs-border-color); + border-radius: 0.375rem; + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + max-height: 300px; +} + +.dash-bootstrap .Select-option { + background-color: var(--bs-body-bg); + color: var(--bs-body-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; +} + +.dash-bootstrap .Select-option:hover, +.dash-bootstrap .Select-option.is-focused { + background-color: var(--bs-primary); + color: white; +} + +.dash-bootstrap .Select-value-label, +.dash-bootstrap .Select-placeholder { + color: var(--bs-body-color); +} + +/* Dash Dropdown (newer versions) */ +.dash-dropdown .Select-control { + background-color: var(--bs-body-bg) !important; + border-color: var(--bs-border-color) !important; +} + +.dash-dropdown .Select-menu { + background-color: var(--bs-body-bg) !important; + max-height: 300px !important; +} + +.dash-dropdown .VirtualizedSelectOption { + background-color: var(--bs-body-bg); + color: var(--bs-body-color); + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; +} + +.dash-dropdown .VirtualizedSelectFocusedOption { + background-color: var(--bs-primary) !important; + color: white !important; +} + +/* Truncate selected values in dropdown */ +.dash-bootstrap .Select-value-label, +.dash-dropdown .Select-value-label { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + display: block; + line-height: 1.4; +} + +/* Multi-select tags */ +.dash-bootstrap .Select--multi .Select-value, +.dash-dropdown .Select--multi .Select-value { + max-width: 180px; + height: 24px !important; + line-height: 22px !important; + display: inline-flex !important; + align-items: center; + overflow: hidden; + margin-top: 2px; + margin-bottom: 2px; +} + +.dash-bootstrap .Select--multi .Select-value-label, +.dash-dropdown .Select--multi .Select-value-label { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 22px; + height: 22px; +} + +/* ============================================ + Dashboard Date Picker Styling + ============================================ */ +.DateRangePicker, +.SingleDatePicker { + width: 100%; +} + +.DateRangePickerInput, +.SingleDatePickerInput { + background-color: var(--bs-body-bg) !important; + border: 1px solid var(--bs-border-color) !important; + border-radius: 0.375rem !important; +} + +.DateInput_input { + background-color: var(--bs-body-bg) !important; + color: var(--bs-body-color) !important; + border: none !important; + padding: 0.375rem 0.75rem !important; + font-size: 1rem !important; +} + +.CalendarDay__selected, +.CalendarDay__selected:hover { + background: var(--bs-primary) !important; + border-color: var(--bs-primary) !important; +} + +.date-picker-wrapper { + position: relative; + width: 100%; +} + +.date-picker-wrapper .date-picker-icon { + position: absolute; + left: 10px; + top: 50%; + transform: translateY(-50%); + z-index: 2; + color: var(--bs-secondary); + pointer-events: none; +} + +.date-picker-wrapper .SingleDatePicker, +.date-picker-wrapper .DateRangePicker { + width: 100%; +} + +.date-picker-wrapper .SingleDatePickerInput, +.date-picker-wrapper .DateRangePickerInput { + width: 100% !important; + display: flex !important; +} + +.date-picker-wrapper .DateInput { + width: 100% !important; +} + +.date-picker-wrapper .DateInput_input { + width: 100% !important; + text-align: left !important; + padding: 0.375rem 0.75rem 0.375rem 2.25rem !important; + font-size: 0.9rem !important; + cursor: text !important; +} + +.DayPickerNavigation { + display: flex; + justify-content: space-between; +} + +.CalendarMonth_caption { + padding-top: 15px !important; + padding-bottom: 40px !important; + color: var(--bs-body-color) !important; +} + +.CalendarMonth_caption strong { + font-size: 1rem; +} + +.date-range-wrapper .DateInput_input { + padding-left: 2.25rem !important; +} + +.date-range-wrapper .DateInput:first-child .DateInput_input { + padding-left: 2.25rem !important; +} + +.date-range-wrapper .DateInput:last-child .DateInput_input { + padding-left: 0.75rem !important; +} + +.DayPicker, +.CalendarMonth, +.CalendarMonthGrid { + background-color: var(--bs-body-bg) !important; +} + +.CalendarDay__default { + background-color: var(--bs-body-bg) !important; + color: var(--bs-body-color) !important; + border-color: var(--bs-border-color) !important; +} + +.CalendarDay__default:hover { + background-color: var(--bs-light) !important; +} + +.DayPickerNavigation_button__default { + background-color: var(--bs-body-bg) !important; + border-color: var(--bs-border-color) !important; +} + +.DayPickerKeyboardShortcuts_show__bottomRight::before { + border-right-color: var(--bs-primary) !important; +} + +/* ============================================ + Dashboard Range Slider Styling + ============================================ */ +.rc-slider-track { + background-color: var(--bs-primary) !important; +} + +.rc-slider-handle { + border-color: var(--bs-primary) !important; +} + +.rc-slider-handle:hover, +.rc-slider-handle:active { + border-color: var(--bs-primary) !important; + box-shadow: 0 0 0 5px rgba(var(--bs-primary-rgb), 0.2) !important; +} + +/* ============================================ + Dashboard Dark Theme Adjustments + ============================================ */ + +/* Fix bg-light in dark mode for dashboard cards */ +[data-bs-theme="dark"] .bg-light { + background-color: var(--bs-gray-800) !important; +} + +/* Fix card backgrounds in dark mode */ +[data-bs-theme="dark"] .card { + background-color: var(--bs-dark); + border-color: var(--bs-gray-700); +} + +[data-bs-theme="dark"] .card-header { + background-color: var(--bs-gray-800); + border-color: var(--bs-gray-700); +} + +/* Dropdown controls in dark mode */ +[data-bs-theme="dark"] .dash-dropdown .Select-control, +[data-bs-theme="dark"] .dash-bootstrap .Select-control { + background-color: var(--bs-gray-800) !important; + border-color: var(--bs-gray-600) !important; +} + +/* Dropdown inner container backgrounds in dark mode */ +[data-bs-theme="dark"] .dash-dropdown .Select-multi-value-wrapper, +[data-bs-theme="dark"] .dash-bootstrap .Select-multi-value-wrapper, +[data-bs-theme="dark"] .dash-dropdown .Select-input, +[data-bs-theme="dark"] .dash-bootstrap .Select-input { + background-color: transparent !important; + color: var(--bs-gray-900) !important; +} + +[data-bs-theme="dark"] .dash-dropdown .Select-input > input, +[data-bs-theme="dark"] .dash-bootstrap .Select-input > input { + background-color: transparent !important; + color: var(--bs-body-color) !important; +} + +[data-bs-theme="dark"] .dash-dropdown .Select-value-label, +[data-bs-theme="dark"] .dash-bootstrap .Select-value-label, +[data-bs-theme="dark"] .dash-dropdown .Select-input input, +[data-bs-theme="dark"] .dash-bootstrap .Select-input input, +[data-bs-theme="dark"] .dash-dropdown .Select-placeholder, +[data-bs-theme="dark"] .dash-bootstrap .Select-placeholder { + color: var(--bs-body-color) !important; +} + +[data-bs-theme="dark"] .dash-dropdown .Select-arrow, +[data-bs-theme="dark"] .dash-bootstrap .Select-arrow { + border-color: var(--bs-body-color) transparent transparent !important; +} + +[data-bs-theme="dark"] .dash-dropdown .Select-option, +[data-bs-theme="dark"] .dash-bootstrap .Select-option, +[data-bs-theme="dark"] .dash-dropdown .VirtualizedSelectOption, +[data-bs-theme="dark"] .dash-bootstrap .VirtualizedSelectOption { + background-color: var(--bs-gray-800) !important; + color: var(--bs-body-color) !important; +} + +[data-bs-theme="dark"] .dash-dropdown .Select-option:hover, +[data-bs-theme="dark"] .dash-bootstrap .Select-option:hover, +[data-bs-theme="dark"] .dash-dropdown .Select-option.is-focused, +[data-bs-theme="dark"] .dash-bootstrap .Select-option.is-focused, +[data-bs-theme="dark"] .dash-dropdown .VirtualizedSelectFocusedOption, +[data-bs-theme="dark"] .dash-bootstrap .VirtualizedSelectFocusedOption { + background-color: var(--bs-primary) !important; + color: white !important; +} + +[data-bs-theme="dark"] .dash-dropdown .Select-menu, +[data-bs-theme="dark"] .dash-bootstrap .Select-menu-outer { + background-color: var(--bs-gray-800) !important; + border-color: var(--bs-gray-600) !important; +} + +[data-bs-theme="dark"] .DateRangePickerInput, +[data-bs-theme="dark"] .SingleDatePickerInput, +[data-bs-theme="dark"] .DateInput_input { + background-color: var(--bs-gray-800) !important; + border-color: var(--bs-gray-600) !important; + color: var(--bs-body-color) !important; +} + +[data-bs-theme="dark"] .DayPicker, +[data-bs-theme="dark"] .CalendarMonth, +[data-bs-theme="dark"] .CalendarMonthGrid { + background-color: var(--bs-gray-800) !important; +} + +[data-bs-theme="dark"] .CalendarDay__default { + background-color: var(--bs-gray-800) !important; + color: var(--bs-body-color) !important; + border-color: var(--bs-gray-700) !important; +} + +[data-bs-theme="dark"] .CalendarDay__default:hover { + background-color: var(--bs-gray-700) !important; +} + +[data-bs-theme="dark"] .DayPickerNavigation_button__default { + background-color: var(--bs-gray-800) !important; + border-color: var(--bs-gray-600) !important; +} + +[data-bs-theme="dark"] .CalendarMonth_caption { + color: var(--bs-body-color) !important; +} + +[data-bs-theme="dark"] .DayPicker_weekHeader, +[data-bs-theme="dark"] .DayPicker_weekHeader_li, +[data-bs-theme="dark"] .DayPicker_weekHeader small { + color: var(--bs-gray-400) !important; +} + +[data-bs-theme="dark"] .DayPickerNavigation_svg__horizontal { + fill: var(--bs-body-color) !important; +} + +[data-bs-theme="dark"] .DateInput_fang { + fill: var(--bs-gray-800) !important; +} + +[data-bs-theme="dark"] .DateInput_fangStroke { + stroke: var(--bs-gray-600) !important; +} + +[data-bs-theme="dark"] .CalendarDay__outside { + color: var(--bs-gray-500) !important; +} + +[data-bs-theme="dark"] .CalendarDay__selected, +[data-bs-theme="dark"] .CalendarDay__selected:hover { + background: var(--bs-primary) !important; + color: white !important; +} + +[data-bs-theme="dark"] .CalendarDay__hovered_span, +[data-bs-theme="dark"] .CalendarDay__selected_span { + background: rgba(var(--bs-primary-rgb), 0.3) !important; + color: var(--bs-body-color) !important; +} + +/* ============================================ + Chart Creation Modal + ============================================ */ + +/* Chart type selector cards */ +.chart-type-option { + border: 2px solid var(--bs-border-color); + background-color: var(--bs-body-bg); + transition: all 0.2s ease-in-out; + cursor: pointer; +} + +.chart-type-option:hover { + border-color: var(--bs-primary); + background-color: rgba(var(--bs-primary-rgb), 0.1); +} + +.chart-type-option.selected { + border-color: var(--bs-primary); + background-color: var(--bs-primary); + color: white; +} + +.chart-type-option i { + color: var(--bs-primary); +} + +.chart-type-option.selected i { + color: white; +} + +/* Cursor pointer utility */ +.cursor-pointer { + cursor: pointer; +} + +/* Modal width to match container-fluid */ +.modal-xl-fluid .modal-dialog { + max-width: 95%; + margin: 1.75rem auto; +} + +@media (min-width: 1200px) { + .modal-xl-fluid .modal-dialog { + max-width: 90%; + } +} + +/* Modal filter sections */ +.modal-filters-container .card { + border: 1px solid var(--bs-border-color); +} + +.modal-filters-container .card-header { + background-color: transparent; + padding: 0.5rem 1rem; +} + +/* Filter section styling */ +.filter-section { + margin-bottom: 0.75rem; +} + +.filter-section-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.5rem 0.75rem; + background-color: var(--bs-light); + border-radius: 0.375rem; + cursor: pointer; + transition: background-color 0.15s ease-in-out; +} + +.filter-section-header:hover { + background-color: var(--bs-gray-200); +} + +[data-bs-theme="dark"] .filter-section-header { + background-color: var(--bs-gray-800); +} + +[data-bs-theme="dark"] .filter-section-header:hover { + background-color: var(--bs-gray-700); +} + +/* ============================================ + Dashboard Loading States + ============================================ */ +.dash-loading { + display: flex; + align-items: center; + justify-content: center; + min-height: 200px; +} + +._dash-loading-callback { + position: relative; +} + +._dash-loading-callback::after { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(255, 255, 255, 0.7); + display: flex; + align-items: center; + justify-content: center; +} + +[data-bs-theme="dark"] ._dash-loading-callback::after { + background-color: rgba(0, 0, 0, 0.5); +} + +.mb-4.border-0 > .card-body { + background-color: var(--bs-gray-100); + border-radius: var(--bs-border-radius); +} + +[data-bs-theme="dark"] .mb-4.border-0 > .card-body { + background-color: var(--bs-gray-800); +} + +/* ============================================ + Button Visibility Improvements + ============================================ */ +/* Make Refresh All button more visible when clickable */ +.refresh-all-btn:not(:disabled):not(.disabled) { + background-color: var(--bs-secondary); + border-color: var(--bs-secondary); + border-width: 2px; + font-weight: 500; + color: white; +} + +.refresh-all-btn:not(:disabled):not(.disabled):hover { + background-color: var(--bs-dark); + border-color: var(--bs-dark); +} + +/* Dark theme: use darker, more visible colors */ +[data-bs-theme="dark"] .refresh-all-btn:not(:disabled):not(.disabled) { + background-color: #6c757d; + border-color: #6c757d; + color: white; +} + +[data-bs-theme="dark"] .refresh-all-btn:not(:disabled):not(.disabled):hover { + background-color: #5a6268; + border-color: #5a6268; + color: white; +} + +/* ========================================================================== + WCAG Accessibility implementation + btn-outline-primary color overrides per theme + ========================================================================== */ + +[data-bs-theme="light"] .btn-outline-primary { + --bs-btn-color: #0060F0; + --bs-btn-border-color: #0060F0; + --bs-btn-hover-bg: #0060F0; + --bs-btn-hover-border-color: #0060F0; + --bs-btn-active-bg: #0060F0; + --bs-btn-active-border-color: #0060F0; +} + +[data-bs-theme="dark"] .btn-outline-primary { + --bs-btn-color: #85B6FF; + --bs-btn-border-color: #85B6FF; + --bs-btn-hover-bg: #85B6FF; + --bs-btn-hover-border-color: #85B6FF; + --bs-btn-active-bg: #85B6FF; + --bs-btn-active-border-color: #85B6FF; +} + +/* Higher contrast for links (Light mode) */ +p a { + color: #1A6BCC; +} + +/* back to original color in dark mode*/ +[data-bs-theme="dark"] p a { + color: #85B6FF; +} + +/* ========================================================================== + Status label colors per theme + ========================================================================== */ + +/* Light mode */ +[data-bs-theme="light"] .status-active { + color: #198754; +} +[data-bs-theme="light"] .status-archived{ + color: #8B6313; +} +[data-bs-theme="light"] .status-historical { + color: #876608; +} +[data-bs-theme="light"] .status-revoked { + color: #dc3545; +} + +/* Dark mode */ +[data-bs-theme="dark"] .status-active { + color: #3FBD7A; +} +[data-bs-theme="dark"] .status-archived, +[data-bs-theme="dark"] .status-historical { + color: #ffcd39; +} +[data-bs-theme="dark"] .status-revoked { + color: #ea868f; +} + +/* Alert-primary link colors */ +[data-bs-theme="light"] .alert-primary a { + color: #0158E4; +} \ No newline at end of file diff --git a/page/sec_certs_page/templates/cc/include.html.jinja2 b/page/sec_certs_page/templates/cc/include.html.jinja2 new file mode 100644 index 00000000..d983b74a --- /dev/null +++ b/page/sec_certs_page/templates/cc/include.html.jinja2 @@ -0,0 +1,171 @@ +{% from "include/entry.html.jinja2" import keywords_card, opt_line %} + +{% macro cc_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} + {{ keywords_card(keyword_scan, doc_prefix, "common-criteria", "Common Criteria", {"Security level": "cc_security_level", + "Claims": "cc_claims", + "Security Assurance Requirements (SAR)": "cc_sar", + "Security Functional Requirements (SFR)": "cc_sfr", + "Protection profiles": "cc_protection_profile_id", + "Certificates": "cc_cert_id", + "Evaluation facilities": "eval_facility"}, hidden, map_funcs) }} +{%- endmacro %} + +{% macro render_frontpage(cert, doc_type, title) %} + {% if cert["pdf_data"][doc_type] %} + {% if cert["pdf_data"][doc_type]["anssi"] %} + {% set frontpage = cert["pdf_data"][doc_type]["anssi"] %} + {% elif cert["pdf_data"][doc_type]["bsi"] %} + {% set frontpage = cert["pdf_data"][doc_type]["bsi"] %} + {% elif cert["pdf_data"][doc_type]["niap"] %} + {% set frontpage = cert["pdf_data"][doc_type]["niap"] %} + {% elif cert["pdf_data"][doc_type]["canada"] %} + {% set frontpage = cert["pdf_data"][doc_type]["canada"] %} + {% elif cert["pdf_data"][doc_type]["nscib"] %} + {% set frontpage = cert["pdf_data"][doc_type]["nscib"] %} + {% elif cert["pdf_data"][doc_type][cert["scheme"]] %} + {% set frontpage = cert["pdf_data"][doc_type][cert["scheme"]] %} + {% endif %} + {% if frontpage %} +

Frontpage

+ + + + + + + {{ opt_line("Certificate ID", "cert_id", frontpage, title) }} + {{ opt_line("Certified item", "cert_item", frontpage, title) }} + {{ opt_line("Certification lab", "cert_lab", frontpage, title) }} + {{ opt_line("Developer", "developer", frontpage, title) }} + +
+ {% endif %} + {% endif %} +{% endmacro %} + +{% macro render_status(status) %} + {% if status == "active" %} + active + {% elif status == "archived" %} + archived + {% else %} + {{ status }} + {% endif %} +{%- endmacro %} + +{% macro render_document_type(document_type) %} + {% if document_type == "cert" %} + Certificate + {% elif document_type == "report" %} + Certification Report + {% elif document_type == "target" %} + Security Target + {% endif %} +{%- endmacro %} + +{% macro render_category(category) %} + + {% set cat = get_cc_category(category) %} + {% if cat %} + + {% endif %} + +{%- endmacro %} + +{% macro render_eal(eal) %} + {% set ealm = eal.replace("+", "") %} + {%- if get_cc_eal(ealm) -%} + {{ eal }} + {%- elif get_cc_sar(eal) -%} + {{ eal }} + {%- else -%} + {{ eal }} + {%- endif -%} +{%- endmacro %} + +{% macro render_sfrs(sfr) %} + {%- if get_cc_sfr(sfr) -%} + {{ sfr }} + {%- else -%} + {{ sfr }} + {%- endif -%} +{%- endmacro %} + +{% macro render_sars(sar) %} + {%- if get_cc_sar(sar) -%} + {{ sar }} + {%- else -%} + {{ sar }} + {%- endif -%} +{%- endmacro %} + + +{% macro render_plot(timeline) %} +
+
+

Timeline

+ Matched certificates (monthly) +
+
+
+ + +{%- endmacro %} \ No newline at end of file diff --git a/page/sec_certs_page/templates/cc/search/base.html.jinja2 b/page/sec_certs_page/templates/cc/search/base.html.jinja2 new file mode 100644 index 00000000..7f7900da --- /dev/null +++ b/page/sec_certs_page/templates/cc/search/base.html.jinja2 @@ -0,0 +1,227 @@ +{% extends "common/base.html.jinja2" %} + +{% block content %} +
+
+ +

Common Criteria

+

Search

+
+
+
+
+ + + +
+ + + +
+
+ + + +
+
+ + + +
+ +
+ + +
+
+
+

Categories + + +

+
+
+ +
+ {% for name, val in categories.items() %} + {% if loop.index0 % 5 == 0 %} +
+ {% endif %} +
+ + + + +
+ {% if (loop.index0 + 1) % 5 == 0 %} +
+ {% endif %} + {% endfor %} +
+
+ +
+
+
General filters
+ + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+ +
+
Search type specific options
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+
+
+ + + + {% block search_content %}{% endblock %} + +
+
+{% endblock %} \ No newline at end of file diff --git a/page/sec_certs_page/templates/fips/include.html.jinja2 b/page/sec_certs_page/templates/fips/include.html.jinja2 new file mode 100644 index 00000000..781226e3 --- /dev/null +++ b/page/sec_certs_page/templates/fips/include.html.jinja2 @@ -0,0 +1,139 @@ +{% from "include/entry.html.jinja2" import keywords_card %} + +{% macro cryptography_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} + {{ keywords_card(keyword_scan, doc_prefix, "crypto", "Cryptography", {"Symmetric Algorithms": "symmetric_crypto", + "Asymmetric Algorithms": "asymmetric_crypto", + "Post-quantum Algorithms": "pq_crypto", + "Hash functions": "hash_function", + "Schemes": "crypto_scheme", + "Protocols": "crypto_protocol", + "Randomness": "randomness", + "Engines": "crypto_engine", + "Libraries": "crypto_library", + "Elliptic Curves": "ecc_curve", + "Block cipher modes": "cipher_mode", + "TLS cipher suites": "tls_cipher_suite"}, hidden, map_funcs) }} +{%- endmacro %} + +{% macro device_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} + {{ keywords_card(keyword_scan, doc_prefix, "device", "Device", {"Device models": "device_model", + "JavaCard versions": "javacard_version", + "JavaCard API constants": "javacard_api_const", + "JavaCard packages": "javacard_package", + "Operating System name": "os_name", + "CPLC": "cplc_data", + "IC data groups": "ic_data_group", + "Trusted Execution Environments": "tee_name", + "Vendor": "vendor"}, hidden, map_funcs) }} +{%- endmacro %} + +{% macro security_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} + {{ keywords_card(keyword_scan, doc_prefix, "security", "Security", {"Security level": "fips_security_level", + "Side-channel analysis": "side_channel_analysis", + "Vulnerabilities": "vulnerability", + "Certification process": "certification_process"}, hidden, map_funcs) }} +{%- endmacro %} + +{% macro other_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} + {{ keywords_card(keyword_scan, doc_prefix, "other", "Other", {"Standards": "standard_id", + "Technical reports": "technical_report_id"}, hidden, map_funcs) }} +{%- endmacro %} + +{% macro render_status(status) %} + {% if status|lower == "active" %} + active + {% elif status|lower == "historical" %} + historical + {% elif status|lower == "revoked" %} + revoked + {% else %} + {{ status }} + {% endif %} +{%- endmacro %} + +{% macro render_document_type(document_type) %} + {% if document_type == "report" %} + Certification Report + {% elif document_type == "target" %} + Security Policy + {% endif %} +{%- endmacro %} + +{% macro render_type(name) %} + + {% set ftype = get_fips_type(name) %} + {% if ftype %} + + {% endif %} + +{%- endmacro %} + +{% macro render_plot(timeline) %} +
+
+

Timeline

+ Matched certificates (monthly) +
+
+
+ + +{%- endmacro %} diff --git a/page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 b/page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 new file mode 100644 index 00000000..5f3837d1 --- /dev/null +++ b/page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 @@ -0,0 +1,55 @@ +{% extends "common/base.html.jinja2" %} + +{% set canonical = True %} +{% block content %} +
+
+

FIPS 140 Implementation Under Test

+
+
+

This page lists daily snapshots of the FIPS 140 CMVP + Implementation under Test list. + As NIST states "The IUT list is provided as a marketing service for vendors who have a viable + contract with an accredited laboratory for the testing of a cryptographic module."

+
+
+
+ {# {{ pagination.info }} #} +
+ {{ pagination.links }} +
+ + + + + + + + + + + + + {% for snapshot in snapshots %} + + + + + + + + + {% endfor %} + +
TimestampLast updatedTotal entriesDisplayed entriesNot displayed entriesActions
{{ snapshot["timestamp"]|fromisoformat|strftime("%d.%m.%Y %H:%M") }}{{ snapshot["last_updated"]|fromisoformat|strftime("%d.%m.%Y") }}{{ snapshot["total"] }}{{ snapshot["displayed"] }}{{ snapshot["not_displayed"] }}Go to snapshot +
+
+ {{ pagination.links }} +
+
+
+
+{% endblock %} diff --git a/page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 b/page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 new file mode 100644 index 00000000..dc4f5bb6 --- /dev/null +++ b/page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 @@ -0,0 +1,55 @@ +{% extends "common/base.html.jinja2" %} + +{% set canonical = True %} +{% block content %} +
+
+

FIPS 140 Modules In Process

+
+
+

This page lists daily snapshots of the FIPS 140 CMVP + Modules in Process list. + As NIST states "The MIP list contains cryptographic modules on which the CMVP is actively + working."

+
+
+
+ {# {{ pagination.info }} #} +
+ {{ pagination.links }} +
+ + + + + + + + + + + + + {% for snapshot in snapshots %} + + + + + + + + + {% endfor %} + +
TimestampLast updatedTotal entriesDisplayed entriesNot displayed entriesActions
{{ snapshot["timestamp"]|fromisoformat|strftime("%d.%m.%Y %H:%M") }}{{ snapshot["last_updated"]|fromisoformat|strftime("%d.%m.%Y") }}{{ snapshot["total"] }}{{ snapshot["displayed"] }}{{ snapshot["not_displayed"] }}Go to snapshot +
+
+ {{ pagination.links }} +
+
+
+
+{% endblock %} diff --git a/page/sec_certs_page/templates/fips/search/base.html.jinja2 b/page/sec_certs_page/templates/fips/search/base.html.jinja2 new file mode 100644 index 00000000..6d2d154c --- /dev/null +++ b/page/sec_certs_page/templates/fips/search/base.html.jinja2 @@ -0,0 +1,217 @@ +{% extends "common/base.html.jinja2" %} + +{% block content %} +
+
+ +

FIPS 140

+

Search

+
+
+
+
+ + +
+ + + +
+
+ + + +
+
+ + + +
+
+ + +
+
+
+

Categories + + +

+
+
+ +
+ {% for name, val in categories.items() %} + {% if loop.index0 % 3 == 0 %} +
+ {% endif %} +
+ + + + +
+ {% if (loop.index0 + 1) % 3 == 0 %} +
+ {% endif %} + {% endfor %} +
+
+ +
+
+
General filters
+ + + + + + + +
+
+
+ +
+
+
+
Search type specific options
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ +
+
+
+ + + {% block search_content %}{% endblock %} +
+
+{% endblock %} diff --git a/page/sec_certs_page/templates/index.html.jinja2 b/page/sec_certs_page/templates/index.html.jinja2 new file mode 100644 index 00000000..5501d73c --- /dev/null +++ b/page/sec_certs_page/templates/index.html.jinja2 @@ -0,0 +1,265 @@ +{% extends "common/base.html.jinja2" %} +{% set canonical = True %} +{% block content %} +
+
+
+
+

About sec-certs

+

+ We want to become the one-stop shop to explore the Common Criteria / FIPS 140 + certification ecosystem. We aggregate and annotate certification data, enabling you to perform + unified searches, + investigate vulnerabilities, analyze trends, compare products side-by-side, subscribe to + certificate changes, + and take other actions on certified products. +

+

+ The sec-certs tool is an ongoing research project by the Centre for Research on Cryptography + and Security. Learn more about our + team + and + research. +

+
+
+ sec-certs + sec-certs +
+
+
+ +
+
+
+
+
+ +
+ New! +

Explore certificates with AI

+

Use our AI assistant to help you explore and understand + Common Criteria and FIPS 140 certificates. Ask questions about a certificate + and let the AI guide you through the complex certification documents. +

+ + CC + + + PP + + + FIPS + +
+
+
+
+ +
+
+

Main features

+
+
+
+ +
+

Unified search

+

Search certificates relevant for your product, filter certificates by categories or status. + Explore the certificates without downloading and reading countless PDFs. +

+

+ We download and process certificates weekly, allowing you to search for your favorite Common + Criteria and FIPS 140 products. +

+ + CC + + + PP + + + FIPS + +
+
+
+ +
+

Certificate references

+

Explore the references between product certificates in a graph. A certificate referencing + another certificate often means that its product is built atop of another security relevant + product.

+

We use regular expressions to create references between certificates, making it easy for you + to find relationships in our reference graphs or certificate details.

+ + CC + + + FIPS + +
+
+
+ +
+

Vulnerability investigation

+

+ Investigate the vulnerabilities affecting certified products. +

+

+ We automatically map certificates to CVE + entries in NIST's National Vulnerability Database affecting them. + The information on relevant CVEs is displayed in the appropriate heuristics section + on pages of the affected certificates. +

+ + CVE + + + CPE + +
+
+ +
+
+
+ +
+

Trend visualization

+

+ Explore our analysis of the evolving security certifications landscape. +

+

+ We process certification PDFs into structured, machine-readable datasets, which are then + used to generate plots. + You can explore sample plots in the Analysis section. + Please note that these are preliminary findings - refer to our published + research + for a more detailed analysis. + +

+ + CC + + + FIPS + +
+
+
+ +
+

Open source & open data

+

+ Contribute to our code or download our extracted dataset in machine-readable format. +

+

+ Each week, we collect thousands of certificate files, convert them into machine-readable + datasets, + and enrich them with additional metadata. Full datasets are available below, while + individual certificate + data can be accessed on each certificate's page. +

+ + GitHub + + + CC + + + PP + + + FIPS + +
+
+
+ +
+

Change notifications

+

Subscribe to notifications about a vulnerability affecting a set of + certified products, all changes in a set of certified products or about new + certificates.

+ {% if not config["SUBSCRIPTIONS_ENABLED"] %} +

Notification subscriptions are currently disabled.

+ {% endif %} +

As a registered user, you can subscribe using the + + + button in certificate details. +

+ {# +

Alternatively, use the update feed button + + + to get an ATOM feed of updates to a certificate. +

+ #} +
+
+
+
+ +
+
+
+

Deploy it yourself!

+

The tools used to create the datasets on this website as well as the datasets themselves are + open-source and available on our GitHub. Documentation, including a quick-start guide, + can be found on below. +

+ GitHub + Docs + Changelog +
+
+

About

+

Want to Learn more about our research? More information, including our publications and + the privacy policy of this site can be found on our about page.

+ Project + Research + +
+
+
+
+{% endblock %} diff --git a/page/sec_certs_page/templates/pp/search/base.html.jinja2 b/page/sec_certs_page/templates/pp/search/base.html.jinja2 new file mode 100644 index 00000000..83b046c6 --- /dev/null +++ b/page/sec_certs_page/templates/pp/search/base.html.jinja2 @@ -0,0 +1,211 @@ +{% extends "common/base.html.jinja2" %} + +{% block content %} +
+
+ +

Protection Profiles

+

Search

+
+
+
+
+ + +
+ + + +
+
+ + + +
+
+ + +
+
+ + +
+
+
+

Categories + + +

+
+
+ +
+ {% for name, val in categories.items() %} + {% if loop.index0 % 5 == 0 %} +
+ {% endif %} +
+ + + + +
+ {% if (loop.index0 + 1) % 5 == 0 %} +
+ {% endif %} + {% endfor %} +
+
+
+
+
General filters
+ + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+
+
Search type specific options
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+
+
+ + {% block search_content %}{% endblock %} +
+
+{% endblock %} diff --git a/page/sec_certs_page/templates/vuln/search.html.jinja2 b/page/sec_certs_page/templates/vuln/search.html.jinja2 new file mode 100644 index 00000000..0978bac4 --- /dev/null +++ b/page/sec_certs_page/templates/vuln/search.html.jinja2 @@ -0,0 +1,82 @@ +{% extends "common/base.html.jinja2" %} + +{% set canonical = True %} +{% block content %} +
+
+
+
+

Vulnerability search

+

Search for vulnerabilities, that can affect your certificate.

+
+
+
+
+
+
+
+
+
+

CVEs

+

Browse through CVEs and see which certificates they impact.

+
+ + + E.g. CVE-2019-15809. +
+ CVE invalid. +
+
+ +
+
+
+
+
+
+

CPEs

+

Browse through CPEs and see which certificates they match.

+
+ + + E.g. cpe:2.3:a:microchip:atmel_toolbox:00.03.11.05:*:*:*:*:*:*:*. + +
+ CPE invalid. +
+
+ +
+
+
+
+
+
+ +
+{% endblock %} From e32914d19592c6fa19b578be31148104df090e29 Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Thu, 9 Apr 2026 07:13:04 -0400 Subject: [PATCH 02/11] fix: move files to root and cleanup structure --- page/sec_certs_page/static/base.css | 1116 ----------------- .../templates/cc/include.html.jinja2 | 171 --- .../templates/cc/search/base.html.jinja2 | 227 ---- .../templates/fips/include.html.jinja2 | 139 -- .../templates/fips/iut/iut_index.html.jinja2 | 55 - .../templates/fips/mip/mip_index.html.jinja2 | 55 - .../templates/fips/search/base.html.jinja2 | 217 ---- .../templates/index.html.jinja2 | 265 ---- .../templates/pp/search/base.html.jinja2 | 211 ---- .../templates/vuln/search.html.jinja2 | 82 -- 10 files changed, 2538 deletions(-) delete mode 100644 page/sec_certs_page/static/base.css delete mode 100644 page/sec_certs_page/templates/cc/include.html.jinja2 delete mode 100644 page/sec_certs_page/templates/cc/search/base.html.jinja2 delete mode 100644 page/sec_certs_page/templates/fips/include.html.jinja2 delete mode 100644 page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 delete mode 100644 page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 delete mode 100644 page/sec_certs_page/templates/fips/search/base.html.jinja2 delete mode 100644 page/sec_certs_page/templates/index.html.jinja2 delete mode 100644 page/sec_certs_page/templates/pp/search/base.html.jinja2 delete mode 100644 page/sec_certs_page/templates/vuln/search.html.jinja2 diff --git a/page/sec_certs_page/static/base.css b/page/sec_certs_page/static/base.css deleted file mode 100644 index 85008f28..00000000 --- a/page/sec_certs_page/static/base.css +++ /dev/null @@ -1,1116 +0,0 @@ -:root { - --sidebar-width: 250px; -} - -/* Skip to main content link - accessible but visually hidden until focused */ -.skip-link { - position: absolute; - top: -40px; - left: 0; - background: #000; - color: white; - padding: 8px; - text-decoration: none; - z-index: 100; -} - -.skip-link:focus { - top: 0; -} - -.nav-button { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; -} - -.show .nav-button, -.collapsing .nav-button { - margin-right: 0 !important; - margin-top: 0.5rem !important; - margin-left: 0 !important; -} - -.nav-current { - background-color: var(--bs-gray-800); -} - -[data-bs-theme="dark"] #navbar { - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); -} - -.part-logo { - filter: drop-shadow(0px 8px 16px rgba(0, 0, 0, 0.15)); -} - -[data-bs-theme="dark"] .part-logo { - filter: invert(100%) drop-shadow(0px 8px 16px rgba(0, 0, 0, 0.15)); -} - -#wrapper { - overflow-x: hidden; -} - -#page-content-wrapper { - margin-top: 51px; - /* padding-left: 50px; - padding-right: 50px; */ -} - -#up-top-icon { - font-size: small !important; - position: fixed; - bottom: 0.7rem; - right: 0.7rem; -} - -#chat { - font-size: small !important; - position: fixed; - bottom: 0.7rem; - right: 3.7rem; -} - -#chat-icon { - padding: 0.175rem 0.5rem; -} - -#chat-modal .modal-lg, #chat-modal .modal-xl { - height: 90vh; -} - -#chat-modal .modal-content { - height: 100%; -} - -#chat-body { - display: flex; - flex-direction: column; - height: 100%; - min-height: 0; -} - -#chat-skeleton { - display: flex; - flex-direction: column; - flex: 1 1 auto; - min-height: 0; -} - -#chat-window { - flex: 1 1 auto; - min-height: 0; - overflow-y: auto; - border: 1px solid #ccc; - border-radius: 0.5em; - padding: 1em; - background: #f8f9fa; - margin-bottom: 1em; -} - -.chat-message-user { - text-align: right; - background: #d1e7dd; - color: #003d1a; - border-radius: 1em 1em 0 1em; - margin: 0.5em 0 0.5em auto; - max-width: 75%; - padding: 0.5em 1em; -} - -.chat-message-assistant { - text-align: left; - background: #d1dce7; - color: #001529; - border-radius: 1em 1em 1em 0; - margin: 0.5em auto 0.5em 0; - max-width: 75%; - padding: 0.5em 1em; -} - -.chat-message-assistant p:last-child { - margin-bottom: 0; -} - -.chat-message-assistant table>:not(caption)>*>* { - background: #d1dce7; -} - -[aria-expanded="false"] .fa-chevron-up, -[aria-expanded="false"] .fa-minus, -[aria-expanded="true"] .fa-chevron-down, -[aria-expanded="true"] .fa-plus { - display: none; -} - -#feedback { - position: fixed; - right: 0; - top: 15%; - margin-right: -3px; -} - -@media screen and (max-width: 768px) { - #feedback { - display: none; - } -} - -#feedback .card { - float: right; - width: 300px; - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - background-color: #fafafa; - transition: margin 0.25s ease; -} - -[data-bs-theme="dark"] #feedback .card { - background-color: #101010; -} - -#feedback .card.collapsed { - margin-right: -300px; -} - -#feedback .btn-secondary { - float: left; - font-size: 1.5rem; - margin-top: 120px; - margin-right: -3.9rem; - padding-left: 1rem; - padding-right: 1rem; - border-radius: 0 0 0.25rem 0.25rem; - background-color: #6c757d; - transform: rotate(90deg); -} - -#feedback .btn-secondary:hover { - background-color: #505050; -} - -.signin-wrapper { - display: flex; - align-items: center; - flex-direction: column; - padding-top: 40px; - padding-bottom: 40px; - min-height: 100vh; -} - -.form-signin { - width: 100%; - max-width: 330px; - padding: 15px; - margin: auto; -} - -.form-signin .checkbox { - font-weight: 400; -} - -.form-signin .form-floating:focus-within { - z-index: 2; -} - -/* -.form-signin input[type="email"] { - margin-bottom: -1px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.form-signin input[type="password"] { - margin-bottom: 10px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -*/ - -.feature-icon { - display: inline-flex; - align-items: center; - justify-content: center; - width: 4rem; - height: 4rem; - margin-bottom: 1rem; - font-size: 2rem; - color: #fff; - border-radius: 0.75rem; -} - -.anchor { - padding-top: 57px; - margin-top: -57px; -} - -.outgoing-list { - list-style: none; -} - -.outgoing-list li:before { - font: var(--fa-font-solid); - content: "\f061"; - margin: 0 10px 0 -25px; - color: var(--bs-body-color); -} - -.incoming-list { - list-style: none; -} - -.incoming-list li:before { - font: var(--fa-font-solid); - content: "\f060"; - margin: 0 10px 0 -25px; - color: var(--bs-body-color); -} - -#content .listing { - padding: 1em; - border-radius: 0.5em; - border: 1px solid rgba(0, 0, 0, 0.2); - background-color: rgba(0, 0, 0, 0.03); -} - -#search-categories div { - display: flex; - flex-direction: column; -} - -body { - font-family: "IBM Plex Sans", - -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, - "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; -} - -.h1, -.h2, -.h3, -.h4, -.h5, -.h6, -h1, -h2, -h3, -h4, -h5, -h6 { - font-weight: 600; -} - -.callout { - padding: 1.25rem; - margin-top: 1.25rem; - margin-bottom: 1.25rem; - color: inherit; - background-color: var(--bs-gray-100); - border-left: 0.25rem solid var(--bs-gray-300); -} - -[data-bs-theme="dark"] .callout { - background-color: var(--bs-gray-800); - border-left: 0.25rem solid var(--bs-gray-700); -} - -.callout-primary { - background-color: var(--bs-primary-bg-subtle); - border-left: 0.25rem solid var(--bs-primary-border-subtle); -} - -.callout-secondary { - background-color: var(--bs-secondary-bg-subtle); - border-left: 0.25rem solid var(--bs-secondary-border-subtle); -} - -.callout-success { - background-color: var(--bs-success-bg-subtle); - border-left: 0.25rem solid var(--bs-success-border-subtle); -} - -.callout-danger { - background-color: var(--bs-danger-bg-subtle); - border-left: 0.25rem solid var(--bs-danger-border-subtle); -} - -.callout-warning { - background-color: var(--bs-warning-bg-subtle); - border-left: 0.25rem solid var(--bs-warning-border-subtle); -} - -.callout-info { - background-color: var(--bs-info-bg-subtle); - border-left: 0.25rem solid var(--bs-info-border-subtle); -} - -.callout-light { - background-color: var(--bs-light-bg-subtle); - border-left: 0.25rem solid var(--bs-light-border-subtle); -} - -.callout-dark { - background-color: var(--bs-dark-bg-subtle); - border-left: 0.25rem solid var(--bs-dark-border-subtle); -} - -[data-bs-theme="dark"] .row.bg-dark { - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19), - 0 -4px 8px 0 rgba(0, 0, 0, 0.2), 0 -6px 20px 0 rgba(0, 0, 0, 0.19); -} - -.hide-light { - display: none; -} - -[data-bs-theme="dark"] .hide-light { - display: initial; -} - -.hide-dark { - display: initial; -} - -[data-bs-theme="dark"] .hide-dark { - display: none; -} - -/* New UX design */ - -.dropdown .dropbtn { - font-size: 16px; - border: none; - color: white; - padding: 14px 16px; - background-color: inherit; - font-family: inherit; /* Important for vertical align on mobile phones */ - margin: 0; /* Important for vertical align on mobile phones */ -} - -.dropdown .dropbtn:focus-visible { - outline: 3px solid #ffc107; - outline-offset: 2px; -} - -#left-navigation { - position: fixed; - left: 0px; - /* background-color: white; */ - width: var(--sidebar-width); - height: 100vh; - padding: 10px; - padding-top: 30px; -} - -#left-navigation .active { - background-color: var(--bs-secondary); - border-color: var(--bs-secondary); -} - -[data-bs-theme="light"] #left-navigation { - background-color: var(--bs-white); -} - -[data-bs-theme="dark"] #left-navigation { - background-color: var(--bs-dark); -} - - -.shifted-section { - margin-left: var(--sidebar-width); -} - -@media (max-width: 767.98px) { - .shifted-section { - margin-left: 10px; - } -} - - -.spaced-table { - border-collapse: separate; - border-spacing: 0 40px; -} - -#content { - display: flex; - flex-direction: column; - min-height: 100vh; - justify-content: space-between; -} - -#network-skeleton { - height: 300px; - overflow: auto; - position: relative; -} - -#network-skeleton::before { - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - z-index: -1; - - display: block; - height: 100%; - width: 100%; - background-image: url('/static/img/references_background.png'); - background-size: contain; - filter: blur(10px); -} - -[data-bs-theme="light"] .bg-darker-light { - background-color: #f0f0f0; -} - -[data-bs-theme="dark"] .bg-darker-light { - background-color: #454545; -} - -.flex-basis-0 { - flex-basis: 0px; -} - -/* ============================================ - Dashboard Styles - ============================================ */ - -/* Dashed border utility for empty state cards */ -.border-dashed { - border-style: dashed !important; -} - -/* Collection card hover effect */ -.collection-card { - transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; -} - -.collection-card:hover { - transform: translateY(-4px); - box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; -} - -/* ============================================ - Dash Dropdown Bootstrap Integration - ============================================ */ -.dash-bootstrap .Select-control { - border-radius: 0.375rem; - border: 1px solid var(--bs-border-color); - background-color: var(--bs-body-bg); - min-height: 38px; -} - -/* Vertically center single-select values */ -.dash-bootstrap .Select-control .Select-value, -.dash-dropdown .Select-control .Select-value { - display: flex !important; - align-items: center; - height: 100%; - padding-top: 0; - padding-bottom: 0; -} - -.dash-bootstrap .Select-control .Select-value-label, -.dash-dropdown .Select-control .Select-value-label { - line-height: 36px; -} - -.dash-bootstrap .Select-placeholder, -.dash-dropdown .Select-placeholder { - line-height: 36px; -} - -.dash-bootstrap .Select-control:hover { - border-color: var(--bs-primary); -} - -.dash-bootstrap .Select-menu-outer { - background-color: var(--bs-body-bg); - border: 1px solid var(--bs-border-color); - border-radius: 0.375rem; - box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); - max-height: 300px; -} - -.dash-bootstrap .Select-option { - background-color: var(--bs-body-bg); - color: var(--bs-body-color); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; -} - -.dash-bootstrap .Select-option:hover, -.dash-bootstrap .Select-option.is-focused { - background-color: var(--bs-primary); - color: white; -} - -.dash-bootstrap .Select-value-label, -.dash-bootstrap .Select-placeholder { - color: var(--bs-body-color); -} - -/* Dash Dropdown (newer versions) */ -.dash-dropdown .Select-control { - background-color: var(--bs-body-bg) !important; - border-color: var(--bs-border-color) !important; -} - -.dash-dropdown .Select-menu { - background-color: var(--bs-body-bg) !important; - max-height: 300px !important; -} - -.dash-dropdown .VirtualizedSelectOption { - background-color: var(--bs-body-bg); - color: var(--bs-body-color); - white-space: nowrap !important; - overflow: hidden !important; - text-overflow: ellipsis !important; -} - -.dash-dropdown .VirtualizedSelectFocusedOption { - background-color: var(--bs-primary) !important; - color: white !important; -} - -/* Truncate selected values in dropdown */ -.dash-bootstrap .Select-value-label, -.dash-dropdown .Select-value-label { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - display: block; - line-height: 1.4; -} - -/* Multi-select tags */ -.dash-bootstrap .Select--multi .Select-value, -.dash-dropdown .Select--multi .Select-value { - max-width: 180px; - height: 24px !important; - line-height: 22px !important; - display: inline-flex !important; - align-items: center; - overflow: hidden; - margin-top: 2px; - margin-bottom: 2px; -} - -.dash-bootstrap .Select--multi .Select-value-label, -.dash-dropdown .Select--multi .Select-value-label { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - line-height: 22px; - height: 22px; -} - -/* ============================================ - Dashboard Date Picker Styling - ============================================ */ -.DateRangePicker, -.SingleDatePicker { - width: 100%; -} - -.DateRangePickerInput, -.SingleDatePickerInput { - background-color: var(--bs-body-bg) !important; - border: 1px solid var(--bs-border-color) !important; - border-radius: 0.375rem !important; -} - -.DateInput_input { - background-color: var(--bs-body-bg) !important; - color: var(--bs-body-color) !important; - border: none !important; - padding: 0.375rem 0.75rem !important; - font-size: 1rem !important; -} - -.CalendarDay__selected, -.CalendarDay__selected:hover { - background: var(--bs-primary) !important; - border-color: var(--bs-primary) !important; -} - -.date-picker-wrapper { - position: relative; - width: 100%; -} - -.date-picker-wrapper .date-picker-icon { - position: absolute; - left: 10px; - top: 50%; - transform: translateY(-50%); - z-index: 2; - color: var(--bs-secondary); - pointer-events: none; -} - -.date-picker-wrapper .SingleDatePicker, -.date-picker-wrapper .DateRangePicker { - width: 100%; -} - -.date-picker-wrapper .SingleDatePickerInput, -.date-picker-wrapper .DateRangePickerInput { - width: 100% !important; - display: flex !important; -} - -.date-picker-wrapper .DateInput { - width: 100% !important; -} - -.date-picker-wrapper .DateInput_input { - width: 100% !important; - text-align: left !important; - padding: 0.375rem 0.75rem 0.375rem 2.25rem !important; - font-size: 0.9rem !important; - cursor: text !important; -} - -.DayPickerNavigation { - display: flex; - justify-content: space-between; -} - -.CalendarMonth_caption { - padding-top: 15px !important; - padding-bottom: 40px !important; - color: var(--bs-body-color) !important; -} - -.CalendarMonth_caption strong { - font-size: 1rem; -} - -.date-range-wrapper .DateInput_input { - padding-left: 2.25rem !important; -} - -.date-range-wrapper .DateInput:first-child .DateInput_input { - padding-left: 2.25rem !important; -} - -.date-range-wrapper .DateInput:last-child .DateInput_input { - padding-left: 0.75rem !important; -} - -.DayPicker, -.CalendarMonth, -.CalendarMonthGrid { - background-color: var(--bs-body-bg) !important; -} - -.CalendarDay__default { - background-color: var(--bs-body-bg) !important; - color: var(--bs-body-color) !important; - border-color: var(--bs-border-color) !important; -} - -.CalendarDay__default:hover { - background-color: var(--bs-light) !important; -} - -.DayPickerNavigation_button__default { - background-color: var(--bs-body-bg) !important; - border-color: var(--bs-border-color) !important; -} - -.DayPickerKeyboardShortcuts_show__bottomRight::before { - border-right-color: var(--bs-primary) !important; -} - -/* ============================================ - Dashboard Range Slider Styling - ============================================ */ -.rc-slider-track { - background-color: var(--bs-primary) !important; -} - -.rc-slider-handle { - border-color: var(--bs-primary) !important; -} - -.rc-slider-handle:hover, -.rc-slider-handle:active { - border-color: var(--bs-primary) !important; - box-shadow: 0 0 0 5px rgba(var(--bs-primary-rgb), 0.2) !important; -} - -/* ============================================ - Dashboard Dark Theme Adjustments - ============================================ */ - -/* Fix bg-light in dark mode for dashboard cards */ -[data-bs-theme="dark"] .bg-light { - background-color: var(--bs-gray-800) !important; -} - -/* Fix card backgrounds in dark mode */ -[data-bs-theme="dark"] .card { - background-color: var(--bs-dark); - border-color: var(--bs-gray-700); -} - -[data-bs-theme="dark"] .card-header { - background-color: var(--bs-gray-800); - border-color: var(--bs-gray-700); -} - -/* Dropdown controls in dark mode */ -[data-bs-theme="dark"] .dash-dropdown .Select-control, -[data-bs-theme="dark"] .dash-bootstrap .Select-control { - background-color: var(--bs-gray-800) !important; - border-color: var(--bs-gray-600) !important; -} - -/* Dropdown inner container backgrounds in dark mode */ -[data-bs-theme="dark"] .dash-dropdown .Select-multi-value-wrapper, -[data-bs-theme="dark"] .dash-bootstrap .Select-multi-value-wrapper, -[data-bs-theme="dark"] .dash-dropdown .Select-input, -[data-bs-theme="dark"] .dash-bootstrap .Select-input { - background-color: transparent !important; - color: var(--bs-gray-900) !important; -} - -[data-bs-theme="dark"] .dash-dropdown .Select-input > input, -[data-bs-theme="dark"] .dash-bootstrap .Select-input > input { - background-color: transparent !important; - color: var(--bs-body-color) !important; -} - -[data-bs-theme="dark"] .dash-dropdown .Select-value-label, -[data-bs-theme="dark"] .dash-bootstrap .Select-value-label, -[data-bs-theme="dark"] .dash-dropdown .Select-input input, -[data-bs-theme="dark"] .dash-bootstrap .Select-input input, -[data-bs-theme="dark"] .dash-dropdown .Select-placeholder, -[data-bs-theme="dark"] .dash-bootstrap .Select-placeholder { - color: var(--bs-body-color) !important; -} - -[data-bs-theme="dark"] .dash-dropdown .Select-arrow, -[data-bs-theme="dark"] .dash-bootstrap .Select-arrow { - border-color: var(--bs-body-color) transparent transparent !important; -} - -[data-bs-theme="dark"] .dash-dropdown .Select-option, -[data-bs-theme="dark"] .dash-bootstrap .Select-option, -[data-bs-theme="dark"] .dash-dropdown .VirtualizedSelectOption, -[data-bs-theme="dark"] .dash-bootstrap .VirtualizedSelectOption { - background-color: var(--bs-gray-800) !important; - color: var(--bs-body-color) !important; -} - -[data-bs-theme="dark"] .dash-dropdown .Select-option:hover, -[data-bs-theme="dark"] .dash-bootstrap .Select-option:hover, -[data-bs-theme="dark"] .dash-dropdown .Select-option.is-focused, -[data-bs-theme="dark"] .dash-bootstrap .Select-option.is-focused, -[data-bs-theme="dark"] .dash-dropdown .VirtualizedSelectFocusedOption, -[data-bs-theme="dark"] .dash-bootstrap .VirtualizedSelectFocusedOption { - background-color: var(--bs-primary) !important; - color: white !important; -} - -[data-bs-theme="dark"] .dash-dropdown .Select-menu, -[data-bs-theme="dark"] .dash-bootstrap .Select-menu-outer { - background-color: var(--bs-gray-800) !important; - border-color: var(--bs-gray-600) !important; -} - -[data-bs-theme="dark"] .DateRangePickerInput, -[data-bs-theme="dark"] .SingleDatePickerInput, -[data-bs-theme="dark"] .DateInput_input { - background-color: var(--bs-gray-800) !important; - border-color: var(--bs-gray-600) !important; - color: var(--bs-body-color) !important; -} - -[data-bs-theme="dark"] .DayPicker, -[data-bs-theme="dark"] .CalendarMonth, -[data-bs-theme="dark"] .CalendarMonthGrid { - background-color: var(--bs-gray-800) !important; -} - -[data-bs-theme="dark"] .CalendarDay__default { - background-color: var(--bs-gray-800) !important; - color: var(--bs-body-color) !important; - border-color: var(--bs-gray-700) !important; -} - -[data-bs-theme="dark"] .CalendarDay__default:hover { - background-color: var(--bs-gray-700) !important; -} - -[data-bs-theme="dark"] .DayPickerNavigation_button__default { - background-color: var(--bs-gray-800) !important; - border-color: var(--bs-gray-600) !important; -} - -[data-bs-theme="dark"] .CalendarMonth_caption { - color: var(--bs-body-color) !important; -} - -[data-bs-theme="dark"] .DayPicker_weekHeader, -[data-bs-theme="dark"] .DayPicker_weekHeader_li, -[data-bs-theme="dark"] .DayPicker_weekHeader small { - color: var(--bs-gray-400) !important; -} - -[data-bs-theme="dark"] .DayPickerNavigation_svg__horizontal { - fill: var(--bs-body-color) !important; -} - -[data-bs-theme="dark"] .DateInput_fang { - fill: var(--bs-gray-800) !important; -} - -[data-bs-theme="dark"] .DateInput_fangStroke { - stroke: var(--bs-gray-600) !important; -} - -[data-bs-theme="dark"] .CalendarDay__outside { - color: var(--bs-gray-500) !important; -} - -[data-bs-theme="dark"] .CalendarDay__selected, -[data-bs-theme="dark"] .CalendarDay__selected:hover { - background: var(--bs-primary) !important; - color: white !important; -} - -[data-bs-theme="dark"] .CalendarDay__hovered_span, -[data-bs-theme="dark"] .CalendarDay__selected_span { - background: rgba(var(--bs-primary-rgb), 0.3) !important; - color: var(--bs-body-color) !important; -} - -/* ============================================ - Chart Creation Modal - ============================================ */ - -/* Chart type selector cards */ -.chart-type-option { - border: 2px solid var(--bs-border-color); - background-color: var(--bs-body-bg); - transition: all 0.2s ease-in-out; - cursor: pointer; -} - -.chart-type-option:hover { - border-color: var(--bs-primary); - background-color: rgba(var(--bs-primary-rgb), 0.1); -} - -.chart-type-option.selected { - border-color: var(--bs-primary); - background-color: var(--bs-primary); - color: white; -} - -.chart-type-option i { - color: var(--bs-primary); -} - -.chart-type-option.selected i { - color: white; -} - -/* Cursor pointer utility */ -.cursor-pointer { - cursor: pointer; -} - -/* Modal width to match container-fluid */ -.modal-xl-fluid .modal-dialog { - max-width: 95%; - margin: 1.75rem auto; -} - -@media (min-width: 1200px) { - .modal-xl-fluid .modal-dialog { - max-width: 90%; - } -} - -/* Modal filter sections */ -.modal-filters-container .card { - border: 1px solid var(--bs-border-color); -} - -.modal-filters-container .card-header { - background-color: transparent; - padding: 0.5rem 1rem; -} - -/* Filter section styling */ -.filter-section { - margin-bottom: 0.75rem; -} - -.filter-section-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.5rem 0.75rem; - background-color: var(--bs-light); - border-radius: 0.375rem; - cursor: pointer; - transition: background-color 0.15s ease-in-out; -} - -.filter-section-header:hover { - background-color: var(--bs-gray-200); -} - -[data-bs-theme="dark"] .filter-section-header { - background-color: var(--bs-gray-800); -} - -[data-bs-theme="dark"] .filter-section-header:hover { - background-color: var(--bs-gray-700); -} - -/* ============================================ - Dashboard Loading States - ============================================ */ -.dash-loading { - display: flex; - align-items: center; - justify-content: center; - min-height: 200px; -} - -._dash-loading-callback { - position: relative; -} - -._dash-loading-callback::after { - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(255, 255, 255, 0.7); - display: flex; - align-items: center; - justify-content: center; -} - -[data-bs-theme="dark"] ._dash-loading-callback::after { - background-color: rgba(0, 0, 0, 0.5); -} - -.mb-4.border-0 > .card-body { - background-color: var(--bs-gray-100); - border-radius: var(--bs-border-radius); -} - -[data-bs-theme="dark"] .mb-4.border-0 > .card-body { - background-color: var(--bs-gray-800); -} - -/* ============================================ - Button Visibility Improvements - ============================================ */ -/* Make Refresh All button more visible when clickable */ -.refresh-all-btn:not(:disabled):not(.disabled) { - background-color: var(--bs-secondary); - border-color: var(--bs-secondary); - border-width: 2px; - font-weight: 500; - color: white; -} - -.refresh-all-btn:not(:disabled):not(.disabled):hover { - background-color: var(--bs-dark); - border-color: var(--bs-dark); -} - -/* Dark theme: use darker, more visible colors */ -[data-bs-theme="dark"] .refresh-all-btn:not(:disabled):not(.disabled) { - background-color: #6c757d; - border-color: #6c757d; - color: white; -} - -[data-bs-theme="dark"] .refresh-all-btn:not(:disabled):not(.disabled):hover { - background-color: #5a6268; - border-color: #5a6268; - color: white; -} - -/* ========================================================================== - WCAG Accessibility implementation - btn-outline-primary color overrides per theme - ========================================================================== */ - -[data-bs-theme="light"] .btn-outline-primary { - --bs-btn-color: #0060F0; - --bs-btn-border-color: #0060F0; - --bs-btn-hover-bg: #0060F0; - --bs-btn-hover-border-color: #0060F0; - --bs-btn-active-bg: #0060F0; - --bs-btn-active-border-color: #0060F0; -} - -[data-bs-theme="dark"] .btn-outline-primary { - --bs-btn-color: #85B6FF; - --bs-btn-border-color: #85B6FF; - --bs-btn-hover-bg: #85B6FF; - --bs-btn-hover-border-color: #85B6FF; - --bs-btn-active-bg: #85B6FF; - --bs-btn-active-border-color: #85B6FF; -} - -/* Higher contrast for links (Light mode) */ -p a { - color: #1A6BCC; -} - -/* back to original color in dark mode*/ -[data-bs-theme="dark"] p a { - color: #85B6FF; -} - -/* ========================================================================== - Status label colors per theme - ========================================================================== */ - -/* Light mode */ -[data-bs-theme="light"] .status-active { - color: #198754; -} -[data-bs-theme="light"] .status-archived{ - color: #8B6313; -} -[data-bs-theme="light"] .status-historical { - color: #876608; -} -[data-bs-theme="light"] .status-revoked { - color: #dc3545; -} - -/* Dark mode */ -[data-bs-theme="dark"] .status-active { - color: #3FBD7A; -} -[data-bs-theme="dark"] .status-archived, -[data-bs-theme="dark"] .status-historical { - color: #ffcd39; -} -[data-bs-theme="dark"] .status-revoked { - color: #ea868f; -} - -/* Alert-primary link colors */ -[data-bs-theme="light"] .alert-primary a { - color: #0158E4; -} \ No newline at end of file diff --git a/page/sec_certs_page/templates/cc/include.html.jinja2 b/page/sec_certs_page/templates/cc/include.html.jinja2 deleted file mode 100644 index d983b74a..00000000 --- a/page/sec_certs_page/templates/cc/include.html.jinja2 +++ /dev/null @@ -1,171 +0,0 @@ -{% from "include/entry.html.jinja2" import keywords_card, opt_line %} - -{% macro cc_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} - {{ keywords_card(keyword_scan, doc_prefix, "common-criteria", "Common Criteria", {"Security level": "cc_security_level", - "Claims": "cc_claims", - "Security Assurance Requirements (SAR)": "cc_sar", - "Security Functional Requirements (SFR)": "cc_sfr", - "Protection profiles": "cc_protection_profile_id", - "Certificates": "cc_cert_id", - "Evaluation facilities": "eval_facility"}, hidden, map_funcs) }} -{%- endmacro %} - -{% macro render_frontpage(cert, doc_type, title) %} - {% if cert["pdf_data"][doc_type] %} - {% if cert["pdf_data"][doc_type]["anssi"] %} - {% set frontpage = cert["pdf_data"][doc_type]["anssi"] %} - {% elif cert["pdf_data"][doc_type]["bsi"] %} - {% set frontpage = cert["pdf_data"][doc_type]["bsi"] %} - {% elif cert["pdf_data"][doc_type]["niap"] %} - {% set frontpage = cert["pdf_data"][doc_type]["niap"] %} - {% elif cert["pdf_data"][doc_type]["canada"] %} - {% set frontpage = cert["pdf_data"][doc_type]["canada"] %} - {% elif cert["pdf_data"][doc_type]["nscib"] %} - {% set frontpage = cert["pdf_data"][doc_type]["nscib"] %} - {% elif cert["pdf_data"][doc_type][cert["scheme"]] %} - {% set frontpage = cert["pdf_data"][doc_type][cert["scheme"]] %} - {% endif %} - {% if frontpage %} -

Frontpage

- - - - - - - {{ opt_line("Certificate ID", "cert_id", frontpage, title) }} - {{ opt_line("Certified item", "cert_item", frontpage, title) }} - {{ opt_line("Certification lab", "cert_lab", frontpage, title) }} - {{ opt_line("Developer", "developer", frontpage, title) }} - -
- {% endif %} - {% endif %} -{% endmacro %} - -{% macro render_status(status) %} - {% if status == "active" %} - active - {% elif status == "archived" %} - archived - {% else %} - {{ status }} - {% endif %} -{%- endmacro %} - -{% macro render_document_type(document_type) %} - {% if document_type == "cert" %} - Certificate - {% elif document_type == "report" %} - Certification Report - {% elif document_type == "target" %} - Security Target - {% endif %} -{%- endmacro %} - -{% macro render_category(category) %} - - {% set cat = get_cc_category(category) %} - {% if cat %} - - {% endif %} - -{%- endmacro %} - -{% macro render_eal(eal) %} - {% set ealm = eal.replace("+", "") %} - {%- if get_cc_eal(ealm) -%} - {{ eal }} - {%- elif get_cc_sar(eal) -%} - {{ eal }} - {%- else -%} - {{ eal }} - {%- endif -%} -{%- endmacro %} - -{% macro render_sfrs(sfr) %} - {%- if get_cc_sfr(sfr) -%} - {{ sfr }} - {%- else -%} - {{ sfr }} - {%- endif -%} -{%- endmacro %} - -{% macro render_sars(sar) %} - {%- if get_cc_sar(sar) -%} - {{ sar }} - {%- else -%} - {{ sar }} - {%- endif -%} -{%- endmacro %} - - -{% macro render_plot(timeline) %} -
-
-

Timeline

- Matched certificates (monthly) -
-
-
- - -{%- endmacro %} \ No newline at end of file diff --git a/page/sec_certs_page/templates/cc/search/base.html.jinja2 b/page/sec_certs_page/templates/cc/search/base.html.jinja2 deleted file mode 100644 index 7f7900da..00000000 --- a/page/sec_certs_page/templates/cc/search/base.html.jinja2 +++ /dev/null @@ -1,227 +0,0 @@ -{% extends "common/base.html.jinja2" %} - -{% block content %} -
-
- -

Common Criteria

-

Search

-
-
-
-
- - - -
- - - -
-
- - - -
-
- - - -
- -
- - -
-
-
-

Categories - - -

-
-
- -
- {% for name, val in categories.items() %} - {% if loop.index0 % 5 == 0 %} -
- {% endif %} -
- - - - -
- {% if (loop.index0 + 1) % 5 == 0 %} -
- {% endif %} - {% endfor %} -
-
- -
-
-
General filters
- - - - - - - - - - - -
-
-
- -
-
-
- -
-
- -
-
Search type specific options
- - - - - - - - - - - -
-
-
- - - -
-
-
- - - -
-
-
-
-
-
- - - - {% block search_content %}{% endblock %} - -
-
-{% endblock %} \ No newline at end of file diff --git a/page/sec_certs_page/templates/fips/include.html.jinja2 b/page/sec_certs_page/templates/fips/include.html.jinja2 deleted file mode 100644 index 781226e3..00000000 --- a/page/sec_certs_page/templates/fips/include.html.jinja2 +++ /dev/null @@ -1,139 +0,0 @@ -{% from "include/entry.html.jinja2" import keywords_card %} - -{% macro cryptography_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} - {{ keywords_card(keyword_scan, doc_prefix, "crypto", "Cryptography", {"Symmetric Algorithms": "symmetric_crypto", - "Asymmetric Algorithms": "asymmetric_crypto", - "Post-quantum Algorithms": "pq_crypto", - "Hash functions": "hash_function", - "Schemes": "crypto_scheme", - "Protocols": "crypto_protocol", - "Randomness": "randomness", - "Engines": "crypto_engine", - "Libraries": "crypto_library", - "Elliptic Curves": "ecc_curve", - "Block cipher modes": "cipher_mode", - "TLS cipher suites": "tls_cipher_suite"}, hidden, map_funcs) }} -{%- endmacro %} - -{% macro device_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} - {{ keywords_card(keyword_scan, doc_prefix, "device", "Device", {"Device models": "device_model", - "JavaCard versions": "javacard_version", - "JavaCard API constants": "javacard_api_const", - "JavaCard packages": "javacard_package", - "Operating System name": "os_name", - "CPLC": "cplc_data", - "IC data groups": "ic_data_group", - "Trusted Execution Environments": "tee_name", - "Vendor": "vendor"}, hidden, map_funcs) }} -{%- endmacro %} - -{% macro security_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} - {{ keywords_card(keyword_scan, doc_prefix, "security", "Security", {"Security level": "fips_security_level", - "Side-channel analysis": "side_channel_analysis", - "Vulnerabilities": "vulnerability", - "Certification process": "certification_process"}, hidden, map_funcs) }} -{%- endmacro %} - -{% macro other_keywords(keyword_scan, doc_prefix, hidden=[], map_funcs={}) -%} - {{ keywords_card(keyword_scan, doc_prefix, "other", "Other", {"Standards": "standard_id", - "Technical reports": "technical_report_id"}, hidden, map_funcs) }} -{%- endmacro %} - -{% macro render_status(status) %} - {% if status|lower == "active" %} - active - {% elif status|lower == "historical" %} - historical - {% elif status|lower == "revoked" %} - revoked - {% else %} - {{ status }} - {% endif %} -{%- endmacro %} - -{% macro render_document_type(document_type) %} - {% if document_type == "report" %} - Certification Report - {% elif document_type == "target" %} - Security Policy - {% endif %} -{%- endmacro %} - -{% macro render_type(name) %} - - {% set ftype = get_fips_type(name) %} - {% if ftype %} - - {% endif %} - -{%- endmacro %} - -{% macro render_plot(timeline) %} -
-
-

Timeline

- Matched certificates (monthly) -
-
-
- - -{%- endmacro %} diff --git a/page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 b/page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 deleted file mode 100644 index 5f3837d1..00000000 --- a/page/sec_certs_page/templates/fips/iut/iut_index.html.jinja2 +++ /dev/null @@ -1,55 +0,0 @@ -{% extends "common/base.html.jinja2" %} - -{% set canonical = True %} -{% block content %} -
-
-

FIPS 140 Implementation Under Test

-
-
-

This page lists daily snapshots of the FIPS 140 CMVP - Implementation under Test list. - As NIST states "The IUT list is provided as a marketing service for vendors who have a viable - contract with an accredited laboratory for the testing of a cryptographic module."

-
-
-
- {# {{ pagination.info }} #} -
- {{ pagination.links }} -
- - - - - - - - - - - - - {% for snapshot in snapshots %} - - - - - - - - - {% endfor %} - -
TimestampLast updatedTotal entriesDisplayed entriesNot displayed entriesActions
{{ snapshot["timestamp"]|fromisoformat|strftime("%d.%m.%Y %H:%M") }}{{ snapshot["last_updated"]|fromisoformat|strftime("%d.%m.%Y") }}{{ snapshot["total"] }}{{ snapshot["displayed"] }}{{ snapshot["not_displayed"] }}Go to snapshot -
-
- {{ pagination.links }} -
-
-
-
-{% endblock %} diff --git a/page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 b/page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 deleted file mode 100644 index dc4f5bb6..00000000 --- a/page/sec_certs_page/templates/fips/mip/mip_index.html.jinja2 +++ /dev/null @@ -1,55 +0,0 @@ -{% extends "common/base.html.jinja2" %} - -{% set canonical = True %} -{% block content %} -
-
-

FIPS 140 Modules In Process

-
-
-

This page lists daily snapshots of the FIPS 140 CMVP - Modules in Process list. - As NIST states "The MIP list contains cryptographic modules on which the CMVP is actively - working."

-
-
-
- {# {{ pagination.info }} #} -
- {{ pagination.links }} -
- - - - - - - - - - - - - {% for snapshot in snapshots %} - - - - - - - - - {% endfor %} - -
TimestampLast updatedTotal entriesDisplayed entriesNot displayed entriesActions
{{ snapshot["timestamp"]|fromisoformat|strftime("%d.%m.%Y %H:%M") }}{{ snapshot["last_updated"]|fromisoformat|strftime("%d.%m.%Y") }}{{ snapshot["total"] }}{{ snapshot["displayed"] }}{{ snapshot["not_displayed"] }}Go to snapshot -
-
- {{ pagination.links }} -
-
-
-
-{% endblock %} diff --git a/page/sec_certs_page/templates/fips/search/base.html.jinja2 b/page/sec_certs_page/templates/fips/search/base.html.jinja2 deleted file mode 100644 index 6d2d154c..00000000 --- a/page/sec_certs_page/templates/fips/search/base.html.jinja2 +++ /dev/null @@ -1,217 +0,0 @@ -{% extends "common/base.html.jinja2" %} - -{% block content %} -
-
- -

FIPS 140

-

Search

-
-
-
-
- - -
- - - -
-
- - - -
-
- - - -
-
- - -
-
-
-

Categories - - -

-
-
- -
- {% for name, val in categories.items() %} - {% if loop.index0 % 3 == 0 %} -
- {% endif %} -
- - - - -
- {% if (loop.index0 + 1) % 3 == 0 %} -
- {% endif %} - {% endfor %} -
-
- -
-
-
General filters
- - - - - - - -
-
-
- -
-
-
-
Search type specific options
- - - - - - - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- -
-
-
- - - {% block search_content %}{% endblock %} -
-
-{% endblock %} diff --git a/page/sec_certs_page/templates/index.html.jinja2 b/page/sec_certs_page/templates/index.html.jinja2 deleted file mode 100644 index 5501d73c..00000000 --- a/page/sec_certs_page/templates/index.html.jinja2 +++ /dev/null @@ -1,265 +0,0 @@ -{% extends "common/base.html.jinja2" %} -{% set canonical = True %} -{% block content %} -
-
-
-
-

About sec-certs

-

- We want to become the one-stop shop to explore the Common Criteria / FIPS 140 - certification ecosystem. We aggregate and annotate certification data, enabling you to perform - unified searches, - investigate vulnerabilities, analyze trends, compare products side-by-side, subscribe to - certificate changes, - and take other actions on certified products. -

-

- The sec-certs tool is an ongoing research project by the Centre for Research on Cryptography - and Security. Learn more about our - team - and - research. -

-
-
- sec-certs - sec-certs -
-
-
- -
-
-
-
-
- -
- New! -

Explore certificates with AI

-

Use our AI assistant to help you explore and understand - Common Criteria and FIPS 140 certificates. Ask questions about a certificate - and let the AI guide you through the complex certification documents. -

- - CC - - - PP - - - FIPS - -
-
-
-
- -
-
-

Main features

-
-
-
- -
-

Unified search

-

Search certificates relevant for your product, filter certificates by categories or status. - Explore the certificates without downloading and reading countless PDFs. -

-

- We download and process certificates weekly, allowing you to search for your favorite Common - Criteria and FIPS 140 products. -

- - CC - - - PP - - - FIPS - -
-
-
- -
-

Certificate references

-

Explore the references between product certificates in a graph. A certificate referencing - another certificate often means that its product is built atop of another security relevant - product.

-

We use regular expressions to create references between certificates, making it easy for you - to find relationships in our reference graphs or certificate details.

- - CC - - - FIPS - -
-
-
- -
-

Vulnerability investigation

-

- Investigate the vulnerabilities affecting certified products. -

-

- We automatically map certificates to CVE - entries in NIST's National Vulnerability Database affecting them. - The information on relevant CVEs is displayed in the appropriate heuristics section - on pages of the affected certificates. -

- - CVE - - - CPE - -
-
- -
-
-
- -
-

Trend visualization

-

- Explore our analysis of the evolving security certifications landscape. -

-

- We process certification PDFs into structured, machine-readable datasets, which are then - used to generate plots. - You can explore sample plots in the Analysis section. - Please note that these are preliminary findings - refer to our published - research - for a more detailed analysis. - -

- - CC - - - FIPS - -
-
-
- -
-

Open source & open data

-

- Contribute to our code or download our extracted dataset in machine-readable format. -

-

- Each week, we collect thousands of certificate files, convert them into machine-readable - datasets, - and enrich them with additional metadata. Full datasets are available below, while - individual certificate - data can be accessed on each certificate's page. -

- - GitHub - - - CC - - - PP - - - FIPS - -
-
-
- -
-

Change notifications

-

Subscribe to notifications about a vulnerability affecting a set of - certified products, all changes in a set of certified products or about new - certificates.

- {% if not config["SUBSCRIPTIONS_ENABLED"] %} -

Notification subscriptions are currently disabled.

- {% endif %} -

As a registered user, you can subscribe using the - - - button in certificate details. -

- {# -

Alternatively, use the update feed button - - - to get an ATOM feed of updates to a certificate. -

- #} -
-
-
-
- -
-
-
-

Deploy it yourself!

-

The tools used to create the datasets on this website as well as the datasets themselves are - open-source and available on our GitHub. Documentation, including a quick-start guide, - can be found on below. -

- GitHub - Docs - Changelog -
-
-

About

-

Want to Learn more about our research? More information, including our publications and - the privacy policy of this site can be found on our about page.

- Project - Research - -
-
-
-
-{% endblock %} diff --git a/page/sec_certs_page/templates/pp/search/base.html.jinja2 b/page/sec_certs_page/templates/pp/search/base.html.jinja2 deleted file mode 100644 index 83b046c6..00000000 --- a/page/sec_certs_page/templates/pp/search/base.html.jinja2 +++ /dev/null @@ -1,211 +0,0 @@ -{% extends "common/base.html.jinja2" %} - -{% block content %} -
-
- -

Protection Profiles

-

Search

-
-
-
-
- - -
- - - -
-
- - - -
-
- - -
-
- - -
-
-
-

Categories - - -

-
-
- -
- {% for name, val in categories.items() %} - {% if loop.index0 % 5 == 0 %} -
- {% endif %} -
- - - - -
- {% if (loop.index0 + 1) % 5 == 0 %} -
- {% endif %} - {% endfor %} -
-
-
-
-
General filters
- - - - - - - - - - - - -
-
-
- -
-
-
- -
-
-
-
Search type specific options
- - - - - - - - - - - -
-
-
- - - -
-
-
- - - -
-
-
-
-
-
- - {% block search_content %}{% endblock %} -
-
-{% endblock %} diff --git a/page/sec_certs_page/templates/vuln/search.html.jinja2 b/page/sec_certs_page/templates/vuln/search.html.jinja2 deleted file mode 100644 index 0978bac4..00000000 --- a/page/sec_certs_page/templates/vuln/search.html.jinja2 +++ /dev/null @@ -1,82 +0,0 @@ -{% extends "common/base.html.jinja2" %} - -{% set canonical = True %} -{% block content %} -
-
-
-
-

Vulnerability search

-

Search for vulnerabilities, that can affect your certificate.

-
-
-
-
-
-
-
-
-
-

CVEs

-

Browse through CVEs and see which certificates they impact.

-
- - - E.g. CVE-2019-15809. -
- CVE invalid. -
-
- -
-
-
-
-
-
-

CPEs

-

Browse through CPEs and see which certificates they match.

-
- - - E.g. cpe:2.3:a:microchip:atmel_toolbox:00.03.11.05:*:*:*:*:*:*:*. - -
- CPE invalid. -
-
- -
-
-
-
-
-
- -
-{% endblock %} From b00f41bf72fbd3869751af4c876ca4d838561784 Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Thu, 9 Apr 2026 07:20:41 -0400 Subject: [PATCH 03/11] fix: accessibility and theming improvements - Add visually-hidden labels for search inputs (CC, FIPS, PP search pages, CVE/CPE vuln search) - Fix heading hierarchy: change "Search" subheading from h3 to h2 on all search pages - Add empty table header label "Actions" in FIPS MIP and IUT index tables - Refactor status badge colors: replace Bootstrap text-success/warning/danger with custom CSS classes (status-active, status-archived, status-historical, status-revoked) supporting separate light/dark mode colors via data-bs-theme selectors in base.css - Split btn-outline-primary color overrides into light (#0060F0) and dark (#85B6FF) themes - Add alert-primary link color override for light mode (#0a58ca) - Fix research link color in index page analysis section using CSS custom property override2 --- sec_certs_page/static/base.css | 93 ++++++++++++++++++- .../templates/cc/include.html.jinja2 | 4 +- .../templates/cc/search/base.html.jinja2 | 17 ++-- .../templates/common/base.html.jinja2 | 1 + .../templates/fips/include.html.jinja2 | 6 +- .../templates/fips/iut/iut_index.html.jinja2 | 2 +- .../templates/fips/mip/mip_index.html.jinja2 | 2 +- .../templates/fips/search/base.html.jinja2 | 9 +- .../templates/pp/search/base.html.jinja2 | 17 ++-- .../templates/vuln/search.html.jinja2 | 6 +- 10 files changed, 125 insertions(+), 32 deletions(-) diff --git a/sec_certs_page/static/base.css b/sec_certs_page/static/base.css index 50a2a781..85008f28 100644 --- a/sec_certs_page/static/base.css +++ b/sec_certs_page/static/base.css @@ -2,6 +2,22 @@ --sidebar-width: 250px; } +/* Skip to main content link - accessible but visually hidden until focused */ +.skip-link { + position: absolute; + top: -40px; + left: 0; + background: #000; + color: white; + padding: 8px; + text-decoration: none; + z-index: 100; +} + +.skip-link:focus { + top: 0; +} + .nav-button { margin-right: 0.5rem !important; margin-left: 0.5rem !important; @@ -94,7 +110,7 @@ .chat-message-user { text-align: right; background: #d1e7dd; - color: #0f5132; + color: #003d1a; border-radius: 1em 1em 0 1em; margin: 0.5em 0 0.5em auto; max-width: 75%; @@ -104,7 +120,7 @@ .chat-message-assistant { text-align: left; background: #d1dce7; - color: #0f3051; + color: #001529; border-radius: 1em 1em 1em 0; margin: 0.5em auto 0.5em 0; max-width: 75%; @@ -361,7 +377,6 @@ h6 { .dropdown .dropbtn { font-size: 16px; border: none; - outline: none; color: white; padding: 14px 16px; background-color: inherit; @@ -369,6 +384,11 @@ h6 { margin: 0; /* Important for vertical align on mobile phones */ } +.dropdown .dropbtn:focus-visible { + outline: 3px solid #ffc107; + outline-offset: 2px; +} + #left-navigation { position: fixed; left: 0px; @@ -1027,3 +1047,70 @@ h6 { color: white; } +/* ========================================================================== + WCAG Accessibility implementation + btn-outline-primary color overrides per theme + ========================================================================== */ + +[data-bs-theme="light"] .btn-outline-primary { + --bs-btn-color: #0060F0; + --bs-btn-border-color: #0060F0; + --bs-btn-hover-bg: #0060F0; + --bs-btn-hover-border-color: #0060F0; + --bs-btn-active-bg: #0060F0; + --bs-btn-active-border-color: #0060F0; +} + +[data-bs-theme="dark"] .btn-outline-primary { + --bs-btn-color: #85B6FF; + --bs-btn-border-color: #85B6FF; + --bs-btn-hover-bg: #85B6FF; + --bs-btn-hover-border-color: #85B6FF; + --bs-btn-active-bg: #85B6FF; + --bs-btn-active-border-color: #85B6FF; +} + +/* Higher contrast for links (Light mode) */ +p a { + color: #1A6BCC; +} + +/* back to original color in dark mode*/ +[data-bs-theme="dark"] p a { + color: #85B6FF; +} + +/* ========================================================================== + Status label colors per theme + ========================================================================== */ + +/* Light mode */ +[data-bs-theme="light"] .status-active { + color: #198754; +} +[data-bs-theme="light"] .status-archived{ + color: #8B6313; +} +[data-bs-theme="light"] .status-historical { + color: #876608; +} +[data-bs-theme="light"] .status-revoked { + color: #dc3545; +} + +/* Dark mode */ +[data-bs-theme="dark"] .status-active { + color: #3FBD7A; +} +[data-bs-theme="dark"] .status-archived, +[data-bs-theme="dark"] .status-historical { + color: #ffcd39; +} +[data-bs-theme="dark"] .status-revoked { + color: #ea868f; +} + +/* Alert-primary link colors */ +[data-bs-theme="light"] .alert-primary a { + color: #0158E4; +} \ No newline at end of file diff --git a/sec_certs_page/templates/cc/include.html.jinja2 b/sec_certs_page/templates/cc/include.html.jinja2 index dcb2cc68..d983b74a 100644 --- a/sec_certs_page/templates/cc/include.html.jinja2 +++ b/sec_certs_page/templates/cc/include.html.jinja2 @@ -45,9 +45,9 @@ {% macro render_status(status) %} {% if status == "active" %} - active + active {% elif status == "archived" %} - archived + archived {% else %} {{ status }} {% endif %} diff --git a/sec_certs_page/templates/cc/search/base.html.jinja2 b/sec_certs_page/templates/cc/search/base.html.jinja2 index b0f6ea54..7f7900da 100644 --- a/sec_certs_page/templates/cc/search/base.html.jinja2 +++ b/sec_certs_page/templates/cc/search/base.html.jinja2 @@ -7,11 +7,12 @@ This page was not yet optimized for use on mobile devices.

Common Criteria

-

Search

+

Search

+ @@ -51,7 +52,7 @@
E.g. - Infineon Security Controller + Infineon Security Controller .
@@ -61,17 +62,17 @@ target="_blank" rel="noopener">Whoosh query language.
E.g. "post quantum" OR "post-quantum" OR "PQC". + role="button" tabindex="0" onclick="window.getSelection().selectAllChildren(this)" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();window.getSelection().selectAllChildren(this)}" aria-label="Click to select text">"post quantum" OR "post-quantum" OR "PQC".
-
-

Categories +
+

Categories

-
+
@@ -107,10 +108,10 @@ diff --git a/sec_certs_page/templates/common/base.html.jinja2 b/sec_certs_page/templates/common/base.html.jinja2 index 8d58d840..d622cd4c 100644 --- a/sec_certs_page/templates/common/base.html.jinja2 +++ b/sec_certs_page/templates/common/base.html.jinja2 @@ -221,6 +221,7 @@ {% endblock %} +
+ -
- Feedback -
From afd6da58fcaca9ee73def3bc0ecf81f68e540b64 Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Fri, 24 Apr 2026 22:26:53 +0200 Subject: [PATCH 06/11] fix(wcag): add aria-label to badge icons; remove role=button from example spans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cc/entry: add aria-label and aria-hidden="true" to 9 badge elements so screen readers announce their meaning in browse mode - cc/search, pp/search, vuln/search: remove role="button", tabindex, onclick, onkeydown and aria-label="Click to select text" from example query spans — these were falsely announced as interactive buttons; text remains readable in screen reader browse mode --- .../templates/cc/entry/index.html.jinja2 | 54 +++++++++---------- .../templates/cc/search/base.html.jinja2 | 5 +- .../templates/pp/search/base.html.jinja2 | 4 +- .../templates/vuln/search.html.jinja2 | 4 +- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/sec_certs_page/templates/cc/entry/index.html.jinja2 b/sec_certs_page/templates/cc/entry/index.html.jinja2 index 8558138f..d93d18b2 100644 --- a/sec_certs_page/templates/cc/entry/index.html.jinja2 +++ b/sec_certs_page/templates/cc/entry/index.html.jinja2 @@ -370,18 +370,18 @@ {{ other["name"] | truncate(120, true) }} {% if other["name"] == cert["name"] and cert["name"] %} + aria-label="Certificate name matches exactly." + data-bs-toggle="tooltip" title="Certificate name matches exactly."> {% endif %} {{ other["heuristics"]["cert_id"] }} {% if other["heuristics"]["cert_id"] == cert["heuristics"]["cert_id"] and cert["heuristics"]["cert_id"] %} + aria-label="Certificate ID matches exactly." + data-bs-toggle="tooltip" title="Certificate ID matches exactly."> {% endif %} @@ -400,18 +400,18 @@ {{ other["name"] | truncate(120, true) }} {% if other["name"] == cert["name"] and cert["name"] %} + aria-label="Certificate name matches exactly." + data-bs-toggle="tooltip" title="Certificate name matches exactly."> {% endif %} {{ other["heuristics"]["cert_id"] }} {% if other["heuristics"]["cert_id"] == cert["heuristics"]["cert_id"] and cert["heuristics"]["cert_id"] %} + aria-label="Certificate ID matches exactly." + data-bs-toggle="tooltip" title="Certificate ID matches exactly."> {% endif %} @@ -447,28 +447,28 @@ title="{{ similar_cert["name"] }}">{{ similar_cert["name"] | truncate(120, true) }} {% if similar_cert["name"] == cert["name"] and cert["name"] %} + aria-label="Certificate name matches exactly." + data-bs-toggle="tooltip" title="Certificate name matches exactly."> {% endif %} {% if "state" in similar_cert %} {% if "cert" in similar_cert["state"] and similar_cert["state"]["cert"]["source_hash"] == cert["state"]["cert"]["source_hash"] and cert["state"]["cert"]["source_hash"] %} + aria-label="Certificate PDF file matches exactly." + data-bs-toggle="tooltip" title="Certificate PDF file matches exactly."> {% endif %} {% if "report" in similar_cert["state"] and similar_cert["state"]["report"]["source_hash"] == cert["state"]["report"]["source_hash"] and cert["state"]["report"]["source_hash"] %} + aria-label="Certification report PDF file matches exactly." + data-bs-toggle="tooltip" title="Certification report PDF file matches exactly."> {% endif %} {% if "st" in similar_cert["state"] and similar_cert["state"]["st"]["source_hash"] == cert["state"]["st"]["source_hash"] and cert["state"]["st"]["source_hash"] %} + aria-label="Security target PDF file matches exactly." + data-bs-toggle="tooltip" title="Security target PDF file matches exactly."> {% endif %} {% endif %} @@ -476,9 +476,9 @@ {{ similar_cert["heuristics"]["cert_id"] }} {% if similar_cert["heuristics"]["cert_id"] == cert["heuristics"]["cert_id"] and cert["heuristics"]["cert_id"] %} + aria-label="Certificate ID matches exactly." + data-bs-toggle="tooltip" title="Certificate ID matches exactly."> {% endif %} diff --git a/sec_certs_page/templates/cc/search/base.html.jinja2 b/sec_certs_page/templates/cc/search/base.html.jinja2 index 7f7900da..88c7c5e6 100644 --- a/sec_certs_page/templates/cc/search/base.html.jinja2 +++ b/sec_certs_page/templates/cc/search/base.html.jinja2 @@ -52,7 +52,7 @@
E.g. - Infineon Security Controller + Infineon Security Controller .
@@ -61,8 +61,7 @@ Supports the Whoosh query language.
- E.g. "post quantum" OR "post-quantum" OR "PQC". + E.g. "post quantum" OR "post-quantum" OR "PQC".
diff --git a/sec_certs_page/templates/pp/search/base.html.jinja2 b/sec_certs_page/templates/pp/search/base.html.jinja2 index 83b046c6..4d51d49f 100644 --- a/sec_certs_page/templates/pp/search/base.html.jinja2 +++ b/sec_certs_page/templates/pp/search/base.html.jinja2 @@ -46,7 +46,7 @@
E.g. - Infineon Security Controller + Infineon Security Controller .

@@ -56,7 +56,7 @@ target="_blank" rel="noopener">Whoosh query language.
E.g. . + >"post quantum" OR "post-quantum" OR "PQC".
diff --git a/sec_certs_page/templates/vuln/search.html.jinja2 b/sec_certs_page/templates/vuln/search.html.jinja2 index 0978bac4..7924dd67 100644 --- a/sec_certs_page/templates/vuln/search.html.jinja2 +++ b/sec_certs_page/templates/vuln/search.html.jinja2 @@ -23,7 +23,7 @@ - E.g. CVE-2019-15809. + E.g. CVE-2019-15809.
CVE invalid.
@@ -42,7 +42,7 @@ - E.g. cpe:2.3:a:microchip:atmel_toolbox:00.03.11.05:*:*:*:*:*:*:*. + E.g. cpe:2.3:a:microchip:atmel_toolbox:00.03.11.05:*:*:*:*:*:*:*.
CPE invalid. From 3f3caa38b7afe9eefbd27fa2a6f2146c87d194a5 Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Thu, 21 May 2026 22:18:02 +0200 Subject: [PATCH 07/11] fixed asssurance level and status buttons --- sec_certs_page/static/base.css | 13 +++++++++++-- sec_certs_page/templates/eucc/include.html.jinja2 | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/sec_certs_page/static/base.css b/sec_certs_page/static/base.css index 345a6d79..70fd6659 100644 --- a/sec_certs_page/static/base.css +++ b/sec_certs_page/static/base.css @@ -1110,7 +1110,8 @@ h6 { /* Light mode */ [data-bs-theme="light"] .status-active { - color: #198754; + color: #57C78B; + /*color: #198754;*/ } [data-bs-theme="light"] .status-archived{ color: #8B6313; @@ -1124,7 +1125,7 @@ h6 { /* Dark mode */ [data-bs-theme="dark"] .status-active { - color: #3FBD7A; + color: #57C78B; } [data-bs-theme="dark"] .status-archived, [data-bs-theme="dark"] .status-historical { @@ -1134,6 +1135,14 @@ h6 { color: #ea868f; } +/* EUCC assurance levels */ +[data-bs-theme="light"] .eucc-assurance-high { + color: #146c43; +} +[data-bs-theme="dark"] .eucc-assurance-high { + color: #86d4ae; +} + /* ========================================================================== Alert link colors per theme ========================================================================== */ diff --git a/sec_certs_page/templates/eucc/include.html.jinja2 b/sec_certs_page/templates/eucc/include.html.jinja2 index a90a5db4..2eb145b2 100644 --- a/sec_certs_page/templates/eucc/include.html.jinja2 +++ b/sec_certs_page/templates/eucc/include.html.jinja2 @@ -38,7 +38,7 @@ {% macro render_assurance_level(level) %} {% if level == "High" %} - high + high {% elif level == "Substantial" %} substantial {% else %} From ce82747a4a8de0d165164b08990c3ed16aa8830c Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Thu, 21 May 2026 22:48:54 +0200 Subject: [PATCH 08/11] fixing colors of buttons and text-EUCC --- sec_certs_page/static/base.css | 40 ++++++++++++++++--- .../templates/eucc/include.html.jinja2 | 2 +- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/sec_certs_page/static/base.css b/sec_certs_page/static/base.css index 70fd6659..5c4b0f81 100644 --- a/sec_certs_page/static/base.css +++ b/sec_certs_page/static/base.css @@ -1103,6 +1103,24 @@ h6 { color: #85B6FF; } +/* Higher contrast links on .bg-darker-light background*/ +[data-bs-theme="dark"] .bg-darker-light a:not(.btn) { + color: #9EC5FE; +} +[data-bs-theme="dark"] .bg-darker-light .btn-link { + --bs-btn-color: #9EC5FE; + --bs-btn-hover-color: #cfe2ff; + --bs-btn-active-color: #cfe2ff; +} + +[data-bs-theme="light"] .bg-darker-light a:not(.btn) { + color: #1A6BCC; +} +[data-bs-theme="light"] .bg-darker-light .btn-link { + --bs-btn-color: #1A6BCC; + --bs-btn-hover-color: #0056B3; + --bs-btn-active-color: #0056B3; +} /* ========================================================================== Status label colors per theme @@ -1110,8 +1128,7 @@ h6 { /* Light mode */ [data-bs-theme="light"] .status-active { - color: #57C78B; - /*color: #198754;*/ + color: #177D4D; } [data-bs-theme="light"] .status-archived{ color: #8B6313; @@ -1137,10 +1154,16 @@ h6 { /* EUCC assurance levels */ [data-bs-theme="light"] .eucc-assurance-high { - color: #146c43; + color: #177D4D; } [data-bs-theme="dark"] .eucc-assurance-high { - color: #86d4ae; + color: #57C78B; +} +[data-bs-theme="light"] .eucc-assurance-substantial { + color: #946300; +} +[data-bs-theme="dark"] .eucc-assurance-substantial { + color: #FFCA2C; } /* ========================================================================== @@ -1148,10 +1171,17 @@ h6 { ========================================================================== */ [data-bs-theme="light"] .alert-primary a, -[data-bs-theme="light"] .alert-info a { +[data-bs-theme="light"] .alert-info a, +[data-bs-theme="light"] .bg-darker-light .alert-primary a, +[data-bs-theme="light"] .bg-darker-light .alert-info a { color: #0158E4; } [data-bs-theme="light"] .alert-warning a { color: #6B4800; +} + +[data-bs-theme="dark"] .alert-info a, +[data-bs-theme="dark"] .bg-darker-light .alert-info a { + color: #9EC5FE; } \ No newline at end of file diff --git a/sec_certs_page/templates/eucc/include.html.jinja2 b/sec_certs_page/templates/eucc/include.html.jinja2 index 2eb145b2..59b65a4c 100644 --- a/sec_certs_page/templates/eucc/include.html.jinja2 +++ b/sec_certs_page/templates/eucc/include.html.jinja2 @@ -40,7 +40,7 @@ {% if level == "High" %} high {% elif level == "Substantial" %} - substantial + substantial {% else %} {{ level }} {% endif %} From 58017b2c9aadc55098e4bca6140b382d1491c514 Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Thu, 21 May 2026 23:21:31 +0200 Subject: [PATCH 09/11] fixed empty table headers --- .../templates/eucc/entry/components/heuristics.html.jinja2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sec_certs_page/templates/eucc/entry/components/heuristics.html.jinja2 b/sec_certs_page/templates/eucc/entry/components/heuristics.html.jinja2 index 77fe0b5d..3e7fe591 100644 --- a/sec_certs_page/templates/eucc/entry/components/heuristics.html.jinja2 +++ b/sec_certs_page/templates/eucc/entry/components/heuristics.html.jinja2 @@ -44,7 +44,7 @@ Name Certificate ID - + Actions {% if previous %} @@ -124,7 +124,7 @@ Name Certificate ID - + Actions {% for similar_cert in similar %} From c0b87304c0d53f574c34c693a6ee27158a7aea1d Mon Sep 17 00:00:00 2001 From: Martin Mikulica Date: Thu, 21 May 2026 23:32:51 +0200 Subject: [PATCH 10/11] added area labels and TAB focusable ring --- sec_certs_page/static/base.css | 8 ++++++++ .../eucc/entry/components/webpage_info.html.jinja2 | 2 ++ .../templates/eucc/search/name_search.html.jinja2 | 2 ++ 3 files changed, 12 insertions(+) diff --git a/sec_certs_page/static/base.css b/sec_certs_page/static/base.css index 5c4b0f81..fc238257 100644 --- a/sec_certs_page/static/base.css +++ b/sec_certs_page/static/base.css @@ -1184,4 +1184,12 @@ h6 { [data-bs-theme="dark"] .alert-info a, [data-bs-theme="dark"] .bg-darker-light .alert-info a { color: #9EC5FE; +} + +/*File metadata collapsible button — visible focus ring*/ + +.metadata-container > button:focus-visible { + outline: 3px solid var(--bs-focus-ring-color, #86b7fe); + outline-offset: 2px; + border-radius: 0.25rem; } \ No newline at end of file diff --git a/sec_certs_page/templates/eucc/entry/components/webpage_info.html.jinja2 b/sec_certs_page/templates/eucc/entry/components/webpage_info.html.jinja2 index c73a6f50..5dfe8c02 100644 --- a/sec_certs_page/templates/eucc/entry/components/webpage_info.html.jinja2 +++ b/sec_certs_page/templates/eucc/entry/components/webpage_info.html.jinja2 @@ -17,6 +17,8 @@ Certificate ID Certificate ID Date: Thu, 21 May 2026 23:41:19 +0200 Subject: [PATCH 11/11] area label search fix --- sec_certs_page/templates/eucc/search/base.html.jinja2 | 1 + 1 file changed, 1 insertion(+) diff --git a/sec_certs_page/templates/eucc/search/base.html.jinja2 b/sec_certs_page/templates/eucc/search/base.html.jinja2 index ceaba03f..98ae2dc1 100644 --- a/sec_certs_page/templates/eucc/search/base.html.jinja2 +++ b/sec_certs_page/templates/eucc/search/base.html.jinja2 @@ -12,6 +12,7 @@
+