Refresh docs-site from feature/lightning-talk
Bring the docs-site tree up to date with the richer version built on the feature/lightning-talk line (guides, expanded reference, landing page) as the base for adding freeroute/routing documentation. Docs-site only; no source code from that branch is merged.
This commit is contained in:
parent
963206d548
commit
847e38e8a3
@ -59,6 +59,7 @@ export default defineConfig({
|
||||
{ label: "Troubleshooting", slug: "development/troubleshooting" },
|
||||
],
|
||||
},
|
||||
{ label: "Lightning Talk", link: "/lightning-talk/" },
|
||||
],
|
||||
head: [
|
||||
{
|
||||
|
||||
@ -75,3 +75,9 @@ mckicad just gives them a voice.
|
||||
description="Install mckicad and connect it to your first KiCad project."
|
||||
href="/getting-started/installation/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="Lightning talk: teaching a language model to draw schematics"
|
||||
description="Ninety seconds on why kicad-sch-api had to go, the SchDocument engine that replaced it, and the synth schematic it drew with zero ERC errors."
|
||||
href="/lightning-talk/"
|
||||
/>
|
||||
|
||||
176
docs-site/src/pages/lightning-talk.astro
Normal file
176
docs-site/src/pages/lightning-talk.astro
Normal file
@ -0,0 +1,176 @@
|
||||
---
|
||||
import "../styles/lightning-talk.css";
|
||||
|
||||
const title = "Teaching a language model to draw schematics";
|
||||
const description =
|
||||
"A 90-second lightning talk on mckicad: why I replaced kicad-sch-api with an internal SchDocument engine, and what it unlocked.";
|
||||
|
||||
// lucide-style icon paths (stroke, viewBox 24)
|
||||
const icons = {
|
||||
problem: '<path d="m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',
|
||||
engine: '<rect width="16" height="16" x="4" y="4" rx="2"/><rect width="6" height="6" x="9" y="9" rx="1"/><path d="M15 2v2M9 2v2M15 20v2M9 20v2M2 15h2M2 9h2M20 15h2M20 9h2"/>',
|
||||
wire: '<circle cx="12" cy="4.5" r="2.5"/><circle cx="4.5" cy="19.5" r="2.5"/><circle cx="19.5" cy="19.5" r="2.5"/><path d="M10.4 6.4 6 16.5M13.6 6.4 18 16.5M7 19.5h10"/>',
|
||||
check: '<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/>',
|
||||
zap: '<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>',
|
||||
};
|
||||
|
||||
const beats = [
|
||||
{
|
||||
n: "01",
|
||||
icon: icons.problem,
|
||||
tag: "The problem",
|
||||
heading: "The library kept lying to me",
|
||||
body: [
|
||||
"mckicad is an MCP server that lets a language model design KiCad schematics on its own. For a long time it stood on <code>kicad-sch-api</code> — and that library kept returning wrong answers.",
|
||||
"Global labels: dropped silently. Custom library pins: empty lists. When the layer you build on returns confident nonsense, nothing downstream can be trusted. So I did the reckless thing and ripped it out.",
|
||||
],
|
||||
},
|
||||
{
|
||||
n: "02",
|
||||
icon: icons.engine,
|
||||
tag: "The engine",
|
||||
heading: "A parser that round-trips clean",
|
||||
body: [
|
||||
"The heart is <code>sexp_tree</code> — a full S-expression parser and serializer for KiCad's native format. Parse it, mutate it, write it back, byte-for-byte identical.",
|
||||
"On top sits <code>SchDocument</code>: load a schematic and ask it real questions. Where is every pin. What net is this wire on. Which labels actually connect. Answers from the file itself, not a guess.",
|
||||
],
|
||||
},
|
||||
{
|
||||
n: "03",
|
||||
icon: icons.wire,
|
||||
tag: "Autowire",
|
||||
heading: "It routes around itself",
|
||||
body: [
|
||||
"Place the components; autowire pulls the nets for you — with real collision detection, so wires route around each other instead of bridging into shorts.",
|
||||
"It clamps stub lengths when they would overlap, offsets labels so they don't collide, and tracks power-wire stubs as obstacles. The messy part of drawing a schematic, done carefully.",
|
||||
],
|
||||
},
|
||||
{
|
||||
n: "04",
|
||||
icon: icons.check,
|
||||
tag: "It checks its own work",
|
||||
heading: "One call, zero ambiguity",
|
||||
body: [
|
||||
"<code>run_schematic_erc</code> runs the full electrical rules check and reports back: zero errors — or exactly what's wrong, and where.",
|
||||
"The engine grades its own homework, so the model gets a hard signal instead of a hopeful vibe.",
|
||||
],
|
||||
},
|
||||
{
|
||||
n: "05",
|
||||
icon: icons.zap,
|
||||
tag: "The proof",
|
||||
heading: "It drew Timbre",
|
||||
body: [
|
||||
"It generated the phase-1 bench schematic for Timbre, a Cypress PSoC-based synthesizer. Zero ERC errors.",
|
||||
"A language model, placing parts and pulling nets, for real hardware headed to a bench. That's the whole point.",
|
||||
],
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{title} · mckicad</title>
|
||||
<meta name="description" content={description} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:type" content="article" />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body class="lt">
|
||||
<a class="lt-skip" href="#talk">Skip to the talk</a>
|
||||
|
||||
<header class="lt-hero">
|
||||
<div class="lt-wrap">
|
||||
<p class="lt-kicker">Lightning talk · 90 seconds</p>
|
||||
<h1>{title}</h1>
|
||||
<p class="lt-lede">
|
||||
I ripped out the library that kept lying to me and built an engine
|
||||
that tells the truth.
|
||||
</p>
|
||||
|
||||
<div class="lt-scope" role="img" aria-label="Terminal readout: running the electrical rules check on the Timbre schematic returns zero errors and zero warnings.">
|
||||
<div class="lt-scope-bar" aria-hidden="true">
|
||||
<span class="lt-dot"></span><span class="lt-dot"></span
|
||||
><span class="lt-dot"></span>
|
||||
<span>erc · timbre-phase1.kicad_sch</span>
|
||||
</div>
|
||||
<div class="lt-scope-body" aria-hidden="true">
|
||||
<div class="cmd">run_schematic_erc timbre-phase1.kicad_sch</div>
|
||||
<div class="out">▸ 47 components · 62 nets · 128 pins</div>
|
||||
<div class="out">▸ checking electrical rules…</div>
|
||||
<div class="ok">✓ 0 errors · 0 warnings</div>
|
||||
<div class="out">
|
||||
ready<span class="lt-cursor" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="lt-actions" aria-label="Primary">
|
||||
<a class="lt-btn primary" href="/getting-started/installation/">
|
||||
Get started
|
||||
</a>
|
||||
<a class="lt-btn ghost" href="/guides/autowire/">Read the autowire guide</a>
|
||||
<a
|
||||
class="lt-btn ghost"
|
||||
href="https://git.supported.systems/MCP/kicad-mcp"
|
||||
rel="noopener">Source</a
|
||||
>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="talk" class="lt-wrap">
|
||||
<ol class="lt-beats">
|
||||
{
|
||||
beats.map((b) => (
|
||||
<li class="lt-beat" data-n={b.n}>
|
||||
<span class="lt-beat-tag">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
set:html={b.icon}
|
||||
/>
|
||||
{b.tag}
|
||||
</span>
|
||||
<h2>{b.heading}</h2>
|
||||
{b.body.map((p) => (
|
||||
<p set:html={p} />
|
||||
))}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ol>
|
||||
</main>
|
||||
|
||||
<section class="lt-closer">
|
||||
<div class="lt-wrap">
|
||||
<div class="lt-stat">
|
||||
1,900 lines
|
||||
<small>of workaround code, deleted</small>
|
||||
</div>
|
||||
<blockquote>
|
||||
“Replaced by an engine that just tells the truth.”
|
||||
</blockquote>
|
||||
<footer>
|
||||
Also delivered as a 90-second spoken talk. ·
|
||||
<a href="/">Back to mckicad</a>
|
||||
</footer>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
373
docs-site/src/styles/lightning-talk.css
Normal file
373
docs-site/src/styles/lightning-talk.css
Normal file
@ -0,0 +1,373 @@
|
||||
/* mckicad lightning talk — standalone phosphor-terminal narrative page.
|
||||
Palette locked to the docs hero SVG so it reads as part of the product. */
|
||||
|
||||
:root {
|
||||
--lt-bg: #0a1410;
|
||||
--lt-panel: #0f1a14;
|
||||
--lt-grid: #1a3a2a;
|
||||
--lt-wire: #2d8659;
|
||||
--lt-dim: #5a9e78;
|
||||
--lt-bright: #a8dbbe;
|
||||
--lt-ink: #d6ece0;
|
||||
--lt-mute: #7a9d8c;
|
||||
--lt-mono: "JetBrains Mono", ui-monospace, "Cascadia Code", "Source Code Pro",
|
||||
Menlo, Consolas, "DejaVu Sans Mono", monospace;
|
||||
--lt-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, sans-serif;
|
||||
--lt-maxw: 62rem;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body.lt {
|
||||
margin: 0;
|
||||
background: var(--lt-bg);
|
||||
color: var(--lt-ink);
|
||||
font-family: var(--lt-sans);
|
||||
line-height: 1.6;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
/* faint engineering-paper grid, echoing the hero schematic */
|
||||
background-image:
|
||||
linear-gradient(var(--lt-grid) 0.5px, transparent 0.5px),
|
||||
linear-gradient(90deg, var(--lt-grid) 0.5px, transparent 0.5px);
|
||||
background-size: 28px 28px;
|
||||
background-position: center top;
|
||||
}
|
||||
|
||||
/* faint CRT scanlines — decorative, killed for reduced-motion / it's opt-out via media */
|
||||
body.lt::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
background: repeating-linear-gradient(
|
||||
0deg,
|
||||
rgba(0, 0, 0, 0.15) 0,
|
||||
rgba(0, 0, 0, 0.15) 1px,
|
||||
transparent 1px,
|
||||
transparent 3px
|
||||
);
|
||||
mix-blend-mode: multiply;
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.lt-wrap {
|
||||
max-width: var(--lt-maxw);
|
||||
margin: 0 auto;
|
||||
padding: 0 1.25rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--lt-bright);
|
||||
}
|
||||
|
||||
/* ── skip link ─────────────────────────────── */
|
||||
.lt-skip {
|
||||
position: absolute;
|
||||
left: -999px;
|
||||
top: 0;
|
||||
background: var(--lt-wire);
|
||||
color: #04120c;
|
||||
padding: 0.5rem 0.9rem;
|
||||
border-radius: 0 0 0.4rem 0;
|
||||
font-family: var(--lt-mono);
|
||||
z-index: 200;
|
||||
}
|
||||
.lt-skip:focus {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* ── hero ──────────────────────────────────── */
|
||||
.lt-hero {
|
||||
padding: clamp(3rem, 9vw, 6.5rem) 0 clamp(2rem, 6vw, 4rem);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lt-kicker {
|
||||
font-family: var(--lt-mono);
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.28em;
|
||||
text-transform: uppercase;
|
||||
color: var(--lt-wire);
|
||||
margin: 0 0 1.1rem;
|
||||
}
|
||||
|
||||
.lt-hero h1 {
|
||||
font-size: clamp(2.1rem, 6.5vw, 4rem);
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0 auto 1.1rem;
|
||||
max-width: 18ch;
|
||||
color: #eafff4;
|
||||
text-shadow: 0 0 24px rgba(45, 134, 89, 0.35);
|
||||
}
|
||||
|
||||
.lt-lede {
|
||||
font-size: clamp(1.05rem, 2.4vw, 1.35rem);
|
||||
color: var(--lt-mute);
|
||||
max-width: 46ch;
|
||||
margin: 0 auto 2.25rem;
|
||||
}
|
||||
|
||||
/* terminal "scope" panel */
|
||||
.lt-scope {
|
||||
max-width: 40rem;
|
||||
margin: 0 auto 2rem;
|
||||
text-align: left;
|
||||
background: var(--lt-panel);
|
||||
border: 1px solid var(--lt-grid);
|
||||
border-radius: 0.7rem;
|
||||
box-shadow: 0 0 0 1px rgba(45, 134, 89, 0.15),
|
||||
0 24px 60px -20px rgba(0, 0, 0, 0.8);
|
||||
overflow: hidden;
|
||||
}
|
||||
.lt-scope-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.6rem 0.9rem;
|
||||
border-bottom: 1px solid var(--lt-grid);
|
||||
font-family: var(--lt-mono);
|
||||
font-size: 0.75rem;
|
||||
color: var(--lt-mute);
|
||||
}
|
||||
.lt-dot {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
border-radius: 50%;
|
||||
background: var(--lt-grid);
|
||||
}
|
||||
.lt-scope-bar span {
|
||||
margin-left: auto;
|
||||
}
|
||||
.lt-scope-body {
|
||||
padding: 1.1rem 1.2rem 1.3rem;
|
||||
font-family: var(--lt-mono);
|
||||
font-size: clamp(0.8rem, 1.9vw, 0.95rem);
|
||||
line-height: 1.7;
|
||||
}
|
||||
.lt-scope-body .cmd {
|
||||
color: var(--lt-bright);
|
||||
}
|
||||
.lt-scope-body .cmd::before {
|
||||
content: "mckicad › ";
|
||||
color: var(--lt-wire);
|
||||
}
|
||||
.lt-scope-body .out {
|
||||
color: var(--lt-dim);
|
||||
}
|
||||
.lt-scope-body .ok {
|
||||
color: #7cf0b0;
|
||||
text-shadow: 0 0 12px rgba(124, 240, 176, 0.5);
|
||||
}
|
||||
.lt-cursor {
|
||||
display: inline-block;
|
||||
width: 0.6ch;
|
||||
height: 1.05em;
|
||||
vertical-align: text-bottom;
|
||||
background: var(--lt-bright);
|
||||
margin-left: 0.15rem;
|
||||
animation: lt-blink 1.1s steps(1) infinite;
|
||||
}
|
||||
@keyframes lt-blink {
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* action buttons */
|
||||
.lt-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.lt-btn {
|
||||
font-family: var(--lt-mono);
|
||||
font-size: 0.9rem;
|
||||
text-decoration: none;
|
||||
padding: 0.7rem 1.25rem;
|
||||
border-radius: 0.45rem;
|
||||
border: 1px solid var(--lt-wire);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
|
||||
}
|
||||
.lt-btn svg {
|
||||
width: 1.05em;
|
||||
height: 1.05em;
|
||||
}
|
||||
.lt-btn.primary {
|
||||
background: var(--lt-wire);
|
||||
color: #04120c;
|
||||
font-weight: 600;
|
||||
}
|
||||
.lt-btn.ghost {
|
||||
color: var(--lt-bright);
|
||||
background: transparent;
|
||||
}
|
||||
.lt-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.lt-btn.ghost:hover {
|
||||
background: rgba(45, 134, 89, 0.12);
|
||||
}
|
||||
|
||||
/* ── beats ─────────────────────────────────── */
|
||||
.lt-beats {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: clamp(1rem, 4vw, 2.5rem) 0;
|
||||
display: grid;
|
||||
gap: clamp(1.25rem, 3vw, 2rem);
|
||||
}
|
||||
.lt-beat {
|
||||
position: relative;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(15, 26, 20, 0.9),
|
||||
rgba(10, 20, 16, 0.9)
|
||||
);
|
||||
border: 1px solid var(--lt-grid);
|
||||
border-left: 3px solid var(--lt-wire);
|
||||
border-radius: 0 0.7rem 0.7rem 0;
|
||||
padding: clamp(1.4rem, 3.5vw, 2rem) clamp(1.3rem, 4vw, 2.4rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
/* ghosted giant numeral, SpiceBook-style */
|
||||
.lt-beat::after {
|
||||
content: attr(data-n);
|
||||
position: absolute;
|
||||
top: -0.35em;
|
||||
right: 0.1em;
|
||||
font-family: var(--lt-mono);
|
||||
font-weight: 700;
|
||||
font-size: clamp(5rem, 16vw, 9rem);
|
||||
line-height: 1;
|
||||
color: var(--lt-wire);
|
||||
opacity: 0.07;
|
||||
pointer-events: none;
|
||||
}
|
||||
.lt-beat-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-family: var(--lt-mono);
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
color: var(--lt-wire);
|
||||
margin-bottom: 0.7rem;
|
||||
}
|
||||
.lt-beat-tag svg {
|
||||
width: 1.05rem;
|
||||
height: 1.05rem;
|
||||
stroke: var(--lt-wire);
|
||||
}
|
||||
.lt-beat h2 {
|
||||
font-size: clamp(1.35rem, 3.4vw, 1.9rem);
|
||||
line-height: 1.15;
|
||||
letter-spacing: -0.01em;
|
||||
margin: 0 0 0.6rem;
|
||||
color: #eafff4;
|
||||
max-width: 24ch;
|
||||
}
|
||||
.lt-beat p {
|
||||
margin: 0;
|
||||
color: var(--lt-mute);
|
||||
max-width: 62ch;
|
||||
}
|
||||
.lt-beat p + p {
|
||||
margin-top: 0.7rem;
|
||||
}
|
||||
.lt-beat code {
|
||||
font-family: var(--lt-mono);
|
||||
font-size: 0.9em;
|
||||
color: var(--lt-bright);
|
||||
background: rgba(45, 134, 89, 0.12);
|
||||
padding: 0.1rem 0.4rem;
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
|
||||
/* ── proof / closer ────────────────────────── */
|
||||
.lt-closer {
|
||||
text-align: center;
|
||||
padding: clamp(3rem, 8vw, 5.5rem) 0 clamp(4rem, 9vw, 6rem);
|
||||
border-top: 1px solid var(--lt-grid);
|
||||
margin-top: clamp(1rem, 4vw, 2rem);
|
||||
}
|
||||
.lt-stat {
|
||||
font-family: var(--lt-mono);
|
||||
font-weight: 700;
|
||||
font-size: clamp(3rem, 12vw, 6.5rem);
|
||||
line-height: 1;
|
||||
color: #eafff4;
|
||||
letter-spacing: -0.03em;
|
||||
text-shadow: 0 0 30px rgba(45, 134, 89, 0.4);
|
||||
}
|
||||
.lt-stat small {
|
||||
display: block;
|
||||
font-family: var(--lt-mono);
|
||||
font-weight: 400;
|
||||
font-size: clamp(0.85rem, 2.2vw, 1.05rem);
|
||||
letter-spacing: 0.24em;
|
||||
text-transform: uppercase;
|
||||
color: var(--lt-wire);
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
.lt-closer blockquote {
|
||||
margin: 2rem auto 0;
|
||||
max-width: 34ch;
|
||||
font-size: clamp(1.15rem, 3vw, 1.6rem);
|
||||
line-height: 1.35;
|
||||
color: var(--lt-ink);
|
||||
font-style: italic;
|
||||
}
|
||||
.lt-closer footer {
|
||||
margin-top: 2.75rem;
|
||||
font-family: var(--lt-mono);
|
||||
font-size: 0.82rem;
|
||||
color: var(--lt-mute);
|
||||
}
|
||||
.lt-closer footer a {
|
||||
color: var(--lt-bright);
|
||||
}
|
||||
|
||||
/* ── responsive niceties ───────────────────── */
|
||||
@media (min-width: 46rem) {
|
||||
.lt-beat {
|
||||
padding-right: clamp(4rem, 14vw, 8rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── accessibility: honour reduced motion ──── */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
.lt-cursor {
|
||||
animation: none;
|
||||
}
|
||||
body.lt::before {
|
||||
display: none;
|
||||
}
|
||||
.lt-btn {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear focus rings everywhere */
|
||||
a:focus-visible,
|
||||
.lt-btn:focus-visible {
|
||||
outline: 2px solid var(--lt-bright);
|
||||
outline-offset: 3px;
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user