Files
ferrix/slides/style.css
T
Rayhaan JaufeerallyandClaude Fable 5.1 2910a2a800 slides: light theme, final edits, single-file bundle
As presented. The palette is light on request of the reviewer; code blocks
and byte dumps keep a dark ground so the byte colours still work. The OPEN
walk lights the hovered bytes as an inverted block and its table cells are
dark text on a tint of their group colour.

build.py inlines reveal.js, the stylesheets, scripts and Markdown sections
into slides/dist/hands-on-bgp.html for uploading.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 20:40:55 +02:00

557 lines
14 KiB
CSS

/*
* Components and helpers used by the slides. The look (palette, type, panels,
* motif) is in theme.css; nothing here sets a brand colour directly.
*/
.hidden {
display: none;
}
/* ---- text -------------------------------------------------------------------- */
/* A quiet aside under the main point. */
.reveal .note {
font-style: italic;
font-size: 75%;
color: var(--muted);
}
/* Image and quote credits: <!-- .element: class="attribution" --> */
.reveal .attribution {
font-size: 45%;
font-style: italic;
color: var(--muted);
}
/* One big statement on an otherwise empty slide. */
.reveal .big {
font-size: 1.9em;
font-weight: 300;
line-height: 1.25;
color: var(--ink-strong);
}
/* ---- layout ------------------------------------------------------------------ */
.container {
display: flex;
justify-content: center;
align-items: center;
gap: 1em;
}
.flex-around {
display: flex;
justify-content: space-around;
align-items: flex-start;
gap: 1em;
}
/* Two equal columns: <div class="cols"><div>…</div><div>…</div></div> */
.cols {
display: flex;
gap: 1.2em;
align-items: center;
text-align: left;
}
.cols > * {
flex: 1 1 0;
min-width: 0;
}
.float-left {
float: left;
}
.float-right {
float: right;
}
.no-border {
background: none !important;
border: none !important;
box-shadow: none !important;
}
.reveal img.blur-edges {
border-radius: 12px;
box-shadow: 0 0 25px 8px rgba(20, 30, 60, 0.2);
}
.reveal table.borders td,
.reveal table.borders th {
border: 1px solid var(--rule);
}
/* ---- boxes: small labelled cards, e.g. one per AS or per community ----------- */
.boxes {
display: flex;
flex-wrap: wrap;
justify-content: center;
font-size: 70%;
margin: 0.6em 0;
}
.boxes > div {
padding: 0.35em 0.8em;
margin: 0.3em 0.5em;
border: 1px solid var(--rule);
border-radius: 10px;
background: var(--ground);
line-height: 1.35;
}
.boxes > div.us {
border-color: var(--accent);
box-shadow: 0 0 18px rgba(var(--accent-rgb), 0.35);
color: var(--ink-strong);
}
.boxes > div.ok {
border-color: #1a8a4f;
}
.boxes > div.bad {
border-color: #d64545;
}
/* ---- BGP bytes, matching the four groups of the /statusz bytes view ---------- */
.reveal pre.bytes {
font-size: 0.5em;
line-height: 1.9;
white-space: pre-wrap;
word-break: break-all;
background: var(--code-ground);
border-radius: 6px;
padding: 15px 20px;
box-sizing: border-box;
color: var(--code-ink);
}
.bytes span,
.legend span {
border-radius: 3px;
padding: 1px 3px;
color: var(--code-ink); /* the fills are dark on any ground */
}
.bytes .hh,
.legend .hh { background: #34406e; }
.bytes .hl,
.legend .hl { background: #6e3440; }
.bytes .ha,
.legend .ha { background: #245c3a; }
.bytes .ha2 { background: #2f7a4b; }
.bytes .hn,
.legend .hn { background: #6b5a1f; }
.legend {
font-size: 50%;
font-family: var(--r-code-font);
}
.legend span {
padding: 1px 0.6em;
margin: 0 0.2em;
}
/* ---- live DNS and RIPE database lookups ------------------------------------ */
.reveal form.dns-lookup,
.reveal form.ripe-lookup {
margin: 0.4em auto 0;
max-width: 34em;
text-align: left;
font-family: var(--r-code-font);
}
.reveal .dns-lookup input,
.reveal .ripe-lookup input {
width: 62%;
padding: 0.3em 0.5em;
font: inherit;
font-size: 0.8em;
color: var(--r-main-color);
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 6px;
outline: none;
}
.reveal .dns-lookup input:focus,
.reveal .ripe-lookup input:focus {
border-color: var(--accent);
}
.reveal .dns-lookup button,
.reveal .ripe-lookup button {
margin-left: 0.4em;
padding: 0.3em 0.9em;
font: inherit;
font-size: 0.8em;
color: #fff;
background: var(--accent);
border: 0;
border-radius: 6px;
cursor: pointer;
}
.reveal .dns-result {
min-height: 3.2em;
max-height: 13em;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: var(--rule) transparent;
margin-top: 0.5em;
padding: 0.5em 0.7em;
font-size: 0.7em;
line-height: 1.5;
white-space: pre-wrap;
word-break: break-all;
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 6px;
}
.reveal .dns-result .ttl,
.reveal .dns-result .type,
.reveal .dns-result .dim { color: var(--muted); }
.reveal .dns-result .addr { color: var(--accent); font-weight: 500; }
.reveal .dns-result .bad { color: #c62828; }
/* RIPE database objects, laid out like apps.db.ripe.net: a light page with
one card per object, one row per attribute, references in blue, rows the
RIPE NCC manages shaded. */
.reveal .ripe-result {
/* A fixed height, not a maximum: the box must not grow when the answer
arrives, or the slide overflows (reveal centres a slide only when it
is shown). */
height: 13.5em;
margin-top: 0.5em;
padding: 0.5em;
overflow-y: auto;
scrollbar-width: thin;
font-size: 0.62em;
text-align: left;
background: #f4f5f7;
border-radius: 6px;
}
.reveal .ripe-card {
margin-bottom: 0.7em;
padding: 0.2em 0.5em;
background: #fff;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}
.reveal .ripe-card:last-child { margin-bottom: 0; }
.reveal .ripe-card table {
width: 100%;
margin: 0;
border-collapse: collapse;
font-family: var(--r-code-font);
font-size: inherit;
color: #1c1c28;
}
.reveal .ripe-card th,
.reveal .ripe-card td {
padding: 0.28em 0.6em;
border: 0;
font-weight: normal;
text-align: left;
vertical-align: top;
background: transparent;
line-height: 1.4;
}
.reveal .ripe-card table th {
width: 8.5em;
color: #1c1c28;
white-space: nowrap;
text-decoration: underline dotted #9a9aa6;
text-underline-offset: 0.2em;
}
.reveal .ripe-card td { word-break: break-all; }
.reveal .ripe-card tr.managed th,
.reveal .ripe-card tr.managed td { background: #dde5f0; }
.reveal .ripe-card .ref { color: #2f6fe4; }
.reveal .ripe-card .comment { margin-left: 0.4em; color: #6b6b78; }
.reveal .ripe-msg {
padding: 0.6em;
font-family: var(--r-code-font);
color: #1c1c28;
}
/* A framed live page on a slide. */
.reveal iframe.live {
border: 1px solid var(--rule);
border-radius: 8px;
background: #fff;
}
/* ---- bytes with one part in focus: everything not .on is dimmed --------------- */
.bytes.focus span:not(.on) {
opacity: 0.22;
}
.bytes.focus span.on {
box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.9);
}
/* Packet layouts: field boxes in the colours of the bytes view. */
.diagram .pkt rect { stroke: none; }
.diagram .pkt.hh rect { fill: #34406e; }
.diagram .pkt.hl rect { fill: #6e3440; }
.diagram .pkt.ha rect { fill: #245c3a; }
.diagram .pkt.ha2 rect { fill: #2f7a4b; }
.diagram .pkt.hn rect { fill: #6b5a1f; }
.diagram text.pkt-name { font-size: 18px; font-weight: 500; fill: #fff; }
.diagram text.pkt-size { font-size: 13px; font-family: "IBM Plex Mono", monospace; fill: #fff; opacity: 0.8; }
.diagram text.pkt-title { paint-order: stroke; stroke: var(--panel); stroke-width: 8px; stroke-linejoin: round; }
.diagram .pkt-expand { stroke: var(--muted); stroke-width: 1.5; stroke-dasharray: 4 5; fill: none; }
/* ---- byte walk: a hex dump and one row per field, in step on hover --------- */
.reveal .bytewalk { text-align: left; }
.reveal .bytewalk .bw-dump { margin-bottom: 8px; }
/* The lit bytes invert: a white block on the dark dump, visible from the back row. */
.reveal .bw-dump span.on { background: #fff; color: var(--code-ground); box-shadow: 0 0 0 3px var(--accent); }
.reveal .bw-rows {
position: relative; /* rows measure their offsetTop against the box */
height: 19em;
overflow-y: auto;
scrollbar-width: thin;
font-size: 46%;
line-height: 1.45;
border: 1px solid var(--rule);
border-radius: 6px;
background: rgba(var(--accent-rgb), 0.04);
}
.reveal .bw-group {
padding: 0.45em 0.8em 0.2em;
color: var(--accent);
font-weight: 700;
}
.reveal .bw-row {
display: grid;
grid-template-columns: 11em 12em 1fr;
gap: 0 1em;
padding: 0.18em 0.8em;
cursor: default;
outline: none;
}
.reveal .bw-row:hover,
.reveal .bw-row:focus,
.reveal .bw-row.on { background: rgba(var(--accent-rgb), 0.14); }
.reveal .bw-dump span[data-i] { cursor: pointer; }
.reveal .bw-row code.hh { background: rgba(52, 64, 110, 0.16); }
.reveal .bw-row code.hl { background: rgba(110, 52, 64, 0.16); }
.reveal .bw-row code.ha { background: rgba(36, 92, 58, 0.16); }
.reveal .bw-row code.ha2 { background: rgba(47, 122, 75, 0.16); }
.reveal .bw-row code.hn { background: rgba(107, 90, 31, 0.16); }
.reveal .bw-row code { display: block; color: var(--ink-strong); min-width: 0; max-width: 100%; justify-self: start; align-self: start; font-family: var(--r-code-font); border-radius: 3px; padding: 0 4px; white-space: normal; word-break: normal; }
.reveal .bw-row b { color: var(--ink-strong); font-weight: 500; }
.reveal .bw-row span { color: var(--ink); }
/* Small two-column explanation under a bytes block. */
.reveal table.decode {
font-size: 58%;
margin-top: 10px;
}
.reveal table.decode td:first-child {
font-family: var(--r-code-font);
color: var(--accent-soft);
white-space: nowrap;
}
/* ---- prefix explorer: type a prefix, see its range ------------------------ */
.reveal form.prefix-explorer {
margin: 0 auto;
max-width: 36em;
text-align: center;
}
.reveal .prefix-explorer input[name="prefix"] {
width: 15em;
padding: 0.25em 0.5em;
font: inherit;
font-family: var(--r-code-font);
font-size: 0.8em;
color: var(--r-main-color);
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 6px;
outline: none;
text-align: center;
}
.reveal .prefix-explorer input[name="prefix"]:focus { border-color: var(--accent); }
.reveal .prefix-explorer input[name="len"] {
width: 12em;
margin-left: 1em;
vertical-align: middle;
accent-color: var(--accent);
}
.reveal .prefix-explorer .px-bits { margin: 0.5em 0 0.4em; min-height: 1.6em; white-space: nowrap; }
.reveal .prefix-explorer .px-bad { color: #c62828; font-size: 70%; }
.reveal .px-range { font-family: var(--r-code-font); font-size: 50%; min-height: 10.5em; }
.reveal .px-levels { text-align: left; margin-bottom: 1em; }
.reveal .px-levels-title { color: var(--muted); margin-bottom: 0.35em; }
.reveal .px-level { display: flex; align-items: center; gap: 0.7em; margin-bottom: 0.3em; }
.reveal .px-level-name { width: 13em; text-align: right; color: var(--accent-soft); white-space: nowrap; }
.reveal .px-level-count { width: 8em; color: var(--muted); white-space: nowrap; }
.reveal .px-track { flex: 1; position: relative; height: 0.9em; background: var(--ground); border: 1px solid var(--rule); border-radius: 2px; }
.reveal .px-track i { position: absolute; top: 0; bottom: 0; min-width: 2px; background: var(--accent); }
.reveal .px-bar {
position: relative;
height: 2.6em;
background: linear-gradient(90deg, rgba(var(--accent-rgb), 0.45), rgba(var(--accent-rgb), 0.12));
border: 1px solid var(--accent);
border-radius: 6px;
}
.reveal .px-bar .px-mid {
position: absolute; left: 0; right: 0; top: 0.6em;
text-align: center; color: var(--ink-strong); font-weight: 500;
}
.reveal .px-bar .px-end { position: absolute; top: 3em; color: var(--accent-soft); }
.reveal .px-bar .px-first { left: 0; }
.reveal .px-bar .px-last { right: 0; }
.reveal .prefix-explorer .px-facts { margin-top: 2.6em; }
/* ---- bits of an address: fixed part vs. free part ------------------------------ */
.bits {
font-family: var(--r-code-font);
font-size: 80%;
letter-spacing: 0.02em;
}
.bits .fixed {
color: #fff;
background: var(--accent);
border-radius: 4px 0 0 4px;
padding: 2px 6px;
}
.bits .part {
color: var(--accent-soft);
background: var(--ground);
border: 1px solid var(--accent);
padding: 1px 4px;
margin: 0 2px;
font-size: 85%;
letter-spacing: 0.12em;
}
.bits .part::before { content: "₂"; color: var(--muted); letter-spacing: 0; margin-right: 2px; }
.bits .part i { font-style: normal; color: var(--muted); }
.bits .free {
color: var(--ink);
background: var(--ground);
border: 1px solid var(--rule);
border-left: none;
border-radius: 0 4px 4px 0;
padding: 1px 6px;
}
/* ---- diagrams: inline SVG drawn with the theme's colours ------------------------ */
.reveal svg.diagram {
width: 100%;
height: auto;
max-height: 470px;
display: block;
margin: 0 auto;
}
.diagram rect,
.diagram ellipse {
fill: var(--ground);
stroke: var(--rule);
stroke-width: 2;
}
.diagram .hot rect {
stroke: var(--accent);
}
.diagram .fabric rect {
fill: rgba(var(--accent-rgb), 0.18);
stroke: var(--accent);
}
.diagram text {
fill: var(--ink);
font-family: "IBM Plex Sans", sans-serif;
font-size: 19px;
text-anchor: middle;
}
.diagram text.small {
font-size: 14px;
fill: var(--muted);
font-family: "IBM Plex Mono", monospace;
}
.diagram text.accent {
fill: var(--accent);
}
.diagram .link {
stroke: var(--muted);
stroke-width: 2.5;
fill: none;
}
.diagram .bgp {
stroke: var(--accent);
stroke-width: 2.5;
stroke-dasharray: 7 6;
fill: none;
}
/* Nested address ranges: each level a little brighter than the one around it. */
.diagram .nest rect {
stroke: var(--accent);
rx: 14;
}
.diagram .nest.l0 rect { fill: rgba(var(--accent-rgb), 0.04); stroke-opacity: 0.35; }
.diagram .nest.l1 rect { fill: rgba(var(--accent-rgb), 0.09); stroke-opacity: 0.55; }
.diagram .nest.l2 rect { fill: rgba(var(--accent-rgb), 0.16); stroke-opacity: 0.8; }
.diagram .nest.l3 rect { fill: rgba(var(--accent-rgb), 0.28); stroke-opacity: 1; }
.diagram text.left { text-anchor: start; }
.diagram text.mono { font-family: "IBM Plex Mono", monospace; }
.diagram .nest-label { font-family: "IBM Plex Mono", monospace; font-size: 22px; font-weight: 500; }
.diagram .nest-desc { font-size: 17px; fill: var(--ink); opacity: 0.85; }
.diagram text.host-addr { font-size: 15px; fill: var(--accent-soft); font-family: "IBM Plex Mono", monospace; }
.diagram .host { fill: var(--accent-soft); stroke: none; }
.diagram .traffic {
stroke: #1a8a4f;
stroke-width: 4;
fill: none;
}