mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-10 18:34:18 +08:00
220 lines
14 KiB
CSS
220 lines
14 KiB
CSS
@layer page {
|
|
/* The Appearance controls, appended to System -> System by fs-appearance.js.
|
|
*
|
|
* This was a popover on <body>, capped to the viewport because eighteen axes plus an upload
|
|
* panel do not fit a floating card on a phone in landscape. As part of a page none of that
|
|
* applies: the sections are ordinary .cbi-section cards, the width is the content column's and
|
|
* the scroll is the document's — so the placement, the max-height clamp, the fade-in and the
|
|
* [hidden] pair a floating card needed are all gone.
|
|
*
|
|
* What is left in the theme's own namespace — the `.fs-ap-*` folds, sections, previews and
|
|
* version line below — lives in the page layer rather than the theme layer, because this is
|
|
* the only page that draws it: an axis control is not chrome. */
|
|
|
|
.fs-ap { display: flex; flex-direction: column; gap: var(--fs-space-5); }
|
|
/* The page note (fs-appearance.js). Only the outer margins: `.alert-message p` carries
|
|
* --fs-space-1 top and bottom, which at the box's own edges adds to the panel's padding and
|
|
* makes a two-sentence note look loose against every other alert on the theme. */
|
|
.fs-ap-note p:first-child { margin-top: 0; }
|
|
.fs-ap-note p:last-child { margin-bottom: 0; }
|
|
/* Grouping headings INSIDE the tab pane, not cards: the pane is already inside the stock
|
|
* .cbi-section card, and a second border around each group is a box in a box. A hairline above
|
|
* each group does the same job — except for the first, which sits under the tab strip. */
|
|
/* the heading row. On a plain group it holds the title; on a FOLDED one the whole row is the
|
|
* disclosure button (fs-appearance.js) — full width, so the target is the heading rather than a
|
|
* chevron nobody can hit on a phone. */
|
|
/* the heading row spans the section on its own now that the rows stack */
|
|
button.fs-ap-fold {
|
|
display: flex; align-items: center; justify-content: space-between; gap: var(--fs-space-3);
|
|
inline-size: 100%; padding: 0; margin: 0;
|
|
background: none; border: 0; cursor: pointer; text-align: start; color: inherit;
|
|
}
|
|
button.fs-ap-fold:hover h4 { color: var(--fs-accent); }
|
|
button.fs-ap-fold:focus-visible { outline: none; box-shadow: var(--fs-focus-ring-solo); border-radius: var(--fs-radius-sm); }
|
|
/* The chevron: the same box with a two-border ::after that the overview's card toggles use
|
|
* (styles/pages/20-overview.css) — one
|
|
* chevron for "this panel opens", drawn here and there rather than an SVG in one place and
|
|
* borders in the other, with the glyph pinned as @mirror chevron/* so the copies cannot drift.
|
|
*
|
|
* It turns on the SAME attribute that tells a screen reader the state, so the two cannot
|
|
* disagree. Rotated with `transform` rather than the individual `rotate` property, because that
|
|
* is what the overview's copy does and the pair must look identical mid-animation. */
|
|
.fs-ap-chev {
|
|
flex: 0 0 auto; inline-size: 26px; block-size: 26px;
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
color: var(--fs-dim); border-radius: var(--fs-radius-sm);
|
|
}
|
|
.fs-ap-chev::after {
|
|
/* @mirror chevron/closed */
|
|
content: "";
|
|
width: 7px;
|
|
height: 7px;
|
|
border-right: 2px solid currentColor;
|
|
border-bottom: 2px solid currentColor;
|
|
border-radius: 1px;
|
|
transform: rotate(45deg); /* closed: chevron down */
|
|
margin-top: -2px; /* optical centring of the down chevron */
|
|
transition: transform var(--fs-dur-move);
|
|
/* @endmirror */
|
|
}
|
|
button.fs-ap-fold[aria-expanded="true"] .fs-ap-chev::after {
|
|
/* @mirror chevron/open */
|
|
transform: rotate(-135deg); /* open: chevron up */
|
|
margin-top: var(--fs-space-0-5);
|
|
/* @endmirror */
|
|
}
|
|
button.fs-ap-fold:hover .fs-ap-chev { color: var(--fs-accent); }
|
|
/* Stock `.cbi-value` rows stack one per line and carry their own hairline, so a folded group needs
|
|
* no layout of its own — it lays its rows out exactly like an unfolded section by doing nothing. */
|
|
/* `hidden` is what keeps a closed group out of the tab order and the a11y tree, and
|
|
* base/10-reset.css is what makes the attribute win over a class's `display` — for every
|
|
* element, not just this one, so there is nothing to restate here. */
|
|
/* the second heading inside the Colours fold — Surfaces shares the fold, not the heading. It
|
|
* wears the SAME .fs-ap-head h4 as every other section title now; a third heading style on one
|
|
* page (h4, folded h4, uppercase eyebrow h5) was a third of the raggedness. Only the space
|
|
* above it is its own. */
|
|
.fs-ap-sub { margin-top: var(--fs-space-4); }
|
|
.fs-ap-head h4 {
|
|
margin: 0;
|
|
font-size: var(--fs-type); font-weight: var(--fs-weight-bold); color: var(--fs-text);
|
|
}
|
|
.fs-ap-section + .fs-ap-section { padding-top: var(--fs-space-4); border-top: var(--fs-hairline); }
|
|
/* The rows are stock `.cbi-value` and this page states no layout for them at all: caption column,
|
|
* field column and the hairline between rows come from base/30-forms.css and theme/60-inputs.css,
|
|
* the rules every other LuCI form is drawn by. What stood here was a responsive two-column grid
|
|
* of stacked cards with an uppercase eyebrow above each control: it fitted a floating popover,
|
|
* and beside General Settings / Language and Style it made the theme's own tab the one page in
|
|
* LuCI that did not look like LuCI. Deleting that grid is the change — do not restate a layout
|
|
* for these rows. */
|
|
/* The accordion switch is meaningless in the top layout — its sections are hover dropdowns,
|
|
* already exclusive. Hidden HERE, not by a branch in the JS: the page is built once, so a branch
|
|
* froze the control to whatever layout it loaded in and the live toggle could never change it. */
|
|
:root[data-layout="top"] .fs-ap-submenus { display: none; }
|
|
|
|
/* Save-as-default / Reset row: two equal buttons, no status text — the Save button's own
|
|
* label/disabled state is the status. They take their look from .btn / .cbi-button-action
|
|
* (base + theme/55-buttons.css); a disabled .cbi-button-action already greys via base. */
|
|
/* Buttons take the width of their own label, which is what every button on every other LuCI page
|
|
* does — they were `flex: 1 1 9em` and stretched to fill the field, so three of them made one
|
|
* long bar and "Choose SVG"/"Remove" each ran half the card. `wrap` keeps a narrow card honest:
|
|
* an item that cannot fit moves to the next line instead of hanging past the edge, which on a
|
|
* flex row is silent. */
|
|
.fs-ap-actrow { display: flex; flex-wrap: wrap; gap: var(--fs-space-2); }
|
|
/* Save and the two resets differ by one word and sit in one row, which is the shape a
|
|
* destructive click lands on by accident. The gap says they are two groups; both resets also
|
|
* ask for a second click. Zero-width, so it costs no height when the row wraps on a phone. */
|
|
.fs-ap-actgap { flex: 0 0 var(--fs-space-4); }
|
|
.fs-ap-actrow .btn { font-size: var(--fs-type); padding: var(--fs-space-2) var(--fs-space-2-5); cursor: pointer; }
|
|
.fs-ap-actrow .btn:disabled { cursor: default; }
|
|
/* the primed Reset (second click confirms) reads as the destructive action it is */
|
|
.fs-ap-armed { color: var(--fs-on-danger); background: var(--fs-danger); border-color: transparent; }
|
|
/* Save's only visible failure line (a rejected save rpc — usually a stale session) — shown in
|
|
* place of the absent status text, hidden until a save actually fails. */
|
|
.fs-ap-err { margin-top: var(--fs-space-2); font-size: var(--fs-type-xs); line-height: 1.35; color: var(--fs-danger); }
|
|
|
|
/* ---- the colour axes ----
|
|
* One row is a swatch, a hex field and the button back to the palette's own colour. */
|
|
/* the same ceiling every other stretching control in a form row takes (02-tokens.css), so the
|
|
* swatch + hex + Palette button end where the selects and the sliders end */
|
|
.fs-colorctl { display: flex; flex-direction: column; gap: var(--fs-space-1-5); max-width: var(--fs-field-max); }
|
|
.fs-color-row { display: flex; align-items: center; gap: var(--fs-space-2); }
|
|
/* The native colour swatch. type="color" is drawn by the browser and cannot be restyled beyond
|
|
* its box, so the box is what is styled: the inner well is stripped to the frame's edge on both
|
|
* engines (WebKit nests two elements, Firefox one) or it paints a white margin inside our
|
|
* border. Fixed 34px square so it lines up with the field beside it at every density. */
|
|
input[type="color"].fs-color-swatch {
|
|
flex: 0 0 auto; inline-size: 34px; block-size: 34px; padding: 0; cursor: pointer;
|
|
background: none; border: var(--fs-hairline); border-radius: var(--fs-radius-sm);
|
|
}
|
|
input[type="color"].fs-color-swatch::-webkit-color-swatch-wrapper { padding: 0; }
|
|
input[type="color"].fs-color-swatch::-webkit-color-swatch { border: 0; border-radius: calc(var(--fs-radius-sm) - 1px); }
|
|
input[type="color"].fs-color-swatch::-moz-color-swatch { border: 0; border-radius: calc(var(--fs-radius-sm) - 1px); }
|
|
/* the hex field is a VALUE, so it is mono and tabular like every other value in the theme —
|
|
* and #0969da is exactly the kind of string a proportional face makes hard to read back */
|
|
input[type="text"].fs-color-hex {
|
|
flex: 1 1 auto; min-inline-size: 0;
|
|
font-family: var(--fs-font-mono); font-size: var(--fs-type-xs); font-variant-numeric: tabular-nums;
|
|
text-transform: lowercase;
|
|
}
|
|
.fs-color-clear { flex: 0 0 auto; font-size: var(--fs-type-xs); padding: var(--fs-space-1-5) var(--fs-space-2); cursor: pointer; }
|
|
.fs-color-clear:disabled { cursor: default; }
|
|
|
|
/* What the chosen colour COSTS, measured live against the surface it is read on (fs-widgets'
|
|
* contrastRatio). It is a readout, not a validation: the theme derives readable ink over a fill
|
|
* but never silently corrects a colour the admin asked for, so this says the number and grades
|
|
* it. Three grades, three colours — and the failing one is --fs-danger, which the admin may have
|
|
* just recoloured, which is exactly the honest outcome. */
|
|
/* It is LuCI's own help-text line now — `.cbi-value-description`, styled in base/95-luci.css,
|
|
* which is where a sentence under a field belongs on every other page. What stays here is the
|
|
* only thing stock has no opinion about: the GRADE's colour, and the tabular figures that keep
|
|
* the ratio from jittering as it updates. */
|
|
.fs-color-contrast { font-variant-numeric: tabular-nums; }
|
|
.fs-contrast-aa { color: var(--fs-good); }
|
|
.fs-contrast-aa-large { color: var(--fs-warn); }
|
|
.fs-contrast-low { color: var(--fs-danger); }
|
|
|
|
/* THE PRESET CHIPS' rules were here — a wrapping row of pills, each painted in the accent it
|
|
* would set, with ink derived from that colour's own lightness. The control is gone from
|
|
* fs-appearance.js: it was the one thing on the page that looked like nothing else in LuCI, it
|
|
* started at the card's edge instead of at the field column, and everything it did the Accent
|
|
* row does with any colour rather than eight. */
|
|
|
|
/* The uploaded image's preview and the two buttons under it, both in an ordinary
|
|
* `.cbi-value-field`. The preview is a thumbnail, not a banner: capped to the same field ceiling
|
|
* as every other stretching control and to a fixed height, so the row keeps one shape whatever
|
|
* the image's aspect is — full width makes an SVG tile look like a letterboxed photograph. */
|
|
.fs-ap-bgprev {
|
|
display: block; width: 100%; max-width: var(--fs-field-max); height: 84px; object-fit: cover;
|
|
border: var(--fs-hairline); border-radius: var(--fs-radius);
|
|
/* the preview follows the buttons in the field, so the gap belongs ABOVE it */
|
|
margin-top: var(--fs-space-2);
|
|
}
|
|
.fs-ap-bgrow { display: flex; flex-wrap: wrap; gap: var(--fs-space-2); }
|
|
.fs-ap-bgrow .btn { font-size: var(--fs-type); padding: var(--fs-space-2) var(--fs-space-2-5); cursor: pointer; }
|
|
.fs-ap-bgrow .btn:disabled { cursor: default; }
|
|
/* The JS hides a row that does not apply to the chosen wallpaper, the empty preview and a
|
|
* not-yet-uploaded Remove with `el.hidden`; base/10-reset.css makes that attribute beat the
|
|
* `display` a class sets, so none of it needs restating here any more. */
|
|
/* Under the File wallpaper only the photo Dim is relevant — the router-identity Tint colours the
|
|
* canvas the photo covers, so hide the Tint hue AND its strength there (fs-ap-tint marks both). */
|
|
:root[data-wallpaper="file"] .fs-ap-tint { display: none; }
|
|
/* and the strength is a multiplier on a chroma WE choose, so it only means anything in hue mode:
|
|
* with the tint off there is nothing to scale, and on a hex canvas the colour is the one the
|
|
* admin entered. (0,3,0) out-ranks the stock row's own display. Not named after Density: that is
|
|
* the UI-density select four rows above, and one name for two rows is how the label itself went
|
|
* wrong. */
|
|
:root:not([data-tint="hue"]) .fs-ap-tintstr { display: none; }
|
|
|
|
/* the version line at the foot of the page */
|
|
.fs-ap-footer {
|
|
display: flex; flex-direction: column; gap: var(--fs-space-2);
|
|
margin-top: var(--fs-space-0-5); padding-top: var(--fs-space-2-5); border-top: var(--fs-hairline);
|
|
}
|
|
.fs-ap-verrow { display: flex; align-items: center; justify-content: space-between; gap: var(--fs-space-2-5); }
|
|
/* links to the project repo — reads as muted text until hovered */
|
|
.fs-ap-version { font-size: var(--fs-type-xs); color: var(--fs-dim); font-variant-numeric: tabular-nums; text-decoration: none; }
|
|
.fs-ap-version:hover { color: var(--fs-accent); text-decoration: underline; }
|
|
|
|
/* The line that names the missing catalogue package. Same weight as the version beside it —
|
|
* it is a fact about this router, not a warning: nothing is broken, one package is absent.
|
|
* Wraps, because the package name is 24 characters and the column is narrow at 390px. */
|
|
.fs-ap-i18n {
|
|
flex-wrap: wrap;
|
|
font-size: var(--fs-type-xs);
|
|
color: var(--fs-dim);
|
|
}
|
|
/* the chip is base/20-typography.css's `code`; only the size follows the line it sits in, which
|
|
* is a step smaller than body text */
|
|
.fs-ap-i18n code { font-size: inherit; }
|
|
|
|
/* No rules here for a segmented control or a range slider of our own: the page draws its enums
|
|
* with `ui.Select` and its numbers with `ui.RangeSlider`, which this theme already styles for
|
|
* every other LuCI form. Two copies of a slider, one of them ours, was the thing to delete. */
|
|
|
|
/* No rules here for a hue slider either: the control is gone from fs-widgets' colorControl, two
|
|
* controls for one value reading as two settings, and the half that could not reach a grey was
|
|
* the slider. The axis still stores a hue and 03-palettes.css still rotates by one, so a saved
|
|
* value goes on painting — but CSS for a control nobody renders is dead CSS in our own
|
|
* namespace, which `npm run css-orphans` exists to keep out. */
|
|
}
|