@energycap/internal-ui 0.1.1 → 0.1.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,52 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@energycap/internal-ui` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/).
7
+
8
+ > **Upgrading?** Breaking changes are called out with a **BREAKING** marker and
9
+ > collected under `### Changed` / `### Removed`. Review those sections before
10
+ > bumping across a minor (pre-1.0) or major version.
11
+
12
+ ## [0.1.3] - 2026-06-30
13
+
14
+ ### Added
15
+
16
+ - This CHANGELOG.
17
+
18
+ ### Changed
19
+
20
+ - Sidebar footer links (`.sidebar-footer a`) now use the brighter
21
+ `on-dark-muted-strong` (slate-400) tone so they read as links against the dark
22
+ sidebar instead of blending into the muted footer text.
23
+
24
+ ## [0.1.2] - 2026-06-30
25
+
26
+ ### Changed
27
+
28
+ - Color and layout refinements across the theme tokens and components.
29
+
30
+ ### Other
31
+
32
+ - Packaging and version maintenance. The docs kitchen-sink now reads the package
33
+ version automatically so it never drifts from the published version.
34
+
35
+ ## [0.1.1] - 2026-06-29
36
+
37
+ ### Fixed
38
+
39
+ - CI release pipeline: npm publish and Netlify deploy path/working-directory
40
+ fixes, and a supported Node version for the release workflow.
41
+
42
+ ## [0.1.0] - 2026-06-29
43
+
44
+ ### Added
45
+
46
+ - Initial release. A framework-agnostic Tailwind v4 theme + component-class
47
+ library: design tokens (Indigo primary, Slate neutrals, Inter / Cascadia Code)
48
+ and component classes (`.btn`, `.card`, `.badge-*`, `.alert-*`, form controls,
49
+ `.table-container`, and the sidebar/layout app shell).
50
+ - Two consumption paths: the `.` export (`src/index.css`) for Tailwind-build
51
+ consumers, and the prebuilt no-build bundle (`dist/internal-ui.css`).
52
+ - CLI (`npx @energycap/internal-ui install-skills`) and bundled agent skills.
package/README.md CHANGED
@@ -37,12 +37,14 @@ color tokens are also exposed as Tailwind utilities.
37
37
  |----------|---------|-------|
38
38
  | `--primary` / `--primary-hover` | `bg-primary` / `bg-primary-hover`, `text-primary` | indigo 600 / 700 |
39
39
  | `--primary-light` | `bg-primary-light`, `border-l-primary-light` | indigo-400 (accent on dark surfaces) |
40
- | `--primary-soft` | — | indigo-600 @ 15% (focus ring / soft fill) |
40
+ | `--primary-soft` | — | indigo-300 (focus ring / soft fill) |
41
41
  | `--canvas` | `bg-canvas` | slate-50 (page background) |
42
42
  | `--surface` / `--surface-alt` | `bg-surface` / `bg-surface-alt` | white / slate-100 |
43
43
  | `--border` / `--border-strong` | `border-border` / `border-border-strong` | slate-200 / slate-400 |
44
44
  | `--ink` / `--ink-soft` | `text-ink` / `text-ink-soft` | slate-900 / slate-800 |
45
45
  | `--muted` / `--muted-strong` | `text-muted` / `text-muted-strong` | slate-500 / slate-600 |
46
+ | `--on-dark` / `--on-dark-soft` | `text-on-dark` / `text-on-dark-soft` | slate-100 / slate-300 (text on dark surfaces) |
47
+ | `--on-dark-muted` / `--on-dark-muted-strong` | `text-on-dark-muted` / `text-on-dark-muted-strong` | slate-500 / slate-400 (muted text on dark) |
46
48
  | `--success` / `--warning` / `--danger` / `--info` | `text-*` / `bg-*` | green-600 / amber-600 / red-600 / blue-500 |
47
49
  | `--danger-hover` | `bg-danger-hover` | red-700 (solid danger button hover) |
48
50
  | `--{success,warning,danger,info}-bg` / `-text` | — | soft fill + readable text for alerts/badges |
@@ -77,3 +79,8 @@ npx @energycap/internal-ui install-skills # -> ./.agents/skills
77
79
  npm run build # compile dist/internal-ui.css (minified)
78
80
  npm run build:debug # same, unminified for inspection
79
81
  ```
82
+
83
+ ## Changelog
84
+
85
+ See [`CHANGELOG.md`](./CHANGELOG.md) for release notes and breaking changes to
86
+ review before upgrading.
package/bin/cli.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /* @energycap/internal-ui CLI — currently just installs the bundled agent skills
3
- into a consuming repo's agent-agnostic .agents/skills directory. */
3
+ (shipped under the package's src/skills) into a consuming repo's agent-agnostic
4
+ .agents/skills directory. */
4
5
  import { cp, mkdir, readdir } from 'node:fs/promises';
5
6
  import { existsSync } from 'node:fs';
6
7
  import { dirname, join, resolve } from 'node:path';
@@ -24,7 +25,7 @@ function parseFlags(args) {
24
25
 
25
26
  async function installSkills(args) {
26
27
  const flags = parseFlags(args);
27
- const src = join(PKG_ROOT, 'skills');
28
+ const src = join(PKG_ROOT, 'src', 'skills');
28
29
  const dest = resolve(process.cwd(), flags.dest || '.agents/skills');
29
30
 
30
31
  if (!existsSync(src)) {
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading:initial;--tw-font-weight:initial;--tw-border-style:solid;--tw-tracking:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-mono:"Cascadia Code", "Fira Code", "Consolas", monospace;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--tracking-wider:.05em;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}body{font-family:var(--font-sans,"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);color:var(--ink);background:var(--canvas);-webkit-font-smoothing:antialiased;line-height:1.5}ol{padding-left:1.5em;list-style:decimal}ul{padding-left:1.5em;list-style:outside}:focus:not(:focus-visible){outline:none}:focus-visible{outline:2px solid var(--primary);outline-offset:2px;border-radius:3px}}@layer components{.btn{cursor:pointer;justify-content:center;align-items:center;gap:calc(var(--spacing) * 1.5);border-radius:var(--radius-md);padding-inline:calc(var(--spacing) * 3.5);padding-block:calc(var(--spacing) * 1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-leading:var(--leading-normal);line-height:var(--leading-normal);--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-white);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));text-decoration-line:none;display:inline-flex}.btn:hover{color:var(--color-white);text-decoration-line:none}.btn:disabled{cursor:not-allowed;opacity:.6}.btn:focus-visible{--tw-outline-style:none;box-shadow:0 0 0 3px var(--primary-soft);outline-style:none}.btn-primary{background-color:var(--primary)}.btn-primary:hover{background-color:var(--primary-hover)}.btn-danger{background-color:var(--danger)}.btn-danger:hover{background-color:var(--danger-hover)}.btn-outline{border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);color:var(--ink)}.btn-outline:hover{border-color:var(--border-strong);background-color:var(--canvas);color:var(--ink)}.btn-sm{padding-inline:calc(var(--spacing) * 2.5);padding-block:var(--spacing);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.btn-icon-only{height:calc(var(--spacing) * 8);width:calc(var(--spacing) * 8);padding:0}.btn-group{align-items:center;gap:calc(var(--spacing) * 1.5);display:inline-flex}.form-group{margin-bottom:calc(var(--spacing) * 5)}.form-group>label{margin-bottom:calc(var(--spacing) * 1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink);display:block}.form-control{border-radius:var(--radius-md);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);width:100%;padding-inline:calc(var(--spacing) * 3);padding-block:calc(var(--spacing) * 2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--ink);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));font-family:inherit}.form-control::placeholder{color:var(--border-strong)}.form-control:focus{border-color:var(--primary);--tw-outline-style:none;box-shadow:0 0 0 3px var(--primary-soft);outline-style:none}textarea.form-control{min-height:calc(var(--spacing) * 30);resize:vertical;font-family:var(--font-mono);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}select.form-control{cursor:pointer;appearance:none;padding-right:calc(var(--spacing) * 9);--tw-leading:var(--leading-snug);line-height:var(--leading-snug);background-image:linear-gradient(45deg, transparent 50%, var(--border-strong) 50%), linear-gradient(135deg, var(--border-strong) 50%, transparent 50%);background-position:right 16px center,right 11px center;background-repeat:no-repeat;background-size:5px 5px,5px 5px}.form-hint{margin-top:var(--spacing);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--muted)}.form-actions{margin-top:calc(var(--spacing) * 6);gap:calc(var(--spacing) * 2.5);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--border);padding-top:calc(var(--spacing) * 4);display:flex}.card{border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);padding-inline:calc(var(--spacing) * 6);padding-block:calc(var(--spacing) * 5);box-shadow:var(--shadow-card)}.card-heading{margin-bottom:calc(var(--spacing) * 4);align-items:center;gap:calc(var(--spacing) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--border);padding-bottom:calc(var(--spacing) * 2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink-soft);display:flex}.card-heading i{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--muted)}.table-container{border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);max-width:100%;box-shadow:var(--shadow-card);overflow:auto}.table-container table{border-collapse:collapse;width:100%}.table-container thead th{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--border);background-color:var(--surface-alt);padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 2.5);text-align:left;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide);color:var(--muted);text-transform:uppercase}.table-container tbody td{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--border);padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 2.5);vertical-align:middle;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.table-container tbody tr:last-child td{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.table-container tbody tr:hover{background-color:var(--canvas)}.table-container tfoot td{border-top-style:var(--tw-border-style);border-top-width:2px;border-color:var(--border);background-color:var(--canvas);padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink-soft)}.table-empty{padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 10);text-align:center;color:var(--muted)}.table-sticky thead th{z-index:2;background-color:var(--surface-alt);box-shadow:inset 0 -1px 0 var(--border);position:sticky;top:0}.row-clickable{cursor:pointer;position:relative}.row-clickable:focus-within{background-color:var(--canvas)}.row-anchor{z-index:1;text-indent:-9999px;color:inherit;position:absolute;inset:0;overflow:hidden}.row-anchor:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:var(--primary);outline-offset:-2px;border-radius:2px}.badge{align-items:center;gap:var(--spacing);padding-inline:calc(var(--spacing) * 2);padding-block:calc(var(--spacing) * .5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);white-space:nowrap;border-radius:3.40282e38px;display:inline-flex}.badge-success{background:var(--success-bg);color:var(--success-text)}.badge-warning{background:var(--warning-bg);color:var(--warning-text)}.badge-danger{background:var(--danger-bg);color:var(--danger-text)}.badge-info{background:var(--info-bg);color:var(--info-text)}.badge-muted{background-color:var(--surface-alt);color:var(--muted-strong)}.alert{margin-bottom:calc(var(--spacing) * 4);align-items:center;gap:calc(var(--spacing) * 2);border-radius:var(--radius-md);padding-inline:calc(var(--spacing) * 3.5);padding-block:calc(var(--spacing) * 2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);display:flex}.alert-success{border-style:var(--tw-border-style);border-width:1px;border-color:var(--success);background:var(--success-bg);color:var(--success-text)}.alert-warning{border-style:var(--tw-border-style);border-width:1px;border-color:var(--warning);background:var(--warning-bg);color:var(--warning-text)}.alert-error,.alert-danger{border-style:var(--tw-border-style);border-width:1px;border-color:var(--danger);background:var(--danger-bg);color:var(--danger-text)}.alert-info{border-style:var(--tw-border-style);border-width:1px;border-color:var(--info);background:var(--info-bg);color:var(--info-text)}.app-shell{min-height:100dvh;display:flex}.sidebar{width:calc(var(--spacing) * 55);background-color:var(--ink);flex-direction:column;flex-shrink:0;display:flex}.sidebar-brand{align-items:center;gap:calc(var(--spacing) * 2.5);border-bottom-style:var(--tw-border-style);border-color:#ffffff1a;border-bottom-width:1px;display:flex}@supports (color:color-mix(in lab, red, red)){.sidebar-brand{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.sidebar-brand{padding-inline:calc(var(--spacing) * 4.5);padding-block:calc(var(--spacing) * 4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide);color:var(--color-white)}.sidebar-nav{padding-inline:0;padding-block:calc(var(--spacing) * 2);flex:1;margin:0;list-style-type:none;overflow-y:auto}.sidebar-nav .nav-section{padding-inline:calc(var(--spacing) * 4.5);padding-top:calc(var(--spacing) * 4);padding-bottom:calc(var(--spacing) * 1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--muted-strong);text-transform:uppercase}.sidebar-nav a{align-items:center;gap:calc(var(--spacing) * 2.5);border-left-style:var(--tw-border-style);padding-inline:calc(var(--spacing) * 4.5);padding-block:calc(var(--spacing) * 2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--border-strong);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));border-color:#0000;border-left-width:3px;text-decoration-line:none;display:flex}.sidebar-nav a:hover{background-color:#ffffff0f}@supports (color:color-mix(in lab, red, red)){.sidebar-nav a:hover{background-color:color-mix(in oklab, var(--color-white) 6%, transparent)}}.sidebar-nav a:hover{color:var(--color-white)}.sidebar-nav a.active{background-color:#ffffff0f}@supports (color:color-mix(in lab, red, red)){.sidebar-nav a.active{background-color:color-mix(in oklab, var(--color-white) 6%, transparent)}}.sidebar-nav a.active{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--color-white);border-left-color:var(--primary-light)}.sidebar-nav .nav-icon{width:calc(var(--spacing) * 4.5);opacity:.6;flex-shrink:0}.sidebar-footer{border-top-style:var(--tw-border-style);border-color:#ffffff1a;border-top-width:1px}@supports (color:color-mix(in lab, red, red)){.sidebar-footer{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.sidebar-footer{padding-inline:calc(var(--spacing) * 4.5);padding-block:calc(var(--spacing) * 3);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--muted-strong)}.sidebar-footer a{color:var(--border-strong);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));text-decoration-line:none}.sidebar-footer a:hover{color:var(--color-white)}.main-content{background-color:var(--canvas);min-width:0;padding-inline:calc(var(--spacing) * 8);padding-block:calc(var(--spacing) * 6);flex:1}.content-header{margin-bottom:calc(var(--spacing) * 6)}.content-header h1{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink)}.subtitle{margin-top:calc(var(--spacing) * .5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--muted)}.toolbar{margin-bottom:calc(var(--spacing) * 4);justify-content:space-between;align-items:center;gap:calc(var(--spacing) * 3);display:flex}.toolbar-spacer{flex:1}.pagination{margin-top:calc(var(--spacing) * 4);justify-content:space-between;align-items:center;gap:calc(var(--spacing) * 3);flex-wrap:wrap;display:flex}.pagination-summary{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--muted)}.pagination-summary strong{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink)}.pagination-controls{align-items:center;gap:calc(var(--spacing) * 1.5);flex-wrap:wrap;display:flex}.pagination-disabled{cursor:not-allowed;opacity:.4}}@layer utilities;:root{--primary:#4f46e5;--primary-hover:#4338ca;--primary-light:#818cf8;--primary-soft:#4f46e526;--canvas:#f8fafc;--surface:#fff;--surface-alt:#f1f5f9;--border:#e2e8f0;--border-strong:#94a3b8;--ink:#0f172a;--ink-soft:#1e293b;--muted:#64748b;--muted-strong:#475569;--success:#16a34a;--warning:#d97706;--danger:#dc2626;--danger-hover:#b91c1c;--info:#3b82f6;--success-bg:#dcfce7;--success-text:#15803d;--warning-bg:#fef9c3;--warning-text:#a16207;--danger-bg:#fee2e2;--danger-text:#b91c1c;--info-bg:#dbeafe;--info-text:#2563eb;--radius-sm:4px;--radius-md:6px;--radius-lg:8px;--shadow-card:0 1px 3px #0f172a0f, 0 0 0 1px #0f172a08}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-mono:"Cascadia Code", "Fira Code", "Consolas", monospace;--color-red-100:oklch(93.6% .032 17.717);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-amber-600:oklch(66.6% .179 58.318);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-700:oklch(55.4% .135 66.442);--color-green-100:oklch(96.2% .044 156.743);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--tracking-wider:.05em;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}body{font-family:var(--font-sans,"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);color:var(--ink);background:var(--canvas);-webkit-font-smoothing:antialiased;line-height:1.5}ol{padding-left:1.5em;list-style:decimal}ul{padding-left:1.5em;list-style:outside}:focus:not(:focus-visible){outline:none}:focus-visible{outline:2px solid var(--primary);outline-offset:2px;border-radius:3px}}@layer components{.btn{cursor:pointer;justify-content:center;align-items:center;gap:calc(var(--spacing) * 1.5);border-radius:var(--radius-md);border-style:var(--tw-border-style);padding-inline:calc(var(--spacing) * 3.5);padding-block:calc(var(--spacing) * 1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-leading:var(--leading-normal);line-height:var(--leading-normal);--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-white);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));border-width:1px;border-color:#0000;text-decoration-line:none;display:inline-flex}.btn:hover{color:var(--color-white);text-decoration-line:none}.btn:disabled{cursor:not-allowed;opacity:.6}.btn:focus-visible{--tw-outline-style:none;box-shadow:0 0 0 3px var(--primary-soft);outline-style:none}.btn-primary{background-color:var(--primary)}.btn-primary:hover{background-color:var(--primary-hover)}.btn-danger{background-color:var(--danger)}.btn-danger:hover{background-color:var(--danger-hover)}.btn-primary:focus-visible,.btn-danger:focus-visible{border-color:var(--color-white)}.btn-outline{border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);color:var(--ink)}.btn-outline:hover{border-color:var(--border-strong);background-color:var(--canvas);color:var(--ink)}.btn-outline:focus-visible{border-color:var(--primary)}.btn-sm{padding-inline:calc(var(--spacing) * 2.5);padding-block:var(--spacing);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.btn-icon-only{height:calc(var(--spacing) * 8);width:calc(var(--spacing) * 8);padding:0}.btn-group{align-items:center;gap:calc(var(--spacing) * 1.5);display:inline-flex}.form-group{margin-bottom:calc(var(--spacing) * 5)}.form-group>label{margin-bottom:calc(var(--spacing) * 1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink);display:block}.form-control{border-radius:var(--radius-md);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);width:100%;padding-inline:calc(var(--spacing) * 3);padding-block:calc(var(--spacing) * 2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--ink);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));font-family:inherit}.form-control::placeholder{color:var(--border-strong)}.form-control:focus{border-color:var(--primary);--tw-outline-style:none;box-shadow:0 0 0 3px var(--primary-soft);outline-style:none}textarea.form-control{min-height:calc(var(--spacing) * 30);resize:vertical;font-family:var(--font-mono);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}select.form-control{cursor:pointer;appearance:none;padding-right:calc(var(--spacing) * 9);--tw-leading:var(--leading-snug);line-height:var(--leading-snug);background-image:linear-gradient(45deg, transparent 50%, var(--border-strong) 50%), linear-gradient(135deg, var(--border-strong) 50%, transparent 50%);background-position:right 16px center,right 11px center;background-repeat:no-repeat;background-size:5px 5px,5px 5px}.form-hint{margin-top:var(--spacing);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--muted)}.form-actions{margin-top:calc(var(--spacing) * 6);gap:calc(var(--spacing) * 2.5);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--border);padding-top:calc(var(--spacing) * 4);display:flex}.card{border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);padding-inline:calc(var(--spacing) * 6);padding-block:calc(var(--spacing) * 5);box-shadow:var(--shadow-card)}.card-heading{margin-bottom:calc(var(--spacing) * 4);align-items:center;gap:calc(var(--spacing) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--border);padding-bottom:calc(var(--spacing) * 2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink-soft);display:flex}.card-heading i{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--muted)}.table-container{border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border);background-color:var(--surface);max-width:100%;box-shadow:var(--shadow-card);overflow:auto}.table-container table{border-collapse:collapse;width:100%}.table-container thead th{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--border);background-color:var(--surface-alt);padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 2.5);text-align:left;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide);color:var(--muted);text-transform:uppercase}.table-container tbody td{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--border);padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 2.5);vertical-align:middle;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.table-container tbody tr:last-child td{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.table-container tbody tr:hover{background-color:var(--canvas)}.table-container tfoot td{border-top-style:var(--tw-border-style);border-top-width:2px;border-color:var(--border);background-color:var(--canvas);padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink-soft)}.table-empty{padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 10);text-align:center;color:var(--muted)}.table-sticky thead th{z-index:2;background-color:var(--surface-alt);box-shadow:inset 0 -1px 0 var(--border);position:sticky;top:0}.row-clickable{cursor:pointer;position:relative}.row-clickable:focus-within{background-color:var(--canvas)}.row-anchor{z-index:1;text-indent:-9999px;color:inherit;position:absolute;inset:0;overflow:hidden}.row-anchor:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:var(--primary);outline-offset:-2px;border-radius:2px}.badge{align-items:center;gap:var(--spacing);padding-inline:calc(var(--spacing) * 2);padding-block:calc(var(--spacing) * .5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);white-space:nowrap;border-radius:3.40282e38px;display:inline-flex}.badge-success{background:var(--success-bg);color:var(--success-text)}.badge-warning{background:var(--warning-bg);color:var(--warning-text)}.badge-danger{background:var(--danger-bg);color:var(--danger-text)}.badge-info{background:var(--info-bg);color:var(--info-text)}.badge-muted{background-color:var(--surface-alt);color:var(--muted-strong)}.alert{margin-bottom:calc(var(--spacing) * 4);align-items:center;gap:calc(var(--spacing) * 2);border-radius:var(--radius-md);padding-inline:calc(var(--spacing) * 3.5);padding-block:calc(var(--spacing) * 2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);display:flex}.alert-success{border-style:var(--tw-border-style);border-width:1px;border-color:var(--success);background:var(--success-bg);color:var(--success-text)}.alert-warning{border-style:var(--tw-border-style);border-width:1px;border-color:var(--warning);background:var(--warning-bg);color:var(--warning-text)}.alert-error,.alert-danger{border-style:var(--tw-border-style);border-width:1px;border-color:var(--danger);background:var(--danger-bg);color:var(--danger-text)}.alert-info{border-style:var(--tw-border-style);border-width:1px;border-color:var(--info);background:var(--info-bg);color:var(--info-text)}.app-shell{height:100dvh;display:flex;overflow:hidden}.sidebar{width:calc(var(--spacing) * 55);background-color:var(--ink);flex-direction:column;flex-shrink:0;display:flex}.sidebar-brand{align-items:center;gap:calc(var(--spacing) * 2.5);border-bottom-style:var(--tw-border-style);border-color:#ffffff1a;border-bottom-width:1px;display:flex}@supports (color:color-mix(in lab, red, red)){.sidebar-brand{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.sidebar-brand{padding-inline:calc(var(--spacing) * 4.5);padding-block:calc(var(--spacing) * 4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide);color:var(--on-dark)}.sidebar>nav{flex-direction:column;flex:1;min-height:0;display:flex}.sidebar-nav{padding-inline:0;padding-block:calc(var(--spacing) * 2);flex:1;margin:0;list-style-type:none;overflow-y:auto}.sidebar-nav .nav-section{padding-inline:calc(var(--spacing) * 4.5);padding-top:calc(var(--spacing) * 4);padding-bottom:calc(var(--spacing) * 1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--on-dark-muted);text-transform:uppercase}.sidebar-nav a{align-items:center;gap:calc(var(--spacing) * 2.5);border-left-style:var(--tw-border-style);padding-inline:calc(var(--spacing) * 4.5);padding-block:calc(var(--spacing) * 2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--on-dark-soft);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));border-color:#0000;border-left-width:3px;text-decoration-line:none;display:flex}.sidebar-nav a:hover{background-color:#ffffff0f}@supports (color:color-mix(in lab, red, red)){.sidebar-nav a:hover{background-color:color-mix(in oklab, var(--color-white) 6%, transparent)}}.sidebar-nav a:hover{color:var(--on-dark)}.sidebar-nav a.active{background-color:#ffffff0f}@supports (color:color-mix(in lab, red, red)){.sidebar-nav a.active{background-color:color-mix(in oklab, var(--color-white) 6%, transparent)}}.sidebar-nav a.active{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--on-dark);border-left-color:var(--primary-light)}.sidebar-nav .nav-icon{width:calc(var(--spacing) * 4.5);opacity:.6;flex-shrink:0}.sidebar-footer{border-top-style:var(--tw-border-style);border-color:#ffffff1a;border-top-width:1px}@supports (color:color-mix(in lab, red, red)){.sidebar-footer{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.sidebar-footer{padding-inline:calc(var(--spacing) * 4.5);padding-block:calc(var(--spacing) * 3);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--on-dark-muted)}.sidebar-footer a{color:var(--on-dark-muted-strong);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));text-decoration-line:none}.sidebar-footer a:hover{color:var(--on-dark)}.main-content{background-color:var(--canvas);min-width:0;padding-inline:calc(var(--spacing) * 8);padding-block:calc(var(--spacing) * 6);flex:1;overflow-y:auto}.content-header{margin-bottom:calc(var(--spacing) * 6)}.content-header h1{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink)}.subtitle{margin-top:calc(var(--spacing) * .5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--muted)}.toolbar{margin-bottom:calc(var(--spacing) * 4);justify-content:space-between;align-items:center;gap:calc(var(--spacing) * 3);display:flex}.toolbar-spacer{flex:1}.pagination{margin-top:calc(var(--spacing) * 4);justify-content:space-between;align-items:center;gap:calc(var(--spacing) * 3);flex-wrap:wrap;display:flex}.pagination-summary{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--muted)}.pagination-summary strong{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--ink)}.pagination-controls{align-items:center;gap:calc(var(--spacing) * 1.5);flex-wrap:wrap;display:flex}.pagination-disabled{cursor:not-allowed;opacity:.4}}@layer utilities;:root{--primary:var(--color-indigo-600);--primary-hover:var(--color-indigo-700);--primary-light:var(--color-indigo-400);--primary-soft:var(--color-indigo-300);--canvas:var(--color-slate-50);--surface:var(--color-white);--surface-alt:var(--color-slate-100);--border:var(--color-slate-200);--border-strong:var(--color-slate-400);--ink:var(--color-slate-900);--ink-soft:var(--color-slate-800);--muted:var(--color-slate-500);--muted-strong:var(--color-slate-600);--on-dark:var(--color-slate-100);--on-dark-soft:var(--color-slate-300);--on-dark-muted-strong:var(--color-slate-400);--on-dark-muted:var(--color-slate-500);--success:var(--color-green-600);--warning:var(--color-amber-600);--danger:var(--color-red-600);--danger-hover:var(--color-red-700);--info:var(--color-blue-500);--success-bg:var(--color-green-100);--success-text:var(--color-green-700);--warning-bg:var(--color-yellow-100);--warning-text:var(--color-yellow-700);--danger-bg:var(--color-red-100);--danger-text:var(--color-red-700);--info-bg:var(--color-blue-100);--info-text:var(--color-blue-600);--radius-sm:4px;--radius-md:6px;--radius-lg:8px;--shadow-card:0 1px 3px #0f172a0f, 0 0 0 1px #0f172a08}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@energycap/internal-ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "EnergyCAP internal UI — shared Tailwind v4 theme + component classes for internal tools. Framework-agnostic.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -12,9 +12,9 @@
12
12
  "files": [
13
13
  "src",
14
14
  "dist",
15
- "skills",
16
15
  "bin",
17
- "README.md"
16
+ "README.md",
17
+ "CHANGELOG.md"
18
18
  ],
19
19
  "bin": {
20
20
  "internal-ui": "./bin/cli.mjs"
@@ -22,8 +22,7 @@
22
22
  "scripts": {
23
23
  "build": "tailwindcss -i ./src/dist-entry.css -o ./dist/internal-ui.css --minify",
24
24
  "build:debug": "tailwindcss -i ./src/dist-entry.css -o ./dist/internal-ui.css",
25
- "sync:skills": "node ./scripts/sync-skills.mjs",
26
- "prepublishOnly": "npm run sync:skills && npm run build"
25
+ "prepublishOnly": "npm run build"
27
26
  },
28
27
  "devDependencies": {
29
28
  "@tailwindcss/cli": "^4.3.0",
@@ -2,10 +2,13 @@
2
2
  .btn {
3
3
  @apply inline-flex items-center justify-center gap-1.5 px-3.5 py-1.5
4
4
  rounded-md text-sm font-medium leading-normal text-white
5
+ border border-transparent
5
6
  no-underline cursor-pointer transition-colors;
6
7
  }
7
8
  .btn:hover { @apply text-white no-underline; }
8
9
  .btn:disabled { @apply opacity-60 cursor-not-allowed; }
10
+ /* Focus mirrors .form-control: a primary-soft glow plus a border that turns
11
+ readable against the button's own fill — white on dark fills, primary on outline. */
9
12
  .btn:focus-visible {
10
13
  @apply outline-none;
11
14
  box-shadow: 0 0 0 3px var(--primary-soft);
@@ -17,8 +20,12 @@
17
20
  .btn-danger { @apply bg-danger; }
18
21
  .btn-danger:hover { @apply bg-danger-hover; }
19
22
 
23
+ .btn-primary:focus-visible,
24
+ .btn-danger:focus-visible { @apply border-white; }
25
+
20
26
  .btn-outline { @apply bg-surface border border-border text-ink; }
21
27
  .btn-outline:hover { @apply bg-canvas border-border-strong text-ink; }
28
+ .btn-outline:focus-visible { @apply border-primary; }
22
29
 
23
30
  .btn-sm { @apply px-2.5 py-1 text-xs; }
24
31
  .btn-icon-only { @apply w-8 h-8 p-0; }
@@ -1,37 +1,42 @@
1
1
  @layer components {
2
- /* App shell: sidebar + content side by side, full viewport height. */
3
- .app-shell { @apply flex min-h-dvh; }
2
+ /* App shell: sidebar + content side by side, locked to the viewport so the
3
+ sidebar stays put and only .main-content scrolls. */
4
+ .app-shell { @apply flex h-dvh overflow-hidden; }
4
5
 
5
6
  /* ── Sidebar ──────────────────────────────────────────────────── */
6
7
  .sidebar { @apply flex flex-col shrink-0 w-55 bg-ink; }
7
8
  .sidebar-brand {
8
9
  @apply flex items-center gap-2.5 px-4.5 py-4 text-sm font-bold tracking-wide
9
- text-white border-b border-white/10;
10
+ text-on-dark border-b border-white/10;
10
11
  }
12
+ /* The <nav> wrapper is the flex child that fills the gap so .sidebar-footer
13
+ drops to the bottom; min-h-0 lets the inner list scroll instead of growing. */
14
+ .sidebar > nav { @apply flex-1 flex flex-col min-h-0; }
11
15
  /* px-0 (alongside m-0) keeps the nav flush even under a consumer global
12
- `ul { padding-left }` reset — list padding must never indent nav items. */
16
+ `ul { padding-left }` reset — list padding must never indent nav items.
17
+ flex-1 also bottoms the footer for consumers who skip the <nav> wrapper. */
13
18
  .sidebar-nav { @apply flex-1 m-0 px-0 py-2 list-none overflow-y-auto; }
14
19
  .sidebar-nav .nav-section {
15
- @apply px-4.5 pt-4 pb-1.5 text-xs font-semibold uppercase tracking-wider text-muted-strong;
20
+ @apply px-4.5 pt-4 pb-1.5 text-xs font-semibold uppercase tracking-wider text-on-dark-muted;
16
21
  }
17
22
  .sidebar-nav a {
18
23
  @apply flex items-center gap-2.5 px-4.5 py-2 text-sm font-medium
19
- text-border-strong no-underline border-l-[3px] border-transparent transition-colors;
24
+ text-on-dark-soft no-underline border-l-[3px] border-transparent transition-colors;
20
25
  }
21
- .sidebar-nav a:hover { @apply bg-white/[0.06] text-white; }
26
+ .sidebar-nav a:hover { @apply bg-white/[0.06] text-on-dark; }
22
27
  .sidebar-nav a.active {
23
- @apply bg-white/[0.06] text-white font-semibold;
28
+ @apply bg-white/[0.06] text-on-dark font-semibold;
24
29
  border-left-color: var(--primary-light);
25
30
  }
26
31
  .sidebar-nav .nav-icon { @apply w-4.5 shrink-0 opacity-60; }
27
32
  .sidebar-footer {
28
- @apply px-4.5 py-3 text-xs text-muted-strong border-t border-white/10;
33
+ @apply px-4.5 py-3 text-xs text-on-dark-muted border-t border-white/10;
29
34
  }
30
- .sidebar-footer a { @apply text-border-strong no-underline transition-colors; }
31
- .sidebar-footer a:hover { @apply text-white; }
35
+ .sidebar-footer a { @apply text-on-dark-muted-strong no-underline transition-colors; }
36
+ .sidebar-footer a:hover { @apply text-on-dark; }
32
37
 
33
38
  /* ── Main content ─────────────────────────────────────────────── */
34
- .main-content { @apply flex-1 min-w-0 px-8 py-6 bg-canvas; }
39
+ .main-content { @apply flex-1 min-w-0 px-8 py-6 bg-canvas overflow-y-auto; }
35
40
  .content-header { @apply mb-6; }
36
41
  .content-header h1 { @apply text-xl font-semibold text-ink; }
37
42
  .subtitle { @apply mt-0.5 text-sm text-muted; }
@@ -48,21 +48,21 @@ sans otherwise):
48
48
  outlines. Interactive rows use `.row-clickable` + an inner `.row-anchor`.
49
49
  5. **Match the existing structure.** New screens should reuse the page scaffolds
50
50
  in `reference/page-templates.md`, not invent a new layout.
51
- 6. **Size with Tailwind's scale.** The system is Tailwind v4 and its components
52
- are composed from Tailwind's spacing/type scale. For spacing or sizing beyond
53
- the component classes, use Tailwind utilities (`px-4`, `gap-2`, `max-h-[60vh]`,
54
- `w-55`) — not arbitrary inline `style="…px"`.
51
+ 6. **Size with Tailwind's scale.** For spacing or sizing beyond the component
52
+ classes, use Tailwind utilities (`px-4`, `gap-2`, `max-h-[60vh]`, `w-55`) not
53
+ arbitrary inline `style="…px"`.
55
54
 
56
55
  ## Token quick reference
57
56
 
58
57
  Colors (each is a `var(--name)` and a `bg-`/`text-`/`border-` utility):
59
58
  `primary`, `primary-hover`, `canvas` (page bg), `surface`, `surface-alt`,
60
59
  `border`, `border-strong`, `ink` (text), `ink-soft`, `muted`, `muted-strong`,
61
- `success`, `warning`, `danger`, `info`. Solid danger button hover:
62
- `danger-hover`. Soft pairs for fills/text: `--success-bg`/`--success-text`
60
+ `success`, `warning`, `danger`, `danger-hover`, `info`. For text on dark surfaces
61
+ (e.g. the `bg-ink` sidebar): `on-dark`, `on-dark-soft`, `on-dark-muted`,
62
+ `on-dark-muted-strong`. Soft fill/text pairs: `--success-bg`/`--success-text`
63
63
  (and warning/danger/info).
64
- Other: `--radius-sm|md|lg`, `--shadow-card`,
65
- `font-sans` (Inter), `font-mono` (Cascadia Code).
64
+ Other: `--radius-sm|md|lg`, `--shadow-card`, `font-sans` (Inter),
65
+ `font-mono` (Cascadia Code).
66
66
 
67
67
  ## Component quick reference
68
68
 
package/src/theme.css CHANGED
@@ -5,47 +5,58 @@
5
5
  on: Indigo primary, Slate neutrals, Inter / Cascadia Code. Values mirror
6
6
  the proven tokens shipped in Opus so existing screens shift minimally.
7
7
 
8
- Pattern (Tailwind v4): the raw tokens live in :root so they are ALWAYS
9
- emitted component CSS can rely on `var(--token)` resolving regardless of
10
- which utilities a consumer happens to generate. `@theme inline` then re-
11
- exposes them as Tailwind utilities (bg-primary, text-muted, ) that point
12
- straight back at the :root vars, with no duplicate variables.
8
+ Pattern (Tailwind v4): the semantic tokens live in :root and reference
9
+ Tailwind's own default-palette vars (var(--color-indigo-600), …) instead of
10
+ restating their hex single source of truth. Tailwind detects each
11
+ referenced palette var and emits it (and only it) into the output, including
12
+ the no-build `dist` bundle compiled with `source(none)`, so `var(--token)`
13
+ always resolves regardless of which utilities a consumer generates. Tokens
14
+ with no 1:1 palette match (custom shadow/radius) stay as literals. `@theme inline`
15
+ then re-exposes the semantics as Tailwind utilities (bg-primary, text-muted, …)
16
+ pointing straight back at these :root vars.
13
17
  ════════════════════════════════════════════════════════════════════ */
14
18
 
15
19
  :root {
16
20
  /* Brand / actions */
17
- --primary: #4f46e5; /* indigo-600 */
18
- --primary-hover: #4338ca; /* indigo-700 */
19
- --primary-light: #818cf8; /* indigo-400 accent on dark surfaces (active nav) */
20
- --primary-soft: rgb(79 70 229 / 0.15); /* indigo-600 @ 15% — focus ring / soft fill */
21
+ --primary: var(--color-indigo-600);
22
+ --primary-hover: var(--color-indigo-700);
23
+ --primary-light: var(--color-indigo-400); /* accent on dark surfaces (active nav) */
24
+ --primary-soft: var(--color-indigo-300); /* focus ring / soft fill */
21
25
 
22
26
  /* Surfaces */
23
- --canvas: #f8fafc; /* slate-50 app background */
24
- --surface: #ffffff; /* cards, inputs, panels */
25
- --surface-alt: #f1f5f9; /* slate-100 table headers, subtle fills */
27
+ --canvas: var(--color-slate-50); /* app background */
28
+ --surface: var(--color-white); /* cards, inputs, panels */
29
+ --surface-alt: var(--color-slate-100); /* table headers, subtle fills */
26
30
 
27
31
  /* Lines */
28
- --border: #e2e8f0; /* slate-200 */
29
- --border-strong: #94a3b8; /* slate-400 */
32
+ --border: var(--color-slate-200);
33
+ --border-strong: var(--color-slate-400);
30
34
 
31
- /* Text */
32
- --ink: #0f172a; /* slate-900 primary text */
33
- --ink-soft: #1e293b; /* slate-800 */
34
- --muted: #64748b; /* slate-500 */
35
- --muted-strong: #475569; /* slate-600 */
35
+ /* Text — on light surfaces */
36
+ --ink: var(--color-slate-900); /* primary text */
37
+ --ink-soft: var(--color-slate-800);
38
+ --muted: var(--color-slate-500);
39
+ --muted-strong: var(--color-slate-600);
40
+
41
+ /* Text — on dark surfaces (e.g. the bg-ink sidebar). Mirrors the light scale;
42
+ `-strong` = more contrast (lighter here), matching --muted-strong vs --muted. */
43
+ --on-dark: var(--color-slate-100); /* primary text on dark */
44
+ --on-dark-soft: var(--color-slate-300); /* secondary */
45
+ --on-dark-muted-strong: var(--color-slate-400); /* muted, higher contrast */
46
+ --on-dark-muted: var(--color-slate-500); /* muted, dim (footer, section labels) */
36
47
 
37
48
  /* Semantic — solid (borders, icons, fills) */
38
- --success: #16a34a; /* green-600 */
39
- --warning: #d97706; /* amber-600 */
40
- --danger: #dc2626; /* red-600 */
41
- --danger-hover: #b91c1c; /* red-700 solid danger button hover */
42
- --info: #3b82f6; /* blue-500 */
49
+ --success: var(--color-green-600);
50
+ --warning: var(--color-amber-600);
51
+ --danger: var(--color-red-600);
52
+ --danger-hover: var(--color-red-700); /* solid danger button hover */
53
+ --info: var(--color-blue-500);
43
54
 
44
55
  /* Semantic — soft background + readable text (alerts, badges) */
45
- --success-bg: #dcfce7; --success-text: #15803d; /* green-100 / green-700 */
46
- --warning-bg: #fef9c3; --warning-text: #a16207; /* yellow-100 / yellow-700 */
47
- --danger-bg: #fee2e2; --danger-text: #b91c1c; /* red-100 / red-700 */
48
- --info-bg: #dbeafe; --info-text: #2563eb; /* blue-100 / blue-600 */
56
+ --success-bg: var(--color-green-100); --success-text: var(--color-green-700);
57
+ --warning-bg: var(--color-yellow-100); --warning-text: var(--color-yellow-700);
58
+ --danger-bg: var(--color-red-100); --danger-text: var(--color-red-700);
59
+ --info-bg: var(--color-blue-100); --info-text: var(--color-blue-600);
49
60
 
50
61
  /* Radius (matches Tailwind v4 defaults; redeclared so component CSS resolves) */
51
62
  --radius-sm: 4px;
@@ -77,6 +88,10 @@
77
88
  --color-ink-soft: var(--ink-soft);
78
89
  --color-muted: var(--muted);
79
90
  --color-muted-strong: var(--muted-strong);
91
+ --color-on-dark: var(--on-dark);
92
+ --color-on-dark-soft: var(--on-dark-soft);
93
+ --color-on-dark-muted: var(--on-dark-muted);
94
+ --color-on-dark-muted-strong: var(--on-dark-muted-strong);
80
95
  --color-success: var(--success);
81
96
  --color-warning: var(--warning);
82
97
  --color-danger: var(--danger);