/* * Both schemes are defined as tokens on :root and swapped under prefers-color-scheme, so the page * follows the operating system without any script and without a flash on load. */ :root { --surface: #ffffff; --surface-sunken: #f4f5f7; --surface-raised: #ffffff; --border: #d8dbe0; --text: #16181d; --text-dim: #5c6270; --accent: #1c5fd6; --danger: #b3261e; --danger-surface: #fce8e6; --ok: #146c2e; --request: #1c5fd6; --response: #146c2e; color-scheme: light dark; font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; line-height: 1.5; } @media (prefers-color-scheme: dark) { :root { --surface: #16181d; --surface-sunken: #101216; --surface-raised: #1e2128; --border: #333944; --text: #e8eaee; --text-dim: #9aa2b1; --accent: #79a9ff; --danger: #f2837c; --danger-surface: #3a1d1b; --ok: #6ed08a; --request: #79a9ff; --response: #6ed08a; } } *, *::before, *::after { box-sizing: border-box; } body { margin: 0; background: var(--surface-sunken); color: var(--text); } main { max-width: 80rem; margin-inline: auto; padding: 1.5rem 1rem 4rem; } h1 { font-size: 1.5rem; margin-block: 0 0.25rem; } h2 { font-size: 1.15rem; margin-block: 0; } h3 { font-size: 1rem; margin-block: 0 0.25rem; } h4 { font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-dim); margin-block: 1.5rem 0.5rem; } a { color: var(--accent); } code, .bytes, .address { font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace; font-size: 0.85em; } .masthead { margin-block-end: 1.5rem; } .hint { color: var(--text-dim); font-size: 0.85rem; } p.hint { margin-block: 0.25rem; } .value { font-weight: 600; } .name { font-weight: 500; } .empty { color: var(--text-dim); background: var(--surface-raised); border: 1px dashed var(--border); border-radius: 0.5rem; padding: 1rem 1.25rem; } .notice, .port { background: var(--surface-raised); border: 1px solid var(--border); border-radius: 0.5rem; padding: 1rem 1.25rem; margin-block-end: 1rem; } .panel-header { display: flex; gap: 1rem; align-items: start; justify-content: space-between; flex-wrap: wrap; margin-block-end: 0.75rem; } .panel-header .actions { display: flex; gap: 0.5rem; } /* -------------------------------------------------------------------------- */ /* Controls */ /* -------------------------------------------------------------------------- */ .controls { display: flex; flex-wrap: wrap; align-items: end; gap: 0.75rem 1rem; margin-block-end: 0.75rem; border: 0; padding: 0; } /* * Each label stays with the control it names. Without this the row wraps between them and a * "Parity" label ends up sitting above somebody else's select. */ .control { display: flex; flex-direction: column; gap: 0.15rem; } fieldset.controls { border: 1px solid var(--border); border-radius: 0.375rem; padding: 0.75rem 1rem; } fieldset.controls legend { font-size: 0.8rem; color: var(--text-dim); padding-inline: 0.35rem; } fieldset:disabled { opacity: 0.6; } label { font-size: 0.85rem; color: var(--text-dim); } button, select, input { font: inherit; font-size: 0.9rem; color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: 0.375rem; padding: 0.35rem 0.6rem; } button { cursor: pointer; } button:hover:not(:disabled) { border-color: var(--accent); } button:disabled { cursor: not-allowed; opacity: 0.55; } :is(button, select, input):focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; } .tabs { display: flex; gap: 0.25rem; margin-block: 1rem 0.5rem; border-block-end: 1px solid var(--border); } .tabs button[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); font-weight: 600; } /* -------------------------------------------------------------------------- */ /* Validation */ /* -------------------------------------------------------------------------- */ /* * :user-invalid rather than :invalid, so a register write field is not flagged red the moment it * is empty or half-typed — only once the field has been left or a submit attempted. Baseline * since 2023, so no fallback is carried. * * The bounds themselves come from the register definition and are set as real min/max/step * attributes, which is what makes the browser's own validation the source of truth here. */ input:user-invalid { border-color: var(--danger); background: var(--danger-surface); } input:user-valid { border-color: var(--ok); } .error-msg { display: none; color: var(--danger); font-size: 0.8rem; } /* Revealed by the browser's own judgement, not by a signal */ input:user-invalid ~ .error-msg, .error-msg.shown { display: block; } .field { display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; } .field input[type="number"] { width: 7rem; } /* -------------------------------------------------------------------------- */ /* Tables */ /* -------------------------------------------------------------------------- */ /* Wide content scrolls inside its own box rather than pushing the page sideways */ .table-scroll { overflow-x: auto; border: 1px solid var(--border); border-radius: 0.375rem; max-block-size: 34rem; overflow-y: auto; } table { border-collapse: collapse; inline-size: 100%; font-size: 0.85rem; } thead th { position: sticky; inset-block-start: 0; background: var(--surface-raised); text-align: start; font-weight: 600; color: var(--text-dim); padding: 0.4rem 0.6rem; border-block-end: 1px solid var(--border); z-index: 1; } td { padding: 0.35rem 0.6rem; border-block-end: 1px solid var(--border); vertical-align: top; } tbody tr:last-child td { border-block-end: 0; } /* * The monitor keeps hundreds of rows and only a screenful is ever in view. content-visibility lets * the browser skip layout and paint for the rest; contain-intrinsic-size keeps the scrollbar from * jumping as those rows are realised, and `auto` lets it remember each row's real height once * measured. */ .frames tbody .row { content-visibility: auto; contain-intrinsic-size: auto none auto 1.9rem; } .frames .row.request td:nth-child(2) { color: var(--request); font-weight: 600; } .frames .row.response td:nth-child(2) { color: var(--response); font-weight: 600; } .frames .row.noise { color: var(--text-dim); background: var(--surface-sunken); } .registers .address { white-space: nowrap; } @media (max-width: 40rem) { .panel-header { flex-direction: column; } }