Add enabled local routing rules and gateway version reporting
All checks were successful
Build and Deploy Gateway / build-and-push (push) Successful in 14s
Build and Deploy Gateway / deploy (push) Successful in 13s

This commit is contained in:
2026-07-11 22:14:43 +03:00
parent a0c66edb02
commit 1304a22f1f
22 changed files with 585 additions and 188 deletions

View File

@@ -800,7 +800,6 @@ p {
overflow-y: auto;
background: color-mix(in oklch, var(--client-bg) 99%, var(--client-panel));
color: var(--client-text);
box-shadow: -26px 0 72px oklch(0.09 0.015 145 / 0.12);
opacity: 0;
visibility: hidden;
transform: translateX(104%);
@@ -862,100 +861,242 @@ p {
}
.client-local-rules-list {
gap: 8px;
gap: 2px;
}
.client-local-rule {
min-width: 0;
display: grid;
grid-template-columns: 112px minmax(0, 1fr) 32px;
grid-template-columns: 24px 116px minmax(0, 1fr) 28px;
align-items: center;
gap: 8px;
padding: 8px;
border-radius: 13px;
background: color-mix(in oklch, var(--client-panel) 56%, var(--client-bg));
box-shadow: 0 10px 28px oklch(0.1 0.015 145 / 0.055);
transition: background 240ms ease, box-shadow 320ms ease, transform 320ms cubic-bezier(0.16, 1, 0.3, 1);
gap: 10px;
padding: 7px 0;
animation: client-local-rule-enter 560ms calc(var(--rule-index) * 55ms) cubic-bezier(0.16, 1, 0.3, 1) both;
transition: opacity 260ms ease, filter 360ms ease;
}
.client-local-rule:focus-within {
background: color-mix(in oklch, var(--client-panel) 74%, var(--client-bg));
box-shadow: 0 14px 34px oklch(0.1 0.015 145 / 0.09);
transform: translateY(-1px);
.client-local-rule.is-disabled {
opacity: 0.42;
filter: saturate(0);
}
.client-local-rule.is-built-in {
grid-template-columns: 92px minmax(0, 1fr) auto;
color: var(--client-muted);
.client-local-rule.is-removing {
pointer-events: none;
animation: client-local-rule-leave 360ms cubic-bezier(0.7, 0, 0.84, 0) both;
}
.client-local-rule.is-built-in strong {
font-size: 10px;
font-weight: 700;
}
.client-local-rule.is-built-in code {
color: var(--client-accent);
font: 700 13px/1 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace;
text-shadow: 0 0 12px color-mix(in oklch, var(--client-accent) 38%, transparent);
}
.client-local-rule.is-built-in small {
font-size: 8px;
white-space: nowrap;
}
.client-local-rule select,
.client-local-rule input {
min-width: 0;
height: 36px;
.client-local-rule-enabled {
width: 24px;
height: 32px;
display: grid;
place-items: center;
padding: 0;
border: 0;
border-radius: 8px;
outline: 0;
background: color-mix(in oklch, var(--client-control) 72%, transparent);
color: var(--client-text);
font-size: 10px;
}
.client-local-rule select {
padding: 0 7px;
background: transparent;
color: var(--client-muted);
cursor: pointer;
}
.client-local-rule-enabled svg {
width: 18px;
height: 18px;
overflow: visible;
fill: none;
stroke: currentColor;
stroke-linecap: round;
stroke-linejoin: round;
transition: color 260ms ease, filter 360ms ease, transform 420ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-local-rule-enabled circle {
stroke-width: 1.4;
transition: fill 320ms ease, stroke 260ms ease;
}
.client-local-rule-enabled path {
stroke-width: 1.8;
stroke-dasharray: 12;
stroke-dashoffset: 12;
transition: stroke-dashoffset 360ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-local-rule-enabled[aria-checked='true'] {
color: var(--client-accent);
}
.client-local-rule-enabled[aria-checked='true'] svg {
filter: drop-shadow(0 0 7px color-mix(in oklch, var(--client-accent) 48%, transparent));
transform: scale(1.08);
}
.client-local-rule-enabled[aria-checked='true'] circle {
fill: color-mix(in oklch, var(--client-accent) 12%, transparent);
}
.client-local-rule-enabled[aria-checked='true'] path {
stroke-dashoffset: 0;
}
.client-rule-type {
position: relative;
min-width: 0;
z-index: 1;
}
.client-rule-type.is-open {
z-index: 4;
}
.client-rule-type-trigger {
width: 100%;
height: 34px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 0;
border: 0;
background: transparent;
color: var(--client-text);
font: 600 9px/1 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace;
text-align: left;
cursor: pointer;
transition: color 220ms ease, text-shadow 300ms ease;
}
.client-rule-type-trigger svg {
width: 9px;
fill: none;
stroke: currentColor;
stroke-width: 1.5;
transition: transform 420ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-rule-type.is-open .client-rule-type-trigger {
color: var(--client-accent);
text-shadow: 0 0 10px color-mix(in oklch, var(--client-accent) 44%, transparent);
}
.client-rule-type.is-open .client-rule-type-trigger svg {
transform: rotate(180deg);
}
.client-rule-type-list {
position: absolute;
top: calc(100% - 1px);
left: -8px;
z-index: 3;
width: max-content;
min-width: calc(100% + 16px);
display: grid;
gap: 1px;
padding: 7px 8px;
background: color-mix(in oklch, var(--client-bg) 91%, transparent);
-webkit-backdrop-filter: blur(18px);
backdrop-filter: blur(18px);
opacity: 0;
visibility: hidden;
filter: blur(8px);
transform: translateY(-8px) scale(0.97);
transform-origin: top left;
pointer-events: none;
transition: opacity 200ms ease, filter 360ms ease, transform 420ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s 420ms;
}
.client-rule-type.is-open .client-rule-type-list {
opacity: 1;
visibility: visible;
filter: blur(0);
transform: translateY(0) scale(1);
pointer-events: auto;
transition-delay: 0s;
}
.client-rule-type-list button {
padding: 7px 6px;
border: 0;
background: transparent;
color: var(--client-muted);
font: 600 9px/1 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace;
text-align: left;
white-space: nowrap;
cursor: pointer;
opacity: 0;
filter: blur(5px);
transform: translateY(-5px);
transition: color 180ms ease, opacity 260ms ease, filter 340ms ease, transform 380ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-rule-type.is-open .client-rule-type-list button {
opacity: 1;
filter: blur(0);
transform: translateY(0);
}
.client-rule-type.is-open .client-rule-type-list button:nth-child(2) {
transition-delay: 35ms;
}
.client-rule-type.is-open .client-rule-type-list button:nth-child(3) {
transition-delay: 70ms;
}
.client-rule-type-list button:hover,
.client-rule-type-list button:focus-visible,
.client-rule-type-list button[aria-selected='true'] {
outline: 0;
color: var(--client-accent);
text-shadow: 0 0 9px color-mix(in oklch, var(--client-accent) 40%, transparent);
}
.client-local-rule input {
padding: 0 10px;
min-width: 0;
height: 34px;
padding: 0 2px;
border: 0;
outline: 0;
background: transparent;
color: var(--client-text);
font: 500 10px/1 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace;
box-shadow: 0 1px 0 transparent;
transition: color 220ms ease, box-shadow 300ms ease, text-shadow 300ms ease;
}
.client-local-rule input::placeholder {
color: color-mix(in oklch, var(--client-muted) 72%, transparent);
color: color-mix(in oklch, var(--client-muted) 70%, transparent);
}
.client-local-rule select:focus-visible,
.client-local-rule input:focus-visible,
.client-local-rule button:focus-visible,
.client-local-rule-add:focus-visible,
.client-local-rules-actions button:focus-visible {
outline: 2px solid var(--client-accent);
outline-offset: 2px;
.client-local-rule input:focus {
box-shadow: 0 1px 0 color-mix(in oklch, var(--client-accent) 58%, transparent);
text-shadow: 0 0 9px color-mix(in oklch, var(--client-accent) 22%, transparent);
}
.client-local-rule > button {
width: 32px;
.client-local-rule > button:last-child {
width: 28px;
height: 32px;
padding: 0;
border: 0;
border-radius: 8px;
background: transparent;
color: var(--client-muted);
font-size: 17px;
cursor: pointer;
transition: color 180ms ease, background 180ms ease, transform 220ms ease;
transition: color 180ms ease, filter 260ms ease, transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-local-rule > button:hover {
background: color-mix(in oklch, oklch(0.68 0.15 28) 10%, transparent);
.client-local-rule > button:last-child:hover {
color: oklch(0.68 0.15 28);
transform: scale(1.08);
filter: drop-shadow(0 0 7px oklch(0.68 0.15 28 / 0.42));
transform: rotate(8deg) scale(1.1);
}
.client-local-rule-enabled:focus-visible,
.client-rule-type-trigger:focus-visible,
.client-local-rule > button:last-child:focus-visible,
.client-local-rule-add:focus-visible,
.client-local-rules-actions button:focus-visible {
outline: 0;
color: var(--client-accent);
text-shadow: 0 0 10px color-mix(in oklch, var(--client-accent) 48%, transparent);
}
.client-local-rules-empty {
@@ -974,16 +1115,43 @@ p {
font-size: 10px;
font-weight: 700;
cursor: pointer;
transition: opacity 220ms ease, color 220ms ease, text-shadow 300ms ease;
}
.client-local-rule-add:hover {
text-shadow: 0 0 10px color-mix(in oklch, var(--client-accent) 55%, transparent);
}
.client-local-rule-add:disabled {
opacity: 0.3;
cursor: not-allowed;
text-shadow: none;
}
.client-local-rule-add-slot {
min-height: 40px;
display: flex;
align-items: center;
gap: 12px;
}
.client-local-rule-add-slot > span {
color: var(--client-muted);
font-size: 8px;
opacity: 0;
filter: blur(5px);
transform: translateX(-6px);
transition: opacity 220ms ease, filter 320ms ease, transform 380ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-local-rule-add-slot > span.is-visible {
opacity: 1;
filter: blur(0);
transform: translateX(0);
}
.client-local-rules-note {
padding: 12px 14px;
border-radius: 12px;
background: color-mix(in oklch, var(--client-control) 44%, transparent);
max-width: 48ch;
color: var(--client-muted);
font-size: 9px;
line-height: 1.65;
@@ -1002,24 +1170,23 @@ p {
}
.client-local-rules-actions button {
padding: 10px 14px;
padding: 8px 0 8px 14px;
border: 0;
border-radius: 9px;
background: color-mix(in oklch, var(--client-control) 72%, transparent);
background: transparent;
color: var(--client-text);
font-size: 10px;
font-weight: 700;
cursor: pointer;
transition: background 200ms ease, color 200ms ease, transform 220ms ease;
transition: color 200ms ease, filter 300ms ease, transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-local-rules-actions button:hover:not(:disabled) {
background: var(--client-control);
color: var(--client-accent);
filter: drop-shadow(0 0 7px color-mix(in oklch, var(--client-accent) 40%, transparent));
transform: translateY(-1px);
}
.client-local-rules-actions .is-primary {
background: color-mix(in oklch, var(--client-accent) 18%, var(--client-control));
color: var(--client-accent);
}
@@ -1028,6 +1195,16 @@ p {
cursor: wait;
}
@keyframes client-local-rule-enter {
from { opacity: 0; filter: blur(8px); transform: translateY(-10px) scale(0.985); }
to { opacity: 1; filter: blur(0); transform: translateY(0) scale(1); }
}
@keyframes client-local-rule-leave {
from { opacity: 1; filter: blur(0); transform: translateX(0) scale(1); }
to { opacity: 0; filter: blur(8px); transform: translateX(18px) scale(0.97); }
}
.client-instructions {
position: fixed;
inset: 0 auto 0 0;
@@ -2524,25 +2701,29 @@ p {
font-size: 18px;
}
.client-local-rule,
.client-local-rule.is-built-in {
grid-template-columns: 1fr 32px;
.client-local-rule {
grid-template-columns: 24px minmax(0, 1fr) 28px;
gap: 8px;
}
.client-local-rule select,
.client-local-rule.is-built-in strong {
grid-column: 1 / -1;
}
.client-local-rule input,
.client-local-rule.is-built-in code {
.client-local-rule-enabled {
grid-column: 1;
grid-row: 1;
}
.client-local-rule.is-built-in small {
.client-rule-type {
grid-column: 2;
grid-row: 1;
}
.client-local-rule > button:last-child {
grid-column: 3;
grid-row: 1;
}
.client-local-rule input {
grid-column: 2 / -1;
grid-row: 2;
white-space: normal;
}
.client-instructions-header h2 {
@@ -2609,7 +2790,17 @@ p {
.client-local-rules-toggle svg,
.client-local-rules-toggle span,
.client-local-rule,
.client-local-rule > button,
.client-local-rule-enabled svg,
.client-local-rule-enabled circle,
.client-local-rule-enabled path,
.client-rule-type-trigger,
.client-rule-type-trigger svg,
.client-rule-type-list,
.client-rule-type-list button,
.client-local-rule input,
.client-local-rule > button:last-child,
.client-local-rule-add,
.client-local-rule-add-slot > span,
.client-local-rules-actions button {
transition: none;
animation: none;