diff --git a/src/ace/sidecar/dashboard_render.py b/src/ace/sidecar/dashboard_render.py index cb13f8f..8af0d38 100644 --- a/src/ace/sidecar/dashboard_render.py +++ b/src/ace/sidecar/dashboard_render.py @@ -271,12 +271,32 @@ text-transform:uppercase;margin-bottom:10px} .card h3{margin:4px 0 8px;font-size:14.5px;color:var(--ink);font-weight:600;letter-spacing:-.01em} .card p{margin:0 0 16px;color:var(--ink-3);font-size:13px;line-height:1.6;flex:1} -.lk{align-self:flex-start;display:inline-flex;align-items:center;font-family:var(--mono);font-size:12px; -color:var(--mint);background:rgba(0,230,153,0.06);border:1px solid rgba(0,230,153,0.25); -border-radius:6px;padding:6px 14px;text-decoration:none;transition:all .2s ease;word-break:break-all} +/* Spacing between glyph and label is `gap`, not a margin on the arrow: the arrow slides on + hover, and a transformed element with a margin drags the gap along with it. break-all is + deliberately not used — it would split "acefleet.dev" mid-word — but the mail buttons still + have to survive a long address in a 270px card, so wrapping is allowed anywhere only once a + word genuinely cannot fit. */ +.lk{align-self:flex-start;display:inline-flex;align-items:center;gap:8px;font-family:var(--mono); +font-size:12px;line-height:1.2;color:var(--mint);background:rgba(0,230,153,0.06); +border:1px solid rgba(0,230,153,0.25);border-radius:7px;padding:9px 14px;text-decoration:none; +overflow-wrap:anywhere; +transition:background .2s ease,border-color .2s ease,color .2s ease,box-shadow .2s ease,transform .2s ease} .lk:hover{background:rgba(0,230,153,0.16);border-color:var(--mint);color:#ffffff; box-shadow:0 0 12px rgba(0,230,153,0.25);transform:translateY(-1px)} -.site-lk{background:rgba(0,230,153,0.1);border-color:rgba(0,230,153,0.4);font-weight:600} +.lk:focus-visible{outline:2px solid var(--mint);outline-offset:2px} +.lk:active{transform:translateY(0)} +.lk .arw{transition:transform .2s ease} +.lk:hover .arw{transform:translateX(3px)} +/* The one outbound link on the page, so it carries more weight than the mail buttons. */ +.site-lk{background:linear-gradient(135deg,rgba(0,230,153,0.22) 0%,rgba(0,230,153,0.08) 100%); +border-color:rgba(0,230,153,0.55);color:#EAFFF6;font-weight:600;font-size:12.5px;padding:11px 18px; +box-shadow:0 2px 10px -2px rgba(0,230,153,0.22)} +.site-lk:hover{background:linear-gradient(135deg,rgba(0,230,153,0.34) 0%,rgba(0,230,153,0.16) 100%); +box-shadow:0 6px 18px -4px rgba(0,230,153,0.35)} +@media (prefers-reduced-motion:reduce){ +.lk,.lk .arw{transition:none} +.lk:hover{transform:none} +.lk:hover .arw{transform:none}} .foot{color:var(--ink-4);font-size:11.5px;margin-top:36px;padding-top:14px; border-top:1px solid var(--line);line-height:1.65} /* ---- modal drawer ---- */ @@ -1009,7 +1029,7 @@ def _qa_item(q: str, body: str, open_first: bool = False) -> str: def _qa(f: Optional[Dict[str, Any]], rc: Dict[str, Any]) -> str: - """§ 09 — the questions this dashboard reliably provokes, answered with the reader's own + """§ 13 — the questions this dashboard reliably provokes, answered with the reader's own numbers. Every figure is recomputed from the scope above rather than written into the prose. The @@ -1017,7 +1037,7 @@ def _qa(f: Optional[Dict[str, Any]], rc: Dict[str, Any]) -> str: measure per-request latency. """ head = _sec( - "10", + "13", "COMMON QUESTIONS", "Why the token counts look the way they do.", "Mechanism, priced against your scope.", @@ -1367,12 +1387,17 @@ def _mailto(subject: str) -> str: def _about() -> str: - """§ 10 — what ACE is, and how to reach the people who build it. + """§ 14 — what ACE is, and how to reach the people who build it. Answers the two questions the measurements above cannot: what the measuring thing *is*, and who to contact about it. One address for questions, feature requests, collaborations, business and team rollout, with ``?subject=`` prefill as the routing — it degrades to a plain mailto if the client ignores it. + + The banner names ACE Fleet because this page is the only thing most readers will ever see + of it: a reader who arrives through the open-source sidecar has no way to tell that it is + one vertical of a broader cost-control platform rather than the whole company, and that is + exactly the impression the section exists to correct. """ cards = ( ( @@ -1405,19 +1430,30 @@ def _about() -> str: body = "".join( f"
" + f"{escape(p)}
✉ {escape(label)}→" for k, h, p, href, label in cards ) return ( - _sec("12", "ACE SIDECAR", "Who makes this.", "And how to reach them.", "ABOUT") + _sec("14", "ACE SIDECAR", "Who makes this.", "And how to reach them.", "ABOUT") + "ACE Fleet is a cost-saving proxy for companies scaling AI applications — it sits in " + "front of the model providers and cuts what an organisation spends on inference as that " + "spend grows, across every workload rather than any single one.
" + "This sidecar is the coding-agent slice of that work, open-sourced on its own: the " + "same accounting turned on one developer's machine, where the spend is small enough to " + "check by hand and the levers are easy to see. It is a showcase of the approach — the " + "platform behind it is considerably wider in scope.
" + f"" "Local developer observability sidecar for AI coding agents. Intercepts local Claude Code & Antigravity traffic, mines session transcripts, proposes workflow skills, and exposes standard Prometheus metrics for time-series scraping.
- About & contact + About & contact