:root { color-scheme: light dark; } * { box-sizing: border-box; } html, body, #root { min-height: 100%; } body { margin: 0; } button, input { font: inherit; color: inherit; } h2, p { margin: 0; } .app { min-height: 100vh; display: grid; } .app-body { min-height: 0; } .app-main { min-width: 0; } .app-loading { min-height: 100vh; display: grid; place-items: center; font: 700 16px/1 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; color: light-dark(oklch(0.42 0.01 145), oklch(0.76 0.01 145)); background: light-dark(oklch(0.965 0.006 145), oklch(0.18 0.012 145)); } .app-boot { min-height: 100vh; display: grid; place-content: center; justify-items: start; gap: 14px; padding: 32px; background: light-dark(oklch(0.965 0.006 145), oklch(0.18 0.012 145)); color: light-dark(oklch(0.24 0.014 145), oklch(0.93 0.008 145)); font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; } .app-boot > span, .app-boot summary { color: light-dark(oklch(0.53 0.014 145), oklch(0.68 0.012 145)); font-size: 11px; } .app-boot h1 { max-width: 22ch; margin: 0; font-size: clamp(22px, 5vw, 34px); letter-spacing: -0.05em; } .app-boot p { max-width: 58ch; color: light-dark(oklch(0.53 0.014 145), oklch(0.68 0.012 145)); font-size: 12px; line-height: 1.7; } .app-boot button, .client-stale-banner button { padding: 8px 12px; border: 0; border-radius: 8px; background: light-dark(oklch(0.91 0.02 185), oklch(0.28 0.03 185)); cursor: pointer; } .app-boot button:focus-visible, .client-stale-banner button:focus-visible { outline: 2px solid oklch(0.65 0.11 185); outline-offset: 3px; } .app-boot details { max-width: min(640px, calc(100vw - 64px)); margin-top: 8px; } .app-boot summary { cursor: pointer; } .app-boot code, .app-boot pre { display: block; overflow-x: auto; margin: 12px 0 0; font-size: 11px; line-height: 1.6; white-space: pre-wrap; } .client-stale-banner { position: fixed; top: 16px; left: 50%; z-index: 60; display: grid; grid-template-columns: auto auto auto; align-items: center; gap: 12px; padding: 9px 10px 9px 14px; border-radius: 12px; background: color-mix(in oklch, var(--client-panel) 90%, transparent); box-shadow: 0 10px 32px oklch(0.08 0.015 145 / 0.14); backdrop-filter: blur(12px); color: var(--client-muted); font: 600 10px/1.3 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; transform: translateX(-50%); } .client-stale-banner strong { color: var(--client-text); } .client-stale-banner button { color: var(--client-text); font-size: 10px; } /* ============ Client overview ============ */ .app.client-app { --client-bg: oklch(0.965 0.006 145); --client-panel: oklch(0.995 0.003 145); --client-control: oklch(0.955 0.006 145); --client-border: oklch(0.86 0.012 145); --client-text: oklch(0.24 0.014 145); --client-muted: oklch(0.53 0.014 145); --harbor-word: oklch(0.39 0.075 232); --harbor-connect: oklch(0.57 0.11 185); --harbor-gateway: oklch(0.61 0.12 72); --client-accent: var(--harbor-connect); --client-accent-soft: color-mix(in oklch, var(--client-accent) 22%, transparent); grid-template-rows: 1fr; color-scheme: light; background: var(--client-bg); } .app.client-app.is-gateway-app { --client-accent: var(--harbor-gateway); } .app-body.client-mode { min-height: 100vh; background: var(--client-bg); } .client-mode .app-main { min-height: 100vh; display: grid; place-items: center; padding: 48px 24px 32px; overflow-y: auto; } .client-shell { position: relative; width: min(100%, 1100px); display: grid; gap: 12px; font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; color: var(--client-text); } .client-shell:has(.harbor-brand.is-gateway-active) { --client-accent: var(--harbor-gateway); } .harbor-versions { position: fixed; right: max(14px, env(safe-area-inset-right)); bottom: max(12px, env(safe-area-inset-bottom)); z-index: 40; display: grid; justify-items: end; gap: 4px; color: var(--client-muted); font: 650 12px/1 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; } .harbor-version { display: flex; align-items: center; gap: 6px; opacity: 0.56; transition: color 240ms ease, opacity 240ms ease; } .harbor-version:focus-within, .harbor-version:hover { color: var(--client-text); opacity: 1; } .harbor-version.is-incompatible { color: oklch(0.68 0.15 28); opacity: 0.9; } .harbor-version-code { width: 1.3ch; color: var(--client-accent); font-size: 10px; text-align: center; } .harbor-version-number { display: flex; align-items: center; } .harbor-version-part { position: relative; min-width: 1ch; padding: 5px 2px; border-radius: 5px; cursor: help; text-align: center; } .harbor-version-part:hover, .harbor-version-part:focus-visible { outline: none; color: var(--client-accent); text-shadow: 0 0 8px color-mix(in oklch, var(--client-accent) 48%, transparent); } .harbor-version-part:focus-visible { box-shadow: 0 0 0 1px var(--client-accent); } .harbor-version-tooltip { position: absolute; right: 0; bottom: calc(100% + 7px); width: min(300px, calc(100vw - 28px)); display: grid; gap: 7px; padding: 12px 13px; border-radius: 12px; background: color-mix(in oklch, var(--client-panel) 84%, transparent); box-shadow: 0 9px 30px oklch(0.08 0.015 145 / 0.16); backdrop-filter: blur(12px) saturate(0.9); color: var(--client-muted); font-size: 11px; font-weight: 500; line-height: 1.5; text-align: left; opacity: 0; visibility: hidden; filter: blur(2px); pointer-events: none; transform: translateY(3px); transition: opacity 90ms ease, filter 120ms ease, transform 140ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s 140ms; } .harbor-version-tooltip strong { color: var(--client-text); font-size: 11px; } .harbor-version-tooltip small { color: var(--client-accent); font-size: 10px; } .harbor-version-tooltip .is-warning { color: oklch(0.68 0.15 28); } .harbor-version-part:hover .harbor-version-tooltip, .harbor-version-part:focus-visible .harbor-version-tooltip { opacity: 1; visibility: visible; filter: blur(0); transform: translateY(0); transition-delay: 20ms, 20ms, 20ms, 0s; } .harbor-brand { position: fixed; top: 50%; left: 50%; z-index: 2; color: var(--harbor-word); font-size: 13px; letter-spacing: -0.035em; transform: translate(-50%, calc(-50% - 25vh)) scale(3); transform-origin: center; transition: transform 1800ms cubic-bezier(0.16, 1, 0.3, 1); user-select: none; pointer-events: none; } .harbor-brand.is-switchable { pointer-events: auto; } .harbor-brand-control { position: relative; appearance: none; border: 0; border-radius: 7px; padding: 3px 5px; background: transparent; color: inherit; font: inherit; letter-spacing: inherit; cursor: pointer; } .harbor-brand-control:focus-visible { outline: 1px solid color-mix(in srgb, var(--harbor-gateway) 55%, transparent); outline-offset: 4px; } .harbor-brand-control:disabled { cursor: wait; } .client-shell.is-first-run .harbor-brand { transform: translate(-50%, calc(-50% - 72px)) scale(1.35); } .harbor-brand-content { position: relative; display: flex; align-items: center; gap: 9px; } .client-shell.is-intro .harbor-brand-content { animation: harbor-first-run 1200ms cubic-bezier(0.16, 1, 0.3, 1); } .client-shell.is-intro .client-form { animation: harbor-first-run-form 650ms 720ms cubic-bezier(0.16, 1, 0.3, 1) both; } @keyframes harbor-first-run { from { transform: translateY(53px) scale(1.59); } } @keyframes harbor-first-run-form { from { opacity: 0; filter: blur(8px); } } .harbor-brand svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; } .harbor-brand .harbor-anchor-left { stroke: var(--harbor-connect); } .harbor-brand .harbor-anchor-right { stroke: var(--harbor-gateway); } .harbor-brand.is-gateway .harbor-anchor-left { stroke: var(--harbor-gateway); } .harbor-brand strong { font-weight: 800; } .harbor-brand-name { display: flex; align-items: center; gap: 0.45em; } .harbor-brand em { color: var(--harbor-connect); font-style: normal; font-weight: 600; } .harbor-brand.is-gateway em { color: var(--harbor-gateway); } .harbor-mode-control, .harbor-mode-stack { position: relative; display: inline-block; width: 4.5em; height: 1.25em; } .harbor-mode-stack { width: 100%; height: 100%; } .harbor-mode-stack em { position: absolute; inset: 0 auto auto 0; transition: color 420ms ease, opacity 420ms ease, filter 420ms ease, transform 560ms cubic-bezier(0.16, 1, 0.3, 1); } .harbor-brand .harbor-mode-connect { z-index: 2; color: var(--harbor-connect); animation: harbor-mode-ambient-front 10s ease-in-out infinite; } .harbor-brand .harbor-mode-gateway { z-index: 1; color: var(--harbor-gateway); opacity: 0.2; filter: blur(0.4px); transform: translate(0.42em, 0.34em) scale(0.96); animation: harbor-mode-ambient-back 10s ease-in-out infinite; } .harbor-brand.is-gateway-active .harbor-mode-connect { z-index: 1; opacity: 0.18; filter: blur(0.4px); transform: translate(0.42em, 0.34em) scale(0.96); } .harbor-brand.is-gateway-active .harbor-mode-gateway { z-index: 2; opacity: 1; filter: none; transform: none; } .harbor-brand.is-gateway-active .harbor-mode-connect { animation-name: harbor-mode-ambient-back; } .harbor-brand.is-gateway-active .harbor-mode-gateway { animation-name: harbor-mode-ambient-front; } .harbor-brand-control.is-mode-animating .harbor-mode-connect { animation: harbor-mode-float-front 1500ms ease-in-out infinite; } .harbor-brand-control.is-mode-animating .harbor-mode-gateway { animation: harbor-mode-float-back 1500ms ease-in-out infinite; } .harbor-brand.is-gateway-active .harbor-brand-control.is-mode-animating .harbor-mode-connect { animation-name: harbor-mode-float-back; } .harbor-brand.is-gateway-active .harbor-brand-control.is-mode-animating .harbor-mode-gateway { animation-name: harbor-mode-float-front; } @keyframes harbor-mode-float-front { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(0.12em); } } @keyframes harbor-mode-float-back { 0%, 100% { transform: translate(0.42em, 0.34em) scale(0.96); } 50% { transform: translate(0.42em, 0.22em) scale(0.96); } } @keyframes harbor-mode-ambient-front { 0%, 88%, 96%, 100% { transform: translateY(0); } 92% { transform: translateY(0.08em); } } @keyframes harbor-mode-ambient-back { 0%, 88%, 96%, 100% { transform: translate(0.42em, 0.34em) scale(0.96); } 92% { transform: translate(0.42em, 0.26em) scale(0.96); } } .harbor-brand .harbor-mode-swap { position: absolute; top: 50%; left: calc(100% + 4px); width: 14px; height: 14px; opacity: 0.82; stroke-width: 1.35; transform: translateY(-50%); transition: color 320ms ease, opacity 320ms ease, transform 420ms cubic-bezier(0.16, 1, 0.3, 1); } .harbor-mode-swap g, .harbor-mode-swap path { transform-box: fill-box; transform-origin: center; transition: transform 420ms cubic-bezier(0.16, 1, 0.3, 1); } .harbor-mode-swap .is-connect { stroke: var(--harbor-connect); transition: transform 560ms cubic-bezier(0.16, 1, 0.3, 1); } .harbor-mode-swap .is-connect path { animation: harbor-arrow-ambient-right 10s ease-in-out infinite; } .harbor-mode-swap .is-gateway { stroke: var(--harbor-gateway); transition: transform 560ms cubic-bezier(0.16, 1, 0.3, 1); } .harbor-mode-swap .is-gateway path { animation: harbor-arrow-ambient-left 10s ease-in-out infinite; } .harbor-brand.is-gateway-active .harbor-mode-swap .is-connect { transform: translateY(6px); } .harbor-brand.is-gateway-active .harbor-mode-swap .is-gateway { transform: translateY(-6px); } .harbor-mode-tooltip { position: absolute; bottom: calc(100% + 9px); left: 0; width: calc(100% + 22px); display: grid; gap: 2px; padding: 5px 6px; border-radius: 5px; background: color-mix(in oklch, var(--client-panel) 68%, transparent); box-shadow: 0 5px 18px oklch(0.08 0.015 145 / 0.1); backdrop-filter: blur(8px) saturate(0.9); color: var(--client-muted); font-size: 4px; line-height: 1.5; letter-spacing: 0; text-align: left; opacity: 0; visibility: hidden; filter: blur(2px); pointer-events: none; transform: translateY(3px); transition: opacity 90ms ease, filter 120ms ease, transform 140ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s 140ms; } .harbor-mode-tooltip strong { color: var(--client-text); font-size: 4.2px; } .harbor-brand-control:hover .harbor-mode-tooltip, .harbor-brand-control:focus-visible .harbor-mode-tooltip { opacity: 1; visibility: visible; filter: blur(0); transform: translateY(0); transition-delay: 20ms, 20ms, 20ms, 0s; } .harbor-brand-control:hover .harbor-mode-swap, .harbor-brand-control:focus-visible .harbor-mode-swap { opacity: 1; } .harbor-brand-control.is-mode-animating .harbor-mode-swap .is-connect path { animation: harbor-arrow-float-right 1500ms ease-in-out infinite; } .harbor-brand-control.is-mode-animating .harbor-mode-swap .is-gateway path { animation: harbor-arrow-float-left 1500ms ease-in-out infinite; } @keyframes harbor-arrow-float-right { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(1.25px); } } @keyframes harbor-arrow-float-left { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-1.25px); } } @keyframes harbor-arrow-ambient-right { 0%, 88%, 96%, 100% { transform: translateX(0); } 92% { transform: translateX(0.75px); } } @keyframes harbor-arrow-ambient-left { 0%, 88%, 96%, 100% { transform: translateX(0); } 92% { transform: translateX(-0.75px); } } .client-instructions-toggle { position: fixed; top: 50%; left: 14px; z-index: 30; width: 42px; height: 54px; display: grid; place-items: center; padding: 0; border: 0; background: transparent; color: var(--client-muted); cursor: pointer; transform: translateY(-50%); transition: transform 440ms cubic-bezier(0.16, 1, 0.3, 1); } .client-instructions-toggle svg { position: relative; z-index: 1; width: 23px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; overflow: visible; transition: transform 500ms cubic-bezier(0.16, 1, 0.3, 1); } .client-instructions-toggle path { opacity: 0; transform: translateX(-5px); transition: opacity 260ms ease, transform 480ms cubic-bezier(0.16, 1, 0.3, 1); } .client-instructions-toggle path:last-child { opacity: 1; transform: translateX(-4px); } .client-instructions-toggle span { position: absolute; left: 48px; width: max-content; color: var(--client-text); font: 700 10px/1.2 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; letter-spacing: 0.04em; opacity: 0; filter: blur(5px); pointer-events: none; transform: translateX(-8px); transition: opacity 350ms ease, filter 350ms ease, transform 500ms cubic-bezier(0.16, 1, 0.3, 1); } .client-instructions-toggle:hover, .client-instructions-toggle:focus-visible { outline: none; transform: translateY(-50%) translateX(3px); } .client-instructions-toggle:hover path, .client-instructions-toggle:focus-visible path { opacity: 1; transform: translateX(0); } .client-instructions-toggle:hover span, .client-instructions-toggle:focus-visible span { opacity: 1; filter: blur(0); transform: translateX(0); } .client-instructions-toggle.is-open svg { transform: rotate(180deg); } .client-instructions-toggle.is-open path { opacity: 0; } .client-instructions-toggle.is-open path:first-child { opacity: 1; transform: translateX(4px); } .client-instructions-toggle.is-open span { opacity: 0; visibility: hidden; } .client-local-rules-toggle { position: fixed; top: 50%; right: 14px; z-index: 30; width: 42px; height: 54px; display: grid; place-items: center; padding: 0; border: 0; background: transparent; color: var(--client-muted); cursor: pointer; transform: translateY(-50%); transition: color 240ms ease, transform 440ms cubic-bezier(0.16, 1, 0.3, 1); } .client-local-rules-toggle svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; transition: color 240ms ease, filter 360ms ease, transform 500ms cubic-bezier(0.16, 1, 0.3, 1); } .client-local-rules-toggle span { position: absolute; right: 48px; width: max-content; color: var(--client-text); font: 700 10px/1.2 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; letter-spacing: 0.04em; opacity: 0; filter: blur(5px); pointer-events: none; transform: translateX(8px); transition: opacity 350ms ease, filter 350ms ease, transform 500ms cubic-bezier(0.16, 1, 0.3, 1); } .client-local-rules-toggle:hover, .client-local-rules-toggle:focus-visible { outline: none; color: var(--client-accent); transform: translateY(-50%) translateX(-3px); } .client-local-rules-toggle:hover svg, .client-local-rules-toggle:focus-visible svg { filter: drop-shadow(0 0 7px color-mix(in oklch, var(--client-accent) 52%, transparent)); } .client-local-rules-toggle:hover span, .client-local-rules-toggle:focus-visible span { opacity: 1; filter: blur(0); transform: translateX(0); } .client-local-rules-toggle:disabled { cursor: default; color: var(--client-muted); } .client-local-rules-toggle:disabled span { opacity: 0.7; filter: blur(0); transform: translateX(0); } .client-local-rules-toggle.is-open { color: var(--client-accent); } .client-local-rules-toggle.has-pending:not(.is-open) { color: oklch(0.68 0.14 72); } .client-local-rules-toggle.has-pending:not(.is-open) svg { filter: drop-shadow(0 0 7px oklch(0.68 0.14 72 / 0.42)); } .client-local-rules-toggle.is-open svg { transform: rotate(90deg); } .client-local-rules-toggle.is-open span { opacity: 0; visibility: hidden; } .client-local-rules { position: fixed; inset: 0 0 0 auto; z-index: 20; width: min(480px, 100vw); overflow-y: auto; background: color-mix(in oklch, var(--client-bg) 99%, var(--client-panel)); color: var(--client-text); opacity: 0; visibility: hidden; transform: translateX(104%); transition: transform 760ms cubic-bezier(0.16, 1, 0.3, 1), opacity 500ms ease, visibility 0s 760ms; } .client-local-rules.is-open { opacity: 1; visibility: visible; transform: translateX(0); transition-delay: 0s; } .client-local-rules-sheet { min-height: 100%; padding: 54px 72px 72px 34px; font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; } .client-local-rules-header { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 9px; margin: 0 8px 34px; } .client-local-rules-header > span, .client-local-rules-group > span { color: var(--client-muted); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; } .client-local-rules-header h2 { grid-column: 1 / -1; font-size: 22px; letter-spacing: -0.045em; } .client-local-rules-header p { grid-column: 1 / -1; max-width: 46ch; color: var(--client-muted); font-size: 11px; line-height: 1.7; } .client-local-rules-save { align-self: center; padding: 0; border: 0; background: transparent; color: var(--client-accent); font-size: 10px; font-weight: 700; cursor: pointer; transition: color 200ms ease, filter 300ms ease, opacity 220ms ease, transform 300ms cubic-bezier(0.16, 1, 0.3, 1); } .client-local-rules-save:hover:not(:disabled) { filter: drop-shadow(0 0 7px color-mix(in oklch, var(--client-accent) 42%, transparent)); transform: translateY(-1px); } .client-local-rules-save:disabled { opacity: 0.28; cursor: default; } .client-local-rules-header .client-local-rules-runtime { color: oklch(0.68 0.14 72); animation: client-local-rules-notice 480ms cubic-bezier(0.16, 1, 0.3, 1) both; } .client-local-rules-form, .client-local-rules-group, .client-local-rules-list { display: grid; } .client-local-rules-form { gap: 28px; } .client-local-rules-group { gap: 11px; } .client-local-rules-list { gap: 2px; } .client-local-rule { position: relative; isolation: isolate; min-width: 0; display: grid; grid-template-columns: 24px 116px minmax(0, 1fr) 112px 28px; align-items: center; gap: 10px; padding: 7px 0; animation: client-local-rule-enter 560ms cubic-bezier(0.16, 1, 0.3, 1) both; transition: opacity 260ms ease, filter 360ms ease; } .client-local-rule:has(.client-rule-type.is-open) { z-index: 5; } .client-local-rule-status { color: var(--client-muted); font-size: 9px; font-weight: 700; letter-spacing: 0.07em; text-align: right; text-transform: uppercase; transition: color 280ms ease, opacity 280ms ease, filter 360ms ease; } .client-local-rule.is-active .client-local-rule-status { color: var(--client-accent); } .client-local-rule.is-pending .client-local-rule-status, .client-local-rule.is-unsaved .client-local-rule-status { color: var(--client-warning, oklch(0.72 0.12 72)); } .client-local-rule.is-disabled { opacity: 0.42; filter: saturate(0); } .client-local-rule.is-removing { pointer-events: none; animation: client-local-rule-leave 760ms cubic-bezier(0.7, 0, 0.84, 0) both; } .client-delete-strike { --client-delete-strike-y: 50%; position: absolute; top: 0; right: 0; bottom: 0; left: 12px; z-index: 100; background: transparent; opacity: 0; pointer-events: none; transform: scaleX(0); transform-origin: left center; } .client-delete-strike::after { content: ''; position: absolute; left: 0; right: 0; top: calc(var(--client-delete-strike-y) - 1px); height: 2px; background: oklch(0.68 0.15 28); clip-path: polygon(0 24%, 100% 50%, 0 76%); filter: drop-shadow(0 0 3px oklch(0.68 0.15 28 / 0.38)); } .client-delete-strike::before { content: ''; position: absolute; inset: 32% 0; background: oklch(0.68 0.15 28 / 0.32); clip-path: polygon(0 46%, 20% 8%, 100% 50%, 20% 92%, 0 54%); filter: blur(3px); } .client-deletable-row.is-removing > .client-delete-strike { animation: client-delete-strike 760ms cubic-bezier(0.16, 1, 0.3, 1) both; } .client-deletable-row.is-removing > :not(.client-delete-strike) { position: relative; z-index: 0; } .client-deletable-row.is-removing > .client-local-rule-enabled { z-index: 101; color: oklch(0.68 0.15 28); } .client-local-rule-enabled { width: 24px; height: 32px; display: grid; place-items: center; padding: 0; border: 0; 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-rule-check { stroke-width: 1.8; stroke-dasharray: 12; stroke-dashoffset: 12; transition: opacity 160ms ease, stroke-dashoffset 360ms cubic-bezier(0.16, 1, 0.3, 1); } .client-rule-delete-cross { stroke-width: 1.6; opacity: 0; transform: rotate(-35deg) scale(0.55); transform-origin: center; transition: opacity 160ms ease, transform 240ms 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'] .client-rule-check { stroke-dashoffset: 0; } .client-deletable-row.is-removing .client-local-rule-enabled circle, .client-deletable-row.is-removing .client-rule-check { opacity: 0; } .client-deletable-row.is-removing .client-rule-delete-cross { opacity: 1; transform: rotate(0) scale(1); filter: drop-shadow(0 0 3px oklch(0.68 0.15 28 / 0.55)); } .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 { 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) 70%, transparent); } .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-delete { width: 28px; height: 32px; padding: 0; border: 0; background: transparent; color: var(--client-muted); font-size: 17px; cursor: pointer; transition: color 180ms ease, filter 260ms ease, transform 300ms cubic-bezier(0.16, 1, 0.3, 1); } .client-local-rule-delete:hover { color: oklch(0.68 0.15 28); 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-delete:focus-visible, .client-local-rule-add:focus-visible, .client-local-rules-save: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 { padding: 14px 4px 4px; color: var(--client-muted); font-size: 10px; line-height: 1.6; } .client-local-rule-add { width: fit-content; padding: 7px 0; border: 0; background: transparent; color: var(--client-accent); 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 { max-width: 48ch; color: var(--client-muted); font-size: 9px; line-height: 1.65; } .client-inline-error.is-routing { position: static; width: 100%; transform: none; } .client-local-rules-actions { display: flex; justify-content: flex-end; gap: 10px; } .client-local-rules-actions button { padding: 8px 0 8px 14px; border: 0; background: transparent; color: var(--client-text); font-size: 10px; font-weight: 700; cursor: pointer; 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) { 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 button:disabled { opacity: 0.45; 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 { 0%, 48% { opacity: 1; filter: blur(0); } 100% { opacity: 0; filter: blur(8px); } } @keyframes client-delete-strike { 0% { opacity: 1; transform: scaleX(0); } 38%, 58% { opacity: 1; transform: scaleX(1); } 100% { opacity: 0; transform: scaleX(1); } } @keyframes client-local-rules-notice { from { opacity: 0; filter: blur(6px); transform: translateY(-6px); } to { opacity: 1; filter: blur(0); transform: translateY(0); } } .client-instructions { position: fixed; inset: 0 auto 0 0; z-index: 20; width: min(470px, 100vw); 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%); transition: transform 760ms cubic-bezier(0.16, 1, 0.3, 1), opacity 500ms ease, visibility 0s 760ms; } .client-instructions.is-open { opacity: 1; visibility: visible; transform: translateX(0); transition-delay: 0s; } .client-instructions-sheet { min-height: 100%; padding: 54px 34px 72px 72px; font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; } .client-instructions-header { display: grid; gap: 9px; margin: 0 8px 38px; } .client-instructions-header span, .client-instruction-summary > span { color: var(--client-muted); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; } .client-instructions-header h2 { margin: 0; font-size: 22px; letter-spacing: -0.045em; } .client-instructions-intro { display: grid; gap: 12px; margin-top: 15px; color: var(--client-muted); font-size: 11px; line-height: 1.7; } .client-instructions-intro p { margin: 0; } .client-instruction-list { display: grid; gap: 15px; } .client-instruction-block { border: 0; border-radius: 22px; background: color-mix(in oklch, var(--client-panel) 56%, var(--client-bg)); box-shadow: 0 14px 36px oklch(0.1 0.015 145 / 0.065); transition: background 300ms ease, box-shadow 500ms ease, transform 500ms cubic-bezier(0.16, 1, 0.3, 1); } .client-instruction-block:nth-child(even) { margin-left: 12px; } .client-instruction-block:nth-child(3n) { margin-right: 9px; } .client-instruction-block:hover, .client-instruction-block.is-open { background: color-mix(in oklch, var(--client-panel) 68%, var(--client-bg)); box-shadow: 0 20px 48px oklch(0.1 0.015 145 / 0.095); transform: translateY(-2px); } .client-instruction-block.is-open { animation: client-instruction-promote 520ms cubic-bezier(0.16, 1, 0.3, 1) both; } @keyframes client-instruction-promote { from { opacity: 0.72; transform: translateY(10px); } to { opacity: 1; transform: translateY(-2px); } } ::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; } ::view-transition-group(*) { animation-duration: 420ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } ::view-transition-group(instruction-proxybridge), ::view-transition-group(instruction-switchyomega), ::view-transition-group(instruction-vscode), ::view-transition-group(instruction-router) { animation-duration: 560ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } .client-instruction-summary { position: relative; width: 100%; display: grid; gap: 7px; padding: 21px 46px 21px 22px; border: 0; background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; } .client-instruction-summary:focus-visible { outline: none; } .client-instruction-block:has(.client-instruction-summary:focus-visible) { background: color-mix(in oklch, var(--client-panel) 72%, var(--client-bg)); box-shadow: 0 20px 48px oklch(0.1 0.015 145 / 0.11); } .client-instruction-summary > i { position: absolute; top: 27px; right: 20px; width: 12px; height: 12px; } .client-instruction-summary > i::before, .client-instruction-summary > i::after { content: ''; position: absolute; top: 5px; left: 0; width: 12px; height: 1px; background: var(--client-muted); transform-origin: center; transition: transform 520ms cubic-bezier(0.16, 1, 0.3, 1), opacity 360ms ease; } .client-instruction-summary > i::after { transform: rotate(90deg); } .client-instruction-block.is-open .client-instruction-summary > i::after { opacity: 0; transform: rotate(180deg); } .client-instruction-block.is-open .client-instruction-summary > i::before { transform: rotate(180deg); } .client-instruction-summary strong { font-size: 14px; } .client-instruction-summary small { max-width: 54ch; color: var(--client-muted); font-size: 10px; line-height: 1.55; } .client-instruction-reveal { display: grid; grid-template-rows: 0fr; opacity: 0; filter: blur(4px); transition: grid-template-rows 600ms cubic-bezier(0.16, 1, 0.3, 1), opacity 420ms ease, filter 500ms ease; } .client-instruction-block.is-open .client-instruction-reveal { grid-template-rows: 1fr; opacity: 1; filter: blur(0); } .client-instruction-body { min-height: 0; overflow: hidden; display: grid; gap: 14px; padding: 0 22px 24px; color: var(--client-muted); font-size: 11px; line-height: 1.7; } .client-instruction-body p, .client-instruction-body ol { margin: 0; } .client-instruction-body ol { display: grid; gap: 9px; padding-left: 22px; } .client-instruction-body li::marker { color: var(--client-accent); font-variant-numeric: tabular-nums; } .client-instruction-body code { display: block; overflow-x: auto; padding: 12px 14px; border-radius: 12px; background: color-mix(in oklch, var(--client-control) 84%, transparent); color: var(--client-text); font: 500 11px/1.5 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; white-space: nowrap; } .client-instruction-body .client-instruction-note { padding: 11px 13px; border-radius: 12px; background: color-mix(in oklch, var(--client-control) 48%, transparent); color: var(--client-text); } .client-instruction-body a { width: fit-content; color: var(--client-accent); font-weight: 700; text-decoration: none; } .client-instruction-body a:hover { text-decoration: underline; text-underline-offset: 3px; } .client-panel { position: relative; display: grid; place-items: center; min-height: 520px; padding: 24px 0; } .client-panel.is-setup .client-form { left: 50%; transform: translateX(-50%); } .client-power-section p { color: var(--client-muted); font-size: 11px; } .client-power-section { position: relative; display: grid; justify-items: center; gap: 18px; text-align: center; animation: client-power-arrive 850ms cubic-bezier(0.16, 1, 0.3, 1) both; } .client-route-rules-pending { min-height: 17px; display: flex; align-items: center; gap: 10px; margin: -10px 0 -8px; color: var(--client-warning, oklch(0.72 0.12 72)); font-size: 9px; font-weight: 700; letter-spacing: 0.06em; opacity: 0; filter: blur(5px); transform: translateY(-3px); transition: opacity 240ms ease, filter 320ms ease, transform 320ms cubic-bezier(0.16, 1, 0.3, 1); } .client-route-rules-pending.is-visible { opacity: 1; filter: blur(0); transform: translateY(0); } .client-route-rules-pending button { padding: 0; border: 0; background: transparent; color: var(--client-accent); font: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; } .client-route-rules-pending button:disabled { cursor: default; opacity: 0.35; } @keyframes client-power-arrive { 0% { opacity: 0; filter: blur(8px); transform: scale(0.94); } 100% { opacity: 1; filter: blur(0); transform: scale(1); } } .client-state-copy { min-height: 54px; } .client-power { position: relative; width: 96px; height: 96px; display: grid; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--client-muted); cursor: pointer; transition: color 800ms cubic-bezier(0.16, 1, 0.3, 1), opacity 600ms ease; } .client-power::before, .client-power::after { content: ''; position: absolute; border-radius: 50%; pointer-events: none; } .client-power::before { width: 54px; height: 54px; border-radius: 50%; background: radial-gradient(circle, color-mix(in oklch, currentColor 38%, transparent), transparent 70%); opacity: 0; filter: blur(2px); transform: translate3d(0, 4px, 0) scale(0.62); transition: opacity 1050ms cubic-bezier(0.16, 1, 0.3, 1), transform 1250ms cubic-bezier(0.16, 1, 0.3, 1), filter 1050ms ease; } .client-power::after { width: 24px; height: 24px; background: radial-gradient(circle, color-mix(in oklch, currentColor 48%, transparent), transparent 72%); opacity: 0; filter: blur(5px); transform: translate3d(-8px, 7px, 0) scale(0.7); transition: opacity 850ms cubic-bezier(0.16, 1, 0.3, 1), transform 950ms cubic-bezier(0.16, 1, 0.3, 1); } .client-power[aria-checked='true']::before { opacity: 0.76; filter: blur(3px); transform: translate3d(-3px, -2px, 0) scale(1.48); } .client-power[aria-checked='true']::after { animation: client-power-light-flicker 4.7s 650ms ease-in-out infinite; } .client-power:hover:not(:disabled) { color: var(--client-muted); } .client-power[aria-checked='true'] { color: var(--client-accent); } .client-power:active:not(:disabled) { opacity: 0.82; } .client-power:active:not(:disabled)::before { animation: none; opacity: 0.86; transform: translate3d(3px, -2px, 0) scale(1.56); } .client-power:active:not(:disabled)::after { animation: none; opacity: 0.7; transform: translate3d(-7px, 8px, 0) scale(1.18); } .client-power:disabled { opacity: 0.45; cursor: not-allowed; } .client-power svg { position: relative; width: 40px; height: 40px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; filter: drop-shadow(0 0 0 transparent); transition: filter 700ms cubic-bezier(0.16, 1, 0.3, 1); } .client-power:hover:not(:disabled) svg { filter: drop-shadow(0 0 4px color-mix(in oklch, var(--client-muted) 32%, transparent)); } .client-power[aria-checked='true']:hover:not(:disabled) { color: var(--client-accent); } .client-power[aria-checked='true']:hover:not(:disabled) svg { filter: drop-shadow(0 0 5px color-mix(in oklch, var(--client-accent) 48%, transparent)); } .client-power[aria-checked='true'] svg { filter: drop-shadow(0 0 4px color-mix(in oklch, var(--client-accent) 42%, transparent)); } @keyframes client-power-light-flicker { 0%, 100% { opacity: 0.18; transform: translate3d(-8px, 7px, 0) scale(0.82); } 19% { opacity: 0.5; transform: translate3d(7px, 5px, 0) scale(1.08); } 46% { opacity: 0.26; transform: translate3d(8px, -7px, 0) scale(0.78); } 71% { opacity: 0.58; transform: translate3d(-6px, -8px, 0) scale(1.12); } } .client-power-section h2 { font: 700 18px/1.3 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; letter-spacing: -0.04em; animation: client-state-reveal 700ms cubic-bezier(0.16, 1, 0.3, 1); } .client-connection-title { display: grid; min-height: 24px; place-items: center; } .client-connection-title > span { grid-area: 1 / 1; opacity: 0; filter: blur(5px); transform: scale(0.97); transition: opacity 480ms ease, filter 620ms cubic-bezier(0.16, 1, 0.3, 1), transform 620ms cubic-bezier(0.16, 1, 0.3, 1); } .client-connection-title > .is-active { opacity: 1; filter: blur(0); transform: scale(1); } .client-state-detail { min-height: 20px; display: grid; place-items: center; margin-top: 8px; } .client-state-detail > * { grid-area: 1 / 1; margin: 0; animation: client-state-reveal 850ms 80ms cubic-bezier(0.16, 1, 0.3, 1) both; } .client-duration { grid-area: 1 / 1; display: block; color: var(--client-text); font-size: 14px; font-variant-numeric: tabular-nums; letter-spacing: 0.04em; opacity: 0; filter: blur(5px); transition: opacity 260ms ease, filter 420ms cubic-bezier(0.16, 1, 0.3, 1); } .client-duration.is-active { opacity: 1; filter: blur(0); } .client-duration-stack { display: grid; place-items: center; } .client-duration-unit .client-duration-part.is-value { display: inline-block; min-width: 2ch; text-align: right; } .client-duration-unit .client-duration-part.is-label { display: inline-block; text-align: left; } .client-duration-unit[data-unit='days'] .is-label { width: 4ch; } .client-duration-unit[data-unit='hours'] .is-label { width: 5ch; } .client-duration-unit[data-unit='minutes'] .is-label { width: 6ch; } .client-duration-unit[data-unit='seconds'] .is-label { width: 7ch; } .client-duration-unit + .client-duration-unit::before { content: ' '; } .client-duration-seconds-value { display: inline-block; } .client-duration-second-digit { display: inline-block; animation: client-second-tick 520ms cubic-bezier(0.16, 1, 0.3, 1); } @keyframes client-second-tick { from { opacity: 0.82; filter: blur(1px); text-shadow: 0 0 8px color-mix(in oklch, var(--client-accent) 52%, transparent); } to { opacity: 1; filter: blur(0); text-shadow: 0 0 0 transparent; } } .client-duration-toggle { width: 290px; min-height: 24px; display: grid; place-items: center; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; cursor: pointer; } .client-duration-toggle:hover .client-duration, .client-duration-toggle:focus-visible .client-duration { text-shadow: 0 0 10px color-mix(in oklch, var(--client-text) 22%, transparent); } .client-duration-toggle:focus-visible { outline: none; } .client-tooltip-anchor { position: relative; } .client-tooltip { position: absolute; bottom: calc(100% + 6px); left: 50%; z-index: 50; width: max-content; max-width: 220px; padding: 6px 8px; border-radius: 8px; background: color-mix(in oklch, var(--client-panel) 78%, transparent); box-shadow: 0 8px 26px oklch(0.08 0.015 145 / 0.16); backdrop-filter: blur(10px) saturate(0.9); color: var(--client-text); font: 600 10px/1.35 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; letter-spacing: 0; text-align: center; white-space: normal; opacity: 0; visibility: hidden; filter: blur(2px); pointer-events: none; transform: translate(-50%, 2px); transition: opacity 90ms ease, filter 120ms ease, transform 140ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s 140ms; } .client-tooltip-anchor:hover > .client-tooltip, .client-tooltip-anchor:focus-within > .client-tooltip { opacity: 1; visibility: visible; filter: blur(0); transform: translate(-50%, 0); transition-delay: 20ms, 20ms, 20ms, 0s; } .client-icon-tooltip { width: 16px; height: 16px; display: grid; place-items: center; } .client-power-section p { min-height: 0; line-height: 20px; } @keyframes client-state-reveal { 0% { opacity: 0; filter: blur(5px); } 100% { opacity: 1; filter: blur(0); } } .client-form { position: absolute; left: calc(50% + 130px); min-width: 0; width: min(360px, calc(50% - 154px)); display: grid; gap: 36px; transform: translateX(0); transition: left 850ms cubic-bezier(0.16, 1, 0.3, 1), transform 850ms cubic-bezier(0.16, 1, 0.3, 1), width 850ms cubic-bezier(0.16, 1, 0.3, 1), opacity 650ms cubic-bezier(0.16, 1, 0.3, 1), filter 650ms cubic-bezier(0.16, 1, 0.3, 1); } .client-form-content { display: grid; gap: 36px; opacity: 1; filter: blur(0); transition: opacity 360ms ease, filter 480ms cubic-bezier(0.16, 1, 0.3, 1); } .client-confirmation-popup { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; padding: 24px; background: color-mix(in oklch, var(--client-bg) 76%, transparent); -webkit-backdrop-filter: blur(0); backdrop-filter: blur(0); opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 260ms ease, -webkit-backdrop-filter 520ms cubic-bezier(0.16, 1, 0.3, 1), backdrop-filter 520ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s 520ms; } .client-confirmation-popup.is-open { -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); opacity: 1; visibility: visible; pointer-events: auto; transition-delay: 0s; } .client-confirmation-dialog { width: min(430px, calc(100vw - 48px)); display: grid; gap: 14px; padding: 32px 34px; background: color-mix(in oklch, var(--client-bg) 82%, transparent); box-shadow: 0 0 86px color-mix(in oklch, var(--client-bg) 86%, transparent); color: var(--client-text); font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; opacity: 0; filter: blur(18px); transform: scale(0.9); transition: opacity 300ms ease, filter 520ms cubic-bezier(0.16, 1, 0.3, 1), transform 560ms cubic-bezier(0.16, 1, 0.3, 1); } .client-confirmation-popup.is-open .client-confirmation-dialog { opacity: 1; filter: blur(0); transform: scale(1); transition-delay: 90ms; } .client-confirmation-dialog > * { opacity: 0; filter: blur(7px); transform: translateY(7px); transition: opacity 260ms ease, filter 420ms cubic-bezier(0.16, 1, 0.3, 1), transform 460ms cubic-bezier(0.16, 1, 0.3, 1); } .client-confirmation-popup.is-open .client-confirmation-kicker { opacity: 1; filter: blur(0); transform: translateY(0); transition-delay: 170ms; } .client-confirmation-popup.is-open .client-confirmation-dialog h2 { opacity: 1; filter: blur(0); transform: translateY(0); transition-delay: 210ms; } .client-confirmation-popup.is-open .client-confirmation-dialog p { opacity: 1; filter: blur(0); transform: translateY(0); transition-delay: 270ms; } .client-confirmation-popup.is-open .client-confirmation-actions { opacity: 1; filter: blur(0); transform: translateY(0); transition-delay: 330ms; } .client-confirmation-kicker { color: var(--client-muted); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; } .client-confirmation-dialog h2 { color: oklch(0.68 0.15 28); font-size: 18px; letter-spacing: -0.035em; } .client-confirmation-dialog p { max-width: 54ch; color: var(--client-muted); font-size: 11px; line-height: 1.7; } .client-confirmation-actions { display: flex; gap: 18px; margin-top: 4px; } .client-confirmation-actions button { padding: 6px 0; border: 0; background: transparent; color: var(--client-text); font-size: 10px; font-weight: 700; cursor: pointer; transition: color 200ms ease, filter 300ms ease, transform 300ms cubic-bezier(0.16, 1, 0.3, 1); } .client-confirmation-actions button:hover:not(:disabled), .client-confirmation-actions button:focus-visible { outline: none; filter: drop-shadow(0 0 7px currentColor); transform: translateY(-1px); } .client-confirmation-actions .is-danger { color: oklch(0.68 0.15 28); } .client-confirmation-actions button:disabled { opacity: 0.4; cursor: wait; } .client-form.is-waiting { opacity: 0; filter: blur(10px); pointer-events: none; } .client-shell:has(.harbor-brand.is-gateway-active) .client-form:not(.is-waiting) { opacity: 0.34; filter: grayscale(1) saturate(0); } .client-subscription { position: relative; min-width: 0; min-height: 88px; display: grid; align-items: center; justify-items: center; } .client-subscription-refresh, .client-subscription-delete { width: 16px; height: 16px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--client-muted); cursor: pointer; transition: color 250ms ease, filter 500ms ease, opacity 300ms ease, transform 600ms cubic-bezier(0.16, 1, 0.3, 1); } .client-subscription-refresh svg, .client-subscription-delete svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; } .client-subscription-delete .client-trash-lid { transform-origin: 12px 7px; transition: transform 360ms cubic-bezier(0.16, 1, 0.3, 1); } .client-subscription-delete:hover:not(:disabled) .client-trash-lid, .client-subscription-delete:focus-visible .client-trash-lid { transform: translateY(-2px) rotate(-10deg); } .client-subscription-refresh:hover:not(:disabled) { color: var(--client-accent); filter: drop-shadow(0 0 6px color-mix(in oklch, var(--client-accent) 55%, transparent)); transform: rotate(90deg); } .client-subscription-refresh:disabled { color: var(--client-accent); cursor: wait; animation: client-spin 900ms linear infinite; } .client-subscription-refresh:focus-visible { outline: 2px solid var(--client-accent); outline-offset: 2px; } .client-subscription-delete:hover:not(:disabled) { color: oklch(0.68 0.15 28); filter: drop-shadow(0 0 6px oklch(0.68 0.15 28 / 0.45)); } .client-subscription-delete:disabled { opacity: 0.4; cursor: wait; } .client-subscription-delete:focus-visible { outline: 2px solid oklch(0.68 0.15 28); outline-offset: 2px; } .client-subscription.is-editing .client-subscription-refresh, .client-subscription.is-editing .client-subscription-delete { opacity: 0; pointer-events: none; } .client-subscription.is-editing .client-icon-tooltip { opacity: 0; pointer-events: none; } .client-subscription-edit, .client-subscription-summary { grid-area: 1 / 1; width: 100%; border: 0; background: transparent; transition: opacity 650ms cubic-bezier(0.16, 1, 0.3, 1), filter 650ms cubic-bezier(0.16, 1, 0.3, 1), transform 650ms cubic-bezier(0.16, 1, 0.3, 1); } .client-subscription-edit { width: min(100%, 380px); min-height: 44px; display: block; position: relative; opacity: 0; filter: blur(16px); transform: translateY(6px) scale(0.96); pointer-events: none; } .client-subscription-edit::before, .client-subscription-edit::after { content: ''; position: absolute; right: 0; bottom: 0; left: 0; height: 1px; pointer-events: none; } .client-subscription-edit::before { background: var(--client-border); } .client-subscription-edit::after { background: var(--client-accent); opacity: 0.72; filter: blur(0.5px); box-shadow: 0 0 8px var(--client-accent), 0 0 18px var(--client-accent-soft); transition: background 500ms ease, box-shadow 500ms ease; } .client-subscription-edit.is-invalid::after { background: oklch(0.68 0.15 28); box-shadow: 0 0 8px oklch(0.68 0.15 28 / 0.72), 0 0 18px oklch(0.68 0.15 28 / 0.24); } .client-subscription.is-timing-out .client-subscription-edit::after { animation: client-subscription-timeout 5s linear forwards; } @keyframes client-subscription-timeout { 0% { opacity: 0.9; box-shadow: 0 0 8px var(--client-accent), 0 0 18px var(--client-accent-soft); } 100% { opacity: 0.08; box-shadow: 0 0 0 transparent; } } .client-subscription.is-editing .client-subscription-edit { opacity: 1; filter: blur(0); transform: translateY(0); pointer-events: auto; } .client-subscription-edit input { width: 100%; min-width: 0; height: 44px; padding: 0 42px; border: 0; outline: 0; background: transparent; color: var(--client-text); caret-color: transparent; font-size: 12px; text-align: center; } .client-subscription-edit input::placeholder { color: var(--client-muted); } .client-subscription-edit input.has-value { color: transparent; caret-color: transparent; } .client-subscription-edit input:-webkit-autofill, .client-subscription-edit input:-webkit-autofill:hover, .client-subscription-edit input:-webkit-autofill:focus { box-shadow: 0 0 0 1000px var(--client-bg) inset; -webkit-text-fill-color: transparent; } .client-subscription-domain { position: absolute; top: 50%; left: 42px; right: 42px; overflow: hidden; color: var(--client-text); font-size: 12px; text-align: center; text-overflow: ellipsis; transform: translateY(-50%); white-space: nowrap; pointer-events: none; } .client-subscription-submit { position: absolute; top: 4px; right: 0; width: 36px; height: 36px; padding: 0; border: 0; background: transparent; color: var(--client-accent); font-size: 19px; font-weight: 700; cursor: pointer; transition: color 250ms ease, filter 500ms ease, opacity 250ms ease, transform 300ms cubic-bezier(0.16, 1, 0.3, 1); } .client-subscription-submit:hover:not(:disabled), .client-subscription-submit:focus-visible { filter: drop-shadow(0 0 5px var(--client-accent)) drop-shadow(0 0 14px var(--client-accent)); transform: scale(1.14); } .client-subscription-submit:disabled { cursor: default; } .client-subscription-edit.is-checking .client-subscription-submit { color: var(--client-muted); animation: client-validation-pulse 900ms ease-in-out infinite alternate; } .client-subscription-edit.is-invalid .client-subscription-submit { color: oklch(0.68 0.15 28); opacity: 0.9; } @keyframes client-validation-pulse { to { opacity: 0.35; } } .client-subscription-heading { display: flex; align-items: center; gap: 8px; } .client-subscription-domain-button { width: 100%; min-width: 0; max-width: 100%; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; cursor: pointer; } .client-subscription-summary { min-width: 0; max-width: 100%; min-height: 88px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 0 2px; color: var(--client-muted); text-align: center; cursor: pointer; overflow: visible; } .client-subscription.is-editing .client-subscription-summary { opacity: 0; filter: blur(18px); transform: translateY(-4px) scale(1.06); pointer-events: none; } .client-subscription-label { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; } .client-subscription-domain-button strong { display: block; overflow: hidden; color: var(--client-text); font-size: 28px; font-weight: 600; letter-spacing: -0.055em; opacity: 0.88; text-shadow: 0 0 20px color-mix(in oklch, var(--client-accent) 24%, transparent); transition: opacity 300ms cubic-bezier(0.16, 1, 0.3, 1), text-shadow 300ms cubic-bezier(0.16, 1, 0.3, 1), transform 300ms cubic-bezier(0.16, 1, 0.3, 1); text-overflow: ellipsis; white-space: nowrap; } .client-subscription-domain-button:hover strong { opacity: 1; transform: translateY(-2px); text-shadow: 0 0 28px color-mix(in oklch, var(--client-accent) 42%, transparent); } .client-usage { width: min(100%, 250px); display: grid; gap: 7px; margin: -10px auto 0; color: var(--client-muted); text-align: center; } .client-usage > span { font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; } @keyframes client-spin { to { transform: rotate(360deg); } } .client-usage > strong { color: var(--client-text); font-size: 14px; font-weight: 600; transition: color 700ms ease, filter 700ms ease, text-shadow 700ms ease; } .client-usage.is-updated { animation: client-usage-glow 1100ms cubic-bezier(0.16, 1, 0.3, 1); } .client-usage.is-updated > strong { color: var(--client-accent); filter: brightness(1.25); text-shadow: 0 0 8px var(--client-accent), 0 0 22px color-mix(in oklch, var(--client-accent) 70%, transparent); } .client-usage.is-updated .client-usage-bar i { animation: client-bar-flare 1100ms cubic-bezier(0.16, 1, 0.3, 1); } @keyframes client-usage-glow { 30% { filter: drop-shadow(0 0 18px color-mix(in oklch, var(--client-accent) 78%, transparent)); } } @keyframes client-bar-flare { 30% { box-shadow: 0 0 6px var(--client-accent), 0 0 20px var(--client-accent); filter: brightness(1.45); } } .client-usage > strong small { color: var(--client-muted); font-size: 10px; font-weight: 500; } .client-usage-bar { height: 2px; overflow: hidden; background: var(--client-border); } .client-usage-bar i { display: block; height: 100%; background: var(--client-accent); box-shadow: 0 0 8px var(--client-accent); transition: width 600ms cubic-bezier(0.16, 1, 0.3, 1); } .client-usage-details { display: flex; justify-content: center; gap: 12px; font-size: 9px; white-space: nowrap; } .client-servers { display: block; } .client-server-prompt { display: block; margin-bottom: 12px; color: var(--client-muted); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-align: center; text-transform: uppercase; animation: client-state-reveal 700ms cubic-bezier(0.16, 1, 0.3, 1) both; } .client-server-grid { display: grid; grid-template-columns: 1fr; gap: 8px; width: min(100%, 210px); margin-inline: auto; } .client-server { min-width: 0; min-height: 50px; display: flex; flex-direction: column; justify-content: center; gap: 3px; padding: 7px 4px 8px; border: 0; border-bottom: 1px solid var(--client-border); border-radius: 0; background: transparent; color: var(--client-text); text-align: center; cursor: pointer; animation: client-server-enter 760ms calc(var(--server-index) * 110ms) cubic-bezier(0.16, 1, 0.3, 1) both; transition: border-color 160ms ease, background 160ms ease, transform 160ms ease; } .client-server-grid.is-leaving { pointer-events: none; } .client-server-grid.is-leaving .client-server { animation: client-server-leave 420ms calc(var(--server-index) * 90ms) cubic-bezier(0.4, 0, 1, 1) forwards; } @keyframes client-server-leave { 0% { opacity: 1; filter: blur(0); transform: translateY(0); } 100% { opacity: 0; filter: blur(3px); transform: translateY(8px); } } @keyframes client-server-enter { 0% { opacity: 0; filter: blur(3px); transform: translateY(-8px); } 100% { opacity: 1; filter: blur(0); transform: translateY(0); } } .client-server:hover:not(:disabled) { transform: translateY(-2px); background: transparent; opacity: 1; } .client-server:active:not(:disabled) { transform: translateY(0) scale(0.97); } .client-server.is-selected { border-bottom: 2px solid var(--client-accent); background: transparent; } .client-server strong { display: block; overflow: hidden; text-overflow: ellipsis; overflow-wrap: anywhere; font-size: 11px; line-height: 1.4; text-align: center; } .client-server small { color: var(--client-muted); font-size: 11px; text-align: center; } .client-server small.good { color: var(--client-accent); } .client-server small.medium { color: oklch(0.72 0.12 80); } .client-server small.slow { color: oklch(0.65 0.16 30); } .client-server:disabled { cursor: wait; } .client-subscription-edit button:focus-visible, .client-subscription-domain-button:focus-visible, .client-server:focus-visible, .client-power:focus-visible { outline: 2px solid var(--client-accent); outline-offset: 3px; } .client-proxies { display: grid; justify-items: center; gap: 5px; width: 240px; margin-top: 6px; } .client-proxies.has-tabs { min-height: 91px; } .client-proxy-label { display: grid; place-items: center; color: var(--client-muted); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; } .client-proxy-label > span { grid-area: 1 / 1; opacity: 0; filter: blur(3px); pointer-events: none; transform: translateX(-12px); transition: color 700ms ease, opacity 520ms ease, filter 620ms ease, transform 700ms cubic-bezier(0.16, 1, 0.3, 1); } .client-proxy-label > span:last-child { color: var(--client-accent); transform: translateX(12px); } .client-proxy-label > span.is-active { opacity: 1; filter: blur(0); pointer-events: auto; transform: translateX(0); } .client-proxy-label a { color: var(--client-accent); text-decoration: none; text-shadow: 0 0 10px color-mix(in oklch, var(--client-accent) 42%, transparent); } .client-proxy-label a:hover { text-decoration: underline; text-underline-offset: 3px; } .client-proxy-label a:focus-visible { outline: 2px solid var(--client-accent); outline-offset: 2px; } .client-proxy-address { color: var(--client-text); font-size: 12px; font-weight: 500; text-shadow: 0 0 12px color-mix(in oklch, var(--client-accent) 12%, transparent); } .client-access-point { display: grid; justify-items: center; gap: 5px; animation: client-access-reveal 450ms cubic-bezier(0.16, 1, 0.3, 1) both; } @keyframes client-access-reveal { 0% { opacity: 0; filter: blur(4px); } 100% { opacity: 1; filter: blur(0); } } .client-access-tabs { display: grid; grid-template-columns: 1fr 1fr; width: 220px; margin-bottom: 8px; border-bottom: 1px solid var(--client-border); } .client-access-tabs .client-access-tab { width: auto; padding: 6px 4px 7px; border: 0; border-bottom: 1px solid transparent; background: transparent; color: var(--client-muted); font: 700 9px/1.2 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; letter-spacing: 0.06em; cursor: pointer; transition: color 220ms ease, border-color 300ms ease, filter 300ms ease; } .client-access-tabs .client-access-tab.is-active { border-bottom-color: var(--client-accent); color: var(--client-text); filter: drop-shadow(0 0 5px color-mix(in oklch, var(--client-accent) 45%, transparent)); } .client-access-tab:focus-visible { outline: 2px solid var(--client-accent); outline-offset: 2px; } .client-proxy-actions { display: flex; gap: 8px; margin-top: 7px; } .client-inline-error { position: absolute; left: 50%; z-index: 3; width: min(360px, 90vw); display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; color: oklch(0.62 0.2 28); font: 600 11px/1.5 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; text-align: center; transform: translateX(-50%); } .client-inline-error.is-connection { top: calc(100% + 12px); } .client-inline-error.is-subscription { top: calc(100% + 2px); } .client-inline-error small { color: var(--client-muted); font-size: 9px; white-space: nowrap; } .client-inline-error button { padding: 4px 7px; border: 0; border-radius: 6px; background: color-mix(in oklch, var(--client-control) 72%, transparent); color: var(--client-text); font-size: 9px; font-weight: 700; cursor: pointer; white-space: nowrap; } .client-inline-error button:focus-visible { outline: 2px solid oklch(0.68 0.15 28); outline-offset: 2px; } .client-operation-progress { color: var(--client-accent); } .client-operation-progress::before { width: 6px; height: 6px; border-radius: 50%; background: currentColor; box-shadow: 0 0 8px currentColor; content: ''; animation: client-operation-pulse 900ms ease-in-out infinite alternate; } @keyframes client-operation-pulse { to { opacity: 0.35; transform: scale(0.72); } } .client-copy-button { position: relative; width: 86px; padding: 6px 10px; border: 0; background: transparent; color: var(--client-muted); font: 700 9px/1.2 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace; letter-spacing: 0.06em; cursor: pointer; opacity: 0.76; transition: color 220ms ease, opacity 220ms ease, transform 220ms cubic-bezier(0.16, 1, 0.3, 1); } .client-copy-label { transition: opacity 100ms ease; } .client-copy-button.is-copied .client-copy-label, .client-copy-button.is-copy-error .client-copy-label { opacity: 0; } .client-copy-feedback { position: absolute; inset: 0; display: grid; place-items: center; color: var(--client-accent); animation: client-copy-fade 800ms cubic-bezier(0.4, 0, 1, 1) forwards; } .client-copy-button.is-copy-error .client-copy-feedback { color: oklch(0.68 0.15 28); filter: drop-shadow(0 0 5px oklch(0.68 0.15 28 / 0.45)); } @keyframes client-copy-fade { 0%, 18% { opacity: 1; filter: drop-shadow(0 0 5px var(--client-accent)); } 100% { opacity: 0; filter: drop-shadow(0 0 0 transparent); } } .client-copy-button:hover { color: var(--client-text); opacity: 1; transform: translateY(-2px); } .client-copy-button:active { transform: translateY(0) scale(0.98); } .client-copy-button.is-copied { opacity: 1; color: var(--client-accent); } .client-copy-button:focus-visible { outline: 2px solid var(--client-accent); outline-offset: 3px; } @media (prefers-color-scheme: dark) { .app.client-app { --client-bg: oklch(0.18 0.012 145); --client-panel: oklch(0.22 0.012 145); --client-control: oklch(0.26 0.012 145); --client-border: oklch(0.34 0.015 145); --client-text: oklch(0.93 0.008 145); --client-muted: oklch(0.68 0.012 145); --harbor-word: oklch(0.78 0.07 232); --harbor-connect: oklch(0.75 0.1 185); --harbor-gateway: oklch(0.79 0.11 72); --client-accent: var(--harbor-connect); --client-accent-soft: color-mix(in oklch, var(--client-accent) 22%, transparent); color-scheme: dark; } } @media (max-width: 560px) { .client-local-rule { grid-template-columns: 24px 104px minmax(0, 1fr) 28px; } .client-local-rule-status { grid-column: 3; text-align: left; } .client-mode .app-main { padding: 20px 14px; } .client-stale-banner { width: calc(100% - 28px); grid-template-columns: 1fr auto; } .client-stale-banner span { grid-column: 1 / -1; grid-row: 2; } .client-panel { position: static; grid-template-columns: 1fr; gap: 26px; min-height: 0; padding: 20px 6px; } .client-power-section { padding-bottom: 40px; } .client-inline-error.is-connection { top: auto; bottom: 0; } .client-form-content { gap: 48px; } .harbor-brand { transform: translate(-50%, calc(-50% - 28vh)) scale(2.15); } .client-instructions-toggle { left: 8px; } .client-local-rules-toggle { right: 8px; } .client-instructions-sheet { padding: 40px 18px 60px 58px; } .client-local-rules-sheet { padding: 40px 58px 60px 18px; } .client-local-rules-header h2 { font-size: 18px; } .client-local-rule { grid-template-columns: 24px minmax(0, 1fr) 28px; gap: 8px; } .client-local-rule-enabled { grid-column: 1; grid-row: 1; } .client-rule-type { grid-column: 2; grid-row: 1; } .client-local-rule-delete { grid-column: 3; grid-row: 1; } .client-local-rule input { grid-column: 2 / -1; grid-row: 2; } .client-instructions-header h2 { font-size: 18px; } .client-instruction-block:nth-child(n) { margin-inline: 0; } .client-form { position: relative; width: 100%; transform: none; } .client-panel.is-setup .client-form { transform: none; } } @media (prefers-reduced-motion: reduce) { .client-operation-progress::before, .client-delete-strike, .client-power, .client-power::before, .client-power::after, .client-power svg, .client-usage-bar i, .client-subscription-refresh, .client-subscription-delete, .client-power-section, .client-form, .client-usage, .client-usage > strong, .client-server, .client-copy-button, .client-access-tab, .client-access-point, .client-copy-feedback, .client-duration, .client-duration-seconds-value, .client-duration-second-digit, .client-instructions, .client-instructions-toggle, .client-instructions-toggle svg, .client-instructions-toggle path, .client-instructions-toggle span, .client-instruction-block, .client-instruction-reveal, .client-instruction-summary > i::before, .client-instruction-summary > i::after, .client-subscription-edit, .client-subscription-edit::after, .client-subscription-submit, .client-subscription-summary, .client-subscription-summary strong, .client-proxy-label > span { transition: none; animation: none; } .client-local-rules, .client-local-rules-toggle, .client-local-rules-toggle svg, .client-local-rules-toggle span, .client-local-rule, .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-delete, .client-local-rule-add, .client-local-rule-add-slot > span, .client-local-rules-save, .client-local-rules-runtime, .client-local-rules-actions button { transition: none; animation: none; } .harbor-brand { transition: none; animation: none; } .harbor-brand-content { animation: none; } .harbor-mode-stack em, .harbor-mode-swap g, .harbor-mode-swap path, .harbor-brand .harbor-mode-swap, .harbor-mode-tooltip { transition: none; animation: none; } .client-form-content, .client-confirmation-popup, .client-confirmation-dialog, .client-confirmation-dialog > *, .client-confirmation-actions button, .client-subscription-delete .client-trash-lid { transition: none; animation: none; } .client-tooltip { transition: none; } .harbor-version, .harbor-version-tooltip { transition: none; } .client-state-copy h2, .client-connection-title > span, .client-state-detail > * { transition: none; animation: none; } }