@multiplatform.one/keycloak-theme 7.83.1 → 7.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/cjs/SpringboardStyles.cjs +61 -0
  2. package/dist/cjs/SpringboardStyles.native.js +67 -0
  3. package/dist/cjs/SpringboardStyles.native.js.map +1 -0
  4. package/dist/cjs/css.cjs +555 -0
  5. package/dist/cjs/css.native.js +559 -0
  6. package/dist/cjs/css.native.js.map +1 -0
  7. package/dist/cjs/glyph.cjs +71 -0
  8. package/dist/cjs/glyph.native.js +75 -0
  9. package/dist/cjs/glyph.native.js.map +1 -0
  10. package/dist/cjs/index.cjs +53 -0
  11. package/dist/cjs/index.native.js +56 -0
  12. package/dist/cjs/index.native.js.map +1 -0
  13. package/dist/cjs/themeName.cjs +42 -0
  14. package/dist/cjs/themeName.native.js +45 -0
  15. package/dist/cjs/themeName.native.js.map +1 -0
  16. package/dist/cjs/tokens.cjs +133 -0
  17. package/dist/cjs/tokens.native.js +136 -0
  18. package/dist/cjs/tokens.native.js.map +1 -0
  19. package/dist/esm/SpringboardStyles.mjs +35 -0
  20. package/dist/esm/SpringboardStyles.mjs.map +1 -0
  21. package/dist/esm/SpringboardStyles.native.js +38 -0
  22. package/dist/esm/SpringboardStyles.native.js.map +1 -0
  23. package/dist/esm/css.mjs +530 -0
  24. package/dist/esm/css.mjs.map +1 -0
  25. package/dist/esm/css.native.js +531 -0
  26. package/dist/esm/css.native.js.map +1 -0
  27. package/dist/esm/glyph.mjs +42 -0
  28. package/dist/esm/glyph.mjs.map +1 -0
  29. package/dist/esm/glyph.native.js +43 -0
  30. package/dist/esm/glyph.native.js.map +1 -0
  31. package/dist/esm/index.mjs +7 -0
  32. package/dist/esm/index.mjs.map +1 -0
  33. package/dist/esm/index.native.js +7 -0
  34. package/dist/esm/index.native.js.map +1 -0
  35. package/dist/esm/themeName.mjs +15 -0
  36. package/dist/esm/themeName.mjs.map +1 -0
  37. package/dist/esm/themeName.native.js +15 -0
  38. package/dist/esm/themeName.native.js.map +1 -0
  39. package/dist/esm/tokens.mjs +98 -0
  40. package/dist/esm/tokens.mjs.map +1 -0
  41. package/dist/esm/tokens.native.js +98 -0
  42. package/dist/esm/tokens.native.js.map +1 -0
  43. package/package.json +12 -3
@@ -0,0 +1,61 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
21
+ value: true
22
+ }), mod);
23
+ var SpringboardStyles_exports = {};
24
+ __export(SpringboardStyles_exports, {
25
+ SpringboardStyles: () => SpringboardStyles,
26
+ resolveMark: () => resolveMark
27
+ });
28
+ module.exports = __toCommonJS(SpringboardStyles_exports);
29
+ var import_react = require("react");
30
+ var import_css = require("./css.cjs");
31
+ var import_glyph = require("./glyph.cjs");
32
+ var import_jsx_runtime = require("react/jsx-runtime");
33
+ function resolveMark(realm) {
34
+ const name = realm?.name?.trim();
35
+ const displayName = realm?.displayName?.trim();
36
+ if (!name && !displayName) return void 0;
37
+ return (0, import_glyph.glyphMark)({
38
+ name: name ?? "",
39
+ displayName
40
+ });
41
+ }
42
+ function SpringboardStyles(props) {
43
+ const {
44
+ realm,
45
+ mark,
46
+ ...cssOptions
47
+ } = props;
48
+ const resolved = mark ?? resolveMark(realm);
49
+ const css = (0, import_react.useMemo)(() => (0, import_css.buildSpringboardCss)({
50
+ ...cssOptions,
51
+ mark: resolved
52
+ }),
53
+ // The options are primitives and the mark is a value object; keying on
54
+ // the resolved fields keeps the memo stable across the re-render that
55
+ // every keystroke in the password field causes.
56
+ [resolved?.monogram, resolved?.background, resolved?.foreground, cssOptions.fontFamily, cssOptions.focusRingWidthPx, cssOptions.focusRingOffsetPx, cssOptions.minPressTargetPx, cssOptions.cardMaxWidthPx]);
57
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)("style", {
58
+ "data-springboard-styles": "",
59
+ children: css
60
+ });
61
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: () => from[key],
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
23
+ value: true
24
+ }), mod);
25
+ var SpringboardStyles_exports = {};
26
+ __export(SpringboardStyles_exports, {
27
+ SpringboardStyles: () => SpringboardStyles,
28
+ resolveMark: () => resolveMark
29
+ });
30
+ module.exports = __toCommonJS(SpringboardStyles_exports);
31
+ var import_jsx_runtime = require("react/jsx-runtime");
32
+ var import_react = require("react");
33
+ var import_css = require("./css.native.js");
34
+ var import_glyph = require("./glyph.native.js");
35
+ function resolveMark(realm) {
36
+ var _realm_name, _realm_displayName;
37
+ var name = realm === null || realm === void 0 ? void 0 : (_realm_name = realm.name) === null || _realm_name === void 0 ? void 0 : _realm_name.trim();
38
+ var displayName = realm === null || realm === void 0 ? void 0 : (_realm_displayName = realm.displayName) === null || _realm_displayName === void 0 ? void 0 : _realm_displayName.trim();
39
+ if (!name && !displayName) return void 0;
40
+ return (0, import_glyph.glyphMark)({
41
+ name: name !== null && name !== void 0 ? name : "",
42
+ displayName
43
+ });
44
+ }
45
+ function SpringboardStyles(props) {
46
+ var {
47
+ realm,
48
+ mark,
49
+ ...cssOptions
50
+ } = props;
51
+ var resolved = mark !== null && mark !== void 0 ? mark : resolveMark(realm);
52
+ var css = (0, import_react.useMemo)(function () {
53
+ return (0, import_css.buildSpringboardCss)({
54
+ ...cssOptions,
55
+ mark: resolved
56
+ });
57
+ },
58
+ // The options are primitives and the mark is a value object; keying on
59
+ // the resolved fields keeps the memo stable across the re-render that
60
+ // every keystroke in the password field causes.
61
+ [resolved === null || resolved === void 0 ? void 0 : resolved.monogram, resolved === null || resolved === void 0 ? void 0 : resolved.background, resolved === null || resolved === void 0 ? void 0 : resolved.foreground, cssOptions.fontFamily, cssOptions.focusRingWidthPx, cssOptions.focusRingOffsetPx, cssOptions.minPressTargetPx, cssOptions.cardMaxWidthPx]);
62
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)("style", {
63
+ "data-springboard-styles": "",
64
+ children: css
65
+ });
66
+ }
67
+ //# sourceMappingURL=SpringboardStyles.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","SpringboardStyles_exports","__export","SpringboardStyles","resolveMark","module","exports","import_jsx_runtime","require","import_react","import_css","import_glyph","realm","_realm_name","_realm_displayName","name","trim","displayName","glyphMark","props","mark","cssOptions","resolved","css","useMemo","buildSpringboardCss","monogram","background"],"sources":["../../src/SpringboardStyles.tsx"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,GAAA,IAAAC,WAAA,CAAAC,SAAA;EAAAC,KAAA;AAAA,IAAAH,GAAA;AAAA,IAAAI,yBAAA;AAAAC,QAAA,CAAAD,yBAAA;EAAAE,iBAAA,EAAAA,CAAA,KAAAA,iBAAA;EAAAC,WAAA,EAAAA,CAAA,KAAAA;AAAA;AAmBAC,MAAA,CAAAC,OAAA,GAAAV,YAAwB,CAAAK,yBAAA;AAExB,IAAAM,kBAAoC,GAAAC,OAAA;AAEpC,IAAAC,YAAA,GAA0BD,OAAA;AA2DjB,IAAAE,UAAA,GAAAF,OAAA;AA7BF,IAAAG,YAAS,GAAAH,OAAY,oBAA4D;AACtF,SAAMJ,WAAOA,CAAAQ,KAAO,EAAM;EAC1B,IAAAC,WAAM,EAAAC,kBAAqB;EAC3B,IAAIC,IAAC,GAAAH,KAAS,aAAaA,KAAO,wBAAAC,WAAA,GAAAD,KAAA,CAAAG,IAAA,cAAAF,WAAA,uBAAAA,WAAA,CAAAG,IAAA;EAClC,IAAAC,WAAO,GAAAL,KAAA,aAAUA,KAAE,KAAM,KAAQ,IAAI,UAAAE,kBAAa,GAAAF,KAAA,CAAAK,WAAA,cAAAH,kBAAA,uBAAAA,kBAAA,CAAAE,IAAA;EACpD,KAAAD,IAAA,KAAAE,WAAA;EAEO,OAAS,IAAAN,YAAA,CAAAO,SAAiD;IAC/DH,IAAM,EAAEA,IAAA,KAAO,IAAM,IAAGA,IAAA,UAAe,IAAAA,IAAA;IAEvCE;EAEA;AAAY;AACiD,SAAAd,kBAAAgB,KAAA;EAAA;IAAAP,KAAA;IAAAQ,IAAA;IAAA,GAAAC;EAAA,IAAAF,KAAA;EAAA,IAAAG,QAAA,GAAAF,IAAA,aAAAA,IAAA,cAAAA,IAAA,GAAAhB,WAAA,CAAAQ,KAAA;EAAA,IAI3DW,GAAA,OAAAd,YAAA,CAAAe,OAAA,cACE;IACA,WAAUd,UAAA,CAAAe,mBAAA;MACV,GAAAJ,UAAU;MACVD,IAAA,EAAAE;IACA;EAAW;EACA;EACA;EAEb;EACF,CAEAA,QAAO,aAAAA,QAAA,mBAAC,IAAAA,QAAM,CAAAI,QAAA,EAChBJ,QAAA,aAAAA,QAAA,uBAAAA,QAAA,CAAAK,UAAA,E","ignoreList":[]}
@@ -0,0 +1,555 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
21
+ value: true
22
+ }), mod);
23
+ var css_exports = {};
24
+ __export(css_exports, {
25
+ buildSpringboardCss: () => buildSpringboardCss
26
+ });
27
+ module.exports = __toCommonJS(css_exports);
28
+ var import_tokens = require("./tokens.cjs");
29
+ function cssString(value) {
30
+ return JSON.stringify(value);
31
+ }
32
+ function customProperties() {
33
+ return [
34
+ // Surfaces.
35
+ `--kc-page-bg: ${import_tokens.wallpaperColors.base};`, `--kc-card-bg: ${import_tokens.plate.fill};`, `--kc-input-bg: ${import_tokens.field.background};`,
36
+ // Ink.
37
+ `--kc-text: ${import_tokens.ink.primary};`, `--kc-muted: ${import_tokens.ink.muted};`, `--kc-placeholder: ${import_tokens.ink.faint};`,
38
+ // Hairlines.
39
+ `--kc-border: ${import_tokens.field.border};`, `--kc-border-hover: ${import_tokens.field.borderHover};`, `--kc-border-focus: ${import_tokens.field.borderFocus};`, `--kc-border-strong: ${import_tokens.field.borderHover};`, `--kc-divider: ${import_tokens.field.divider};`,
40
+ // Interaction.
41
+ `--kc-hover-bg: ${import_tokens.field.ghost};`, `--kc-press-bg: ${import_tokens.field.ghostHover};`, `--kc-ring: ${import_tokens.accent.sky};`, `--kc-link: ${import_tokens.accent.sky};`,
42
+ // Call to action.
43
+ `--kc-cta-bg: ${import_tokens.accent.indigo};`, `--kc-cta-fg: ${import_tokens.ink.primary};`, `--kc-cta-hover: ${import_tokens.accent.indigoHover};`, `--kc-cta-press: ${import_tokens.accent.indigoPress};`,
44
+ // Disabled — washed chrome, lowest legible ink.
45
+ `--kc-disabled-bg: ${import_tokens.field.ghost};`, `--kc-disabled-border: ${import_tokens.field.border};`, `--kc-disabled-text: ${import_tokens.ink.faint};`,
46
+ // Feedback.
47
+ `--kc-error-text: ${import_tokens.status.error};`, `--kc-error-border: ${import_tokens.status.error};`, `--kc-warning-border: ${import_tokens.status.warning};`, `--kc-success-border: ${import_tokens.status.success};`, `--kc-info-border: ${import_tokens.status.info};`, `--kc-menu-shadow: rgba(0,0,0,0.45);`,
48
+ // Springboard's own, consumed only by this sheet.
49
+ `--sb-plate-fill: ${import_tokens.plate.fill};`, `--sb-plate-highlight: ${import_tokens.plate.highlight};`, `--sb-plate-radius: ${import_tokens.plate.radius}px;`, `--sb-icon-size: ${import_tokens.icon.size}px;`, `--sb-icon-radius: ${import_tokens.icon.radius}px;`, `--sb-caption-size: ${import_tokens.caption.fontSize}px;`, `--sb-caption-line: ${import_tokens.caption.lineHeight}px;`].join("\n ");
50
+ }
51
+ const onWallpaperShadow = `0 ${import_tokens.caption.shadowOffsetY}px ${import_tokens.caption.shadowBlur}px ${import_tokens.wallpaperColors.textShadow}`;
52
+ const plateShadow = `0 ${import_tokens.trigger.shadowOffsetY}px ${import_tokens.trigger.shadowBlur}px rgba(0,0,0,0.45)`;
53
+ const iconShadow = `0 ${import_tokens.icon.shadowOffsetY}px ${import_tokens.icon.shadowBlur}px ${import_tokens.icon.shadowColor}`;
54
+ function markRules(scope, mark) {
55
+ const monogramSize = Math.round(import_tokens.icon.size * 0.34);
56
+ const monogramLine = Math.round(import_tokens.icon.size * 0.4);
57
+ return `
58
+ /* \u2500\u2500 the estate's glyph: the springboard's own squircle \u2500\u2500\u2500\u2500\u2500\u2500 */
59
+ ${scope} .login-pf-page #kc-page-title,
60
+ ${scope} .login-pf-page #kc-username {
61
+ display: flex;
62
+ flex-direction: column;
63
+ align-items: center;
64
+ gap: ${import_tokens.caption.marginTop}px;
65
+ }
66
+ ${scope} .login-pf-page #kc-page-title::before,
67
+ ${scope} .login-pf-page #kc-username::before {
68
+ content: ${cssString(mark.monogram)};
69
+ box-sizing: border-box;
70
+ width: var(--sb-icon-size);
71
+ height: var(--sb-icon-size);
72
+ border-radius: var(--sb-icon-radius);
73
+ background: ${mark.background};
74
+ color: ${mark.foreground};
75
+ box-shadow: ${iconShadow};
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ font-size: ${monogramSize}px;
80
+ line-height: ${monogramLine}px;
81
+ font-weight: 800;
82
+ letter-spacing: 0.5px;
83
+ user-select: none;
84
+ }`;
85
+ }
86
+ function buildSpringboardCss(options = {}) {
87
+ const {
88
+ mark,
89
+ fontFamily = import_tokens.fontFamily,
90
+ focusRingWidthPx = 2,
91
+ focusRingOffsetPx = 2,
92
+ minPressTargetPx = 44,
93
+ cardMaxWidthPx = 420
94
+ } = options;
95
+ const scope = "html.login-pf";
96
+ const vars = customProperties();
97
+ const cardPadY = import_tokens.plate.paddingVertical + 12;
98
+ const cardPadX = import_tokens.plate.paddingHorizontal + 8;
99
+ return `
100
+ /* \u2500\u2500 springboard tokens, both colour schemes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
101
+ /* One dark surface in light and dark alike \u2014 see ./tokens.ts. */
102
+ ${scope},
103
+ ${scope}.t_dark {
104
+ ${vars}
105
+ }
106
+
107
+ /* \u2500\u2500 the wallpaper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
108
+ ${scope} {
109
+ background-color: ${import_tokens.wallpaperColors.base};
110
+ background-image: ${import_tokens.wallpaperLayers};
111
+ /* Fixed so the glows stay anchored to the viewport instead of tiling
112
+ down a page that grew a scrollbar (a long consent screen, a locale
113
+ list). The springboard's wallpaper is a layer behind everything, not
114
+ a background that scrolls with content. */
115
+ background-attachment: fixed;
116
+ background-repeat: no-repeat;
117
+ background-size: cover;
118
+ min-height: 100%;
119
+ }
120
+ ${scope} body {
121
+ background: transparent none;
122
+ color: ${import_tokens.ink.primary};
123
+ font-family: ${fontFamily};
124
+ -webkit-font-smoothing: antialiased;
125
+ }
126
+ ${scope} .login-pf-page {
127
+ background: transparent;
128
+ padding-bottom: 40px;
129
+ }
130
+
131
+ /* \u2500\u2500 the realm title, sitting straight on the wallpaper \u2500\u2500\u2500\u2500\u2500\u2500 */
132
+ /* Caption anatomy from the launcher: white with a halo, because this
133
+ text has no plate under it and may land on either glow. */
134
+ ${scope} .login-pf-page #kc-header-wrapper {
135
+ color: ${import_tokens.wallpaperColors.text};
136
+ text-shadow: ${onWallpaperShadow};
137
+ font-weight: 700;
138
+ font-size: 22px;
139
+ line-height: 1.3;
140
+ letter-spacing: normal;
141
+ text-transform: none;
142
+ padding: 44px 16px 18px;
143
+ }
144
+
145
+ /* \u2500\u2500 the card: the dock's glass shelf, grown to hold a form \u2500\u2500 */
146
+ ${scope} .login-pf-page .card-pf {
147
+ max-width: ${cardMaxWidthPx}px;
148
+ margin: 0 auto;
149
+ background: var(--sb-plate-fill);
150
+ border: 1px solid var(--sb-plate-highlight);
151
+ border-radius: var(--sb-plate-radius);
152
+ /* The shelf's top-edge inner highlight ('inset 0 1px 0 #fff4' in the
153
+ launcher payload) plus the trigger's elevation under the slab. */
154
+ box-shadow:
155
+ inset 0 1px 0 ${import_tokens.plate.highlight},
156
+ ${plateShadow};
157
+ /* "blur-ish" is the launcher's own word for the dock material. Where
158
+ backdrop-filter is unsupported the fill alone still reads as a slab,
159
+ so this degrades rather than breaks. */
160
+ backdrop-filter: blur(22px) saturate(140%);
161
+ -webkit-backdrop-filter: blur(22px) saturate(140%);
162
+ padding: ${cardPadY}px ${cardPadX}px;
163
+ overflow: hidden;
164
+ }
165
+ ${scope} .login-pf-page .login-pf-header h1,
166
+ ${scope} .login-pf-page #kc-page-title {
167
+ color: ${import_tokens.ink.primary};
168
+ font-weight: 700;
169
+ font-size: 20px;
170
+ line-height: 1.3;
171
+ margin: 0 0 ${import_tokens.plate.gap}px;
172
+ }
173
+ ${mark ? markRules(scope, mark) : ""}
174
+
175
+ /* \u2500\u2500 labels and prose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
176
+ ${scope} .login-pf-page label,
177
+ ${scope} .login-pf-page .pf-c-form__label,
178
+ ${scope} .login-pf-page .pf-c-form__label-text {
179
+ color: ${import_tokens.ink.secondary};
180
+ font-weight: 500;
181
+ font-size: 14px;
182
+ }
183
+ ${scope} .login-pf-page .instruction,
184
+ ${scope} .login-pf-page .subtitle,
185
+ ${scope} .login-pf-page .pf-c-form__helper-text,
186
+ ${scope} .login-pf-page #kc-info,
187
+ ${scope} .login-pf-page .login-pf-signup {
188
+ color: ${import_tokens.ink.muted};
189
+ }
190
+ ${scope} .login-pf-page #kc-attempted-username {
191
+ color: ${import_tokens.ink.primary};
192
+ font-weight: 600;
193
+ }
194
+
195
+ /* \u2500\u2500 fields: inset into the slab, not laid on top of it \u2500\u2500\u2500\u2500\u2500\u2500 */
196
+ ${scope} .login-pf-page .pf-c-form-control,
197
+ ${scope} .login-pf-page input[type="text"],
198
+ ${scope} .login-pf-page input[type="password"],
199
+ ${scope} .login-pf-page input[type="email"],
200
+ ${scope} .login-pf-page input[type="tel"],
201
+ ${scope} .login-pf-page input[type="number"],
202
+ ${scope} .login-pf-page select,
203
+ ${scope} .login-pf-page textarea {
204
+ min-height: ${minPressTargetPx}px;
205
+ background-color: ${import_tokens.field.background};
206
+ color: ${import_tokens.ink.primary};
207
+ border: 1px solid ${import_tokens.field.border};
208
+ box-shadow: none;
209
+ }
210
+ ${scope} .login-pf-page .pf-c-form-control:hover,
211
+ ${scope} .login-pf-page select:hover,
212
+ ${scope} .login-pf-page textarea:hover {
213
+ border-color: ${import_tokens.field.borderHover};
214
+ }
215
+ ${scope} .login-pf-page .pf-c-form-control:focus,
216
+ ${scope} .login-pf-page select:focus,
217
+ ${scope} .login-pf-page textarea:focus {
218
+ border-color: ${import_tokens.field.borderFocus};
219
+ background-color: ${import_tokens.field.background};
220
+ }
221
+ ${scope} .login-pf-page .pf-c-form-control::placeholder,
222
+ ${scope} .login-pf-page input::placeholder {
223
+ color: ${import_tokens.ink.faint};
224
+ }
225
+ ${scope} .login-pf-page .pf-c-form-control[aria-invalid="true"] {
226
+ border-color: ${import_tokens.status.error};
227
+ }
228
+ /* \u2605 THE INPUT GROUP IS OPAQUE WHITE IN PATTERNFLY, and that one fact
229
+ defeats the whole field treatment above. '.pf-c-input-group' wraps the
230
+ password field and its visibility toggle; both of those are painted in
231
+ TRANSLUCENT springboard colours, so over a white parent the field
232
+ composites to mid-grey and the toggle to near-white \u2014 which is exactly
233
+ how it rendered before this rule existed. Clearing the parent is what
234
+ makes the two translucent children land on the slab instead. */
235
+ /* LC-149 FIELD-TRAILING-ACTION: the reveal sits inside the password field
236
+ as a chromeless trailing eye, not a bordered button beside it. The field
237
+ keeps the end cap clear, and PatternFly's in-field invalid glyph steps
238
+ aside for it. */
239
+ ${scope} .login-pf-page .pf-c-input-group {
240
+ background: transparent;
241
+ position: relative;
242
+ display: flex;
243
+ align-items: stretch;
244
+ }
245
+ ${scope} .login-pf-page .pf-c-input-group .pf-c-form-control,
246
+ ${scope} .login-pf-page .pf-c-input-group .pf-c-form-control[aria-invalid="true"] {
247
+ flex: 1 1 auto;
248
+ padding-inline-end: ${minPressTargetPx}px;
249
+ background-image: none;
250
+ }
251
+ ${scope} .login-pf-page .pf-c-input-group .pf-c-button.pf-m-control,
252
+ ${scope} .login-pf-page .pf-c-input-group .pf-c-button.pf-m-control:hover,
253
+ ${scope} .login-pf-page .pf-c-input-group .pf-c-button.pf-m-control:active {
254
+ position: absolute;
255
+ inset-block: 0;
256
+ inset-inline-end: 0;
257
+ z-index: 1;
258
+ width: ${minPressTargetPx}px;
259
+ min-width: ${minPressTargetPx}px;
260
+ min-height: 0;
261
+ padding: 0;
262
+ background-color: transparent;
263
+ border-color: transparent;
264
+ box-shadow: none;
265
+ color: ${import_tokens.ink.secondary};
266
+ }
267
+ ${scope} .login-pf-page .pf-c-input-group .pf-c-button.pf-m-control:hover {
268
+ color: ${import_tokens.ink.primary};
269
+ }
270
+
271
+ /* Chrome paints autofilled inputs a fixed pale yellow that no colour
272
+ property overrides \u2014 the inset shadow is the documented way to repaint
273
+ the field, and without it a remembered username lands as a white bar in
274
+ the middle of the slab. */
275
+ ${scope} .login-pf-page input:-webkit-autofill,
276
+ ${scope} .login-pf-page input:-webkit-autofill:hover,
277
+ ${scope} .login-pf-page input:-webkit-autofill:focus {
278
+ -webkit-box-shadow: 0 0 0 1000px ${import_tokens.field.background} inset;
279
+ -webkit-text-fill-color: ${import_tokens.ink.primary};
280
+ caret-color: ${import_tokens.ink.primary};
281
+ }
282
+
283
+ /* \u2500\u2500 buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
284
+ ${scope} .login-pf-page .pf-c-button {
285
+ min-height: ${minPressTargetPx}px;
286
+ font-weight: 600;
287
+ }
288
+ ${scope} .login-pf-page .pf-c-button.pf-m-primary,
289
+ ${scope} .login-pf-page input.pf-m-primary[type="submit"],
290
+ ${scope} .login-pf-page input.pf-m-primary[type="button"] {
291
+ background-color: ${import_tokens.accent.indigo};
292
+ border-color: ${import_tokens.accent.indigo};
293
+ color: ${import_tokens.ink.primary};
294
+ box-shadow: ${iconShadow};
295
+ }
296
+ ${scope} .login-pf-page .pf-c-button.pf-m-primary:hover,
297
+ ${scope} .login-pf-page input.pf-m-primary[type="submit"]:hover {
298
+ background-color: ${import_tokens.accent.indigoHover};
299
+ border-color: ${import_tokens.accent.indigoHover};
300
+ }
301
+ ${scope} .login-pf-page .pf-c-button.pf-m-primary:active,
302
+ ${scope} .login-pf-page input.pf-m-primary[type="submit"]:active {
303
+ background-color: ${import_tokens.accent.indigoPress};
304
+ border-color: ${import_tokens.accent.indigoPress};
305
+ }
306
+ ${scope} .login-pf-page .pf-c-button.pf-m-primary:disabled,
307
+ ${scope} .login-pf-page input.pf-m-primary[type="submit"]:disabled {
308
+ background-color: ${import_tokens.field.ghost};
309
+ border-color: ${import_tokens.field.border};
310
+ color: ${import_tokens.ink.faint};
311
+ box-shadow: none;
312
+ }
313
+ ${scope} .login-pf-page .pf-c-button.pf-m-control,
314
+ ${scope} .login-pf-page .pf-c-button.pf-m-secondary,
315
+ ${scope} .login-pf-page .pf-c-button.btn-default:not(.pf-m-primary) {
316
+ background-color: ${import_tokens.field.ghost};
317
+ border-color: ${import_tokens.field.border};
318
+ color: ${import_tokens.ink.primary};
319
+ }
320
+ ${scope} .login-pf-page .pf-c-button.pf-m-control:hover,
321
+ ${scope} .login-pf-page .pf-c-button.pf-m-secondary:hover,
322
+ ${scope} .login-pf-page .pf-c-button.btn-default:not(.pf-m-primary):hover {
323
+ background-color: ${import_tokens.field.ghostHover};
324
+ border-color: ${import_tokens.field.borderHover};
325
+ color: ${import_tokens.ink.primary};
326
+ }
327
+ /* PatternFly draws control-button borders on an ::after overlay and
328
+ accents its bottom edge on interaction; on the slab that reads as a
329
+ stray underline beneath the password-visibility toggle. */
330
+ ${scope} .login-pf-page .pf-c-button::after,
331
+ ${scope} .login-pf-page .pf-c-button:hover::after,
332
+ ${scope} .login-pf-page .pf-c-button:focus::after,
333
+ ${scope} .login-pf-page .pf-c-button:active::after {
334
+ content: none;
335
+ }
336
+
337
+ /* \u2500\u2500 the remember-me checkbox \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
338
+ /* \u2605 THE RESET IS PART OF THE SKIN, not borrowed from the house sheet.
339
+ A native checkbox is a 13px white box drawn by the platform: no colour
340
+ property reaches it, so on the slab it reads as a bright chip with no
341
+ relationship to anything around it. 'appearance: none' is what makes it
342
+ paintable at all. The visual square stays 22px inside a transparent
343
+ border that pads the hit box out to the press-target floor, so the
344
+ control is small and the target is not (DG-A11Y-01).
345
+
346
+ The house sheet bakes its tick glyph as a data-URI at build time from
347
+ the ramp's CTA foreground, so the springboard's tick is restated here
348
+ rather than inherited through a custom property. */
349
+ ${scope} .login-pf-page input[type="checkbox"] {
350
+ appearance: none;
351
+ -webkit-appearance: none;
352
+ position: static;
353
+ box-sizing: content-box;
354
+ width: 22px;
355
+ height: 22px;
356
+ border: ${Math.round((minPressTargetPx - 22) / 2)}px solid transparent;
357
+ border-radius: ${Math.round((minPressTargetPx - 22) / 2) + 8}px;
358
+ background-clip: padding-box;
359
+ background-repeat: no-repeat;
360
+ background-position: center;
361
+ background-size: 15px 15px;
362
+ margin: 0 4px 0 0;
363
+ flex: 0 0 auto;
364
+ cursor: pointer;
365
+ background-color: ${import_tokens.field.background};
366
+ box-shadow: inset 0 0 0 1.5px ${import_tokens.field.borderHover};
367
+ }
368
+ ${scope} .login-pf-page .checkbox label,
369
+ ${scope} .login-pf-page .pf-c-check {
370
+ display: inline-flex;
371
+ align-items: center;
372
+ min-height: ${minPressTargetPx}px;
373
+ padding-left: 0;
374
+ margin: 0;
375
+ cursor: pointer;
376
+ }
377
+ ${scope} .login-pf-page input[type="checkbox"]:checked,
378
+ ${scope}.t_dark .login-pf-page input[type="checkbox"]:checked {
379
+ background-color: ${import_tokens.accent.indigo};
380
+ box-shadow: inset 0 0 0 1.5px ${import_tokens.accent.indigo};
381
+ background-image: url("data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="${import_tokens.ink.primary}" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>`)}");
382
+ }
383
+
384
+ /* \u2500\u2500 links \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
385
+ ${scope} .login-pf-page a {
386
+ color: ${import_tokens.accent.sky};
387
+ }
388
+ ${scope} .login-pf-page a:hover {
389
+ color: ${import_tokens.accent.sky};
390
+ }
391
+
392
+ /* \u2500\u2500 alerts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
393
+ ${scope} .login-pf-page .pf-c-alert.pf-m-inline {
394
+ background: ${import_tokens.field.background};
395
+ border: 1px solid ${import_tokens.field.border};
396
+ border-left-width: 3px;
397
+ border-left-color: ${import_tokens.status.info};
398
+ }
399
+ ${scope} .login-pf-page .pf-c-alert.pf-m-inline.pf-m-danger {
400
+ border-left-color: ${import_tokens.status.error};
401
+ }
402
+ ${scope} .login-pf-page .pf-c-alert.pf-m-inline.pf-m-warning {
403
+ border-left-color: ${import_tokens.status.warning};
404
+ }
405
+ ${scope} .login-pf-page .pf-c-alert.pf-m-inline.pf-m-success {
406
+ border-left-color: ${import_tokens.status.success};
407
+ }
408
+ ${scope} .login-pf-page .pf-c-alert__title {
409
+ color: ${import_tokens.ink.primary};
410
+ }
411
+ ${scope} .login-pf-page .pf-c-alert__icon {
412
+ color: ${import_tokens.ink.muted};
413
+ }
414
+ ${scope} .login-pf-page span#input-error,
415
+ ${scope} .login-pf-page [id^="input-error"],
416
+ ${scope} .login-pf-page .pf-m-error,
417
+ ${scope} .login-pf-page .required {
418
+ color: ${import_tokens.status.error};
419
+ }
420
+
421
+ /* \u2500\u2500 identity providers: the SSO buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
422
+ /* \u2605 CHROME ONLY. Every provider row is an <a href={p.loginUrl}> that
423
+ keycloakify renders from social.providers; nothing here changes what
424
+ it points at, what it is called, or whether it appears. */
425
+ ${scope} .login-pf-page #kc-social-providers h2 {
426
+ color: ${import_tokens.ink.muted};
427
+ font-size: 13px;
428
+ font-weight: 500;
429
+ }
430
+ ${scope} .login-pf-page hr,
431
+ ${scope} .login-pf-page #kc-social-providers hr {
432
+ border-top: 1px solid ${import_tokens.field.divider};
433
+ opacity: 1;
434
+ }
435
+ ${scope} .login-pf-page .kc-social-item,
436
+ ${scope} .login-pf-page .kc-social-links a,
437
+ ${scope} .login-pf-page #kc-social-providers li a {
438
+ min-height: ${minPressTargetPx}px;
439
+ background: ${import_tokens.field.ghost};
440
+ border: 1px solid ${import_tokens.field.border};
441
+ border-radius: var(--sb-icon-radius);
442
+ color: ${import_tokens.ink.primary};
443
+ text-decoration: none;
444
+ }
445
+ ${scope} .login-pf-page .kc-social-item:hover,
446
+ ${scope} .login-pf-page .kc-social-links a:hover,
447
+ ${scope} .login-pf-page #kc-social-providers li a:hover {
448
+ background: ${import_tokens.field.ghostHover};
449
+ border-color: ${import_tokens.field.borderHover};
450
+ color: ${import_tokens.ink.primary};
451
+ }
452
+ ${scope} .login-pf-page .kc-social-provider-name,
453
+ ${scope} .login-pf-page .kc-social-icon-text {
454
+ color: ${import_tokens.ink.primary};
455
+ }
456
+
457
+ /* \u2500\u2500 the OTP credential tiles (login-otp.ftl) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
458
+ ${scope} .login-pf-page .pf-c-tile {
459
+ background: ${import_tokens.field.background};
460
+ border: 1px solid ${import_tokens.field.border};
461
+ border-radius: var(--sb-icon-radius);
462
+ color: ${import_tokens.ink.primary};
463
+ }
464
+ ${scope} .login-pf-page .pf-c-tile__input:checked + .pf-c-tile,
465
+ ${scope} .login-pf-page .pf-c-tile__input:checked + label {
466
+ border-color: ${import_tokens.accent.indigo};
467
+ background: ${import_tokens.field.ghostHover};
468
+ }
469
+ ${scope} .login-pf-page .pf-c-tile__title,
470
+ ${scope} .login-pf-page .pf-c-tile__icon {
471
+ color: ${import_tokens.ink.primary};
472
+ }
473
+
474
+ /* \u2500\u2500 the registration / back-to-app footer band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
475
+ /* The stock sheet bleeds #kc-info to the card edge as a #f0f0f0 band.
476
+ On the slab it becomes the dock's own darker step. */
477
+ ${scope} .login-pf-page #kc-info {
478
+ margin: ${import_tokens.plate.gap}px -${cardPadX}px -${cardPadY}px;
479
+ padding: 0;
480
+ color: ${import_tokens.ink.muted};
481
+ }
482
+ ${scope} .login-pf-page #kc-info-wrapper {
483
+ background: rgba(8, 11, 20, 0.42);
484
+ border-top: 1px solid ${import_tokens.field.divider};
485
+ border-radius: 0 0 ${import_tokens.plate.radius - 1}px ${import_tokens.plate.radius - 1}px;
486
+ padding: 14px ${cardPadX}px;
487
+ color: ${import_tokens.ink.muted};
488
+ text-align: center;
489
+ }
490
+ ${scope} .login-pf-page #kc-info-wrapper a {
491
+ color: ${import_tokens.accent.sky};
492
+ }
493
+
494
+ /* \u2500\u2500 the locale menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
495
+ ${scope} .login-pf-page #kc-current-locale-link {
496
+ color: ${import_tokens.ink.muted};
497
+ }
498
+ ${scope} .login-pf-page #kc-current-locale-link:hover {
499
+ background: ${import_tokens.field.ghost};
500
+ color: ${import_tokens.ink.primary};
501
+ }
502
+ ${scope} .login-pf-page .pf-c-dropdown__menu {
503
+ background: ${import_tokens.wallpaperColors.base};
504
+ border: 1px solid ${import_tokens.plate.highlight};
505
+ box-shadow: ${plateShadow};
506
+ }
507
+ ${scope} .login-pf-page .pf-c-dropdown__menu-item {
508
+ color: ${import_tokens.ink.primary};
509
+ }
510
+ ${scope} .login-pf-page .pf-c-dropdown__menu-item:hover {
511
+ background: ${import_tokens.field.ghost};
512
+ color: ${import_tokens.ink.primary};
513
+ }
514
+
515
+ /* \u2500\u2500 focus ring (DG-A11Y-01: non-removable) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
516
+ /* !important outranks both PatternFly's focus styles and the house
517
+ ThemeProvider's global outline reset. The keyboard ring is the one
518
+ affordance a skin must never take away. */
519
+ ${scope} a:focus-visible,
520
+ ${scope} button:focus-visible,
521
+ ${scope} input:focus-visible,
522
+ ${scope} select:focus-visible,
523
+ ${scope} textarea:focus-visible,
524
+ ${scope} [tabindex]:focus-visible {
525
+ outline: ${focusRingWidthPx}px solid ${import_tokens.accent.sky} !important;
526
+ outline-offset: ${focusRingOffsetPx}px !important;
527
+ box-shadow: none !important;
528
+ }
529
+ /* LC-133 FOCUS-IS-BORDER (FZ-7717): a text field is the exception. It
530
+ focuses with its own border in the accent, at the width it already has,
531
+ so it changes colour and never size. */
532
+ ${scope} .login-pf-page .pf-c-form-control:focus,
533
+ ${scope} .login-pf-page .pf-c-form-control:focus-visible {
534
+ border-color: ${import_tokens.field.borderFocus};
535
+ outline: none !important;
536
+ }
537
+
538
+ /* \u2500\u2500 small screens keep the slab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
539
+ @media (max-width: 767px) {
540
+ ${scope} .login-pf-page .card-pf {
541
+ margin: 0 12px;
542
+ background: var(--sb-plate-fill);
543
+ border: 1px solid var(--sb-plate-highlight);
544
+ border-radius: var(--sb-plate-radius);
545
+ box-shadow:
546
+ inset 0 1px 0 ${import_tokens.plate.highlight},
547
+ ${plateShadow};
548
+ }
549
+ ${scope} .login-pf-page #kc-header-wrapper {
550
+ padding: 28px 16px 14px;
551
+ font-size: 19px;
552
+ }
553
+ }
554
+ `;
555
+ }