@webority/theme 0.96.0 → 0.98.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/theme",
3
- "version": "0.96.0",
3
+ "version": "0.98.0",
4
4
  "description": "Webority shared design system — Bootstrap 5.3 SCSS overrides, --wui-* tokens, and shared component CSS. The single source of brand chrome for React portals and Razor sites.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "publishConfig": {
@@ -29,17 +29,14 @@
29
29
  "./scss/*": "./scss/_*.scss",
30
30
  "./css": "./dist/webority-theme.css",
31
31
  "./css/flags": "./dist/webority-flags.css",
32
- "./css/brand-signal": "./dist/webority-brand-signal.css",
33
32
  "./css/runtime-brand": "./dist/webority-runtime-brand.css",
34
33
  "./purge-safelist.json": "./dist/purge-safelist.json",
35
34
  "./token-meanings.json": "./token-meanings.json",
36
35
  "./postcss/forced-states": "./dist/postcss/forced-states.mjs",
36
+ "./runtime": "./dist/runtime.mjs",
37
37
  "./logos/*": "./logos/*",
38
38
  "./package.json": "./package.json"
39
39
  },
40
- "bin": {
41
- "webority-theme-export": "./dist/webority-theme-export.mjs"
42
- },
43
40
  "sass": "index.scss",
44
41
  "style": "dist/webority-theme.css",
45
42
  "dependencies": {
@@ -56,6 +53,6 @@
56
53
  "vite": "^8.0.12"
57
54
  },
58
55
  "scripts": {
59
- "build": "sass index.scss dist/webority-theme.css --load-path=node_modules --style=compressed --no-source-map --quiet-deps --silence-deprecation=if-function && sass scss/_flags.scss dist/webority-flags.css --style=compressed --no-source-map --quiet && sass scss/_brand-signal.scss dist/webority-brand-signal.css --style=compressed --no-source-map --quiet && sass scss/_runtime-brand.scss dist/webority-runtime-brand.css --style=compressed --no-source-map --quiet && node ../../scripts/force-state-selectors.mjs dist/webority-theme.css dist/webority-brand-signal.css && node ../../scripts/gen-purge-safelist.mjs && node ../../scripts/sync-rcl-assets.mjs theme && vite build --config vite.cli.config.js && node scripts/exportCanvasTheme.mjs"
56
+ "build": "sass index.scss dist/webority-theme.css --load-path=node_modules --style=compressed --no-source-map --quiet-deps --silence-deprecation=if-function && sass scss/_flags.scss dist/webority-flags.css --style=compressed --no-source-map --quiet && sass scss/_runtime-brand.scss dist/webority-runtime-brand.css --style=compressed --no-source-map --quiet && node ../../scripts/force-state-selectors.mjs dist/webority-theme.css && node ../../scripts/gen-purge-safelist.mjs && node ../../scripts/sync-rcl-assets.mjs theme && vite build --config vite.cli.config.js && node scripts/exportCanvasTheme.mjs"
60
57
  }
61
58
  }
@@ -1,5 +1,5 @@
1
- // Runtime brand: an opt-in layer that lets a product's exported token file (webority-theme-export,
2
- // format webority-theme-tokens/1) restyle the precompiled theme without recompiling it.
1
+ // Runtime brand: an opt-in layer that lets a product's token file (webority-theme-tokens/2, written by
2
+ // `webority brand`) restyle the precompiled theme without recompiling it.
3
3
  //
4
4
  // Loaded AFTER webority-theme.css and BEFORE the token file's values. It holds no colour of its own.
5
5
  // Bootstrap compiles $primary into a few component rules as literals; this layer re-points each of
@@ -1138,7 +1138,7 @@ button.wui-step-tile-body:hover .step-label {
1138
1138
  .form-section-body {
1139
1139
  display: flex;
1140
1140
  flex-direction: column;
1141
- gap: 16px;
1141
+ gap: var(--wui-space-lg);
1142
1142
  }
1143
1143
 
1144
1144
  // layout="side": the title and description take a column beside the fields. Below lg the
@@ -396,10 +396,17 @@
396
396
  }
397
397
 
398
398
  // ── Fitted: tabs share the width equally (no scroll). ──
399
+ // Every tab takes an equal share; a label longer than its share ends in an ellipsis.
399
400
  .app-tabs-fitted .app-tab {
400
401
  flex: 1 1 0;
402
+ min-width: 0;
401
403
  justify-content: center;
402
404
  }
405
+ .app-tabs-fitted .wui-tab-label {
406
+ min-width: 0;
407
+ overflow: hidden;
408
+ text-overflow: ellipsis;
409
+ }
403
410
  .app-tabs-wrap > .app-tabs-fitted {
404
411
  flex: 1 1 auto;
405
412
  }
@@ -219,6 +219,14 @@
219
219
  .wui-modal-body .field > .field-error {
220
220
  align-self: stretch;
221
221
  }
222
+
223
+ // Stacked fields in a dialog keep the distance AppFormSection puts between its fields (.form-section-body
224
+ // in _flow.scss). Only fields in normal flow: a child of the body, or of a form in the body. A field in a
225
+ // grid or flex layout takes that layout's gap.
226
+ .wui-modal-body > .field + .field,
227
+ .wui-modal-body > form > .field + .field {
228
+ margin-top: var(--wui-space-lg);
229
+ }
222
230
  .wui-form-section-head {
223
231
  margin-bottom: 16px;
224
232
  }
@@ -1 +0,0 @@
1
- @font-face{font-family:"Webority Serif";font-style:normal;font-weight:600;font-display:swap;src:url("../fonts/serif/WeboritySerif-DemiBold.woff2") format("woff2")}:root{--wui-signal-violet: #4A0FBF;--wui-signal-violet-hover: #3D0CA0;--wui-signal-tint: #F1EBFF;--wui-signal-ink: #16093A;--wui-signal-heading: #4C1D95;--wui-signal-pink: #B517C8;--wui-signal-dark-fill: #5A22D6;--wui-signal-dark-fill-hover: #6B35E6;--bs-font-sans-serif: "Webority Sans", system-ui, -apple-system, "Segoe UI", sans-serif;--bs-body-font-family: var(--bs-font-sans-serif);--wui-font-display: "Webority Serif", Georgia, "Times New Roman", serif;--wui-primary: #4A0FBF;--wui-primary-hover: #3D0CA0;--wui-primary-pressed: #340A88;--wui-primary-50: #8B66E6;--wui-primary-30: #B9A2F2;--wui-primary-20: #D9CBFA;--wui-primary-15: #E6DCFD;--wui-primary-10: #F1EBFF;--wui-primary-5: #F8F5FF;--wui-primary-text: #FFFFFF;--wui-primary-ink: var(--wui-primary, #4A0FBF);--wui-accent-dark: #340A88;--wui-surface-soft: #F1EBFF;--wui-surface-violet: #E6DCFD;--wui-surface-violet-soft: #F8F5FF;--wui-hero-gradient: radial-gradient(ellipse 120% 80% at 50% 30%, #8B66E6 0%, #4A0FBF 35%, #3D0CA0 75%, #16093A 100%);--wui-cta-gradient: radial-gradient(ellipse 120% 100% at 50% 50%, #2B1150 0%, #16093A 60%, #0E0626 100%);--wui-text-heading: #16093A;--wui-text-1: #2B2B2B;--wui-text-2: #5A5A5A;--wui-text-3: #6A6A6A;--wui-text-4: #9A9A9A;--wui-text-5: #CFC9DE;--wui-ink: #16093A;--wui-bg-page: #F8F6FD;--wui-bg-light: #FFFFFF;--wui-bg-elevated: #FBFAFE;--wui-bg-muted: #F3EFFB;--wui-field-bg: #FBFAFE;--wui-border-light: #E8E4F2;--wui-border-soft: #F3F0FA;--wui-progress-track: #E8E4F2;--wui-neutral-border-dark: #E8E4F2;--wui-neutral-bg-dark: #F3EFFB;--wui-shadow-overlay: 0 8px 28px -6px rgba(22, 9, 58, 0.16);--wui-shadow-overlay-lg: 0 24px 60px -16px rgba(22, 9, 58, 0.30);--wui-dark-bg-page: #000000;--wui-dark-bg-elevated: #0F0F0F;--wui-dark-bg-surface: #161616;--wui-dark-bg-muted: #1E1E1E;--wui-dark-border: #2A2A2A;--wui-dark-border-strong: #333333;--wui-dark-progress-track: #333333;--wui-dark-text: #EDEDED;--wui-dark-text-muted: #C0C0C0;--wui-dark-text-subtle: #A0A0A0;--wui-dark-primary: #A98BFF;--wui-dark-primary-hover: #BFA6FF;--bs-primary: #4A0FBF;--bs-primary-rgb: 74, 15, 191;--bs-link-color: var(--wui-primary-ink, #4A0FBF);--bs-link-color-rgb: var(--wui-primary-ink-rgb, 74, 15, 191);--bs-link-hover-color: var(--wui-primary-hover, #3D0CA0);--bs-link-hover-color-rgb: var(--wui-primary-hover-rgb, 61, 12, 160);--bs-focus-ring-color: rgba(74, 15, 191, 0.3)}.btn-primary{--bs-btn-color: var(--wui-primary-text, #fff);--bs-btn-bg: var(--wui-primary, #4A0FBF);--bs-btn-border-color: var(--wui-primary, #4A0FBF);--bs-btn-hover-color: var(--wui-primary-text, #fff);--bs-btn-hover-bg: var(--wui-primary-hover, #3D0CA0);--bs-btn-hover-border-color: var(--wui-primary-hover, #3D0CA0);--bs-btn-focus-shadow-rgb: var(--bs-primary-rgb, 74, 15, 191);--bs-btn-active-color: var(--wui-primary-text, #fff);--bs-btn-active-bg: var(--wui-primary-pressed, #340A88);--bs-btn-active-border-color: var(--wui-primary-pressed, #340A88);--bs-btn-disabled-color: var(--wui-primary-text, #fff);--bs-btn-disabled-bg: var(--wui-primary, #4A0FBF);--bs-btn-disabled-border-color: var(--wui-primary, #4A0FBF)}.btn-outline-primary{--bs-btn-color: var(--color-primary-ink);--bs-btn-border-color: var(--color-primary);--bs-btn-hover-color: var(--wui-primary-text, #fff);--bs-btn-hover-bg: var(--wui-primary, #4A0FBF);--bs-btn-hover-border-color: var(--wui-primary, #4A0FBF);--bs-btn-active-color: var(--wui-primary-text, #fff);--bs-btn-active-bg: var(--wui-primary-pressed, #340A88);--bs-btn-active-border-color: var(--wui-primary-pressed, #340A88);--bs-btn-focus-shadow-rgb: var(--bs-primary-rgb, 74, 15, 191)}.form-check-input:checked{background-color:var(--color-primary);border-color:var(--color-primary)}.page-title,.result-title{font-family:var(--wui-font-display);font-weight:600;font-style:normal;letter-spacing:-0.01em;color:var(--color-text)}.page-header-sm .page-title,.page-header.page-header-bar .page-title{font-family:inherit}:root[data-theme=dark],:root[data-bs-theme=dark]{--wui-signal-heading: #C4AEFF;--color-primary-soft: color-mix(in srgb, #FFFFFF 8%, transparent);--color-primary: var(--wui-signal-dark-fill, #5A22D6);--color-primary-hover: var(--wui-signal-dark-fill-hover, #6B35E6);--color-primary-text: var(--wui-dark-primary-text, #FFFFFF);--color-primary-hover-text: var(--wui-dark-primary-text, #FFFFFF);--bs-body-bg-rgb: 0, 0, 0;--bs-body-color-rgb: 237, 237, 237;--bs-emphasis-color-rgb: 237, 237, 237;--bs-secondary-color-rgb: 192, 192, 192;--bs-tertiary-color-rgb: 160, 160, 160;--bs-secondary-bg-rgb: 22, 22, 22;--bs-tertiary-bg-rgb: 30, 30, 30;--bs-border-color-rgb: 42, 42, 42;--bs-link-color: var(--wui-dark-primary, #A98BFF);--bs-link-color-rgb: var(--wui-dark-primary-rgb, 169, 139, 255);--bs-link-hover-color: var(--wui-dark-primary-hover, #BFA6FF);--bs-link-hover-color-rgb: var(--wui-dark-primary-hover-rgb, 191, 166, 255);--bs-focus-ring-color: rgba(169, 139, 255, 0.4)}:root[data-theme=dark] .btn-primary,:root[data-bs-theme=dark] .btn-primary{--bs-btn-bg: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-border-color: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-hover-bg: var(--wui-signal-dark-fill-hover, #6B35E6);--bs-btn-hover-border-color: var(--wui-signal-dark-fill-hover, #6B35E6);--bs-btn-active-bg: var(--wui-primary, #4A0FBF);--bs-btn-active-border-color: var(--wui-primary, #4A0FBF);--bs-btn-disabled-bg: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-disabled-border-color: var(--wui-signal-dark-fill, #5A22D6)}:root[data-theme=dark] .btn-outline-primary,:root[data-bs-theme=dark] .btn-outline-primary{--bs-btn-hover-bg: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-hover-border-color: var(--wui-signal-dark-fill, #5A22D6)}:root[data-theme=dark] .form-check-input:checked,:root[data-bs-theme=dark] .form-check-input:checked{background-color:var(--wui-signal-dark-fill, #5A22D6);border-color:var(--wui-signal-dark-fill, #5A22D6)}:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .progress-bar:not([class*=wui-progress-]){color:var(--wui-dark-primary-text, #FFFFFF)}:root[data-theme=dark] :where(.stepper:not(.wizard-stepper)),:root[data-bs-theme=dark] :where(.stepper:not(.wizard-stepper)){--wui-step-accent-fg: var(--wui-signal-ink, #16093A)}:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .struct-card.checked,:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .tpg-arrow:is(:hover,.wui-force-hover):not(:disabled),:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .tpg-page:is(:hover,.wui-force-hover):not(.is-active),:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .u-action:is(:hover,.wui-force-hover):not(:disabled),:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .tbl-empty-icon,:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .u-avatar,:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .wui-file-viewer-audio-art{background:var(--color-primary-soft)}:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .wui-calendar-view-btn[aria-pressed=true],:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .compare-table td.is-highlight{background:color-mix(in srgb, #FFFFFF 8%, var(--color-surface))}:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .table-ledger tbody tr.is-selected:is(:hover,.wui-force-hover){--bs-table-bg-state: color-mix(in srgb, #FFFFFF 12%, transparent)}:where(:root[data-theme=dark],:root[data-bs-theme=dark]) .table-ledger tbody tr.is-selected>:first-child{box-shadow:inset 3px 0 0 0 var(--color-primary),inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)))}@media(prefers-color-scheme: dark){:root[data-theme=auto]{--wui-signal-heading: #C4AEFF;--color-primary-soft: color-mix(in srgb, #FFFFFF 8%, transparent);--color-primary: var(--wui-signal-dark-fill, #5A22D6);--color-primary-hover: var(--wui-signal-dark-fill-hover, #6B35E6);--color-primary-text: var(--wui-dark-primary-text, #FFFFFF);--color-primary-hover-text: var(--wui-dark-primary-text, #FFFFFF);--bs-body-bg-rgb: 0, 0, 0;--bs-body-color-rgb: 237, 237, 237;--bs-emphasis-color-rgb: 237, 237, 237;--bs-secondary-color-rgb: 192, 192, 192;--bs-tertiary-color-rgb: 160, 160, 160;--bs-secondary-bg-rgb: 22, 22, 22;--bs-tertiary-bg-rgb: 30, 30, 30;--bs-border-color-rgb: 42, 42, 42;--bs-link-color: var(--wui-dark-primary, #A98BFF);--bs-link-color-rgb: var(--wui-dark-primary-rgb, 169, 139, 255);--bs-link-hover-color: var(--wui-dark-primary-hover, #BFA6FF);--bs-link-hover-color-rgb: var(--wui-dark-primary-hover-rgb, 191, 166, 255);--bs-focus-ring-color: rgba(169, 139, 255, 0.4)}:root[data-theme=auto] .btn-primary{--bs-btn-bg: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-border-color: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-hover-bg: var(--wui-signal-dark-fill-hover, #6B35E6);--bs-btn-hover-border-color: var(--wui-signal-dark-fill-hover, #6B35E6);--bs-btn-active-bg: var(--wui-primary, #4A0FBF);--bs-btn-active-border-color: var(--wui-primary, #4A0FBF);--bs-btn-disabled-bg: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-disabled-border-color: var(--wui-signal-dark-fill, #5A22D6)}:root[data-theme=auto] .btn-outline-primary{--bs-btn-hover-bg: var(--wui-signal-dark-fill, #5A22D6);--bs-btn-hover-border-color: var(--wui-signal-dark-fill, #5A22D6)}:root[data-theme=auto] .form-check-input:checked{background-color:var(--wui-signal-dark-fill, #5A22D6);border-color:var(--wui-signal-dark-fill, #5A22D6)}:where(:root[data-theme=auto]) .progress-bar:not([class*=wui-progress-]){color:var(--wui-dark-primary-text, #FFFFFF)}:root[data-theme=auto] :where(.stepper:not(.wizard-stepper)){--wui-step-accent-fg: var(--wui-signal-ink, #16093A)}:where(:root[data-theme=auto]) .struct-card.checked,:where(:root[data-theme=auto]) .tpg-arrow:is(:hover,.wui-force-hover):not(:disabled),:where(:root[data-theme=auto]) .tpg-page:is(:hover,.wui-force-hover):not(.is-active),:where(:root[data-theme=auto]) .u-action:is(:hover,.wui-force-hover):not(:disabled),:where(:root[data-theme=auto]) .tbl-empty-icon,:where(:root[data-theme=auto]) .u-avatar,:where(:root[data-theme=auto]) .wui-file-viewer-audio-art{background:var(--color-primary-soft)}:where(:root[data-theme=auto]) .wui-calendar-view-btn[aria-pressed=true],:where(:root[data-theme=auto]) .compare-table td.is-highlight{background:color-mix(in srgb, #FFFFFF 8%, var(--color-surface))}:where(:root[data-theme=auto]) .table-ledger tbody tr.is-selected:is(:hover,.wui-force-hover){--bs-table-bg-state: color-mix(in srgb, #FFFFFF 12%, transparent)}:where(:root[data-theme=auto]) .table-ledger tbody tr.is-selected>:first-child{box-shadow:inset 3px 0 0 0 var(--color-primary),inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)))}}
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import{readFileSync as e,writeFileSync as t}from"node:fs";var n=`webority-theme-tokens/1`,r=[`--wui-primary`,`--bs-primary`,`--bs-primary-rgb`,`--bs-link-color-rgb`,`--bs-body-font-family`];function i(e){console.error(`webority-theme-export: ${e}`),console.error(`usage: webority-theme-export <compiled.css>... --product <name> [--out <tokens.json>] [--widths 1440,390]`),process.exit(2)}function a(e){let t=[],n,r,a=[];for(let o=0;o<e.length;o++)e[o]===`--product`?n=e[++o]:e[o]===`--out`?r=e[++o]:e[o]===`--widths`?a=(e[++o]??``).split(`,`).map(e=>e.trim()):e[o].startsWith(`--`)?i(`unknown option ${e[o]}`):t.push(e[o]);return t.length===0&&i(`no compiled CSS file given`),(!n||!/^[a-z0-9-]+$/.test(n))&&i(`--product must be the product's lowercase name`),a.some(e=>!/^[1-9]\d*$/.test(e))&&i(`--widths takes whole pixel widths, such as 1440,390`),a.length>0&&!r&&i(`--widths needs --out, the file name each width's file is named after`),{files:t,product:n,out:r,widths:a.map(Number)}}var o=16;function s(e,t){let n=e.trim(),r=/^(clamp|calc|min|max)\((.*)\)$/.exec(n);if(r){let e=l(r[2],`,`).map(e=>s(e,t));return e.some(e=>e===null)?null:r[1]===`calc`?e.length===1?e[0]:null:r[1]===`clamp`?e.length===3?Math.min(Math.max(e[1],e[0]),e[2]):null:r[1]===`min`?Math.min(...e):Math.max(...e)}let i=n.split(/\s+/),a=0,c=1;for(let e=0;e<i.length;e++){if(e%2==1){if(i[e]!==`+`&&i[e]!==`-`)return null;c=i[e]===`+`?1:-1;continue}let n=/^(-?\d*\.?\d+)(px|rem|vw)?$/.exec(i[e]);if(!n||!n[2]&&Number(n[1])!==0)return null;let r=Number(n[1]),s=n[2]===`rem`?r*o:n[2]===`vw`?r*t/100:r;a+=c*s}return i.length%2==1?a:null}function c(e,t){return Object.fromEntries(Object.entries(e).map(([e,n])=>{let r=s(n,t);return[e,r===null?n:`${Math.round(r*100)/100}px`]}))}function l(e,t){let n=[],r=0,i=null,a=0;for(let o=0;o<e.length;o++){let s=e[o];i?s===`\\`?o++:s===i&&(i=null):s===`"`||s===`'`?i=s:s===`(`||s===`[`?r++:s===`)`||s===`]`?r--:s===t&&r===0&&(n.push(e.slice(a,o)),a=o+1)}return n.push(e.slice(a)),n}var u=10,d=/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i,f=/^rgba?\(([\s\S]*)\)$/i,p=/^color-mix\(([\s\S]*)\)$/i,m=/^var\(([\s\S]*)\)$/i;function h(e,t,n=0){if(n>u)return null;let r=e.trim(),i=m.exec(r);if(i){let e=l(i[1],`,`),r=e[0].trim();if(!/^--[a-z0-9-]+$/i.test(r))return null;let a=t(r);if(a!==void 0)return h(a,t,n+1);let o=e.slice(1).join(`,`).trim();return o?h(o,t,n+1):null}let a=d.exec(r);if(a){let e=a[1];e.length<=4&&(e=[...e].map(e=>e+e).join(``)),e.length===6&&(e+=`ff`);let t=t=>Number.parseInt(e.slice(t,t+2),16);return[t(0),t(2),t(4),t(6)/255]}let o=f.exec(r);if(o)return g(o[1]);let s=p.exec(r);if(s)return y(s[1],t,n);let c=r.toLowerCase();return c===`white`?[255,255,255,1]:c===`black`?[0,0,0,1]:c===`transparent`?[0,0,0,0]:null}function g(e){let t=e.trim(),n,r=l(t,`/`);if(r.length>2)return null;r.length===2&&(t=r[0].trim(),n=r[1].trim());let i=l(t,`,`).flatMap(e=>e.trim().split(/\s+/)).filter(Boolean);if(i.length!==3&&i.length!==4)return null;let a=i.slice(0,3).map(e=>/^-?\d*\.?\d+$/.test(e)?Math.min(255,Math.max(0,Number(e))):null);if(a.some(e=>e===null))return null;if(i.length===4){if(n!==void 0)return null;n=i[3]}let o=n===void 0?1:_(n);return o===null?null:[...a,o]}function _(e){let t=e.trim(),n=/^(-?\d*\.?\d+)%$/.exec(t);return n?Math.min(1,Math.max(0,Number(n[1])/100)):/^-?\d*\.?\d+$/.test(t)?Math.min(1,Math.max(0,Number(t))):null}function v(e){let t=e.trim(),n=/\s+(-?\d*\.?\d+)%$/.exec(t);if(!n)return{colour:t};let r=t.slice(0,n.index).trim();return r?{colour:r,percent:Number(n[1])}:null}function y(e,t,n){let r=l(e,`,`);if(r.length!==3||!/^in\s+srgb$/i.test(r[0].trim()))return null;let i=v(r[1]),a=v(r[2]);if(!i||!a)return null;let o=h(i.colour,t,n+1),s=h(a.colour,t,n+1);if(!o||!s)return null;let c=i.percent,u=a.percent,d=1;if(c===void 0&&u===void 0)c=50,u=50;else if(u===void 0)u=100-c;else if(c===void 0)c=100-u;else if(c+u!==100){let e=c+u;e>0?(e<100&&(d=e/100),c=c*100/e,u=u*100/e):(c=0,u=0)}let f=c/100,p=u/100,m=o[3]*f+s[3]*p;return[...[0,1,2].map(e=>m===0?0:(o[e]*o[3]*f+s[e]*s[3]*p)/m),m*d]}function b(e){let t=e.slice(0,3).map(e=>Math.round(Math.min(255,Math.max(0,e))).toString(16).padStart(2,`0`)).join(``),n=Math.round(Math.min(1,Math.max(0,e[3]))*255);return`#${t}${n<255?n.toString(16).padStart(2,`0`):``}`}function x(e){let t=[],n=0,r=null,i=0,a=-1;for(let o=0;o<e.length;o++){let s=e[o];if(r)s===`\\`?o++:s===r&&(r=null);else if(s===`"`||s===`'`)r=s;else if(s===`{`)n===0&&(a=o),n++;else if(s===`}`){if(n--,n===0){let n=e.slice(i,a).trim();n.startsWith(`@`)||t.push({selectors:l(n,`,`).map(S),body:e.slice(a+1,o)}),i=o+1}}else s===`;`&&n===0&&(i=o+1)}return t}function S(e){return e.trim().replace(/\s+/g,` `).replace(/["']/g,``)}var C=new Set([`:root`,`[data-bs-theme=light]`,`:root[data-bs-theme=light]`,`:root[data-theme=light]`]),w=new Set([`:root[data-theme=dark]`,`:root[data-bs-theme=dark]`]),T=new Set([`[data-bs-theme=dark]`]);function E(e){let t=[];for(let n of l(e,`;`)){let e=n.indexOf(`:`);if(e<0)continue;let r=n.slice(0,e).trim();r.startsWith(`--`)&&t.push([r,n.slice(e+1).trim().replace(/\s*!important$/,``)])}return t}function D(e,t){let n=e;for(let e=0;e<8;e+=1){let e=/^var\(\s*(--[\w-]+)\s*\)$/.exec(n);if(!e)return n;if(n=t(e[1]),n===void 0)return null}return null}function O(e,t,n){for(let[r,i]of Object.entries(e)){if(!i.startsWith(`var(`)&&!i.startsWith(`color-mix(`))continue;let a=h(i,t,0);if(a){e[r]=b(a);continue}let o=i.startsWith(`var(`)?D(i,t):null;o!==null&&o!==i?e[r]=o:console.error(`webority-theme-export: ${r} in ${n} left as written: ${i}`)}}var{files:k,product:A,out:j,widths:M}=a(process.argv.slice(2)),N={},P={},F={};for(let t of k){let n=e(t,`utf8`).replace(/\/\*[\s\S]*?\*\//g,``);for(let e of x(n)){let t=t=>e.selectors.some(e=>t.has(e)),n=t(w)?P:t(T)?F:t(C)?N:null;if(n)for(let[t,r]of E(e.body))n[t]=r}}O(N,e=>N[e],`light`),O(P,e=>e in P?P[e]:N[e],`dark`),O(F,e=>e in F?F[e]:e in P?P[e]:N[e],`bootstrapDark`);var I=r.filter(e=>!(e in N));I.length>0&&(console.error(`webority-theme-export: ${k.join(`, `)} declares no ${I.join(`, `)} on :root.`),console.error(`Pass the compiled stylesheet that carries the full theme, not a page or component bundle.`),process.exit(1));var L=e=>Object.fromEntries(Object.entries(e).sort(([e],[t])=>e.localeCompare(t))),R=`${JSON.stringify({format:n,product:A,light:L(N),dark:L(P),bootstrapDark:L(F)},null,2)}\n`;if(M.length>0){let e=j.replace(/\.json$/i,``);for(let r of M){let i=`${e}-${r}.json`,a={light:c(N,r),dark:c(P,r),bootstrapDark:c(F,r)},o={format:n,product:A,width:r,light:L(a.light),dark:L(a.dark),bootstrapDark:L(a.bootstrapDark)};t(i,`${JSON.stringify(o,null,2)}\n`),process.stderr.write(`webority-theme-export: ${Object.keys(N).length} light values at ${r}px -> ${i}\n`)}}else j?(t(j,R),process.stderr.write(`webority-theme-export: ${Object.keys(N).length} light and ${Object.keys(P).length} dark and ${Object.keys(F).length} Bootstrap dark values -> ${j}\n`)):process.stdout.write(R);export{};
@@ -1,249 +0,0 @@
1
- // Signal: an opt-in brand layer, a violet-primary palette with ink headings and a serif display face.
2
- // Its dark mode is pure black with neutral grey surfaces; violet is kept for accents only.
3
- //
4
- // Loaded AFTER webority-theme.css; the default theme never contains these values. It re-points the
5
- // --wui-* tokens, then overrides the few Bootstrap values the theme compiles as literals (button
6
- // variables, link and focus-ring colours, dark-mode rgb triplets), because those are not tokens.
7
- //
8
- // Dark mode must match or beat the theme's own selectors, which are
9
- // :root[data-theme="dark"], :root[data-bs-theme="dark"] and, under @media (prefers-color-scheme: dark),
10
- // :root[data-theme="auto"] (see _wui-aliases.scss). A lone [data-theme=dark] loses to the second and
11
- // third, so the dark block below is emitted under all three.
12
-
13
- // The theme ships the Demi Bold file but declares no weight-600 face for the display family.
14
- @font-face {
15
- font-family: "Webority Serif";
16
- font-style: normal;
17
- font-weight: 600;
18
- font-display: swap;
19
- src: url("../fonts/serif/WeboritySerif-DemiBold.woff2") format("woff2");
20
- }
21
-
22
- :root {
23
- // Named brand constants; the dark fills below read --wui-signal-dark-fill and --wui-signal-dark-fill-hover.
24
- --wui-signal-violet: #4A0FBF;
25
- --wui-signal-violet-hover: #3D0CA0;
26
- --wui-signal-tint: #F1EBFF;
27
- --wui-signal-ink: #16093A;
28
- --wui-signal-heading: #4C1D95;
29
- // Reserved for unread counts (white text on it is 5.6:1); never a button or link colour.
30
- --wui-signal-pink: #B517C8;
31
- // Filled primary controls in dark mode: lighter than the light-mode fill so the edge shows on the ink page.
32
- --wui-signal-dark-fill: #5A22D6;
33
- --wui-signal-dark-fill-hover: #6B35E6;
34
-
35
- --bs-font-sans-serif: "Webority Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
36
- --bs-body-font-family: var(--bs-font-sans-serif);
37
- --wui-font-display: "Webority Serif", Georgia, "Times New Roman", serif;
38
-
39
- --wui-primary: #4A0FBF;
40
- --wui-primary-hover: #3D0CA0;
41
- --wui-primary-pressed: #340A88;
42
- --wui-primary-50: #8B66E6;
43
- --wui-primary-30: #B9A2F2;
44
- --wui-primary-20: #D9CBFA;
45
- --wui-primary-15: #E6DCFD;
46
- --wui-primary-10: #F1EBFF;
47
- --wui-primary-5: #F8F5FF;
48
- --wui-primary-text: #FFFFFF;
49
- // Violet clears 4.5:1 as text on every light surface and its tint, so it is its own ink.
50
- --wui-primary-ink: var(--wui-primary, #4A0FBF);
51
- --wui-accent-dark: #340A88;
52
- --wui-surface-soft: #F1EBFF;
53
- --wui-surface-violet: #E6DCFD;
54
- --wui-surface-violet-soft: #F8F5FF;
55
- --wui-hero-gradient: radial-gradient(ellipse 120% 80% at 50% 30%, #8B66E6 0%, #4A0FBF 35%, #3D0CA0 75%, #16093A 100%);
56
- --wui-cta-gradient: radial-gradient(ellipse 120% 100% at 50% 50%, #2B1150 0%, #16093A 60%, #0E0626 100%);
57
-
58
- --wui-text-heading: #16093A;
59
- --wui-text-1: #2B2B2B;
60
- --wui-text-2: #5A5A5A;
61
- // Muted text: #777777 measures 4.48:1 on white and less on the tints; #6A6A6A clears 4.5:1 on every tint, the violet one included.
62
- --wui-text-3: #6A6A6A;
63
- --wui-text-4: #9A9A9A;
64
- --wui-text-5: #CFC9DE;
65
- --wui-ink: #16093A;
66
-
67
- --wui-bg-page: #F8F6FD;
68
- --wui-bg-light: #FFFFFF;
69
- --wui-bg-elevated: #FBFAFE;
70
- --wui-bg-muted: #F3EFFB;
71
- --wui-field-bg: #FBFAFE;
72
- --wui-border-light: #E8E4F2;
73
- --wui-border-soft: #F3F0FA;
74
- --wui-progress-track: #E8E4F2;
75
- --wui-neutral-border-dark: #E8E4F2;
76
- --wui-neutral-bg-dark: #F3EFFB;
77
- --wui-shadow-overlay: 0 8px 28px -6px rgba(22, 9, 58, 0.16);
78
- --wui-shadow-overlay-lg: 0 24px 60px -16px rgba(22, 9, 58, 0.30);
79
-
80
- // Dark mode is pure black and neutral grey; violet appears only on accents (fills, links, focus, selection marks).
81
- --wui-dark-bg-page: #000000;
82
- --wui-dark-bg-elevated: #0F0F0F;
83
- --wui-dark-bg-surface: #161616;
84
- --wui-dark-bg-muted: #1E1E1E;
85
- --wui-dark-border: #2A2A2A;
86
- --wui-dark-border-strong: #333333;
87
- --wui-dark-progress-track: #333333;
88
- --wui-dark-text: #EDEDED;
89
- --wui-dark-text-muted: #C0C0C0;
90
- --wui-dark-text-subtle: #A0A0A0;
91
- --wui-dark-primary: #A98BFF;
92
- --wui-dark-primary-hover: #BFA6FF;
93
-
94
- // Values the theme compiles as literals rather than tokens.
95
- --bs-primary: #4A0FBF;
96
- --bs-primary-rgb: 74, 15, 191;
97
- // Each link value reads the token a product re-points; a triplet cannot be derived from a hex at
98
- // runtime, so it reads its own -rgb token and a product sets the pair together.
99
- --bs-link-color: var(--wui-primary-ink, #4A0FBF);
100
- --bs-link-color-rgb: var(--wui-primary-ink-rgb, 74, 15, 191);
101
- --bs-link-hover-color: var(--wui-primary-hover, #3D0CA0);
102
- --bs-link-hover-color-rgb: var(--wui-primary-hover-rgb, 61, 12, 160);
103
- --bs-focus-ring-color: rgba(74, 15, 191, 0.3);
104
- }
105
-
106
- // Bootstrap compiles its button variables to literal indigo; re-point them on the classes.
107
- .btn-primary {
108
- --bs-btn-color: var(--wui-primary-text, #fff);
109
- --bs-btn-bg: var(--wui-primary, #4A0FBF);
110
- --bs-btn-border-color: var(--wui-primary, #4A0FBF);
111
- --bs-btn-hover-color: var(--wui-primary-text, #fff);
112
- --bs-btn-hover-bg: var(--wui-primary-hover, #3D0CA0);
113
- --bs-btn-hover-border-color: var(--wui-primary-hover, #3D0CA0);
114
- --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb, 74, 15, 191);
115
- --bs-btn-active-color: var(--wui-primary-text, #fff);
116
- --bs-btn-active-bg: var(--wui-primary-pressed, #340A88);
117
- --bs-btn-active-border-color: var(--wui-primary-pressed, #340A88);
118
- --bs-btn-disabled-color: var(--wui-primary-text, #fff);
119
- --bs-btn-disabled-bg: var(--wui-primary, #4A0FBF);
120
- --bs-btn-disabled-border-color: var(--wui-primary, #4A0FBF);
121
- }
122
-
123
- .btn-outline-primary {
124
- --bs-btn-color: var(--color-primary-ink);
125
- --bs-btn-border-color: var(--color-primary);
126
- --bs-btn-hover-color: var(--wui-primary-text, #fff);
127
- --bs-btn-hover-bg: var(--wui-primary, #4A0FBF);
128
- --bs-btn-hover-border-color: var(--wui-primary, #4A0FBF);
129
- --bs-btn-active-color: var(--wui-primary-text, #fff);
130
- --bs-btn-active-bg: var(--wui-primary-pressed, #340A88);
131
- --bs-btn-active-border-color: var(--wui-primary-pressed, #340A88);
132
- --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb, 74, 15, 191);
133
- }
134
-
135
- .form-check-input:checked {
136
- background-color: var(--color-primary);
137
- border-color: var(--color-primary);
138
- }
139
-
140
- // Display type: Webority Serif Demi Bold only at 24px and above (page and result titles); every
141
- // smaller title stays in Webority Sans.
142
- .page-title,
143
- .result-title {
144
- font-family: var(--wui-font-display);
145
- font-weight: 600;
146
- font-style: normal;
147
- letter-spacing: -0.01em;
148
- color: var(--color-text);
149
- }
150
- // The compact page titles (size sm and the page header bar) are 20px, so they keep the sans face.
151
- .page-header-sm .page-title,
152
- .page-header.page-header-bar .page-title {
153
- font-family: inherit;
154
- }
155
-
156
- @mixin wui-signal-dark {
157
- --wui-signal-heading: #C4AEFF;
158
- // Selected, hover and highlight fills are a neutral lift; the violet stays on the text, border
159
- // or edge that marks the state. check-contrast.mjs mirrors the 8%; change them together.
160
- --color-primary-soft: color-mix(in srgb, #FFFFFF 8%, transparent);
161
- // The published primary pair is the one the primary button paints: deep violet with a white label.
162
- // The lilac --wui-dark-primary stays the ink for text, links and focus on the dark surfaces.
163
- --color-primary: var(--wui-signal-dark-fill, #5A22D6);
164
- --color-primary-hover: var(--wui-signal-dark-fill-hover, #6B35E6);
165
- --color-primary-text: var(--wui-dark-primary-text, #FFFFFF);
166
- --color-primary-hover-text: var(--wui-dark-primary-text, #FFFFFF);
167
- --bs-body-bg-rgb: 0, 0, 0;
168
- --bs-body-color-rgb: 237, 237, 237;
169
- --bs-emphasis-color-rgb: 237, 237, 237;
170
- --bs-secondary-color-rgb: 192, 192, 192;
171
- --bs-tertiary-color-rgb: 160, 160, 160;
172
- --bs-secondary-bg-rgb: 22, 22, 22;
173
- --bs-tertiary-bg-rgb: 30, 30, 30;
174
- --bs-border-color-rgb: 42, 42, 42;
175
- --bs-link-color: var(--wui-dark-primary, #A98BFF);
176
- --bs-link-color-rgb: var(--wui-dark-primary-rgb, 169, 139, 255);
177
- --bs-link-hover-color: var(--wui-dark-primary-hover, #BFA6FF);
178
- --bs-link-hover-color-rgb: var(--wui-dark-primary-hover-rgb, 191, 166, 255);
179
- --bs-focus-ring-color: rgba(169, 139, 255, 0.4);
180
-
181
- .btn-primary {
182
- --bs-btn-bg: var(--wui-signal-dark-fill, #5A22D6);
183
- --bs-btn-border-color: var(--wui-signal-dark-fill, #5A22D6);
184
- --bs-btn-hover-bg: var(--wui-signal-dark-fill-hover, #6B35E6);
185
- --bs-btn-hover-border-color: var(--wui-signal-dark-fill-hover, #6B35E6);
186
- --bs-btn-active-bg: var(--wui-primary, #4A0FBF);
187
- --bs-btn-active-border-color: var(--wui-primary, #4A0FBF);
188
- --bs-btn-disabled-bg: var(--wui-signal-dark-fill, #5A22D6);
189
- --bs-btn-disabled-border-color: var(--wui-signal-dark-fill, #5A22D6);
190
- }
191
-
192
- .btn-outline-primary {
193
- --bs-btn-hover-bg: var(--wui-signal-dark-fill, #5A22D6);
194
- --bs-btn-hover-border-color: var(--wui-signal-dark-fill, #5A22D6);
195
- }
196
-
197
- .form-check-input:checked {
198
- background-color: var(--wui-signal-dark-fill, #5A22D6);
199
- border-color: var(--wui-signal-dark-fill, #5A22D6);
200
- }
201
-
202
- // The untoned bar fills with the deep violet --bs-primary, where the dark-mode label ink fails. The tone
203
- // bars and the count badges sit on the light dark-mode fills and keep --color-progress-label.
204
- :where(&) .progress-bar:not([class*="wui-progress-"]) {
205
- color: var(--wui-dark-primary-text, #FFFFFF);
206
- }
207
-
208
- // The active step's number sits on the lilac ink fill (--wui-step-accent); white is 2.68:1 there.
209
- :where(.stepper:not(.wizard-stepper)) {
210
- --wui-step-accent-fg: var(--wui-signal-ink, #16093A);
211
- }
212
-
213
- // Components that mix their violet fill inline rather than through --color-primary-soft.
214
- // :where(&) keeps each rule at the component's own specificity, so a tone variant still wins.
215
- :where(&) .struct-card.checked,
216
- :where(&) .tpg-arrow:hover:not(:disabled),
217
- :where(&) .tpg-page:hover:not(.is-active),
218
- :where(&) .u-action:hover:not(:disabled),
219
- :where(&) .tbl-empty-icon,
220
- :where(&) .u-avatar,
221
- :where(&) .wui-file-viewer-audio-art {
222
- background: var(--color-primary-soft);
223
- }
224
- :where(&) .wui-calendar-view-btn[aria-pressed="true"],
225
- :where(&) .compare-table td.is-highlight {
226
- background: color-mix(in srgb, #FFFFFF 8%, var(--color-surface));
227
- }
228
- :where(&) .table-ledger tbody tr.is-selected:hover {
229
- --bs-table-bg-state: color-mix(in srgb, #FFFFFF 12%, transparent);
230
- }
231
- // A grey row alone reads as disabled; the violet edge says chosen. One step below the row status
232
- // bar's specificity, so a status row keeps its own colour bar.
233
- :where(&) .table-ledger tbody tr.is-selected > :first-child {
234
- box-shadow:
235
- inset 3px 0 0 0 var(--color-primary),
236
- inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)));
237
- }
238
- }
239
-
240
- :root[data-theme="dark"],
241
- :root[data-bs-theme="dark"] {
242
- @include wui-signal-dark;
243
- }
244
-
245
- :root[data-theme="auto"] {
246
- @media (prefers-color-scheme: dark) {
247
- @include wui-signal-dark;
248
- }
249
- }