@openziti/ziti-console-lib 1.5.5 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/styles/dark.css +16 -0
- package/assets/styles/global.scss +159 -63
- package/fesm2022/openziti-ziti-console-lib.mjs +4351 -226
- package/fesm2022/openziti-ziti-console-lib.mjs.map +1 -1
- package/index.d.ts +780 -46
- package/index.d.ts.map +1 -1
- package/package.json +3 -2
package/assets/styles/dark.css
CHANGED
|
@@ -9,6 +9,9 @@ body {
|
|
|
9
9
|
--stroke: #2A2B31;
|
|
10
10
|
--black: #FFF;
|
|
11
11
|
--shaded: #1D2024;
|
|
12
|
+
/* pull the list-table header fully to the border/stroke slate so it matches the
|
|
13
|
+
raised surfaces used elsewhere in dark mode (filter bar, hover) */
|
|
14
|
+
--lt-header-mix: 100%;
|
|
12
15
|
--formBackground: #1D2024;
|
|
13
16
|
--background: #18191D;
|
|
14
17
|
--mainBackground: var(--navigation);
|
|
@@ -38,6 +41,19 @@ body {
|
|
|
38
41
|
--jse-main-border: var(--inputBorder);
|
|
39
42
|
--jse-delimiter-color: var(--tableText);
|
|
40
43
|
--jse-key-color: var(--tableText);
|
|
44
|
+
/* page-header resource icon: lift off the dark brand navy so the glyph reads */
|
|
45
|
+
--lt-header-icon: #7e97ff;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* list-table accents: the light-mode brand blue and the dark status/type text
|
|
49
|
+
shades are too dark to read on the dark surface, so lift the text tokens to
|
|
50
|
+
lighter tints of the same hues. Fills stay subtle; only the labels/links change. */
|
|
51
|
+
.lt-skin {
|
|
52
|
+
--lt-link: #7e97ff;
|
|
53
|
+
--lt-icon-active: #7e97ff;
|
|
54
|
+
--lt-info-text: #9bb0ff;
|
|
55
|
+
--lt-positive-text: #5fd98a;
|
|
56
|
+
--lt-warning-text: #f0b45e;
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
.filters .navigate {
|
|
@@ -55,23 +55,32 @@ body {
|
|
|
55
55
|
(--primary, --background, --stroke, ...). Consuming apps reskin the table by
|
|
56
56
|
overriding these (or the underlying tokens) in their own global styles. */
|
|
57
57
|
--lt-bg: transparent;
|
|
58
|
-
--lt-header-bg: var(--background);
|
|
59
|
-
--lt-header-text: var(--groupText);
|
|
60
|
-
--lt-header-underline: var(--stroke);
|
|
58
|
+
--lt-header-bg: var(--background, #f6f7fb);
|
|
59
|
+
--lt-header-text: var(--groupText, #78859f);
|
|
60
|
+
--lt-header-underline: var(--stroke, #d4d9e2);
|
|
61
61
|
--lt-row-bg: transparent;
|
|
62
62
|
--lt-row-alt-bg: transparent; /* no zebra — rows read via the hairline divider + hover */
|
|
63
63
|
--lt-row-hover: var(--tableRowHover, rgba(0, 39, 171, 0.06));
|
|
64
64
|
--lt-row-selected: color-mix(in srgb, var(--primary) 8%, transparent);
|
|
65
|
-
--lt-cell-text: var(--text);
|
|
66
|
-
--lt-link: var(--primary);
|
|
67
|
-
--lt-border: var(--stroke);
|
|
68
|
-
--lt-icon: var(--icon);
|
|
69
|
-
--lt-icon-active: var(--primary);
|
|
65
|
+
--lt-cell-text: var(--text, #000);
|
|
66
|
+
--lt-link: var(--primary, #0027ab);
|
|
67
|
+
--lt-border: var(--stroke, #d4d9e2);
|
|
68
|
+
--lt-icon: var(--icon, #658292);
|
|
69
|
+
--lt-icon-active: var(--primary, #0027ab);
|
|
70
70
|
--lt-row-height: 3.125rem;
|
|
71
|
-
--lt-radius: var(--inputBorderRadius);
|
|
72
|
-
--lt-toolbar-height: 2.
|
|
73
|
-
--lt-control-bg: var(--background);
|
|
71
|
+
--lt-radius: var(--inputBorderRadius, 0.375rem);
|
|
72
|
+
--lt-toolbar-height: 2.3rem;
|
|
73
|
+
--lt-control-bg: var(--background, #f6f7fb);
|
|
74
74
|
--lt-font: 'Open Sans', sans-serif;
|
|
75
|
+
/* shared toolbar-control metrics (buttons, menus) so spacing/type stay consistent */
|
|
76
|
+
--lt-control-gap: 0.4375rem;
|
|
77
|
+
--lt-control-padding-x: 0.625rem;
|
|
78
|
+
--lt-control-font-size: 0.8125rem;
|
|
79
|
+
--lt-control-font-weight: 500;
|
|
80
|
+
/* one hairline border for every toolbar/footer control so they read as a set */
|
|
81
|
+
--lt-control-border-width: 1px;
|
|
82
|
+
/* one gap between toolbar controls so the filter row and the right cluster match */
|
|
83
|
+
--lt-control-row-gap: 0.4375rem;
|
|
75
84
|
--redShadow: rgba(255, 13, 73, 0.3);
|
|
76
85
|
--redText: #9c0027;
|
|
77
86
|
--shadow: 0rem 0rem 0.5rem 0.125rem rgba(0,0,0,0.08);
|
|
@@ -1027,6 +1036,20 @@ lib-form-field-container {
|
|
|
1027
1036
|
}
|
|
1028
1037
|
}
|
|
1029
1038
|
|
|
1039
|
+
// Reserve room for the copy icon so it clears the input's right edge.
|
|
1040
|
+
.form-row:has(> .icon-copy.copy-text) {
|
|
1041
|
+
--copy-icon-width: 1.25rem; // matches .icon-copy.copy-text width
|
|
1042
|
+
--copy-icon-inset: 0.75rem; // gap between the icon and the input's right edge
|
|
1043
|
+
|
|
1044
|
+
.form-field-input {
|
|
1045
|
+
padding-right: calc(var(--copy-icon-width) + var(--copy-icon-inset));
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
> .icon-copy.copy-text {
|
|
1049
|
+
right: var(--copy-icon-inset);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1030
1053
|
a {
|
|
1031
1054
|
&.delete-button,
|
|
1032
1055
|
&.download-button {
|
|
@@ -2290,32 +2313,65 @@ a {
|
|
|
2290
2313
|
// --lt-* defaults for that table's subtree only, drawing from ZAC's own tokens so it
|
|
2291
2314
|
// matches the app and follows its theming; the legacy page (.ag-cell) is untouched.
|
|
2292
2315
|
.lt-skin {
|
|
2293
|
-
--lt-bg: var(--background);
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
--
|
|
2297
|
-
--lt-
|
|
2316
|
+
--lt-bg: var(--background, #f6f7fb);
|
|
2317
|
+
// shade the header off the row surface using the theme's own cool neutral (the
|
|
2318
|
+
// border color), so it stays in the same family as the rest of the table instead of
|
|
2319
|
+
// a flat grey. The theme's --shaded can equal the background (no contrast), so this
|
|
2320
|
+
// derives its own band. --lt-header-mix sets how far to pull toward the border: the
|
|
2321
|
+
// light default is a gentle step; dark themes raise it (see dark.css) so the header
|
|
2322
|
+
// lands on the same raised-surface slate the rest of dark mode uses.
|
|
2323
|
+
--lt-header-bg: color-mix(in srgb, var(--lt-border) var(--lt-header-mix, 42%), var(--lt-row-bg));
|
|
2324
|
+
// the muted group color is too faint on the shaded header band, so pull it toward the
|
|
2325
|
+
// theme text color: darker in light mode, lighter in dark, keeping the cool hue
|
|
2326
|
+
--lt-header-text: color-mix(in srgb, var(--groupText, #78859f) 70%, var(--text));
|
|
2327
|
+
--lt-header-underline: var(--stroke, #d4d9e2);
|
|
2328
|
+
--lt-row-bg: var(--background, #f6f7fb);
|
|
2298
2329
|
--lt-row-alt-bg: transparent;
|
|
2299
|
-
--lt-row-hover: var(--shaded);
|
|
2330
|
+
--lt-row-hover: var(--shaded, #f6f7fb);
|
|
2300
2331
|
--lt-row-selected: color-mix(in srgb, var(--primary) 8%, transparent);
|
|
2301
|
-
--lt-cell-text: var(--text);
|
|
2302
|
-
--lt-link: var(--primary);
|
|
2303
|
-
--lt-icon: var(--icon);
|
|
2304
|
-
--lt-icon-active: var(--primary);
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2332
|
+
--lt-cell-text: var(--text, #000);
|
|
2333
|
+
--lt-link: var(--primary, #0027ab);
|
|
2334
|
+
--lt-icon: var(--icon, #658292);
|
|
2335
|
+
--lt-icon-active: var(--primary, #0027ab);
|
|
2336
|
+
// status/type accent palette (text + fill base). Defaults are the light-mode
|
|
2337
|
+
// shades; dark.css lifts the text tokens so these pills stay legible on the dark
|
|
2338
|
+
// surface.
|
|
2339
|
+
--lt-info-text: #1e40af;
|
|
2340
|
+
--lt-info: #2563eb;
|
|
2341
|
+
--lt-positive-text: #166534;
|
|
2342
|
+
--lt-positive: #16a34a;
|
|
2343
|
+
--lt-negative: #dc2626;
|
|
2344
|
+
--lt-warning-text: #92400e;
|
|
2345
|
+
--lt-warning: var(--highlighted, #f5a93d);
|
|
2346
|
+
--lt-border: var(--stroke, #d4d9e2);
|
|
2347
|
+
--lt-control-bg: var(--background, #f6f7fb);
|
|
2348
|
+
--lt-radius: 0.3rem;
|
|
2308
2349
|
--lt-row-height: 3.375rem;
|
|
2350
|
+
// nested tree card: the well it floats on, and a border strong enough to read
|
|
2351
|
+
// against that well (the base --lt-border is too light to show there)
|
|
2352
|
+
--lt-tree-well: color-mix(in srgb, var(--lt-border) 22%, var(--lt-row-bg));
|
|
2353
|
+
--lt-tree-card-border: color-mix(in srgb, var(--lt-border) 70%, var(--lt-icon));
|
|
2354
|
+
// vertical rail drawn beside nested rows in the flat variant (lighter than the card border)
|
|
2355
|
+
--lt-tree-rail: color-mix(in srgb, var(--lt-border) 55%, var(--lt-icon));
|
|
2356
|
+
// drop shadow under the nested card's last row (the lift)
|
|
2357
|
+
--lt-tree-card-shadow: 0 2px 4px color-mix(in srgb, #000 10%, transparent);
|
|
2358
|
+
// left inset of a nested card before its per-depth indent; must match treeCardBaseRem in the component
|
|
2359
|
+
--lt-card-inset: 4rem;
|
|
2309
2360
|
|
|
2310
2361
|
// extra skin knobs; defaults match the values above so ZAC is unchanged
|
|
2311
2362
|
--lt-control-border: var(--lt-border);
|
|
2363
|
+
// the control-border shorthand, as one token so the many inputs/menus share it
|
|
2364
|
+
--lt-control-border-full: var(--lt-control-border-width) solid var(--lt-control-border, var(--lt-border));
|
|
2312
2365
|
--lt-header-sorted-text: var(--lt-icon-active);
|
|
2313
2366
|
--lt-header-sorted-weight: 700;
|
|
2314
|
-
--lt-name-text: var(--tableText);
|
|
2367
|
+
--lt-name-text: var(--tableText, #22222a);
|
|
2315
2368
|
--lt-name-weight: 700;
|
|
2316
2369
|
--lt-name-size: 0.8125rem;
|
|
2317
2370
|
--lt-name-hover: var(--lt-link);
|
|
2318
|
-
|
|
2371
|
+
// more room above the controls (separating them from the page header), less below
|
|
2372
|
+
// (tightening them to the table)
|
|
2373
|
+
--lt-toolbar-margin-top: 1rem;
|
|
2374
|
+
--lt-toolbar-margin-bottom: 0;
|
|
2319
2375
|
--lt-toolbar-pad-bottom: 0.625rem;
|
|
2320
2376
|
--lt-container-reserve: 5.625rem;
|
|
2321
2377
|
}
|
|
@@ -2327,6 +2383,15 @@ a {
|
|
|
2327
2383
|
--inputBorderRadius: 0.375rem;
|
|
2328
2384
|
}
|
|
2329
2385
|
|
|
2386
|
+
// roomier gutters on the skinned list pages so the content breathes away from the
|
|
2387
|
+
// panel edges instead of hugging them (base page gutter is 1.25rem)
|
|
2388
|
+
.ziti-page-container.lt-skin-page {
|
|
2389
|
+
padding-top: 1.5rem;
|
|
2390
|
+
padding-left: 2rem;
|
|
2391
|
+
padding-right: 2rem;
|
|
2392
|
+
padding-bottom: 1.25rem;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2330
2395
|
.lt-skin .lt-scroll {
|
|
2331
2396
|
border: 1px solid var(--lt-control-border, var(--lt-border));
|
|
2332
2397
|
border-radius: var(--lt-radius);
|
|
@@ -2367,13 +2432,16 @@ a {
|
|
|
2367
2432
|
.lt-cell .lt-chip {
|
|
2368
2433
|
display: inline-flex;
|
|
2369
2434
|
align-items: center;
|
|
2435
|
+
min-height: 1.75rem;
|
|
2436
|
+
box-sizing: border-box;
|
|
2370
2437
|
margin-right: 0.25rem;
|
|
2371
|
-
padding: 0.
|
|
2372
|
-
font-size: 0.
|
|
2438
|
+
padding: 0.15625rem 0.625rem;
|
|
2439
|
+
font-size: 0.8125rem;
|
|
2373
2440
|
font-weight: 600;
|
|
2374
|
-
line-height: 1.
|
|
2441
|
+
line-height: 1.2;
|
|
2375
2442
|
color: var(--lt-link);
|
|
2376
2443
|
background: color-mix(in srgb, var(--lt-link) 12%, transparent);
|
|
2444
|
+
border: none;
|
|
2377
2445
|
border-radius: 0.25rem;
|
|
2378
2446
|
vertical-align: middle;
|
|
2379
2447
|
}
|
|
@@ -2383,39 +2451,54 @@ a {
|
|
|
2383
2451
|
background: color-mix(in srgb, var(--secondary) 14%, transparent);
|
|
2384
2452
|
}
|
|
2385
2453
|
|
|
2454
|
+
// --- table pill standard ---------------------------------------------------
|
|
2455
|
+
// The shared look for status-style pills in list tables (Type, Status, Is Admin,
|
|
2456
|
+
// Token, Roles): weight 500, pill radius, a shared min-height so pills with and
|
|
2457
|
+
// without an icon match, and all contents sized together. The status-style pills
|
|
2458
|
+
// (Type, Status, Is Admin, Token) use the compact size - font-size 0.73125rem,
|
|
2459
|
+
// min-height 1.575rem; the Roles attribute chips run one step larger (0.8125rem /
|
|
2460
|
+
// 1.75rem). The strength comes from contrast, not a heavy fill: a light 14% tint
|
|
2461
|
+
// background paired with a dark, saturated label color, and a clearly defined 1px
|
|
2462
|
+
// border (accent at 42% mixed into the page background). Each variant keeps its
|
|
2463
|
+
// own accent; only the color changes.
|
|
2464
|
+
|
|
2386
2465
|
// Online/Offline status pill (Status column): online gets a green checkmark
|
|
2387
2466
|
// (like the Is Admin badge), offline a muted dot. Both icons are drawn via
|
|
2388
2467
|
// ::before because inline <svg> is stripped from [innerHTML] cellHtml output.
|
|
2389
2468
|
.lt-cell .lt-status {
|
|
2390
2469
|
display: inline-flex;
|
|
2391
2470
|
align-items: center;
|
|
2392
|
-
gap: 0.
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2471
|
+
gap: 0.3375rem;
|
|
2472
|
+
min-height: 1.575rem;
|
|
2473
|
+
box-sizing: border-box;
|
|
2474
|
+
padding: 0.140625rem 0.5625rem 0.140625rem 0.421875rem;
|
|
2475
|
+
font-size: 0.73125rem;
|
|
2476
|
+
font-weight: 500;
|
|
2396
2477
|
line-height: 1.2;
|
|
2478
|
+
border: 1px solid transparent;
|
|
2397
2479
|
border-radius: 999px;
|
|
2398
2480
|
|
|
2481
|
+
// shared icon slot so the offline dot and the online check badge take the same
|
|
2482
|
+
// width and the labels line up across rows
|
|
2399
2483
|
&::before {
|
|
2400
2484
|
content: '';
|
|
2401
2485
|
flex: 0 0 auto;
|
|
2486
|
+
width: 0.84375rem;
|
|
2487
|
+
height: 0.84375rem;
|
|
2488
|
+
background-repeat: no-repeat;
|
|
2489
|
+
background-position: center;
|
|
2490
|
+
background-size: contain;
|
|
2402
2491
|
}
|
|
2403
2492
|
}
|
|
2404
2493
|
|
|
2494
|
+
// filled green disc with a white check (badge style), not a bare checkmark
|
|
2405
2495
|
.lt-cell .lt-status-online::before {
|
|
2406
|
-
|
|
2407
|
-
height: 0.8125rem;
|
|
2408
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath fill='none' stroke='%2316a34a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M2.5 7.6 5.7 10.8 11.5 3.6'/%3E%3C/svg%3E");
|
|
2409
|
-
background-repeat: no-repeat;
|
|
2410
|
-
background-position: center;
|
|
2411
|
-
background-size: contain;
|
|
2496
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='7' fill='%2316a34a'/%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M4.8 8.2 7 10.4 11.2 5.6'/%3E%3C/svg%3E");
|
|
2412
2497
|
}
|
|
2413
2498
|
|
|
2499
|
+
// small dot centered in the shared icon slot (keeps the theme color via currentColor)
|
|
2414
2500
|
.lt-cell .lt-status-offline::before {
|
|
2415
|
-
|
|
2416
|
-
height: 0.4375rem;
|
|
2417
|
-
border-radius: 50%;
|
|
2418
|
-
background: currentColor;
|
|
2501
|
+
background: radial-gradient(circle at center, currentColor 0 0.225rem, transparent 0.243rem);
|
|
2419
2502
|
}
|
|
2420
2503
|
|
|
2421
2504
|
// Color-coded Type pill: Default = blue, Router = green, each with a small icon.
|
|
@@ -2424,45 +2507,54 @@ a {
|
|
|
2424
2507
|
.lt-type-badge {
|
|
2425
2508
|
display: inline-flex;
|
|
2426
2509
|
align-items: center;
|
|
2427
|
-
gap: 0.
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2510
|
+
gap: 0.45rem;
|
|
2511
|
+
min-height: 1.575rem;
|
|
2512
|
+
box-sizing: border-box;
|
|
2513
|
+
padding: 0.140625rem 0.5625rem 0.140625rem 0.421875rem;
|
|
2514
|
+
font-size: 0.73125rem;
|
|
2515
|
+
font-weight: 500;
|
|
2431
2516
|
line-height: 1.2;
|
|
2517
|
+
// faint accent-tinted outline, matching the page header icon container (.lth-icon)
|
|
2518
|
+
border: 1px solid transparent;
|
|
2432
2519
|
border-radius: 999px;
|
|
2433
2520
|
|
|
2521
|
+
// the icon is the same resource glyph the side nav uses (icomoon font), kept large
|
|
2522
|
+
// so the detailed glyph stays legible at pill size; it inherits the pill text color
|
|
2434
2523
|
&::before {
|
|
2435
|
-
content: '';
|
|
2436
2524
|
flex: 0 0 auto;
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
background-size: contain;
|
|
2525
|
+
font-family: 'icomoon';
|
|
2526
|
+
font-size: 1.18125rem;
|
|
2527
|
+
line-height: 1;
|
|
2528
|
+
speak: none;
|
|
2442
2529
|
}
|
|
2443
2530
|
}
|
|
2444
2531
|
|
|
2445
2532
|
.lt-type-default {
|
|
2446
|
-
color:
|
|
2447
|
-
background: color-mix(in srgb,
|
|
2533
|
+
color: var(--lt-info-text);
|
|
2534
|
+
background: color-mix(in srgb, var(--lt-info) 14%, transparent);
|
|
2535
|
+
border-color: color-mix(in srgb, var(--lt-info) 42%, var(--background));
|
|
2448
2536
|
|
|
2537
|
+
// identities resource icon
|
|
2449
2538
|
&::before {
|
|
2450
|
-
|
|
2539
|
+
content: '\e92e';
|
|
2451
2540
|
}
|
|
2452
2541
|
}
|
|
2453
2542
|
|
|
2454
2543
|
.lt-type-router {
|
|
2455
|
-
color:
|
|
2456
|
-
background: color-mix(in srgb,
|
|
2544
|
+
color: var(--lt-positive-text);
|
|
2545
|
+
background: color-mix(in srgb, var(--lt-positive) 14%, transparent);
|
|
2546
|
+
border-color: color-mix(in srgb, var(--lt-positive) 42%, var(--background));
|
|
2457
2547
|
|
|
2548
|
+
// routers resource icon
|
|
2458
2549
|
&::before {
|
|
2459
|
-
|
|
2550
|
+
content: '\e95d';
|
|
2460
2551
|
}
|
|
2461
2552
|
}
|
|
2462
2553
|
|
|
2463
2554
|
.lt-type-other {
|
|
2464
2555
|
color: var(--lt-cell-text);
|
|
2465
2556
|
background: color-mix(in srgb, var(--lt-border) 45%, transparent);
|
|
2557
|
+
border-color: color-mix(in srgb, var(--lt-border) 55%, var(--background));
|
|
2466
2558
|
|
|
2467
2559
|
&::before {
|
|
2468
2560
|
display: none;
|
|
@@ -2470,13 +2562,17 @@ a {
|
|
|
2470
2562
|
}
|
|
2471
2563
|
|
|
2472
2564
|
.lt-cell .lt-status-online {
|
|
2473
|
-
color:
|
|
2474
|
-
background: color-mix(in srgb,
|
|
2565
|
+
color: var(--lt-positive-text);
|
|
2566
|
+
background: color-mix(in srgb, var(--lt-positive) 14%, transparent);
|
|
2567
|
+
border-color: color-mix(in srgb, var(--lt-positive) 42%, var(--background));
|
|
2475
2568
|
}
|
|
2476
2569
|
|
|
2477
2570
|
.lt-cell .lt-status-offline {
|
|
2478
|
-
color
|
|
2479
|
-
|
|
2571
|
+
// darken the muted group color toward the theme text (darker in light, lighter
|
|
2572
|
+
// in dark) so the label contrasts strongly with its own fill
|
|
2573
|
+
color: color-mix(in srgb, var(--groupText) 55%, var(--text));
|
|
2574
|
+
background: color-mix(in srgb, var(--groupText) 16%, transparent);
|
|
2575
|
+
border-color: color-mix(in srgb, var(--groupText) 42%, var(--background));
|
|
2480
2576
|
}
|
|
2481
2577
|
|
|
2482
2578
|
.cert {
|