ssh-browser 0.5.1

Open files on an SSH host as a real browser origin.
Documentation
/* What ssh-browser's own pages look like.
 *
 * Two readers of one file: the extension's dashboard links it out of `dist/`, and the daemon
 * compiles it in and serves it at the root of the suffix. That is the whole reason it is a
 * file rather than a `<style>` block — the root of the suffix and the dashboard are the same
 * page in two places, and a second copy of these rules is how they stop being.
 *
 * Themed, by the same palette the daemon renders a listing with. It was not, and the seam
 * showed: choosing a dark theme turned the daemon's pages dark and left this one white,
 * because its four colours were hex values written here that no scheme had a say in.
 *
 * So there is no palette in this file. It arrives first — inline from the daemon, and in the
 * extension from `/_control/theme` through the service worker — and every colour below is a
 * `var()` reading it. Before any daemon has answered there is nothing to inject and these
 * fall back to the browser's own black on white, which is the honest look for a page that
 * cannot reach anything.
 */
/* On `html`, the way the listing's stylesheet does it. Put on `body` the colour stops at the
   content box, so a short page leaves the browser's own white below the fold on one of these
   two pages and not the other. */
html {
  background: var(--bg);
}
body {
  color: var(--fg);
  font:
    14px/1.6 system-ui,
    sans-serif;
  margin: 0 auto;
  max-width: 720px;
  padding: 32px 20px 64px;
}
h1 {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.04em;
  margin: 0 0 24px;
}
h2 {
  border-bottom: 1px solid var(--line);
  color: var(--dim);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  margin: 32px 0 12px;
  padding-bottom: 6px;
  text-transform: uppercase;
}
#status {
  margin-bottom: 16px;
}
#status:empty {
  display: none;
}
#status.bad {
  color: var(--bad);
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* A site, as a card. The dashboard's is a button because clicking it routes within that
   page; the daemon's is a link because there is nowhere to route to and the site's own URL
   is the honest destination. One rule, so that they stay one card. */
li > button,
li > a {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: inherit;
  cursor: pointer;
  display: block;
  font: inherit;
  margin-bottom: 8px;
  padding: 12px 14px;
  text-align: left;
  text-decoration: none;
  width: 100%;
}
li > button:hover,
li > a:hover {
  background: var(--hover);
  border-color: var(--dim);
}
li > button:disabled {
  cursor: progress;
  opacity: 0.55;
}
.name {
  font-size: 15px;
  font-weight: 600;
}
/* The site's own name, which is a hostname label and is meant to read as one. The
   section headings above it are upper-cased as labels; doing that to `yukawa-mercury`
   would be shouting somebody's host name back at them. */
.site-name {
  border: 0;
  font-size: 20px;
  letter-spacing: 0;
  margin: 0 0 4px;
  padding: 0;
  text-transform: none;
}
.url {
  color: var(--good);
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 13px;
}
.where {
  color: var(--dim);
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 12px;
}
.bad-host {
  color: var(--bad);
  font-size: 12px;
}
.empty {
  color: var(--dim);
}
.back {
  color: var(--dim);
  display: inline-block;
  margin-bottom: 16px;
  text-decoration: none;
}
.back:hover {
  text-decoration: underline;
}
.site-url {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 18px;
  overflow-wrap: anywhere;
}
dl {
  display: grid;
  gap: 4px 16px;
  grid-template-columns: max-content 1fr;
  margin: 0;
}
dt {
  color: var(--dim);
  font-size: 12px;
}
dd {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 13px;
  margin: 0;
  overflow-wrap: anywhere;
}
.act {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.act input {
  border: 1px solid var(--line);
  border-radius: 6px;
  flex: 1 1 240px;
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, monospace;
  padding: 7px 10px;
}
.act button,
.open-site {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  cursor: pointer;
  font: inherit;
  padding: 7px 14px;
  text-decoration: none;
}
.act button:hover,
.open-site:hover {
  background: var(--hover);
}
.danger {
  border-color: var(--bad) !important;
  color: var(--bad);
}
.note {
  color: var(--dim);
  font-size: 12px;
  margin: 8px 0 0;
}
footer {
  border-top: 1px solid var(--line);
  color: var(--dim);
  font-size: 12px;
  margin-top: 40px;
  padding-top: 12px;
}
footer input {
  border: 1px solid var(--line);
  border-radius: 4px;
  font: inherit;
  padding: 2px 6px;
  width: 6em;
}
.cmd {
  background: var(--hover);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 13px;
  margin: 0;
  overflow-x: auto;
  padding: 10px 12px;
  user-select: all;
}
select {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: inherit;
  font: inherit;
  padding: 7px 10px;
}