411 lines
10 KiB
CSS
411 lines
10 KiB
CSS
/**
|
|
* Side card settings section chrome (DSH-native tokens throughout):
|
|
* - the section is a column of GROUP CONTAINER cards (the PluginCard recipe:
|
|
* l2 hairline, 16px radius, layer-3 fill) with a heading + inventory count
|
|
* badge (the settings catalogHeading recipe), opening with a one-line
|
|
* intro (the DSH section heading+intro recipe);
|
|
* - 常规 holds full-width settings rows (the DSH settings-row recipe:
|
|
* title/desc left + control right, hairline separators) whose toggles are
|
|
* custom switches — a real checkbox (native semantics and focus) driving
|
|
* a styled track/thumb;
|
|
* - the feature inventories are responsive GRIDS of small toggle cards
|
|
* (auto-fill columns — several cards per row, wrapping): icon chip +
|
|
* title + type id, the card's on/off state IS its visual state
|
|
* (enabled = brand border + tinted fill + circular check badge,
|
|
* disabled = neutral hairline + dimmed);
|
|
* - features that declare related settings carry a gear corner button
|
|
* opening a native Modal (wider than the primitive default) whose rows
|
|
* follow the same row recipe with switch controls and a Done footer;
|
|
* - the width input stays a native settings row (a value, not a switch).
|
|
*/
|
|
|
|
.section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 14px;
|
|
width: 100%;
|
|
/* Tall inventories (7 tab cards + 9 viewer cards + general rows) must
|
|
never be clipped by the settings shell: fill the shell's options area
|
|
and scroll inside the section when the content outgrows the panel. */
|
|
height: 100%;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
/* One-line section intro (the DSH section heading+intro recipe). */
|
|
.intro {
|
|
margin: 0;
|
|
padding: 0 2px;
|
|
font-size: 13px;
|
|
line-height: 20px;
|
|
color: var(--dsw-alias-label-tertiary);
|
|
}
|
|
|
|
/* Group container: the DSH card recipe (PluginCard) — l2 hairline, r16,
|
|
layer-3 fill; holds its own heading + stacked rows / card grid. */
|
|
.group {
|
|
flex: none;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
padding: 18px 20px 20px;
|
|
box-sizing: border-box;
|
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
border-radius: 16px;
|
|
background: var(--dsw-alias-bg-layer-3);
|
|
}
|
|
|
|
/* Group heading: 13/600 + the inventory count badge (the settings
|
|
catalogHeading recipe: count in tabular-nums, tertiary). */
|
|
.groupHeading {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 7px;
|
|
padding: 0 2px 6px;
|
|
font-size: 13px;
|
|
line-height: 20px;
|
|
font-weight: 600;
|
|
color: var(--dsw-alias-label-primary);
|
|
}
|
|
|
|
.count {
|
|
font-size: 12px;
|
|
line-height: 18px;
|
|
font-weight: 400;
|
|
color: var(--dsw-alias-label-tertiary);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* Responsive inventory: as many small cards per row as the width allows. */
|
|
.grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
|
|
gap: 10px;
|
|
}
|
|
|
|
/* One small toggle card (visual chrome; the interactive part is .cardMain). */
|
|
.card {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
border-radius: 12px;
|
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
background: transparent;
|
|
font: inherit;
|
|
color: inherit;
|
|
cursor: pointer;
|
|
transition: background 0.12s ease, border-color 0.12s ease;
|
|
}
|
|
|
|
/* Hover affordance on disabled cards only (enabled cards are already lit). */
|
|
.card:not(.cardOn):hover {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
border-color: var(--dsw-alias-label-dimmed);
|
|
}
|
|
|
|
/* Enabled = highlighted: brand border + tinted fill. */
|
|
.cardOn {
|
|
border-color: var(--dsw-alias-button-primary-fill);
|
|
background: var(--dsw-alias-interactive-bg-active);
|
|
}
|
|
|
|
/* The card's switch: the whole main area (top row + desc) flips the feature. */
|
|
.cardMain {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
width: 100%;
|
|
padding: 12px;
|
|
border: 0;
|
|
border-radius: inherit;
|
|
background: transparent;
|
|
font: inherit;
|
|
color: inherit;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cardMain:focus-visible,
|
|
.cardGear:focus-visible {
|
|
outline: 2px solid var(--dsw-alias-border-l4);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
.cardTop {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
}
|
|
|
|
/* The icon sits in a rounded chip: brand-tinted while the card is on,
|
|
neutral (layer-2 fill + hairline) while off. */
|
|
.cardIconChip {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 8px;
|
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
background: var(--dsw-alias-bg-layer-2);
|
|
color: var(--dsw-alias-label-tertiary);
|
|
}
|
|
|
|
.cardOn .cardIconChip {
|
|
border-color: color-mix(in srgb, var(--dsw-alias-button-primary-fill) 35%, transparent);
|
|
background: color-mix(in srgb, var(--dsw-alias-button-primary-fill) 12%, transparent);
|
|
color: var(--dsw-alias-button-primary-fill);
|
|
}
|
|
|
|
.cardTitle {
|
|
flex: 1;
|
|
min-width: 0;
|
|
font-size: 13px;
|
|
line-height: 20px;
|
|
font-weight: 600;
|
|
color: var(--dsw-alias-label-secondary);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.cardOn .cardTitle {
|
|
color: var(--dsw-alias-label-primary);
|
|
}
|
|
|
|
/* The check badge: a circular brand-filled pin at the card's far right
|
|
(enabled only), the icon in the inverted surface token (the .save recipe). */
|
|
.cardCheck {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: 50%;
|
|
background: var(--dsw-alias-button-primary-fill);
|
|
color: var(--dsw-alias-bg-layer-3);
|
|
}
|
|
|
|
.cardDesc {
|
|
font-size: 11px;
|
|
line-height: 16px;
|
|
color: var(--dsw-alias-label-tertiary);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.cardOn .cardDesc {
|
|
color: var(--dsw-alias-label-secondary);
|
|
}
|
|
|
|
/* Cards with a settings gear keep the desc clear of it: the gear sits in
|
|
the desc row, sharing the check badge's right edge (a vertical column of
|
|
controls at the card's right side). */
|
|
.cardWithGear .cardDesc {
|
|
padding-right: 30px;
|
|
}
|
|
|
|
/* The gear corner button: directly UNDER the check badge on the card's
|
|
right edge — the two controls are vertically aligned (same right inset,
|
|
one row apart) and the SAME 16px size, not side by side. */
|
|
.cardGear {
|
|
position: absolute;
|
|
right: 12px;
|
|
top: 46px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 16px;
|
|
height: 16px;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: 50%;
|
|
background: transparent;
|
|
color: var(--dsw-alias-label-tertiary);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cardGear:hover {
|
|
color: var(--dsw-alias-label-primary);
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|
|
/* Settings-row recipe (the DSH General section rows): title/desc left,
|
|
control right, hairline separators (stripped on the last row). */
|
|
.row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
padding: 12px 2px;
|
|
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
|
}
|
|
|
|
.row:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.rowText {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.title {
|
|
font-size: 14px;
|
|
line-height: 22px;
|
|
color: var(--dsw-alias-label-primary);
|
|
}
|
|
|
|
.desc {
|
|
font-size: 12px;
|
|
line-height: 18px;
|
|
color: var(--dsw-alias-label-tertiary);
|
|
}
|
|
|
|
/* Custom switch: a real checkbox (native semantics + focus, visually
|
|
hidden) driving a styled 36x20 track with a sliding thumb. */
|
|
.switch {
|
|
position: relative;
|
|
display: inline-flex;
|
|
flex: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.switchInput {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
margin: 0;
|
|
opacity: 0;
|
|
}
|
|
|
|
.switchTrack {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
width: 36px;
|
|
height: 20px;
|
|
padding: 2px;
|
|
box-sizing: border-box;
|
|
border-radius: 10px;
|
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
background: var(--dsw-alias-bg-layer-1);
|
|
transition: background 0.15s ease, border-color 0.15s ease;
|
|
}
|
|
|
|
.switchThumb {
|
|
display: block;
|
|
width: 14px;
|
|
height: 14px;
|
|
border-radius: 50%;
|
|
background: var(--dsw-alias-label-secondary);
|
|
transition: transform 0.15s ease, background 0.15s ease;
|
|
}
|
|
|
|
.switch:hover .switchTrack {
|
|
border-color: var(--dsw-alias-label-dimmed);
|
|
}
|
|
|
|
.switchInput:checked + .switchTrack {
|
|
border-color: var(--dsw-alias-button-primary-fill);
|
|
background: var(--dsw-alias-button-primary-fill);
|
|
}
|
|
|
|
.switchInput:checked + .switchTrack .switchThumb {
|
|
transform: translateX(16px);
|
|
background: var(--dsw-alias-bg-layer-3);
|
|
}
|
|
|
|
.switchInput:focus-visible + .switchTrack {
|
|
outline: 2px solid var(--dsw-alias-state-business-primary);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
.control {
|
|
flex: none;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.percentInput {
|
|
width: 76px;
|
|
}
|
|
|
|
.suffix {
|
|
font-size: 14px;
|
|
line-height: 22px;
|
|
color: var(--dsw-alias-label-secondary);
|
|
}
|
|
|
|
/* Secondary settings popup: a wider dialog than the primitive default (the
|
|
dialog portals to document.body; the doubled class keeps the width rule
|
|
above the primitive's .dialog regardless of stylesheet order). */
|
|
.popupDialog.popupDialog {
|
|
width: min(460px, 100%);
|
|
}
|
|
|
|
/* Popup rows: the same settings-row recipe with switch controls. */
|
|
.popupRows {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: 100%;
|
|
}
|
|
|
|
.popupRow {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
padding: 14px 2px;
|
|
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
|
}
|
|
|
|
.popupRow:hover {
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
}
|
|
|
|
.popupRows > :last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
/* The popup's Done button: the settings primary-button recipe
|
|
(PluginCard .save: label-primary fill, inverted surface text). */
|
|
.done {
|
|
appearance: none;
|
|
border: 1px solid transparent;
|
|
border-radius: 8px;
|
|
padding: 5px 14px;
|
|
font: inherit;
|
|
font-size: 13px;
|
|
line-height: 1.5;
|
|
cursor: pointer;
|
|
background: var(--dsw-alias-label-primary);
|
|
color: var(--dsw-alias-bg-layer-3);
|
|
}
|
|
|
|
.done:focus-visible {
|
|
outline: 2px solid var(--dsw-alias-brand-primary);
|
|
outline-offset: 1px;
|
|
}
|
|
|
|
.error {
|
|
padding: 10px 0 2px;
|
|
font-size: 12px;
|
|
line-height: 17px;
|
|
color: var(--dsw-alias-state-error-primary);
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.card,
|
|
.switchTrack,
|
|
.switchThumb {
|
|
transition: none;
|
|
}
|
|
}
|