@tekkare/romulus 0.1.177 → 0.1.179

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/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.16.0"
6
6
  },
7
- "version": "0.1.176",
7
+ "version": "0.1.178",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
@@ -1 +1 @@
1
- .grid-2{grid-template-columns:repeat(2,1fr)}.grid-2,.grid-3{display:grid;gap:var(--space-20)}.grid-3{grid-template-columns:repeat(3,1fr)}.grid-4{display:grid;gap:var(--space-16);grid-template-columns:repeat(4,1fr)}.grid-2-1{display:grid;gap:var(--space-20);grid-template-columns:2fr 1fr}.pane-title{color:var(--text-primary);font-family:var(--font-serif);font-size:var(--font-32);font-weight:700;letter-spacing:-.02em;line-height:1.1;margin:0 0 16px}.pane-sub{color:var(--text-muted);font-size:var(--font-13);line-height:1.55;margin:0 0 24px;max-width:78ch}.chart-section{margin-inline:auto;max-width:var(--content-max-w,1440px);padding:0 0 var(--space-40);width:100%}.section-label{align-items:center;color:var(--text-secondary);display:flex;font-size:var(--font-11);font-weight:700;gap:var(--space-8);letter-spacing:.12em;margin:40px 0 18px;text-transform:uppercase}body.text-large .pane-title{font-size:38px}body.text-xl .pane-title{font-size:46px}body.text-large .section-label{font-size:var(--font-13)}body.text-xl .section-label{font-size:var(--font-14)}.chart-card{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:10px;box-shadow:var(--shadow-sm);display:flex;flex-direction:column;transition:box-shadow .18s,border-color .18s}.chart-card:hover{border-color:var(--color-violet-pale);box-shadow:0 6px 16px rgba(107,63,255,.1),0 1px 3px rgba(30,41,59,.04)}.chart-card-head{padding:22px var(--space-24) 14px;padding-right:64px;position:relative}.chart-card-title{color:var(--text-primary);font-size:15px;font-weight:700;letter-spacing:-.01em;line-height:1.3;margin:0 0 5px}.chart-card-context{color:var(--text-muted);font-size:var(--font-12);line-height:1.55;margin:0}.rm-card-actions{position:relative}.chart-card-head>.chart-card-actions{position:absolute;right:12px;top:12px}.cc-export{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:6px;color:var(--text-secondary);cursor:pointer;display:flex;font-size:var(--font-14);height:28px;justify-content:center;transition:background .15s,color .15s,border-color .15s;width:28px}.cc-export:hover{color:var(--color-secondary)}.cc-export:hover,.rm-card-actions.open .cc-export{background:var(--bg-hover);border-color:var(--color-violet-pale)}.rm-card-actions.open .cc-export{color:var(--color-primary)}.cc-menu{animation:cc-menu-in .12s cubic-bezier(.2,0,0,1);background:var(--bg-surface);border:1px solid var(--border-default);border-radius:8px;box-shadow:var(--shadow-lg);display:none;min-width:200px;padding:var(--space-6) 0;position:absolute;right:0;top:34px;z-index:500}.rm-card-actions.open .cc-menu{display:block}.cc-menu-section{color:var(--text-muted);font-size:var(--font-10);font-weight:700;letter-spacing:.08em;padding:var(--space-8) 14px var(--space-4);text-transform:uppercase}.cc-menu-item{align-items:center;background:none;border:0;color:var(--text-secondary);cursor:pointer;display:flex;font-family:var(--font-sans);font-size:var(--font-13);gap:var(--space-10);padding:7px 14px;text-align:left;width:100%}.cc-menu-item i{color:var(--text-muted);font-size:var(--font-14)}.cc-menu-item:hover{background:var(--bg-surface-3);color:var(--text-primary)}.cc-menu-item:hover i{color:var(--text-secondary)}.cc-menu-divider{background:var(--bg-surface-3);height:1px;margin:4px 0}.cc-menu-note{border-top:1px solid var(--bg-surface-3);color:var(--text-secondary);font-size:var(--font-12);margin:4px 0 0;padding:var(--space-8) 14px var(--space-4)}.cc-menu-item[disabled]{cursor:default;opacity:.55}.cc-menu-item[disabled]:hover{background:none;color:var(--text-secondary)}.chart-card:fullscreen,.rm-card-zoom,.rm-rcard:fullscreen,.rm-table-card:fullscreen{background:var(--bg-surface);border-radius:0;box-sizing:border-box;height:100vh;overflow:auto;padding:var(--space-16);width:100vw}.rm-card-zoom{border:0;inset:0;margin:0;position:fixed;z-index:500}body.rm-card-zoom-open{overflow:hidden}.chart-card.rm-card-zoom .chart-card-body,.chart-card:fullscreen .chart-card-body{display:flex;flex-direction:column}.chart-card.rm-card-zoom .rm-chart,.chart-card:fullscreen .rm-chart{flex:1 1 auto}.chart-card.rm-card-zoom .echart,.chart-card:fullscreen .echart{height:72vh!important}@keyframes cc-menu-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.chart-card-body{flex:1;padding:var(--space-4) var(--space-12) var(--space-8)}.chart-card-body>.rm-empty{box-sizing:border-box;gap:var(--space-6);justify-content:center;max-width:none;min-height:240px;padding:36px var(--space-24)}.chart-card-foot{align-items:center;background:var(--bg-surface-2);border-radius:0 0 10px 10px;border-top:1px solid var(--border-soft);color:var(--text-muted);display:flex;flex-wrap:wrap;font-size:var(--font-11);gap:var(--space-10);padding:var(--space-12) var(--space-24)}.chart-card-foot .src{align-items:center;display:flex;gap:var(--space-4)}.chart-card-foot .src b{color:var(--text-secondary);font-weight:600}.chart-card-foot .dot{background:var(--border-default);border-radius:50%;height:3px;width:3px}.chart-card-foot .updated{color:var(--text-secondary);font-weight:500}.kpi-card{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:8px;box-shadow:0 2px 8px rgba(30,41,59,.06);padding:var(--space-16) 18px}.kpi-label{color:var(--text-muted);font-size:var(--font-11);font-weight:600;letter-spacing:.1em;margin:0 0 6px;text-transform:uppercase}.kpi-value{color:var(--color-primary);font-family:var(--font-serif);font-size:28px;font-weight:700;line-height:1;margin:0}.kpi-value.healthcare{color:var(--color-healthcare)}.kpi-value.discovery{color:var(--color-discovery)}.kpi-value.pharma{color:var(--color-pharma)}.kpi-value.databank{color:var(--color-databank)}.kpi-trend{align-items:center;display:inline-flex;font-size:var(--font-12);font-weight:600;gap:var(--space-4);margin-top:6px}.kpi-trend i{font-size:var(--font-11)}.kpi-trend--up{color:var(--color-success)}.kpi-trend--down{color:var(--color-danger)}.kpi-foot,.kpi-trend--flat{color:var(--text-muted)}.kpi-foot{font-size:var(--font-11);margin-top:4px}.kpi-extra{margin-top:12px}.badge{border-radius:4px;display:inline-block;font-size:var(--font-10);font-weight:600;padding:var(--space-2) var(--space-8)}.badge-active{background:var(--color-success-bg);color:var(--color-success)}.badge-pending{background:var(--color-warning-bg);color:var(--color-warning)}.badge-error{background:var(--color-danger-bg);color:var(--color-danger)}.badge-info{background:var(--bg-hover);color:var(--color-primary)}.badge-grey{background:var(--bg-surface-3);color:var(--text-secondary)}table.tk{border-collapse:collapse;font-size:var(--font-13);width:100%}.sr-only,table.tk>caption.sr-only{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border:0;white-space:nowrap}table.tk caption{caption-side:top;color:var(--text-primary);font-size:var(--font-13);font-weight:var(--weight-bold);padding:0 0 var(--space-8);text-align:left}table.tk th{background:var(--bg-surface-2);border-bottom:1px solid var(--border-default);color:var(--text-secondary);font-size:var(--font-11);font-weight:700;letter-spacing:.08em;padding:var(--space-12) 14px;text-align:left;text-transform:uppercase}table.tk tbody th[scope=row]{background:transparent;font-size:var(--font-13);font-weight:var(--weight-bold);letter-spacing:0;text-transform:none}table.tk tbody th[scope=row],table.tk td{border-bottom:1px solid var(--border-soft);color:var(--text-primary)}table.tk td{padding:var(--space-12) 14px}table.tk tbody tr:nth-child(2n) td,table.tk tbody tr:nth-child(2n) th[scope=row]{background:var(--bg-surface-2)}table.tk tbody tr:hover td,table.tk tbody tr:hover th[scope=row]{background:var(--bg-hover)}table.tk th[aria-sort]{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}table.tk th[aria-sort]:hover{color:var(--text-primary)}.tk-wrap{overflow-x:auto}.tk-num{font-variant-numeric:tabular-nums;text-align:right}.tk-skeleton{height:14px;width:80%}.tk-empty{color:var(--text-muted);text-align:center}.nav-group{display:flex;flex-direction:column}.nav-group-header{align-items:center;background:none;border:0;color:var(--text-muted);cursor:pointer;display:flex;font-family:var(--font-sans);font-size:var(--font-11);font-weight:700;gap:var(--space-8);letter-spacing:.08em;padding:var(--space-8) var(--space-12);text-align:left;text-transform:uppercase;transition:color var(--duration-fast) var(--ease-out);width:100%}.nav-group-header:hover{color:var(--text-secondary)}.nav-group-header .caret{display:inline-flex;margin-left:auto;transition:transform var(--duration-fast) var(--ease-out)}.nav-group[data-open=true]>.nav-group-header{color:var(--color-primary)}.nav-group[data-open=true]>.nav-group-header .caret{transform:rotate(180deg)}.nav-group-items{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-2) 0 var(--space-8)}.cc-export:focus-visible,.cc-menu-item:focus-visible,.chart-card :focus-visible,.nav-group-header:focus-visible,table.tk th[aria-sort]:focus-visible{box-shadow:var(--shadow-focus);outline:2px solid var(--color-secondary);outline-offset:2px}.cc-menu-item,.nav-group-header{min-height:40px}body.text-large .kpi-label{font-size:var(--font-13)}body.text-large .kpi-value{font-size:34px}body.text-large .kpi-trend{font-size:var(--font-14)}body.text-large .kpi-foot{font-size:var(--font-13)}body.text-large .chart-card-title{font-size:17px}body.text-large .chart-card-context{font-size:var(--font-14)}body.text-large .badge,body.text-large .chart-card-foot{font-size:var(--font-12)}body.text-large .badge{padding:3px 9px}body.text-large table.tk{font-size:15px}body.text-large table.tk th{font-size:var(--font-13)}body.text-xl .kpi-label{font-size:var(--font-14)}body.text-xl .kpi-value{font-size:40px}body.text-xl .kpi-trend{font-size:var(--font-16)}body.text-xl .kpi-foot{font-size:var(--font-14)}body.text-xl .chart-card-title{font-size:20px}body.text-xl .chart-card-context{font-size:var(--font-16)}body.text-xl .badge,body.text-xl .chart-card-foot{font-size:var(--font-14)}body.text-xl .badge{padding:3px var(--space-10)}body.text-xl table.tk{font-size:var(--font-16)}body.text-xl table.tk th{font-size:var(--font-14)}body.high-contrast .cc-export,body.high-contrast .cc-menu,body.high-contrast .chart-card,body.high-contrast .kpi-card{border-width:2px}body.high-contrast .chart-card:hover{border-color:var(--border-default)}body.rm-switching,body.rm-switching *,body.rm-switching :after,body.rm-switching :before,body.theme-switching,body.theme-switching *,body.theme-switching :after,body.theme-switching :before{transition:none!important}body.high-contrast *{box-shadow:none!important}.rm-skeleton{animation:rm-skeleton-shimmer 1.5s ease-in-out infinite;background:linear-gradient(90deg,var(--bg-hover) 0,var(--bg-surface-2) 50%,var(--bg-hover) 100%);background-size:200% 100%;border-radius:var(--radius-md)}@keyframes rm-skeleton-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media (prefers-reduced-motion:reduce){.rm-skeleton{animation:none;background:var(--bg-hover)}}.rm-state-loading{display:flex;flex-direction:column;gap:var(--space-10);justify-content:center;min-height:240px;padding:var(--space-8) var(--space-4)}.rm-spinner{animation:rm-spinner-turn .8s linear infinite;border:3px solid var(--border-default);border-radius:50%;border-top-color:var(--color-secondary);height:32px;width:32px}@keyframes rm-spinner-turn{to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.rm-spinner{animation-duration:3s}}.rm-state{color:var(--text-secondary);flex-direction:column;font-family:var(--font-sans);gap:var(--space-6);min-height:240px;padding:36px var(--space-24);text-align:center}.rm-state,.rm-state__icon{align-items:center;display:flex;justify-content:center}.rm-state__icon{background:var(--bg-surface-3);border-radius:50%;color:var(--text-muted);height:56px;margin-bottom:6px;width:56px}.rm-state__title{color:var(--text-primary);font-size:var(--font-14);font-weight:var(--weight-semibold);margin:0}.rm-state__text{color:var(--text-muted);font-size:var(--font-12);line-height:1.5;margin:0;max-width:280px}.rm-state__action{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md);color:var(--text-secondary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-12);font-weight:var(--weight-semibold);gap:var(--space-6);margin-top:10px;padding:var(--space-6) 14px}.rm-state__action:hover{background:var(--bg-surface-3);color:var(--text-primary)}.rm-state--error .rm-state__icon{background:var(--color-danger-bg);color:var(--color-danger)}.rm-state--error .rm-state__action{border-color:var(--color-danger);color:var(--color-danger)}.rm-state--error .rm-state__action:hover{background:var(--color-danger-bg)}*{scrollbar-color:var(--border-default) transparent;scrollbar-width:thin}::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-corner,::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background-clip:padding-box;background-color:var(--border-default);border:3px solid transparent;border-radius:var(--radius-pill)}::-webkit-scrollbar-thumb:hover{background-color:var(--text-muted)}
1
+ .grid-2{grid-template-columns:repeat(2,1fr)}.grid-2,.grid-3{display:grid;gap:var(--space-20)}.grid-3{grid-template-columns:repeat(3,1fr)}.grid-4{display:grid;gap:var(--space-16);grid-template-columns:repeat(4,1fr)}.grid-2-1{display:grid;gap:var(--space-20);grid-template-columns:2fr 1fr}.pane-title{color:var(--text-primary);font-family:var(--font-serif);font-size:var(--font-32);font-weight:700;letter-spacing:-.02em;line-height:1.1;margin:0 0 16px}.pane-sub{color:var(--text-muted);font-size:var(--font-13);line-height:1.55;margin:0 0 24px;max-width:78ch}.chart-section{margin-inline:auto;max-width:var(--content-max-w,1440px);padding:0 0 var(--space-40);width:100%}.section-label{align-items:center;color:var(--text-secondary);display:flex;font-size:var(--font-11);font-weight:700;gap:var(--space-8);letter-spacing:.12em;margin:40px 0 18px;text-transform:uppercase}body.text-large .pane-title{font-size:38px}body.text-xl .pane-title{font-size:46px}body.text-large .section-label{font-size:var(--font-13)}body.text-xl .section-label{font-size:var(--font-14)}.chart-card{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:10px;box-shadow:var(--shadow-sm);display:flex;flex-direction:column;transition:box-shadow .18s,border-color .18s}.chart-card:hover{border-color:var(--color-violet-pale);box-shadow:0 6px 16px rgba(107,63,255,.1),0 1px 3px rgba(30,41,59,.04)}.chart-card-head{padding:22px var(--space-24) 14px;padding-right:64px;position:relative}.chart-card-title{color:var(--text-primary);font-size:15px;font-weight:700;letter-spacing:-.01em;line-height:1.3;margin:0 0 5px}.chart-card-context{color:var(--text-muted);font-size:var(--font-12);line-height:1.55;margin:0}.rm-card-actions{position:relative}.chart-card-head>.chart-card-actions{position:absolute;right:12px;top:12px}.cc-export{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:6px;color:var(--text-secondary);cursor:pointer;display:flex;font-size:var(--font-14);height:28px;justify-content:center;transition:background .15s,color .15s,border-color .15s;width:28px}.cc-export:hover{color:var(--color-secondary)}.cc-export:hover,.rm-card-actions.open .cc-export{background:var(--bg-hover);border-color:var(--color-violet-pale)}.rm-card-actions.open .cc-export{color:var(--color-primary)}.cc-menu{animation:cc-menu-in .12s cubic-bezier(.2,0,0,1);background:var(--bg-surface);border:1px solid var(--border-default);border-radius:8px;box-shadow:var(--shadow-lg);display:none;min-width:200px;padding:var(--space-6) 0;position:absolute;right:0;top:34px;z-index:500}.rm-card-actions.open .cc-menu{display:block}.cc-menu-section{color:var(--text-muted);font-size:var(--font-10);font-weight:700;letter-spacing:.08em;padding:var(--space-8) 14px var(--space-4);text-transform:uppercase}.cc-menu-item{align-items:center;background:none;border:0;color:var(--text-secondary);cursor:pointer;display:flex;font-family:var(--font-sans);font-size:var(--font-13);gap:var(--space-10);padding:7px 14px;text-align:left;width:100%}.cc-menu-item i{color:var(--text-muted);font-size:var(--font-14)}.cc-menu-item:hover{background:var(--bg-surface-3);color:var(--text-primary)}.cc-menu-item:hover i{color:var(--text-secondary)}.cc-menu-divider{background:var(--bg-surface-3);height:1px;margin:4px 0}.cc-menu-note{border-top:1px solid var(--bg-surface-3);color:var(--text-secondary);font-size:var(--font-12);margin:4px 0 0;padding:var(--space-8) 14px var(--space-4)}.cc-menu-item[disabled]{cursor:default;opacity:.55}.cc-menu-item[disabled]:hover{background:none;color:var(--text-secondary)}.chart-card:fullscreen,.rm-card-zoom,.rm-rcard:fullscreen,.rm-table-card:fullscreen{background:var(--bg-surface);border-radius:0;box-sizing:border-box;height:100vh;overflow:auto;padding:var(--space-16);width:100vw}.rm-card-zoom{border:0;inset:0;margin:0;position:fixed;z-index:500}body.rm-card-zoom-open{overflow:hidden}.chart-card.rm-card-zoom .chart-card-body,.chart-card:fullscreen .chart-card-body{display:flex;flex-direction:column}.chart-card.rm-card-zoom .rm-chart,.chart-card:fullscreen .rm-chart{flex:1 1 auto}.chart-card.rm-card-zoom .echart,.chart-card:fullscreen .echart{height:72vh!important}@keyframes cc-menu-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.chart-card-body{flex:1;padding:var(--space-4) var(--space-12) var(--space-8)}.chart-card-body>.rm-empty{box-sizing:border-box;gap:var(--space-6);justify-content:center;max-width:none;min-height:240px;padding:36px var(--space-24)}.chart-card-foot{align-items:center;background:var(--bg-surface-2);border-radius:0 0 10px 10px;border-top:1px solid var(--border-soft);color:var(--text-muted);display:flex;flex-wrap:wrap;font-size:var(--font-11);gap:var(--space-10);padding:var(--space-12) var(--space-24)}.chart-card-foot .src{align-items:center;display:flex;gap:var(--space-4)}.chart-card-foot .src b{color:var(--text-secondary);font-weight:600}.chart-card-foot .dot{background:var(--border-default);border-radius:50%;height:3px;width:3px}.chart-card-foot .updated{color:var(--text-secondary);font-weight:500}.kpi-card{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:8px;box-shadow:0 2px 8px rgba(30,41,59,.06);padding:var(--space-16) 18px}.kpi-label{color:var(--text-muted);font-size:var(--font-11);font-weight:600;letter-spacing:.1em;margin:0 0 6px;text-transform:uppercase}.kpi-value{color:var(--color-primary);font-family:var(--font-serif);font-size:28px;font-weight:700;line-height:1;margin:0}.kpi-value.healthcare{color:var(--color-healthcare)}.kpi-value.discovery{color:var(--color-discovery)}.kpi-value.pharma{color:var(--color-pharma)}.kpi-value.databank{color:var(--color-databank)}.kpi-trend{align-items:center;display:inline-flex;font-size:var(--font-12);font-weight:600;gap:var(--space-4);margin-top:6px}.kpi-trend i{font-size:var(--font-11)}.kpi-trend--up{color:var(--color-success)}.kpi-trend--down{color:var(--color-danger)}.kpi-foot,.kpi-trend--flat{color:var(--text-muted)}.kpi-foot{font-size:var(--font-11);margin-top:4px}.kpi-extra{margin-top:12px}.badge{border-radius:4px;display:inline-block;font-size:var(--font-10);font-weight:600;padding:var(--space-2) var(--space-8)}.badge-active{background:var(--color-success-bg);color:var(--color-success)}.badge-pending{background:var(--color-warning-bg);color:var(--color-warning)}.badge-error{background:var(--color-danger-bg);color:var(--color-danger)}.badge-info{background:var(--bg-hover);color:var(--color-primary)}.badge-grey{background:var(--bg-surface-3);color:var(--text-secondary)}table.tk{border-collapse:collapse;font-size:var(--font-13);width:100%}.sr-only,table.tk>caption.sr-only{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border:0;white-space:nowrap}table.tk caption{caption-side:top;color:var(--text-primary);font-size:var(--font-13);font-weight:var(--weight-bold);padding:0 0 var(--space-8);text-align:left}table.tk th{background:var(--bg-surface-2);border-bottom:1px solid var(--border-default);color:var(--text-secondary);font-size:var(--font-11);font-weight:700;letter-spacing:.08em;padding:var(--space-12) 14px;text-align:left;text-transform:uppercase}table.tk tbody th[scope=row]{background:transparent;font-size:var(--font-13);font-weight:var(--weight-bold);letter-spacing:0;text-transform:none}table.tk tbody th[scope=row],table.tk td{border-bottom:1px solid var(--border-soft);color:var(--text-primary)}table.tk td{padding:var(--space-12) 14px}table.tk tbody tr:nth-child(2n) td,table.tk tbody tr:nth-child(2n) th[scope=row]{background:var(--bg-surface-2)}table.tk tbody tr:hover td,table.tk tbody tr:hover th[scope=row]{background:var(--bg-hover)}table.tk th[aria-sort]{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}table.tk th[aria-sort]:hover{color:var(--text-primary)}.tk-wrap{min-width:0;overflow-x:auto}.tk-num{font-variant-numeric:tabular-nums;text-align:right}.tk-skeleton{height:14px;width:80%}.tk-empty{color:var(--text-muted);text-align:center}.nav-group{display:flex;flex-direction:column}.nav-group-header{align-items:center;background:none;border:0;color:var(--text-muted);cursor:pointer;display:flex;font-family:var(--font-sans);font-size:var(--font-11);font-weight:700;gap:var(--space-8);letter-spacing:.08em;padding:var(--space-8) var(--space-12);text-align:left;text-transform:uppercase;transition:color var(--duration-fast) var(--ease-out);width:100%}.nav-group-header:hover{color:var(--text-secondary)}.nav-group-header .caret{display:inline-flex;margin-left:auto;transition:transform var(--duration-fast) var(--ease-out)}.nav-group[data-open=true]>.nav-group-header{color:var(--color-primary)}.nav-group[data-open=true]>.nav-group-header .caret{transform:rotate(180deg)}.nav-group-items{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-2) 0 var(--space-8)}.cc-export:focus-visible,.cc-menu-item:focus-visible,.chart-card :focus-visible,.nav-group-header:focus-visible,table.tk th[aria-sort]:focus-visible{box-shadow:var(--shadow-focus);outline:2px solid var(--color-secondary);outline-offset:2px}.cc-menu-item,.nav-group-header{min-height:40px}body.text-large .kpi-label{font-size:var(--font-13)}body.text-large .kpi-value{font-size:34px}body.text-large .kpi-trend{font-size:var(--font-14)}body.text-large .kpi-foot{font-size:var(--font-13)}body.text-large .chart-card-title{font-size:17px}body.text-large .chart-card-context{font-size:var(--font-14)}body.text-large .badge,body.text-large .chart-card-foot{font-size:var(--font-12)}body.text-large .badge{padding:3px 9px}body.text-large table.tk{font-size:15px}body.text-large table.tk th{font-size:var(--font-13)}body.text-xl .kpi-label{font-size:var(--font-14)}body.text-xl .kpi-value{font-size:40px}body.text-xl .kpi-trend{font-size:var(--font-16)}body.text-xl .kpi-foot{font-size:var(--font-14)}body.text-xl .chart-card-title{font-size:20px}body.text-xl .chart-card-context{font-size:var(--font-16)}body.text-xl .badge,body.text-xl .chart-card-foot{font-size:var(--font-14)}body.text-xl .badge{padding:3px var(--space-10)}body.text-xl table.tk{font-size:var(--font-16)}body.text-xl table.tk th{font-size:var(--font-14)}body.high-contrast .cc-export,body.high-contrast .cc-menu,body.high-contrast .chart-card,body.high-contrast .kpi-card{border-width:2px}body.high-contrast .chart-card:hover{border-color:var(--border-default)}body.rm-switching,body.rm-switching *,body.rm-switching :after,body.rm-switching :before,body.theme-switching,body.theme-switching *,body.theme-switching :after,body.theme-switching :before{transition:none!important}body.high-contrast *{box-shadow:none!important}.rm-skeleton{animation:rm-skeleton-shimmer 1.5s ease-in-out infinite;background:linear-gradient(90deg,var(--bg-hover) 0,var(--bg-surface-2) 50%,var(--bg-hover) 100%);background-size:200% 100%;border-radius:var(--radius-md)}@keyframes rm-skeleton-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media (prefers-reduced-motion:reduce){.rm-skeleton{animation:none;background:var(--bg-hover)}}.rm-state-loading{display:flex;flex-direction:column;gap:var(--space-10);justify-content:center;min-height:240px;padding:var(--space-8) var(--space-4)}.rm-spinner{animation:rm-spinner-turn .8s linear infinite;border:3px solid var(--border-default);border-radius:50%;border-top-color:var(--color-secondary);height:32px;width:32px}@keyframes rm-spinner-turn{to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.rm-spinner{animation-duration:3s}}.rm-state{color:var(--text-secondary);flex-direction:column;font-family:var(--font-sans);gap:var(--space-6);min-height:240px;padding:36px var(--space-24);text-align:center}.rm-state,.rm-state__icon{align-items:center;display:flex;justify-content:center}.rm-state__icon{background:var(--bg-surface-3);border-radius:50%;color:var(--text-muted);height:56px;margin-bottom:6px;width:56px}.rm-state__title{color:var(--text-primary);font-size:var(--font-14);font-weight:var(--weight-semibold);margin:0}.rm-state__text{color:var(--text-muted);font-size:var(--font-12);line-height:1.5;margin:0;max-width:280px}.rm-state__action{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md);color:var(--text-secondary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-12);font-weight:var(--weight-semibold);gap:var(--space-6);margin-top:10px;padding:var(--space-6) 14px}.rm-state__action:hover{background:var(--bg-surface-3);color:var(--text-primary)}.rm-state--error .rm-state__icon{background:var(--color-danger-bg);color:var(--color-danger)}.rm-state--error .rm-state__action{border-color:var(--color-danger);color:var(--color-danger)}.rm-state--error .rm-state__action:hover{background:var(--color-danger-bg)}*{scrollbar-color:var(--border-default) transparent;scrollbar-width:thin}::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-corner,::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background-clip:padding-box;background-color:var(--border-default);border:3px solid transparent;border-radius:var(--radius-pill)}::-webkit-scrollbar-thumb:hover{background-color:var(--text-muted)}
@@ -99,5 +99,5 @@ defineExpose({ instance: chart })
99
99
  </template>
100
100
 
101
101
  <style scoped>
102
- .rm-chart{margin:0}.rm-chart__frame{position:relative}.echart{width:100%}.rm-chart__skeleton{inset:0;position:absolute}
102
+ .rm-chart{margin:0;min-width:0}.rm-chart__frame{position:relative}.echart{width:100%}.rm-chart__skeleton{inset:0;position:absolute}
103
103
  </style>
@@ -90,7 +90,7 @@ const emit = defineEmits<{
90
90
  const WORDS = {
91
91
  fr: {
92
92
  source: 'Source :',
93
- verified: 'Vérifié le',
93
+ verified: 'Dernière mise à jour le',
94
94
  emptyTitle: 'Aucun résultat',
95
95
  emptyText:
96
96
  'Aucune ligne ne correspond aux filtres en cours. Élargissez votre période ou retirez une dimension.',
@@ -98,7 +98,7 @@ const WORDS = {
98
98
  },
99
99
  en: {
100
100
  source: 'Source:',
101
- verified: 'Verified on',
101
+ verified: 'Last updated',
102
102
  emptyTitle: 'No results',
103
103
  emptyText:
104
104
  'No row matches the current filters. Widen your period or drop a dimension.',
@@ -132,5 +132,5 @@ function toggle() {
132
132
  </template>
133
133
 
134
134
  <style scoped>
135
- .rm-hybrid{font-family:var(--font-sans);width:100%}.rm-hybrid__table{border-collapse:collapse;table-layout:auto;width:100%}.rm-hybrid__th{color:var(--text-muted);font-size:var(--font-12);font-weight:var(--weight-normal);line-height:14px;padding:var(--space-4) var(--space-10);text-align:right;white-space:nowrap}.rm-hybrid__th:first-child{padding-left:0;text-align:left}.rm-hybrid__th:last-child{padding-right:0}.rm-hybrid__row{height:34px}.rm-hybrid__label_cell{font-weight:var(--weight-normal);max-width:0;padding:0;position:relative;text-align:left;width:100%}.rm-hybrid__bar{border-radius:var(--radius-sm);bottom:2px;left:0;opacity:.14;position:absolute;top:2px}.rm-hybrid__label{display:block;overflow:hidden;padding:var(--space-6) var(--space-10) var(--space-6) var(--space-8);position:relative;text-overflow:ellipsis}.rm-hybrid__label,.rm-hybrid__value{color:var(--text-primary);font-size:var(--font-13);white-space:nowrap}.rm-hybrid__value{font-variant-numeric:tabular-nums;font-weight:var(--weight-medium);padding:var(--space-6) var(--space-10);text-align:right}.rm-hybrid__value:last-child{padding-right:0}.rm-hybrid__share{color:var(--text-muted);font-weight:var(--weight-normal);margin-left:2px}.rm-hybrid__footer{display:flex;justify-content:center;margin-top:16px}
135
+ .rm-hybrid{font-family:var(--font-sans);min-width:0;width:100%}.rm-hybrid__table{border-collapse:collapse;table-layout:auto;width:100%}.rm-hybrid__th{color:var(--text-muted);font-size:var(--font-12);font-weight:var(--weight-normal);line-height:14px;padding:var(--space-4) var(--space-10);text-align:right;white-space:nowrap}.rm-hybrid__th:first-child{padding-left:0;text-align:left}.rm-hybrid__th:last-child{padding-right:0}.rm-hybrid__row{height:34px}.rm-hybrid__label_cell{font-weight:var(--weight-normal);max-width:0;padding:0;position:relative;text-align:left;width:100%}.rm-hybrid__bar{border-radius:var(--radius-sm);bottom:2px;left:0;opacity:.14;position:absolute;top:2px}.rm-hybrid__label{display:block;overflow:hidden;padding:var(--space-6) var(--space-10) var(--space-6) var(--space-8);position:relative;text-overflow:ellipsis}.rm-hybrid__label,.rm-hybrid__value{color:var(--text-primary);font-size:var(--font-13);white-space:nowrap}.rm-hybrid__value{font-variant-numeric:tabular-nums;font-weight:var(--weight-medium);padding:var(--space-6) var(--space-10);text-align:right}.rm-hybrid__value:last-child{padding-right:0}.rm-hybrid__share{color:var(--text-muted);font-weight:var(--weight-normal);margin-left:2px}.rm-hybrid__footer{display:flex;justify-content:center;margin-top:16px}
136
136
  </style>
@@ -31,8 +31,8 @@ const props = withDefaults(
31
31
 
32
32
  /** Memes mots que le pied de RmChartCard. */
33
33
  const WORDS = {
34
- fr: { source: 'Source :', verified: 'Vérifié le' },
35
- en: { source: 'Source:', verified: 'Verified on' },
34
+ fr: { source: 'Source :', verified: 'Dernière mise à jour le' },
35
+ en: { source: 'Source:', verified: 'Last updated' },
36
36
  } as const
37
37
  const t = computed(() => WORDS[props.lang])
38
38
 
@@ -574,5 +574,5 @@ function heatClass(col: RmTableColumn, row: Record<string, any>) {
574
574
  </template>
575
575
 
576
576
  <style scoped>
577
- .rm-table-wrapper{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md,8px);flex:1;overflow:hidden}.rm-table-wrapper--flat{background:transparent;border:none;border-radius:0}.rm-table__scroll{overflow:auto}.rm-table{border-collapse:collapse;font-size:var(--font-13,13px);width:100%}.rm-sr-only{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border:0;white-space:nowrap}.rm-table caption{caption-side:top;color:var(--text-primary);font-size:var(--font-13,13px);font-weight:700;padding:0 0 var(--space-8,var(--space-8));text-align:left}.rm-table__th{background:var(--bg-surface-2);border-bottom:1px solid var(--border-default);color:var(--text-secondary);font-size:var(--font-11,11px);font-weight:700;letter-spacing:.08em;padding:var(--space-12) 14px;text-align:left;text-transform:uppercase;white-space:nowrap}.rm-table--sticky .rm-table__th{border-bottom:none;box-shadow:inset 0 -1px 0 var(--border-default);position:sticky;top:0;z-index:2}.rm-table__th--center{text-align:center}.rm-table__th--num,.rm-table__th--right{text-align:right}.rm-table__th--check,.rm-table__th--expand{padding-right:0;width:36px}.rm-table__sort{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:var(--space-6,var(--space-6));letter-spacing:inherit;padding:0;text-transform:inherit}.rm-table__sort:hover{color:var(--text-primary)}.rm-table__sort:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid var(--text-muted);content:"";display:inline-block;height:0;opacity:.5;vertical-align:middle;width:0}.rm-table__th[aria-sort=ascending] .rm-table__sort:after{border-bottom:5px solid var(--color-primary);border-top:none;opacity:1}.rm-table__th[aria-sort=descending] .rm-table__sort:after{border-top:5px solid var(--color-primary);opacity:1}.rm-table a:focus-visible,.rm-table button:focus-visible{border-radius:var(--radius-sm,4px);outline:2px solid var(--color-primary);outline-offset:2px}.rm-table__td{border-bottom:1px solid var(--border-soft);color:var(--text-primary);padding:var(--space-12) 14px;text-align:left;vertical-align:top}th.rm-table__td{background:transparent;font-weight:700;letter-spacing:0;text-transform:none}.rm-table__td--center{text-align:center}.rm-table__td--right{text-align:right}.rm-table__td--num{font-variant-numeric:tabular-nums;text-align:right}.rm-table__td--check,.rm-table__td--expand{color:var(--text-muted);padding-right:0;width:36px}.rm-table__row--striped>.rm-table__td{background:var(--bg-surface-2)}.rm-table__row--emphasis>.rm-table__td{background:var(--bg-hover);font-weight:var(--weight-semibold,600)}.rm-table__row--emphasis>.rm-table__td:first-child{box-shadow:inset 3px 0 0 var(--color-primary)}.rm-table__search{align-items:center;border-bottom:1px solid var(--border-default);display:flex;gap:var(--space-8);padding:var(--space-8) var(--space-12)}.rm-table__search :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-table__search-input{background:none;border:none;color:var(--text-primary);font-family:inherit;font-size:var(--font-13,13px);width:100%}.rm-table__search-input::-moz-placeholder{color:var(--text-muted)}.rm-table__search-input::placeholder{color:var(--text-muted)}.rm-table__search-input:focus-visible{outline:none}.rm-table--hoverable .rm-table__row:hover>.rm-table__td,.rm-table__row--selected>.rm-table__td{background:var(--bg-hover)}.rm-table__row--expandable{cursor:pointer}.rm-table__caret{display:inline-flex;transition:transform .16s var(--ease-out,ease)}.rm-table__caret.is-open{color:var(--color-primary);transform:rotate(90deg)}.rm-table__group>th{background:var(--bg-hover);color:var(--color-primary);font-size:var(--font-11,11px);font-weight:700;letter-spacing:.08em;padding:var(--space-8,var(--space-8)) var(--space-12,var(--space-12));text-align:left;text-transform:uppercase}.rm-table__detail>td{background:var(--bg-surface-2);border-bottom:1px solid var(--border-soft);padding:0}.rm-table__detail-body{color:var(--text-secondary);font-size:var(--font-12,12px);line-height:1.6;padding:var(--space-12,var(--space-12)) var(--space-20,var(--space-20))}.rm-table__td--heat-1{background:#fee5e5!important;color:#911616}.rm-table__td--heat-2{background:#ffe7d2!important;color:#8a4309}.rm-table__td--heat-3{background:#fff6cc!important;color:#6b5400}.rm-table__td--heat-4{background:#d8f3dc!important;color:#1b5e25}.rm-table__td--heat-5{background:#b7e4c7!important;color:#0e4b19}body.night .rm-table__td--heat-1{background:#3f1414!important;color:#ffb4b4}body.night .rm-table__td--heat-2{background:#3d2410!important;color:#ffc58a}body.night .rm-table__td--heat-3{background:#3a3210!important;color:#ffe07a}body.night .rm-table__td--heat-4{background:#18351f!important;color:#8ae0a4}body.night .rm-table__td--heat-5{background:#0f4019!important;color:#b4f0c2}.rm-table--compact .rm-table__td,.rm-table--compact .rm-table__th{font-size:var(--font-12,12px);padding:var(--space-6,var(--space-6)) var(--space-12,var(--space-12))}.rm-table--compact .rm-table__th{font-size:var(--font-10,10px)}.rm-table__bulk{align-items:center;background:var(--bg-hover);border-bottom:1px solid var(--color-violet-pale);display:flex;font-size:var(--font-12,12px);justify-content:space-between;padding:var(--space-8,var(--space-8)) var(--space-16,var(--space-16))}.rm-table__bulk-count b{color:var(--color-primary)}.rm-table__bulk-actions{display:flex;gap:var(--space-4,var(--space-4))}.rm-table__pager{align-items:center;background:var(--bg-surface);border-top:1px solid var(--border-default);display:flex;font-size:var(--font-12,12px);gap:var(--space-12,var(--space-12));justify-content:space-between;padding:var(--space-8,var(--space-8)) var(--space-12,var(--space-12))}.rm-table__pager-count{color:var(--text-secondary);font-variant-numeric:tabular-nums}.rm-table__pager-controls{align-items:center;display:flex;gap:var(--space-4,var(--space-4))}.rm-table__pager-page{background:none;border:1px solid transparent;border-radius:var(--radius-sm,6px);color:var(--text-secondary);cursor:pointer;font:inherit;font-variant-numeric:tabular-nums;height:28px;min-width:28px;padding:0 var(--space-6)}.rm-table__pager-page:hover{background:var(--bg-hover);color:var(--color-secondary)}.rm-table__pager-page.is-current{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-text-inverse)}.rm-table__pager-gap{color:var(--text-muted);padding:0 var(--space-2)}.rm-table__empty{color:var(--text-muted);padding:var(--space-32) var(--space-16);text-align:center}.rm-table__skeleton{height:14px;width:80%}
577
+ .rm-table-wrapper{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md,8px);flex:1;min-width:0;overflow:hidden}.rm-table-wrapper--flat{background:transparent;border:none;border-radius:0}.rm-table__scroll{overflow:auto}.rm-table{border-collapse:collapse;font-size:var(--font-13,13px);width:100%}.rm-sr-only{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border:0;white-space:nowrap}.rm-table caption{caption-side:top;color:var(--text-primary);font-size:var(--font-13,13px);font-weight:700;padding:0 0 var(--space-8,var(--space-8));text-align:left}.rm-table__th{background:var(--bg-surface-2);border-bottom:1px solid var(--border-default);color:var(--text-secondary);font-size:var(--font-11,11px);font-weight:700;letter-spacing:.08em;padding:var(--space-12) 14px;text-align:left;text-transform:uppercase;white-space:nowrap}.rm-table--sticky .rm-table__th{border-bottom:none;box-shadow:inset 0 -1px 0 var(--border-default);position:sticky;top:0;z-index:2}.rm-table__th--center{text-align:center}.rm-table__th--num,.rm-table__th--right{text-align:right}.rm-table__th--check,.rm-table__th--expand{padding-right:0;width:36px}.rm-table__sort{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:var(--space-6,var(--space-6));letter-spacing:inherit;padding:0;text-transform:inherit}.rm-table__sort:hover{color:var(--text-primary)}.rm-table__sort:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid var(--text-muted);content:"";display:inline-block;height:0;opacity:.5;vertical-align:middle;width:0}.rm-table__th[aria-sort=ascending] .rm-table__sort:after{border-bottom:5px solid var(--color-primary);border-top:none;opacity:1}.rm-table__th[aria-sort=descending] .rm-table__sort:after{border-top:5px solid var(--color-primary);opacity:1}.rm-table a:focus-visible,.rm-table button:focus-visible{border-radius:var(--radius-sm,4px);outline:2px solid var(--color-primary);outline-offset:2px}.rm-table__td{border-bottom:1px solid var(--border-soft);color:var(--text-primary);padding:var(--space-12) 14px;text-align:left;vertical-align:top}th.rm-table__td{background:transparent;font-weight:700;letter-spacing:0;text-transform:none}.rm-table__td--center{text-align:center}.rm-table__td--right{text-align:right}.rm-table__td--num{font-variant-numeric:tabular-nums;text-align:right}.rm-table__td--check,.rm-table__td--expand{color:var(--text-muted);padding-right:0;width:36px}.rm-table__row--striped>.rm-table__td{background:var(--bg-surface-2)}.rm-table__row--emphasis>.rm-table__td{background:var(--bg-hover);font-weight:var(--weight-semibold,600)}.rm-table__row--emphasis>.rm-table__td:first-child{box-shadow:inset 3px 0 0 var(--color-primary)}.rm-table__search{align-items:center;border-bottom:1px solid var(--border-default);display:flex;gap:var(--space-8);padding:var(--space-8) var(--space-12)}.rm-table__search :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-table__search-input{background:none;border:none;color:var(--text-primary);font-family:inherit;font-size:var(--font-13,13px);width:100%}.rm-table__search-input::-moz-placeholder{color:var(--text-muted)}.rm-table__search-input::placeholder{color:var(--text-muted)}.rm-table__search-input:focus-visible{outline:none}.rm-table--hoverable .rm-table__row:hover>.rm-table__td,.rm-table__row--selected>.rm-table__td{background:var(--bg-hover)}.rm-table__row--expandable{cursor:pointer}.rm-table__caret{display:inline-flex;transition:transform .16s var(--ease-out,ease)}.rm-table__caret.is-open{color:var(--color-primary);transform:rotate(90deg)}.rm-table__group>th{background:var(--bg-hover);color:var(--color-primary);font-size:var(--font-11,11px);font-weight:700;letter-spacing:.08em;padding:var(--space-8,var(--space-8)) var(--space-12,var(--space-12));text-align:left;text-transform:uppercase}.rm-table__detail>td{background:var(--bg-surface-2);border-bottom:1px solid var(--border-soft);padding:0}.rm-table__detail-body{color:var(--text-secondary);font-size:var(--font-12,12px);line-height:1.6;padding:var(--space-12,var(--space-12)) var(--space-20,var(--space-20))}.rm-table__td--heat-1{background:#fee5e5!important;color:#911616}.rm-table__td--heat-2{background:#ffe7d2!important;color:#8a4309}.rm-table__td--heat-3{background:#fff6cc!important;color:#6b5400}.rm-table__td--heat-4{background:#d8f3dc!important;color:#1b5e25}.rm-table__td--heat-5{background:#b7e4c7!important;color:#0e4b19}body.night .rm-table__td--heat-1{background:#3f1414!important;color:#ffb4b4}body.night .rm-table__td--heat-2{background:#3d2410!important;color:#ffc58a}body.night .rm-table__td--heat-3{background:#3a3210!important;color:#ffe07a}body.night .rm-table__td--heat-4{background:#18351f!important;color:#8ae0a4}body.night .rm-table__td--heat-5{background:#0f4019!important;color:#b4f0c2}.rm-table--compact .rm-table__td,.rm-table--compact .rm-table__th{font-size:var(--font-12,12px);padding:var(--space-6,var(--space-6)) var(--space-12,var(--space-12))}.rm-table--compact .rm-table__th{font-size:var(--font-10,10px)}.rm-table__bulk{align-items:center;background:var(--bg-hover);border-bottom:1px solid var(--color-violet-pale);display:flex;font-size:var(--font-12,12px);justify-content:space-between;padding:var(--space-8,var(--space-8)) var(--space-16,var(--space-16))}.rm-table__bulk-count b{color:var(--color-primary)}.rm-table__bulk-actions{display:flex;gap:var(--space-4,var(--space-4))}.rm-table__pager{align-items:center;background:var(--bg-surface);border-top:1px solid var(--border-default);display:flex;font-size:var(--font-12,12px);gap:var(--space-12,var(--space-12));justify-content:space-between;padding:var(--space-8,var(--space-8)) var(--space-12,var(--space-12))}.rm-table__pager-count{color:var(--text-secondary);font-variant-numeric:tabular-nums}.rm-table__pager-controls{align-items:center;display:flex;gap:var(--space-4,var(--space-4))}.rm-table__pager-page{background:none;border:1px solid transparent;border-radius:var(--radius-sm,6px);color:var(--text-secondary);cursor:pointer;font:inherit;font-variant-numeric:tabular-nums;height:28px;min-width:28px;padding:0 var(--space-6)}.rm-table__pager-page:hover{background:var(--bg-hover);color:var(--color-secondary)}.rm-table__pager-page.is-current{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-text-inverse)}.rm-table__pager-gap{color:var(--text-muted);padding:0 var(--space-2)}.rm-table__empty{color:var(--text-muted);padding:var(--space-32) var(--space-16);text-align:center}.rm-table__skeleton{height:14px;width:80%}
578
578
  </style>
@@ -82,6 +82,7 @@ const WORDS = {
82
82
  favorites: 'Favoris',
83
83
  actions: 'Actions',
84
84
  unsaved: 'Modifications non enregistrées',
85
+ modified: 'modifiée',
85
86
  applied: 'Vue appliquée',
86
87
  save: 'Sauvegarder',
87
88
  aria: 'Vue affichée',
@@ -92,6 +93,7 @@ const WORDS = {
92
93
  favorites: 'Favorites',
93
94
  actions: 'Actions',
94
95
  unsaved: 'Unsaved changes',
96
+ modified: 'edited',
95
97
  applied: 'View applied',
96
98
  save: 'Save',
97
99
  aria: 'Current view',
@@ -99,7 +101,15 @@ const WORDS = {
99
101
  } as const
100
102
 
101
103
  const t = computed(() => WORDS[props.lang])
102
- const label = computed(() => props.viewName || t.value.none)
104
+ /**
105
+ * Le nom de la vue, suivi de son etat quand l'ecran ne lui correspond plus.
106
+ * La pastille coloree ne suffisait pas : on lisait « Vue : GLP-1 » sur un
107
+ * ecran qui ne montrait plus les produits de GLP-1.
108
+ */
109
+ const label = computed(() => {
110
+ if (!props.viewName) return t.value.none
111
+ return props.dirty ? `${props.viewName} (${t.value.modified})` : props.viewName
112
+ })
103
113
 
104
114
  const open = ref(false)
105
115
  const root = ref<HTMLElement | null>(null)
@@ -88,6 +88,12 @@ function download(blob, fileName) {
88
88
  setTimeout(() => URL.revokeObjectURL(url), 1e4);
89
89
  return blob.size;
90
90
  }
91
+ function titleGap(title) {
92
+ return title ? 22 : 0;
93
+ }
94
+ function drawableCharts(payload) {
95
+ return (payload.charts ?? []).map((chart) => ({ title: chart.title, svg: svgOf(chart.el) })).filter((chart) => !!chart.svg);
96
+ }
91
97
  function svgOf(el) {
92
98
  return el instanceof SVGSVGElement ? el : el.querySelector("svg");
93
99
  }
@@ -106,6 +112,21 @@ function serialize(svg) {
106
112
  if (!clone.getAttribute("viewBox")) clone.setAttribute("viewBox", `0 0 ${width} ${height}`);
107
113
  return { markup: new XMLSerializer().serializeToString(clone), width, height };
108
114
  }
115
+ async function capture(el) {
116
+ try {
117
+ const { default: html2canvas } = await import("html2canvas-pro");
118
+ const canvas = await html2canvas(el, {
119
+ scale: 2,
120
+ backgroundColor: null,
121
+ logging: false,
122
+ useCORS: true
123
+ });
124
+ if (!canvas.width || !canvas.height) return null;
125
+ return { data: canvas.toDataURL("image/png"), width: canvas.width, height: canvas.height };
126
+ } catch {
127
+ return null;
128
+ }
129
+ }
109
130
  async function raster(markup, width, height, scale = 2) {
110
131
  const image = new Image();
111
132
  image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(markup)}`;
@@ -292,15 +313,15 @@ export function useRmExport() {
292
313
  return { fileName, rows: rowCount, bytes: download(blob, fileName) };
293
314
  }
294
315
  async function toPng(config, payload, lang) {
295
- const charts = (payload.charts ?? []).map((chart) => svgOf(chart.el)).filter(Boolean);
296
- if (!charts.length) throw new Error(lang === "en" ? "No chart on this page" : "Aucun graphique sur cette page");
316
+ const drawn = drawableCharts(payload);
317
+ if (!drawn.length) throw new Error(lang === "en" ? "No chart on this page" : "Aucun graphique sur cette page");
297
318
  const scale = 2;
298
319
  const pad = 24;
299
320
  const sources = sourcesOf(config, payload);
300
321
  const head = config.options.includes("logo") ? sources.length ? 88 : 72 : 0;
301
- const parts = charts.map((svg) => serialize(svg));
322
+ const parts = drawn.map((chart) => ({ ...serialize(chart.svg), title: chart.title }));
302
323
  const width = Math.max(...parts.map((part) => part.width)) + pad * 2;
303
- const height = parts.reduce((total, part) => total + part.height + pad, pad) + head;
324
+ const height = parts.reduce((total, part) => total + part.height + pad + titleGap(part.title), pad) + head;
304
325
  const canvas = document.createElement("canvas");
305
326
  canvas.width = width * scale;
306
327
  canvas.height = height * scale;
@@ -321,6 +342,12 @@ export function useRmExport() {
321
342
  }
322
343
  let y = head + pad;
323
344
  for (const part of parts) {
345
+ if (part.title) {
346
+ context.fillStyle = "#1A1A2E";
347
+ context.font = "bold 14px Figtree, Helvetica, sans-serif";
348
+ context.fillText(part.title, pad, y + 12);
349
+ y += titleGap(part.title);
350
+ }
324
351
  const raw = await raster(part.markup, part.width, part.height, scale);
325
352
  context.drawImage(raw, pad, y, part.width, part.height);
326
353
  y += part.height + pad;
@@ -332,19 +359,21 @@ export function useRmExport() {
332
359
  return { fileName, rows: 0, bytes: download(blob, fileName) };
333
360
  }
334
361
  async function toSvg(config, payload, lang) {
335
- const charts = (payload.charts ?? []).map((chart) => svgOf(chart.el)).filter(Boolean);
336
- if (!charts.length) throw new Error(lang === "en" ? "No chart on this page" : "Aucun graphique sur cette page");
362
+ const drawn = drawableCharts(payload);
363
+ if (!drawn.length) throw new Error(lang === "en" ? "No chart on this page" : "Aucun graphique sur cette page");
337
364
  const pad = 24;
338
365
  const sources = sourcesOf(config, payload);
339
366
  const head = config.options.includes("logo") ? sources.length ? 88 : 72 : 0;
340
- const parts = charts.map((svg) => serialize(svg));
367
+ const parts = drawn.map((chart) => ({ ...serialize(chart.svg), title: chart.title }));
341
368
  const width = Math.max(...parts.map((part) => part.width)) + pad * 2;
342
- const height = parts.reduce((total, part) => total + part.height + pad, pad) + head;
369
+ const height = parts.reduce((total, part) => total + part.height + pad + titleGap(part.title), pad) + head;
343
370
  let y = head + pad;
344
371
  const nested = parts.map((part) => {
372
+ const label = part.title ? `<text x="${pad}" y="${y + 12}" font-family="Figtree, Helvetica, sans-serif" font-size="14" font-weight="bold" fill="#1A1A2E">${escapeXml(part.title)}</text>` : "";
373
+ y += titleGap(part.title);
345
374
  const markup2 = part.markup.replace(/^<svg /, `<svg x="${pad}" y="${y}" `);
346
375
  y += part.height + pad;
347
- return markup2;
376
+ return label + markup2;
348
377
  }).join("\n");
349
378
  const header = head ? `<text x="${pad}" y="32" font-family="Figtree, Helvetica, sans-serif" font-size="20" font-weight="bold" fill="#1A1A2E">${BRAND_TITLE}</text><text x="${pad}" y="52" font-family="Figtree, Helvetica, sans-serif" font-size="12" fill="#6C6C8A">${escapeXml(`${payload.title} \xB7 ${BRAND_LINE} \xB7 ${longDate(lang)}`)}</text>` + (sources.length ? `<text x="${pad}" y="68" font-family="Figtree, Helvetica, sans-serif" font-size="12" fill="#6C6C8A">${escapeXml(`Source${sources.length > 1 ? "s" : ""} : ${sources.map((source) => sourceLabel(source, lang)).join(" \xB7 ")}`)}</text>` : "") : "";
350
379
  const markup = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}"><rect width="${width}" height="${height}" fill="#FFFFFF"/>${header}${nested}</svg>`;
@@ -541,8 +570,47 @@ export function useRmExport() {
541
570
  );
542
571
  y += cardHeight + 6;
543
572
  }
573
+ const snapshots = (payload.nodes ?? []).filter((node) => {
574
+ if (node.kind === "chart") return false;
575
+ if (node.kind === "kpi") return config.sections.includes("kpi");
576
+ if (node.kind === "table") return config.sections.includes("table") || config.sections.includes("cards");
577
+ return config.sections.includes("cards");
578
+ });
579
+ const shots = [];
580
+ for (const node of snapshots) {
581
+ const shot = await capture(node.el);
582
+ if (shot) shots.push(shot);
583
+ }
584
+ const faithful = shots.length > 0;
585
+ if (faithful) {
586
+ sectionTitle(lang === "en" ? "Page" : "La page");
587
+ for (const shot of shots) {
588
+ let drawWidth = inner;
589
+ let drawHeight = shot.height / shot.width * drawWidth;
590
+ const maxHeight = bottom - margin;
591
+ if (drawHeight > maxHeight) {
592
+ drawHeight = maxHeight;
593
+ drawWidth = shot.width / shot.height * drawHeight;
594
+ }
595
+ if (y + drawHeight > bottom) {
596
+ doc.addPage();
597
+ y = margin;
598
+ }
599
+ doc.addImage(
600
+ shot.data,
601
+ "PNG",
602
+ margin + (inner - drawWidth) / 2,
603
+ y,
604
+ drawWidth,
605
+ drawHeight,
606
+ void 0,
607
+ "FAST"
608
+ );
609
+ y += drawHeight + 6;
610
+ }
611
+ }
544
612
  let rowCount = 0;
545
- if (config.sections.includes("cards")) {
613
+ if (config.sections.includes("cards") && !faithful) {
546
614
  const cards = cardsOf(payload, config, lang);
547
615
  if (cards.length) {
548
616
  if (y + 12 > bottom) {
@@ -754,7 +822,7 @@ export function useRmExport() {
754
822
  y += 6;
755
823
  }
756
824
  }
757
- if (config.sections.includes("table")) {
825
+ if (config.sections.includes("table") && !faithful) {
758
826
  const MAX_COLUMNS = landscape ? 16 : 10;
759
827
  payload.sheets.forEach((sheet) => {
760
828
  const all = columnsOf(sheet, config.columns);
@@ -838,6 +906,10 @@ export function useRmExport() {
838
906
  });
839
907
  }
840
908
  const pages = doc.getNumberOfPages();
909
+ const footList = sourcesOf(config, payload);
910
+ const footSources = footList.length ? printable(
911
+ `Source${footList.length > 1 ? "s" : ""} : ${footList.map((source) => sourceLabel(source, lang)).join(" \xB7 ")}`
912
+ ) : "";
841
913
  for (let page = 1; page <= pages; page += 1) {
842
914
  doc.setPage(page);
843
915
  const width = doc.internal.pageSize.getWidth();
@@ -854,6 +926,13 @@ export function useRmExport() {
854
926
  )[0] ?? "";
855
927
  doc.text(trail, margin, foot);
856
928
  doc.text(`${page} / ${pages}`, width - margin, foot, { align: "right" });
929
+ if (footSources) {
930
+ doc.text(
931
+ doc.splitTextToSize(footSources, width - margin * 2)[0] ?? "",
932
+ margin,
933
+ foot - 8.5
934
+ );
935
+ }
857
936
  }
858
937
  const fileName = `${config.fileName}.pdf`;
859
938
  const blob = doc.output("blob");
@@ -16,7 +16,20 @@ export interface RmPalette {
16
16
  primary: string;
17
17
  accent: string;
18
18
  neutral: string;
19
- /** Palette sequentielle, du plus clair au plus fonce : heatmaps, choroplethes. */
19
+ /**
20
+ * Palette sequentielle, du plus clair au plus fonce : heatmaps, choroplethes.
21
+ *
22
+ * Pour la palette par defaut, les six paliers echantillonnent la rampe de la
23
+ * reference (`#EEF1FE` vers `cat[2]` vers `cat[0]`, soit blanc bleute vers
24
+ * ambre vers violet OIP). Une rampe qui ne joue que sur la clarte d'une
25
+ * seule teinte demande de comparer deux violets voisins ; celle-ci fait
26
+ * varier la teinte en meme temps que la clarte, et deux tranches voisines se
27
+ * distinguent sans revenir a la legende.
28
+ *
29
+ * `cvdSafe` garde sa rampe bleue a teinte unique : c'est la seule qui soit
30
+ * validee pour les trois dyschromatopsies, et le detour par l'ambre la
31
+ * casserait.
32
+ */
20
33
  seq: string[];
21
34
  }
22
35
  /**
@@ -92,10 +105,14 @@ export declare function rmBaseOption(theme: RmChartTheme, decal?: boolean): {
92
105
  };
93
106
  borderColor: string;
94
107
  borderWidth: number;
108
+ appendTo: string;
109
+ confine: boolean;
110
+ enterable: boolean;
111
+ extraCssText: string;
95
112
  };
96
113
  };
97
114
  export declare const rmTooltipTrigger: (count: number) => "axis" | "item";
98
- export declare function rmLegend(theme: RmChartTheme, count: number, position?: 'top' | 'bottom'): {
115
+ export declare function rmLegend(theme: RmChartTheme, count: number, position?: 'top' | 'bottom', names?: string[]): {
99
116
  pageIconSize?: number | undefined;
100
117
  pageIconColor?: string | undefined;
101
118
  pageIconInactiveColor?: string | undefined;
@@ -194,6 +211,10 @@ export declare function rmBarVerticalOption(categories: (string | number)[], ser
194
211
  };
195
212
  borderColor: string;
196
213
  borderWidth: number;
214
+ appendTo: string;
215
+ confine: boolean;
216
+ enterable: boolean;
217
+ extraCssText: string;
197
218
  };
198
219
  legend: {
199
220
  pageIconSize?: number | undefined;
@@ -398,6 +419,10 @@ export declare function rmBarHorizontalOption(labels: string[], values: (number
398
419
  };
399
420
  borderColor: string;
400
421
  borderWidth: number;
422
+ appendTo: string;
423
+ confine: boolean;
424
+ enterable: boolean;
425
+ extraCssText: string;
401
426
  };
402
427
  };
403
428
  /** Line ou area chart. `step` produit la marche d'escalier des series de prix. */
@@ -459,6 +484,10 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
459
484
  };
460
485
  borderColor: string;
461
486
  borderWidth: number;
487
+ appendTo: string;
488
+ confine: boolean;
489
+ enterable: boolean;
490
+ extraCssText: string;
462
491
  };
463
492
  legend: {
464
493
  pageIconSize?: number | undefined;
@@ -716,6 +745,10 @@ export declare function rmDonutOption(data: {
716
745
  };
717
746
  borderColor: string;
718
747
  borderWidth: number;
748
+ appendTo: string;
749
+ confine: boolean;
750
+ enterable: boolean;
751
+ extraCssText: string;
719
752
  };
720
753
  legend: {
721
754
  pageIconSize?: number | undefined;
@@ -4,14 +4,14 @@ export const RM_PALETTES = {
4
4
  primary: "#2100AD",
5
5
  accent: "#6B3FFF",
6
6
  neutral: "#D6CCFF",
7
- seq: ["#EEF1FE", "#D6CCFF", "#B485FF", "#8B5CF6", "#6B3FFF", "#2100AD"]
7
+ seq: ["#EEF1FE", "#F1D09D", "#F4AF3C", "#CB7E2B", "#763F6C", "#2100AD"]
8
8
  },
9
9
  defaultDark: {
10
10
  cat: ["#9B7CFF", "#3DD9B9", "#FBBF24", "#7AA0FF", "#F472B6", "#B485FF"],
11
11
  primary: "#9B7CFF",
12
12
  accent: "#B485FF",
13
13
  neutral: "#4A3F70",
14
- seq: ["#1A1A24", "#2D2A42", "#4A3F70", "#7C5FE6", "#9B7CFF", "#D6CCFF"]
14
+ seq: ["#EEF1FE", "#F3DDA7", "#F8C950", "#E8B250", "#C197A7", "#9B7CFF"]
15
15
  },
16
16
  cvdSafe: {
17
17
  cat: ["#0072B2", "#E69F00", "#009E73", "#CC79A7", "#56B4E9", "#F0E442"],
@@ -86,7 +86,17 @@ export function rmBaseOption(theme, decal = false) {
86
86
  backgroundColor: theme.tooltipBg,
87
87
  textStyle: { color: theme.tooltipText, fontFamily: FONT, fontSize: 12 },
88
88
  borderColor: theme.tooltipBorder,
89
- borderWidth: 1
89
+ borderWidth: 1,
90
+ // Posee par defaut DANS le conteneur du graphe, l'infobulle est rognee
91
+ // par la premiere carte a `overflow: hidden` des qu'elle en deborde :
92
+ // sur une colonne de quarante series il n'en reste qu'un morceau. Dans
93
+ // le body elle passe par-dessus la carte ; `confine` la garde ancree au
94
+ // cadre du graphe, et la hauteur plafonnee l'empeche de sortir de
95
+ // l'ecran (elle defile alors, d'ou `enterable`).
96
+ appendTo: "body",
97
+ confine: true,
98
+ enterable: true,
99
+ extraCssText: "max-height:70vh;overflow:auto;"
90
100
  }
91
101
  };
92
102
  }
@@ -96,8 +106,12 @@ const LEGEND_MAX_INLINE = 6;
96
106
  const LEGEND_NAME_MAX = 38;
97
107
  const LEGEND_NAME_TAIL = 12;
98
108
  const rmLegendName = (name) => name.length > LEGEND_NAME_MAX ? `${name.slice(0, LEGEND_NAME_MAX - LEGEND_NAME_TAIL - 1)}\u2026${name.slice(-LEGEND_NAME_TAIL)}` : name;
99
- export function rmLegend(theme, count, position = "bottom") {
100
- const scroll = count > LEGEND_MAX_INLINE;
109
+ const LEGEND_ITEM_PAD = 32;
110
+ const LEGEND_CHAR_WIDTH = 6.2;
111
+ const LEGEND_WIDTH_BUDGET = 620;
112
+ const rmLegendWidth = (names) => names.reduce((total, name) => total + LEGEND_ITEM_PAD + rmLegendName(name).length * LEGEND_CHAR_WIDTH, 0);
113
+ export function rmLegend(theme, count, position = "bottom", names = []) {
114
+ const scroll = count > LEGEND_MAX_INLINE || rmLegendWidth(names) > LEGEND_WIDTH_BUDGET;
101
115
  return {
102
116
  ...position === "bottom" ? { bottom: 0, left: "center" } : { top: 0 },
103
117
  type: scroll ? "scroll" : "plain",
@@ -144,7 +158,7 @@ export function rmBarVerticalOption(categories, series, theme, palette, decal =
144
158
  return {
145
159
  ...rmBaseOption(theme, decal),
146
160
  tooltip: { ...rmBaseOption(theme, decal).tooltip, trigger: rmTooltipTrigger(series.length) },
147
- legend: series.length > 1 ? rmLegend(theme, series.length) : void 0,
161
+ legend: series.length > 1 ? rmLegend(theme, series.length, "bottom", series.map((s) => String(s.name ?? ""))) : void 0,
148
162
  // La legende passee sous le graphe prend sa place dans la gouttiere basse,
149
163
  // sinon elle recouvre les libelles de l'axe des abscisses.
150
164
  grid: { ...rmBaseOption(theme, decal).grid, bottom: series.length > 1 ? 56 : 36 },
@@ -229,7 +243,7 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
229
243
  },
230
244
  // Legende obligatoire en double axe : sans elle, rien ne dit quelle courbe
231
245
  // se lit sur quel axe.
232
- legend: series.length > 1 || dual ? rmLegend(theme, series.length, legendPosition) : void 0,
246
+ legend: series.length > 1 || dual ? rmLegend(theme, series.length, legendPosition, series.map((s) => String(s.name ?? ""))) : void 0,
233
247
  grid: {
234
248
  // Sans graduation a gauche, la gouttiere de 48 px ne sert plus qu'a
235
249
  // laisser depasser la premiere pastille de valeur.
@@ -258,6 +258,15 @@ export interface RmExportPayload {
258
258
  title?: string;
259
259
  el: Element;
260
260
  }[];
261
+ /**
262
+ * Cartes de l'ecran, a capturer telles quelles pour le rapport mis en page.
263
+ *
264
+ * Le rapport reconstruisait ses tableaux et ses fiches a partir de la
265
+ * donnee : il ne ressemblait plus a la page, colonnes et mises en forme
266
+ * comprises. Une page qui donne ses noeuds obtient une capture fidele ; les
267
+ * autres gardent le rendu reconstruit.
268
+ */
269
+ nodes?: RmExportNode[];
261
270
  /** URL a copier pour le format « Permalink ». */
262
271
  permalink?: string;
263
272
  /**
@@ -269,6 +278,15 @@ export interface RmExportPayload {
269
278
  /** Plafond de lignes par onglet, pour ne pas geler l'onglet du navigateur. */
270
279
  limit?: number;
271
280
  }
281
+ /**
282
+ * Une carte de l'ecran, pour le rapport fidele. `kind` dit a quelle case du
283
+ * panneau elle repond (chiffres cles, graphique, tableau, fiche).
284
+ */
285
+ export interface RmExportNode {
286
+ kind: 'kpi' | 'chart' | 'table' | 'card';
287
+ el: Element;
288
+ title?: string;
289
+ }
272
290
  /** Extension de fichier par format. */
273
291
  export declare const RM_EXPORT_EXTENSIONS: Record<string, string>;
274
292
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekkare/romulus",
3
- "version": "0.1.177",
3
+ "version": "0.1.179",
4
4
  "description": "Romulus Design System - Nuxt module by Tekkare",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,6 +33,7 @@
33
33
  "@nuxt/kit": "^3.16.0",
34
34
  "@phosphor-icons/vue": "^2.2.1",
35
35
  "echarts": "^5.6.0",
36
+ "html2canvas-pro": "^1.6.7",
36
37
  "jspdf": "^4.2.0",
37
38
  "jspdf-autotable": "^5.0.7",
38
39
  "write-excel-file": "^1.4.30"