At medium and high contrast, secondary-container turns dark. The empty part of progress bars, highlighted code lines and a targeted roadmap header now use surface-container-highest, so the fill and the text stay readable. The selected project in the project jump is light at these levels too; its check mark marks it. The selected sidebar query gets the pill style even with its "clear" icon next to it. The icon sits inside the pill and takes the pill's text color. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
661 lines
31 KiB
CSS
661 lines
31 KiB
CSS
/*
|
|
* Components: buttons, text fields, cards/boxes, banners, tabs, badges,
|
|
* pagination, progress, tooltips, dialogs, date picker, autocomplete.
|
|
* Uses --nm-state-* from layout.css.
|
|
*/
|
|
|
|
/***** Buttons *****/
|
|
input[type="submit"], input[type="button"], input[type="reset"], button[type="submit"] {
|
|
block-size: 40px;
|
|
padding-block: 0;
|
|
padding-inline: 24px;
|
|
margin-block: 4px;
|
|
border: 1px solid var(--md-sys-color-outline);
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background-color: transparent;
|
|
color: var(--md-sys-color-primary);
|
|
font: var(--md-sys-typescale-label-large);
|
|
letter-spacing: var(--md-sys-typescale-label-large-tracking);
|
|
cursor: pointer;
|
|
transition: var(--nm-transition), box-shadow var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard);
|
|
}
|
|
|
|
/* Filled: the main action of a form */
|
|
input[type="submit"], button[type="submit"] {
|
|
border-color: transparent;
|
|
background-color: var(--md-sys-color-primary);
|
|
color: var(--md-sys-color-on-primary);
|
|
}
|
|
|
|
/* Tonal: "Create and continue" and similar secondary submits */
|
|
input[type="submit"][name="continue"], input[type="submit"][name="follow"] {
|
|
background-color: var(--md-sys-color-secondary-container);
|
|
color: var(--md-sys-color-on-secondary-container);
|
|
}
|
|
|
|
input[type="submit"]:hover, input[type="button"]:hover, input[type="reset"]:hover, button[type="submit"]:hover {
|
|
background-image: var(--nm-state-hover);
|
|
}
|
|
input[type="submit"]:hover, button[type="submit"]:hover { background-color: var(--md-sys-color-primary); box-shadow: var(--md-sys-elevation-level1); }
|
|
input[type="submit"][name="continue"]:hover, input[type="submit"][name="follow"]:hover { background-color: var(--md-sys-color-secondary-container); }
|
|
input[type="submit"]:active, input[type="button"]:active, button[type="submit"]:active { background-image: var(--nm-state-pressed); box-shadow: none; }
|
|
|
|
input[type="submit"]:disabled, input[type="button"]:disabled, button:disabled {
|
|
background-color: color-mix(in srgb, var(--md-sys-color-on-surface) var(--md-sys-state-disabled-container-opacity), transparent);
|
|
border-color: transparent;
|
|
color: color-mix(in srgb, var(--md-sys-color-on-surface) var(--md-sys-state-disabled-content-opacity), transparent);
|
|
box-shadow: none;
|
|
cursor: default;
|
|
}
|
|
|
|
/***** Text fields (outlined) *****/
|
|
input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="number"],
|
|
input[type="date"], input[type="search"], input[type="tel"], input:not([type]), select, textarea {
|
|
min-block-size: 40px;
|
|
padding-block: 8px;
|
|
padding-inline: 12px;
|
|
border: 1px solid var(--md-sys-color-outline);
|
|
border-radius: var(--md-sys-shape-corner-extra-small);
|
|
background-color: transparent;
|
|
color: var(--md-sys-color-on-surface);
|
|
font: var(--md-sys-typescale-body-medium);
|
|
letter-spacing: var(--md-sys-typescale-body-medium-tracking);
|
|
transition: border-color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard);
|
|
}
|
|
input[type="text"]:hover, input[type="password"]:hover, input[type="email"]:hover, input[type="url"]:hover,
|
|
input[type="number"]:hover, input[type="date"]:hover, input[type="search"]:hover, select:hover, textarea:hover {
|
|
border-color: var(--md-sys-color-on-surface);
|
|
}
|
|
input[type="text"]:focus, input[type="text"]:active,
|
|
input[type="password"]:focus, input[type="password"]:active,
|
|
input[type="email"]:focus, input[type="url"]:focus, input[type="search"]:focus,
|
|
input[type="date"]:focus, input[type="date"]:active,
|
|
input[type="number"]:focus, input[type="number"]:active,
|
|
select:focus, select:active,
|
|
textarea:focus, textarea:active {
|
|
border-color: var(--md-sys-color-primary);
|
|
outline: 1px solid var(--md-sys-color-primary); /* 1px border + 1px outline = M3's 2px focused outline without layout shift */
|
|
outline-offset: -2px;
|
|
}
|
|
select {
|
|
background-color: transparent;
|
|
background-image: url(../images/arrow-drop-down.svg);
|
|
background-position: calc(100% - 6px) 50%;
|
|
background-size: 24px;
|
|
padding-inline-end: 32px;
|
|
}
|
|
[dir="rtl"] select { background-position: 6px 50%; }
|
|
/* The chevron is an image, so it cannot use color roles: one file per mode.
|
|
:where() keeps the swap at select's specificity so select[multiple] below still drops it */
|
|
:where(:root[data-mode="dark"]) select { background-image: url(../images/arrow-drop-down-dark.svg); }
|
|
@media (prefers-color-scheme: dark) { :where(:root:not([data-mode="light"])) select { background-image: url(../images/arrow-drop-down-dark.svg); } }
|
|
/* Autocomplete fields (parent task, watchers): M3 leading search icon, same per-mode files */
|
|
input.autocomplete {
|
|
background: transparent url(../images/search.svg) no-repeat 12px 50% / 20px;
|
|
padding-inline-start: 40px !important; /* core sets 20px with !important */
|
|
}
|
|
[dir="rtl"] input.autocomplete { background-position: calc(100% - 12px) 50%; }
|
|
/* :where() keeps the mode swap at the base rule's specificity, so core's own cases still win:
|
|
the jump box search (own icon, no background) and the ajax-loading spinner */
|
|
:where(:root[data-mode="dark"]) input.autocomplete { background-image: url(../images/search-dark.svg); }
|
|
@media (prefers-color-scheme: dark) { :where(:root:not([data-mode="light"])) input.autocomplete { background-image: url(../images/search-dark.svg); } }
|
|
select[multiple] { background-image: none; padding-inline-end: 12px; }
|
|
input::placeholder, textarea::placeholder { color: var(--md-sys-color-on-surface-variant); opacity: 1; }
|
|
input[type="checkbox"], input[type="radio"] { accent-color: var(--md-sys-color-primary); }
|
|
input[type="file"] { color: var(--md-sys-color-on-surface-variant); }
|
|
input[type="file"]::file-selector-button {
|
|
block-size: 40px;
|
|
margin-inline-end: 12px;
|
|
padding-inline: 24px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background-color: var(--md-sys-color-secondary-container);
|
|
color: var(--md-sys-color-on-secondary-container);
|
|
font: var(--md-sys-typescale-label-large);
|
|
cursor: pointer;
|
|
}
|
|
input:disabled, select:disabled, textarea:disabled {
|
|
border-color: color-mix(in srgb, var(--md-sys-color-on-surface) var(--md-sys-state-disabled-container-opacity), transparent);
|
|
color: color-mix(in srgb, var(--md-sys-color-on-surface) var(--md-sys-state-disabled-content-opacity), transparent);
|
|
}
|
|
|
|
/***** Cards: .box, tabular forms, fieldsets *****/
|
|
.box {
|
|
padding: 16px;
|
|
margin-block-end: 16px;
|
|
background-color: var(--md-sys-color-surface-container-low);
|
|
color: var(--md-sys-color-on-surface);
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-medium);
|
|
line-height: 1.5;
|
|
}
|
|
/* M3 has no legend notched into a border. A fieldset on its own is a filled card with the
|
|
legend as headline inside. A fieldset inside a card or form, and a collapsible one, is a
|
|
section: a full-width divider with the legend as subheader below it (M3 divider guidance). */
|
|
fieldset {
|
|
padding: 16px;
|
|
margin-block-end: 16px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-medium);
|
|
background-color: var(--md-sys-color-surface-container-low);
|
|
}
|
|
:is(.box, fieldset) fieldset, fieldset.collapsible:not(.box) {
|
|
padding: 8px 0 0;
|
|
margin-block: 8px;
|
|
border: 0;
|
|
border-block-start: 1px solid var(--md-sys-color-outline-variant);
|
|
border-radius: 0;
|
|
background-color: transparent;
|
|
}
|
|
/* A section that opens its card needs no divider: the card edge already separates it */
|
|
:is(.box, fieldset) > fieldset:first-child { margin-block-start: 0; padding-block-start: 0; border-block-start: 0; }
|
|
/* Floated, the legend leaves the border and flows as the first line of the fieldset */
|
|
fieldset > legend {
|
|
float: inline-start;
|
|
inline-size: 100%;
|
|
padding: 0 0 8px;
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
font: var(--md-sys-typescale-title-small);
|
|
letter-spacing: var(--md-sys-typescale-title-small-tracking);
|
|
}
|
|
fieldset > legend ~ * { clear: inline-start; }
|
|
fieldset.collapsed > legend { padding-block-end: 0; }
|
|
/* The chevron stays with a label that wraps */
|
|
fieldset.collapsible > legend { display: flex; align-items: center; gap: 4px; }
|
|
.tabular label { color: var(--md-sys-color-on-surface-variant); font-weight: 500; }
|
|
.tabular p { padding-block: 4px; }
|
|
/* Center the 24px label line on the 40px fields next to it */
|
|
.tabular label:not(.floating):not(.block):not(.inline):not(.no-css) { padding-block-start: 8px; }
|
|
/* Checkboxes and radios placed directly in a row align with that label line too */
|
|
/* Checkboxes and radios next to such a label align with its text line */
|
|
.tabular p:has(> label:not(.floating):not(.block):not(.inline):not(.no-css)) > input:is([type="checkbox"], [type="radio"]) { margin-block: 13px 0; }
|
|
/* Rows without a field at the label's height start at the top: checkbox lists (watchers)
|
|
and the issue description, whose editor stays hidden until "Edit" is clicked */
|
|
.tabular p:is(:has(label.floating), :has(> #issue_description_and_toolbar[style*="none"])) > label:not(.floating):not(.block):not(.inline):not(.no-css) { padding-block-start: 0; }
|
|
hr { background: var(--md-sys-color-outline-variant); }
|
|
blockquote { border-inline-start: 4px solid var(--md-sys-color-outline-variant); color: var(--md-sys-color-on-surface-variant); }
|
|
|
|
/* Core gives wide form fields 90%, 95% or 99% and caps .tabular fields at 95%. They all
|
|
run to the content edge, so the right edges in a form line up */
|
|
.tabular :is(input, select) { max-inline-size: 100%; }
|
|
/* Core pins these to 90% by id */
|
|
#user_login, #user_firstname, #user_lastname, #user_mail, #my_account_form select, #user_form select { inline-size: 100%; }
|
|
/* Desktop and tablet landscape: three field widths, so the right edges in a form line up.
|
|
Standard: selects and text fields fill the column up to 480px (wider than core's widest,
|
|
size=60). Compact: numbers and dates, 140px fits a date with its picker. Full: long text.
|
|
Below 900px core's responsive.css runs every field full width. */
|
|
@media screen and (min-width: 900px) {
|
|
.tabular :is(select, input:is([type="text"], [type="password"], [type="email"], [type="url"], [type="search"], [type="tel"], :not([type]))) {
|
|
inline-size: 100%;
|
|
max-inline-size: 480px;
|
|
box-sizing: border-box;
|
|
}
|
|
.tabular :is(input[type="number"], input[type="date"], input.date, input:is([size="1"], [size="2"], [size="3"], [size="4"], [size="5"], [size="6"])) { inline-size: 140px; }
|
|
/* The icon button after a select (new category, new version) stays on its line */
|
|
.tabular select:has(+ .icon-only) { inline-size: calc(100% - 36px); max-inline-size: calc(480px - 36px); }
|
|
}
|
|
html .tabular textarea, html textarea.wiki-edit, html textarea.text_cf, html input.string_cf, html input.link_cf,
|
|
html textarea#custom_field_possible_values, html textarea#custom_field_default_value,
|
|
html input#issue_subject, html input#document_title, html input#content_comments, html input#time_entry_comments,
|
|
html .tabular .jstTabs, html .tabular .wiki-preview, html .jstBlock .jstTabs, html .jstBlock .wiki-preview,
|
|
html .tabular.settings :is(textarea, .jstTabs, .wiki-preview) { inline-size: 100%; max-inline-size: none; box-sizing: border-box; }
|
|
/* Core pins % Done to 95px by id; it follows the standard width like the other selects */
|
|
html select#issue_done_ratio { inline-size: 100%; }
|
|
/* An invalid field keeps the error colour while focused */
|
|
.tabular label.error + :is(input, select, textarea):focus {
|
|
border-color: var(--md-sys-color-error);
|
|
outline-color: var(--md-sys-color-error);
|
|
}
|
|
/* Rows without a field start at the top, like a row with only links (two-factor auth) */
|
|
.tabular p:not(:has(input:not([type=hidden]), select, textarea, .nm-segmented)) > label:not(.floating):not(.block):not(.inline):not(.no-css) { padding-block-start: 0; }
|
|
/* Cancel next to a submit button */
|
|
input[type="submit"] + a { margin-inline-start: 8px; }
|
|
|
|
/* Checkbox lists in forms (custom field values, notified projects) */
|
|
.check_box_group {
|
|
padding-block: 4px;
|
|
padding-inline: 8px;
|
|
border-color: var(--md-sys-color-outline);
|
|
border-radius: var(--md-sys-shape-corner-extra-small);
|
|
background-color: transparent;
|
|
}
|
|
|
|
/***** Banners: flash messages, errors, warnings, empty states *****/
|
|
#errorExplanation, div.flash, .nodata, .warning, .conflict {
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-medium);
|
|
padding-block: 14px;
|
|
padding-inline: 48px 16px;
|
|
font: var(--md-sys-typescale-body-large);
|
|
letter-spacing: var(--md-sys-typescale-body-large-tracking);
|
|
}
|
|
div.flash svg.icon-svg, #errorExplanation svg.icon-svg, .conflict svg.icon-svg { margin-inline: -32px 8px; }
|
|
div.flash.error, #errorExplanation {
|
|
background-color: var(--md-sys-color-error-container);
|
|
color: var(--md-sys-color-on-error-container);
|
|
}
|
|
div.flash.notice {
|
|
background-color: var(--md-sys-color-success-container);
|
|
color: var(--md-sys-color-on-success-container);
|
|
}
|
|
div.flash.warning, .conflict {
|
|
background-color: var(--md-sys-color-warning-container);
|
|
color: var(--md-sys-color-on-warning-container);
|
|
}
|
|
.nodata, .warning {
|
|
padding-inline: 16px;
|
|
background-color: var(--md-sys-color-surface-container);
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
}
|
|
div.flash.error svg.icon-svg, #errorExplanation svg.icon-svg,
|
|
div.flash.notice svg.icon-svg, div.flash.warning svg.icon-svg, .conflict svg.icon-svg { stroke: currentColor; }
|
|
|
|
/***** Secondary tabs (settings, history, admin) *****/
|
|
#content .tabs { block-size: 48px; margin-block-end: 16px; }
|
|
#content .tabs ul { padding-inline-start: 0; border-block-end: 1px solid var(--md-sys-color-outline-variant); }
|
|
#content .tabs ul li { margin-inline-end: 0; margin-block-end: 0; }
|
|
#content .tabs ul li a, #content .tabs ul li a:hover {
|
|
position: relative;
|
|
padding-block: 14px;
|
|
padding-inline: 16px;
|
|
border: 0;
|
|
border-radius: 0;
|
|
background-color: transparent;
|
|
box-shadow: none;
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
font: var(--md-sys-typescale-title-small);
|
|
letter-spacing: var(--md-sys-typescale-title-small-tracking);
|
|
}
|
|
#content .tabs ul li a:hover { background-image: var(--nm-state-hover); color: var(--md-sys-color-on-surface); }
|
|
#content .tabs ul li a.selected, #content .tabs ul li a.selected:hover {
|
|
background-color: transparent;
|
|
border: 0;
|
|
box-shadow: inset 0 -2px 0 var(--md-sys-color-primary);
|
|
color: var(--md-sys-color-on-surface);
|
|
}
|
|
/* Scroll arrows for tabs that overflow: standard icon buttons at the end of the tab row */
|
|
#content .tabs div.tabs-buttons {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: end;
|
|
gap: 4px;
|
|
inline-size: auto;
|
|
block-size: 48px;
|
|
padding-inline-start: 8px;
|
|
box-sizing: border-box;
|
|
background: var(--md-sys-color-surface);
|
|
border-block-end: 1px solid var(--md-sys-color-outline-variant);
|
|
}
|
|
#content .tabs button.tab-left, #content .tabs button.tab-right,
|
|
#main-menu button.tab-left, #main-menu button.tab-right {
|
|
position: static;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
inline-size: 40px;
|
|
block-size: 40px;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background-color: transparent;
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
}
|
|
:is(#content .tabs, #main-menu) button:is(.tab-left, .tab-right) svg.icon-svg { stroke: currentColor; }
|
|
:is(#content .tabs, #main-menu) button:is(.tab-left, .tab-right):hover { background-image: var(--nm-state-hover); }
|
|
:is(#content .tabs, #main-menu) button:is(.tab-left, .tab-right).disabled {
|
|
background: transparent;
|
|
color: color-mix(in srgb, var(--md-sys-color-on-surface) var(--md-sys-state-disabled-content-opacity), transparent);
|
|
}
|
|
|
|
/***** Badges *****/
|
|
.badge {
|
|
inset-block-end: 2px;
|
|
padding-block: 2px;
|
|
padding-inline: 6px;
|
|
border-radius: var(--md-sys-shape-corner-small);
|
|
font: var(--md-sys-typescale-label-small);
|
|
letter-spacing: var(--md-sys-typescale-label-small-tracking);
|
|
}
|
|
.badge-private { background: var(--md-sys-color-error); border-color: var(--md-sys-color-error); color: var(--md-sys-color-on-error); }
|
|
.badge-count, .badge-issues-count {
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background: var(--md-sys-color-secondary-container);
|
|
color: var(--md-sys-color-on-secondary-container);
|
|
}
|
|
.badge-status-open { border-color: var(--md-sys-color-primary); color: var(--md-sys-color-primary); }
|
|
.badge-status-closed { border-color: var(--md-sys-color-success); color: var(--md-sys-color-success); }
|
|
.badge-status-locked { border-color: var(--md-sys-color-outline); color: var(--md-sys-color-on-surface-variant); }
|
|
|
|
/***** Pagination *****/
|
|
span.pagination { margin-inline-start: 0; color: var(--md-sys-color-on-surface-variant); }
|
|
.pagination ul.pages { margin-inline: 0 8px; }
|
|
.pagination ul.pages li,
|
|
.pagination ul.pages li:first-child,
|
|
.pagination ul.pages li:last-child {
|
|
margin-inline-end: 4px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
line-height: 40px;
|
|
min-inline-size: 40px;
|
|
}
|
|
.pagination ul.pages li a, .pagination ul.pages li span {
|
|
display: block;
|
|
padding-block: 0;
|
|
padding-inline: 12px;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
}
|
|
.pagination ul.pages li.page:hover { background-color: transparent; background-image: var(--nm-state-hover); }
|
|
.pagination ul.pages li.page a:hover { color: var(--md-sys-color-on-surface); text-decoration: none; }
|
|
.pagination ul.pages li.current {
|
|
background-color: var(--md-sys-color-secondary-container);
|
|
color: var(--md-sys-color-on-secondary-container);
|
|
font-weight: 500;
|
|
}
|
|
.pagination ul.pages li.current span { color: inherit; }
|
|
|
|
/***** Linear progress *****/
|
|
table.progress { border-radius: var(--md-sys-shape-corner-full); overflow: hidden; }
|
|
table.progress td { block-size: 4px; padding: 0; }
|
|
.version-overview table.progress td { block-size: 8px; }
|
|
table.progress td.closed { background: var(--md-sys-color-primary); }
|
|
table.progress td.done { background: color-mix(in srgb, var(--md-sys-color-primary) 55%, var(--md-sys-color-surface-container-highest)); }
|
|
/* Not secondary-container: at medium/high contrast it is dark and the empty track looks filled */
|
|
table.progress td.todo { background: var(--md-sys-color-surface-container-highest); }
|
|
|
|
/***** Tooltips (plain) *****/
|
|
/* jQuery UI also adds .ui-widget.ui-widget-content, which would win over a bare .ui-tooltip. */
|
|
.ui-tooltip.ui-widget.ui-widget-content {
|
|
background: var(--md-sys-color-inverse-surface);
|
|
color: var(--md-sys-color-inverse-on-surface);
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-extra-small);
|
|
box-shadow: none;
|
|
font: var(--md-sys-typescale-body-small);
|
|
letter-spacing: var(--md-sys-typescale-body-small-tracking);
|
|
padding-block: 4px;
|
|
padding-inline: 8px;
|
|
}
|
|
|
|
/***** Tooltips (rich): calendar and Gantt issue hover cards *****/
|
|
div.tooltip:hover span.tip {
|
|
inline-size: 300px;
|
|
background-color: var(--md-sys-color-surface-container);
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-medium);
|
|
box-shadow: var(--md-sys-elevation-level2);
|
|
padding-block: 12px;
|
|
padding-inline: 16px;
|
|
font: var(--md-sys-typescale-body-medium);
|
|
letter-spacing: var(--md-sys-typescale-body-medium-tracking);
|
|
}
|
|
div.tooltip span.tip strong { color: var(--md-sys-color-on-surface); font-weight: 500; }
|
|
div.tooltip span.tip .avatar { vertical-align: middle; }
|
|
/* Structured by theme.js (structureTip): title block, then a label/value grid. */
|
|
div.tooltip span.nm-tip .nm-tip__title {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
margin-block-end: 12px;
|
|
}
|
|
div.tooltip span.nm-tip .nm-tip__title > a {
|
|
font: var(--md-sys-typescale-label-medium);
|
|
letter-spacing: var(--md-sys-typescale-label-medium-tracking);
|
|
text-decoration: none;
|
|
}
|
|
div.tooltip span.nm-tip .nm-tip__title > span {
|
|
color: var(--md-sys-color-on-surface);
|
|
font: var(--md-sys-typescale-title-small);
|
|
letter-spacing: var(--md-sys-typescale-title-small-tracking);
|
|
}
|
|
div.tooltip span.nm-tip .nm-tip__fields {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 4px 16px;
|
|
align-items: center;
|
|
}
|
|
div.tooltip span.nm-tip .nm-tip__fields > strong {
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
font: var(--md-sys-typescale-label-medium);
|
|
letter-spacing: var(--md-sys-typescale-label-medium-tracking);
|
|
}
|
|
div.tooltip span.nm-tip .nm-tip__fields > span {
|
|
color: var(--md-sys-color-on-surface);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
min-inline-size: 0;
|
|
}
|
|
|
|
/***** jQuery UI: dialogs, date picker, menus *****/
|
|
.ui-widget, .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: var(--md-ref-typeface-plain); }
|
|
.ui-widget.ui-widget-content, .ui-widget-content {
|
|
background: var(--md-sys-color-surface-container-high);
|
|
border-color: var(--md-sys-color-outline-variant);
|
|
color: var(--md-sys-color-on-surface);
|
|
}
|
|
.ui-widget-content a { color: var(--md-sys-color-primary); }
|
|
.ui-dialog.ui-widget.ui-widget-content {
|
|
padding: 8px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-extra-large);
|
|
box-shadow: var(--md-sys-elevation-level3);
|
|
}
|
|
.ui-widget-header {
|
|
background: transparent;
|
|
border: 0;
|
|
color: var(--md-sys-color-on-surface);
|
|
}
|
|
.ui-dialog .ui-dialog-titlebar { padding-block: 16px 8px; padding-inline: 16px; }
|
|
.ui-dialog .ui-dialog-title { font: var(--md-sys-typescale-headline-small); }
|
|
.ui-dialog .ui-dialog-content { padding-inline: 16px; }
|
|
.ui-dialog .ui-dialog-titlebar-close {
|
|
inline-size: 40px;
|
|
block-size: 40px;
|
|
margin-block-start: -20px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background: transparent;
|
|
}
|
|
.ui-widget-overlay { background: var(--md-sys-color-scrim); opacity: 32%; }
|
|
|
|
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
|
|
background: transparent;
|
|
border-color: transparent;
|
|
color: var(--md-sys-color-on-surface);
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
}
|
|
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus {
|
|
background: color-mix(in srgb, var(--md-sys-color-on-surface) var(--md-sys-state-hover-state-layer-opacity), transparent);
|
|
border-color: transparent;
|
|
color: var(--md-sys-color-on-surface);
|
|
}
|
|
.ui-state-highlight, .ui-widget-content .ui-state-highlight {
|
|
background: transparent;
|
|
border: 1px solid var(--md-sys-color-primary);
|
|
color: var(--md-sys-color-primary);
|
|
}
|
|
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {
|
|
background: var(--md-sys-color-primary);
|
|
border-color: var(--md-sys-color-primary);
|
|
color: var(--md-sys-color-on-primary);
|
|
}
|
|
.ui-datepicker { padding: 12px; border-radius: var(--md-sys-shape-corner-large); box-shadow: var(--md-sys-elevation-level3); }
|
|
.ui-datepicker th { color: var(--md-sys-color-on-surface-variant); font: var(--md-sys-typescale-body-small); }
|
|
.ui-datepicker td a, .ui-datepicker td span { text-align: center; padding: 6px; }
|
|
|
|
.ui-autocomplete, .ui-menu, .tribute-container ul {
|
|
background: var(--md-sys-color-surface-container);
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-extra-small);
|
|
box-shadow: var(--md-sys-elevation-level2);
|
|
color: var(--md-sys-color-on-surface);
|
|
padding-block: 8px;
|
|
}
|
|
.ui-menu .ui-menu-item-wrapper.ui-state-active, .tribute-container li.highlight {
|
|
margin: 0;
|
|
background: var(--md-sys-color-secondary-container);
|
|
border-color: transparent;
|
|
color: var(--md-sys-color-on-secondary-container);
|
|
}
|
|
|
|
/***** Icons *****/
|
|
/* The theme sprite (images/icons.svg) draws Material Symbols with fill="currentColor",
|
|
so icon color comes from `color`. Core's `stroke` rules still style plugin icons. */
|
|
svg.icon-svg { color: var(--md-sys-color-on-surface-variant); }
|
|
a.icon .icon-svg, a.icon-only .icon-svg, span.icon-actions .icon-svg, a .icon-svg { color: var(--md-sys-color-primary); }
|
|
a.icon:hover .icon-svg, a.icon-only:hover .icon-svg, span.icon-actions:hover .icon-svg { color: var(--md-sys-color-on-surface); }
|
|
.icon-ok svg.icon-svg { color: var(--md-sys-color-success); }
|
|
.icon-error svg.icon-svg { color: var(--md-sys-color-error); }
|
|
.icon-warning svg.icon-svg { color: var(--md-sys-color-warning); }
|
|
div.flash svg.icon-svg, #errorExplanation svg.icon-svg, .conflict svg.icon-svg,
|
|
.top-menu__links svg.icon-svg, #account .dropdown-trigger .icon-svg,
|
|
#main-menu svg.icon-svg, #sidebar :is(a.selected, .icon-clear-query) svg.icon-svg, .drdn-items svg.icon-svg { color: inherit; }
|
|
html .context-menu-selection svg.icon-svg { color: var(--md-sys-color-on-secondary-container) !important; }
|
|
|
|
/***** Wiki toolbar (jstoolbar.css loads after the theme) *****/
|
|
/* Core draws the buttons as fixed-color background images, unreadable in dark mode.
|
|
The same SVGs are used as masks here, filled with currentColor. */
|
|
html .jstElements { block-size: auto; padding-block-end: 4px; }
|
|
html .jstElements button {
|
|
position: relative;
|
|
inline-size: 32px;
|
|
block-size: 32px;
|
|
margin-inline-end: 0;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background-color: transparent;
|
|
background-image: none;
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
opacity: 1;
|
|
vertical-align: middle;
|
|
}
|
|
html .jstElements button:hover { background-color: color-mix(in srgb, currentColor var(--md-sys-state-hover-state-layer-opacity), transparent); color: var(--md-sys-color-on-surface); }
|
|
html .jstElements button::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 7px;
|
|
background-color: currentColor;
|
|
mask: var(--nm-jst-icon) center / contain no-repeat;
|
|
}
|
|
html .jstElements button.jstb_pre::after { display: none; }
|
|
html .jstb_pre::before { color: currentColor; font: var(--md-sys-typescale-label-small); }
|
|
html .jstSpacer { margin-inline-end: 8px; }
|
|
html .jstb_strong { --nm-jst-icon: url(/jstoolbar/bold.svg); }
|
|
html .jstb_em { --nm-jst-icon: url(/jstoolbar/italic.svg); }
|
|
html .jstb_ins { --nm-jst-icon: url(/jstoolbar/underline.svg); }
|
|
html .jstb_del { --nm-jst-icon: url(/jstoolbar/strikethrough.svg); }
|
|
html .jstb_code { --nm-jst-icon: url(/jstoolbar/letter-c.svg); }
|
|
html .jstb_h1 { --nm-jst-icon: url(/jstoolbar/h1.svg); }
|
|
html .jstb_h2 { --nm-jst-icon: url(/jstoolbar/h2.svg); }
|
|
html .jstb_h3 { --nm-jst-icon: url(/jstoolbar/h3.svg); }
|
|
html .jstb_ul { --nm-jst-icon: url(/jstoolbar/list.svg); }
|
|
html .jstb_ol { --nm-jst-icon: url(/jstoolbar/list-numbers.svg); }
|
|
html .jstb_tl { --nm-jst-icon: url(/jstoolbar/list-check.svg); }
|
|
html .jstb_bq { --nm-jst-icon: url(/jstoolbar/indent-increase.svg); }
|
|
html .jstb_unbq { --nm-jst-icon: url(/jstoolbar/indent-decrease.svg); }
|
|
html .jstb_precode { --nm-jst-icon: url(/jstoolbar/code.svg); }
|
|
html .jstb_link { --nm-jst-icon: url(/jstoolbar/wiki_link.svg); }
|
|
html .jstb_img { --nm-jst-icon: url(/jstoolbar/image.svg); }
|
|
html .jstb_table { --nm-jst-icon: url(/jstoolbar/table.svg); }
|
|
html .jstb_help { --nm-jst-icon: url(/jstoolbar/help.svg); }
|
|
html .wiki-preview { background-color: transparent; color: var(--md-sys-color-on-surface); border-color: var(--md-sys-color-outline-variant); border-radius: var(--md-sys-shape-corner-extra-small); }
|
|
html .table-generator td { background-color: var(--md-sys-color-surface-container-high); border-color: var(--md-sys-color-outline); }
|
|
html .table-generator td.selected-cell, html .table-generator td:hover { background-color: var(--md-sys-color-primary-container); }
|
|
|
|
/***** Appearance picker (added by javascripts/theme.js to the profile menu and mobile flyout) *****/
|
|
.nm-appearance { padding-block: 8px 12px; padding-inline: 12px; }
|
|
.nm-appearance__title {
|
|
margin-block-end: 8px;
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
font: var(--md-sys-typescale-label-medium);
|
|
letter-spacing: var(--md-sys-typescale-label-medium-tracking);
|
|
}
|
|
/* M3 segmented button */
|
|
.nm-segmented { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; margin-block-end: 12px; } /* equal segments */
|
|
.nm-segmented button {
|
|
border-radius: 0;
|
|
block-size: 32px;
|
|
padding-inline: 8px;
|
|
border: 1px solid var(--md-sys-color-outline);
|
|
background: transparent;
|
|
color: var(--md-sys-color-on-surface);
|
|
font: var(--md-sys-typescale-label-large);
|
|
cursor: pointer;
|
|
}
|
|
.nm-segmented button + button { margin-inline-start: -1px; }
|
|
.nm-segmented button:first-child { border-start-start-radius: var(--md-sys-shape-corner-full); border-end-start-radius: var(--md-sys-shape-corner-full); }
|
|
.nm-segmented button:last-child { border-start-end-radius: var(--md-sys-shape-corner-full); border-end-end-radius: var(--md-sys-shape-corner-full); }
|
|
.nm-segmented button:hover { background-image: var(--nm-state-hover); }
|
|
.nm-segmented button[aria-pressed="true"] { background-color: var(--md-sys-color-secondary-container); color: var(--md-sys-color-on-secondary-container); }
|
|
/* Color swatches: the selected one gets a ring */
|
|
.nm-swatches { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; }
|
|
.nm-swatch {
|
|
flex-shrink: 0;
|
|
inline-size: 28px;
|
|
block-size: 28px;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background: var(--nm-swatch);
|
|
cursor: pointer;
|
|
}
|
|
/* Custom color: a native color input stretched invisibly over a rainbow (or the picked color) swatch */
|
|
/* label.: beats core label.no-css { inline-size: auto } (the class keeps .tabular label styles off) */
|
|
label.nm-swatch--custom { position: relative; inline-size: 28px; background: var(--nm-swatch, conic-gradient(#e53935, #fdd835, #43a047, #1e88e5, #8e24aa, #e53935)); }
|
|
.nm-swatch--custom input { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; padding: 0; border: 0; opacity: 0; cursor: pointer; }
|
|
.nm-swatch--custom:focus-within { outline: 2px solid var(--md-sys-color-primary); outline-offset: 2px; }
|
|
/* theme.js lazy-loads the scheme generator from here; Redmine rewrites url() to the digested path */
|
|
:root { --nm-scheme-js: url(./scheme.js); }
|
|
.nm-swatch[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--md-sys-color-surface-container), 0 0 0 4px var(--md-sys-color-on-surface); }
|
|
/* Reset to default: M3 text button, shown once the user changed something */
|
|
.nm-appearance__reset {
|
|
margin-block-start: 12px;
|
|
block-size: 32px;
|
|
padding-inline: 12px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background: transparent;
|
|
color: var(--md-sys-color-primary);
|
|
font: var(--md-sys-typescale-label-large);
|
|
cursor: pointer;
|
|
}
|
|
.nm-appearance__reset:hover { background-image: var(--nm-state-hover); }
|
|
/* Default appearance on Administration > Settings > Display (redmine_tonalmine plugin) */
|
|
.nm-appearance--default { max-inline-size: 280px; padding: 0; }
|
|
/* Each group is its own form row: 40px tall like the fields (M3 segmented button height), so
|
|
the label lines up; the row padding spaces them */
|
|
.nm-appearance--default .nm-segmented { margin: 0; }
|
|
.nm-appearance--default .nm-segmented button { block-size: 40px; margin-block: 0; }
|
|
.nm-appearance--default .nm-swatches { min-block-size: 40px; align-items: center; }
|
|
/* The custom swatch is a <label class="no-css">; also undo .tabular.settings label margins and mobile full width */
|
|
html .tabular label.nm-swatch--custom { display: block; margin: 0; inline-size: 28px; }
|
|
html .flyout-menu .nm-appearance { padding-inline: 16px; }
|
|
html .flyout-menu .nm-appearance__title { color: var(--md-sys-color-on-surface-variant); }
|
|
|
|
/***** Loading indicator: an M3 snackbar-style chip on inverse surface *****/
|
|
#ajax-indicator {
|
|
inline-size: auto;
|
|
padding-block: 12px;
|
|
padding-inline: 16px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-extra-small);
|
|
background-color: var(--md-sys-color-inverse-surface);
|
|
color: var(--md-sys-color-inverse-on-surface);
|
|
box-shadow: var(--md-sys-elevation-level3);
|
|
font: var(--md-sys-typescale-body-medium);
|
|
opacity: 1;
|
|
}
|
|
|
|
/***** Code block copy button and dragged table rows *****/
|
|
div.pre-wrapper a.copy-pre-content-link {
|
|
padding: 4px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background-color: var(--md-sys-color-surface-container-high);
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
}
|
|
tr.ui-sortable-helper { border-color: var(--md-sys-color-outline-variant); box-shadow: var(--md-sys-elevation-level2); }
|