/* Gate chrome only. Nothing here reaches a hosted site: it renders in an
   iframe with its own opaque origin and its own policy. */

:root {
  --bg: #12100f;
  --panel: #1c1917;
  --line: #302a26;
  --ink: #f2ede7;
  --muted: #9a8f85;
  --accent: #7fd18a;
  --danger: #f2836b;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

/* Any rule that sets `display` silently beats the browser's own
   `[hidden] { display: none }`, which is how the viewer — `display: block` —
   went on filling the page while hidden, pushing the welcome screen below the
   fold behind a blank white rectangle. Stated once, for everything. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

/* Flex column, not a grid with counted rows: the share bar and the drop
   overlay come and go, and a `grid-template-rows` list silently reassigns the
   1fr to whichever child happens to be third. That is how the viewer once
   collapsed to the height of its content while the status bar floated in the
   middle of a black page. */
body {
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 var(--font);
}

/* --- chrome ------------------------------------------------------------- */

.chrome {
  flex: none;
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 10px 14px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.brand {
  padding: 0 4px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--accent);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.brand:hover { background: var(--line); }
.brand:focus-visible { outline: 2px solid var(--accent); }

.address-form {
  display: flex;
  flex: 1;
  gap: 8px;
  min-width: 0;
}

.address {
  flex: 1;
  min-width: 0;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink);
  font: 13px/1.4 var(--mono);
}

.address:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

button, .button {
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--line);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}

button:hover, .button:hover { border-color: var(--accent); }

/* --- stage -------------------------------------------------------------- */

.stage {
  position: relative;
  flex: 1;
  overflow: auto;
  min-height: 0; /* let it shrink instead of pushing the status bar off-screen */
}

.viewer {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: #fff; /* sites assume a page, not a dark app shell */
}

.notice {
  margin: 24px auto;
  max-width: 40rem;
  padding: 14px 18px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
  color: var(--muted);
}

.notice--error {
  border-color: var(--danger);
  color: var(--danger);
}

/* --- welcome ------------------------------------------------------------ */

.welcome {
  margin: 0 auto;
  padding: 40px 20px 60px;
  max-width: 44rem;
}

.welcome h1 {
  margin: 0;
  font-size: 28px;
  letter-spacing: -.01em;
}

.tagline {
  margin: 6px 0 28px;
  color: var(--muted);
}

/* Two ways in, side by side, because the gate has exactly two things to
   offer and a reader arriving cold should not have to guess which is which. */

.choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 16px;
}

.choice {
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
}

.choice h2 {
  margin: 0 0 8px;
  font-size: 16px;
}

.choice p {
  margin: 0 0 16px;
}

/* The publish card is also the drop target, so it reacts to a drag. */
#dropzone.is-active {
  border-color: var(--accent);
  border-style: dashed;
}

.visit-form {
  display: flex;
  gap: 8px;
}

.visit-form .address {
  flex: 1;
  min-width: 0;
}

.pick { display: inline-block; }

.share {
  flex: none;
  padding: 14px 18px;
  background: var(--panel);
  border-bottom: 1px solid var(--accent);
}

.share p { margin: 0 0 12px; }

.share-row {
  display: flex;
  gap: 8px;
}

.share-link {
  flex: 1;
  min-width: 0;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  font: 12px/1.4 var(--mono);
}

/* --- identity ----------------------------------------------------------- */

.signin { margin-top: 14px; }

.avatar {
  flex: none;
  display: block;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  overflow: hidden;
}

.avatar svg { display: block; width: 100%; height: 100%; }

.avatar--large {
  width: 72px;
  height: 72px;
  border-radius: 10px;
}

#signin-dialog {
  max-width: 30rem;
  padding: 24px;
  width: calc(100% - 2rem);
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  color: var(--ink);
}

#signin-dialog::backdrop { background: rgba(0, 0, 0, .6); }
#signin-dialog h2 { margin: 0 0 12px; font-size: 16px; }
#signin-dialog p { margin: 0 0 12px; }

.field {
  display: block;
  margin: 16px 0 8px;
}

.field-label {
  display: block;
  margin-bottom: 6px;
  font-size: 12px;
  color: var(--muted);
}

.field select {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.4 inherit;
}

.field input {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.4 inherit;
}

.field input:focus-visible {
  outline: none;
  border-color: var(--accent);
}

.reveal {
  display: flex;
  gap: 6px;
  align-items: center;
  font-size: 12px;
  color: var(--muted);
}

.remember {
  margin-top: 14px;
  align-items: flex-start;
  color: var(--ink);
}

.remember input { margin-top: 2px; }

.avatar--chip {
  width: 16px;
  height: 16px;
  border-radius: 3px;
}

.author-chip {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  padding: 0 6px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--muted);
  font: inherit;
  cursor: pointer;
}

.author-chip:hover {
  border-color: var(--line);
  color: var(--ink);
}

/* Verified, merely declared, and contradicted are three different claims, and
   a reader should be able to tell them apart without opening anything. */
.author-chip[data-state="verified"] { color: var(--accent); }
.author-chip[data-state="broken"] { color: var(--danger); border-color: var(--danger); }

#author-dialog {
  max-width: 32rem;
  padding: 24px;
  width: calc(100% - 2rem);
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  color: var(--ink);
}

#author-dialog::backdrop { background: rgba(0, 0, 0, .6); }
#author-dialog h2 { margin: 0 0 12px; font-size: 16px; }
#author-dialog p { margin: 0 0 12px; }

.author-facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 16px;
  margin: 0 0 16px;
  font-size: 12px;
}

.author-facts dt { color: var(--muted); }
.author-facts dd { margin: 0; word-break: break-all; }
.author-facts dd.mono { font-family: var(--mono); }

.signin-error {
  margin: 12px 0 0;
  color: var(--danger);
  font-size: 13px;
}

/* The whole point of the second step: big enough to compare at a glance. */
.identity-card {
  display: flex;
  gap: 14px;
  align-items: center;
  margin: 16px 0;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
}

.identity-card p { margin: 0; }

.recognised {
  font-weight: 600;
  margin-bottom: 4px !important;
}

.recognised.recognised--new { font-weight: 400; color: var(--muted); }

.signed-in {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.signed-in p { margin: 0; }

.fingerprint {
  font-family: var(--mono);
  letter-spacing: 0.04em;
}

/* --- update offer ------------------------------------------------------- */

.update {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  padding: 12px 18px;
  background: var(--panel);
  border-bottom: 1px solid var(--accent);
}

.update-who {
  display: flex;
  gap: 12px;
  align-items: center;
  min-width: 0;
}

.update-text { margin: 0; min-width: 0; }
.update-text span { display: block; }

.update-row {
  display: flex;
  gap: 8px;
}

.muted { color: var(--muted); }
.small { font-size: 12px; }
code { font-family: var(--mono); }

/* --- status bar --------------------------------------------------------- */

.statusbar {
  flex: none;
  display: flex;
  /* Wraps, because this row grew: site name, author, peers, progress, Share,
     Save .torrent and Diagnostics. On a phone that is 477px of content in a
     390px window, and without wrapping it pushed the whole document sideways
     — the page could be dragged right, with the buttons off-screen. */
  flex-wrap: wrap;
  column-gap: 18px;
  row-gap: 2px;
  padding: 6px 14px;
  background: var(--panel);
  border-top: 1px solid var(--line);
  color: var(--muted);
  font: 12px/1.6 var(--mono);
}

.statusbar span:first-child {
  flex: 1;
  min-width: 0;             /* or the ellipsis never triggers inside a flex row */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- toggles ------------------------------------------------------------ */

.toggle {
  display: flex;
  gap: 6px;
  align-items: center;
  color: var(--muted);
  white-space: nowrap;
  cursor: pointer;
}

.toggle input:disabled + span { opacity: .4; }

/* --- kept sites --------------------------------------------------------- */

.kept {
  margin-top: 28px;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
}

.kept h2 {
  margin: 0 0 8px;
  font-size: 15px;
}

.kept p { margin: 0 0 12px; }

.kept-list {
  margin: 0 0 12px;
  padding: 0;
  list-style: none;
}

.kept-list li {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 8px 0;
  border-top: 1px solid var(--line);
}

.kept-list a {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--accent);
}

.kept-list button {
  padding: 4px 10px;
  font-size: 12px;
}

/* --- drop target -------------------------------------------------------- */

/* The whole window accepts a dropped folder, so the whole window has to look
   like it does — otherwise a reader aims at the dashed box, misses, and the
   browser opens the file instead. */

.drop-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 10;
  align-items: center;
  justify-content: center;
  background: rgba(18, 16, 15, .88);
  border: 3px dashed var(--accent);
  color: var(--accent);
  font-size: 20px;
  pointer-events: none; /* never swallow the drop it is advertising */
}

body.is-dragging .drop-overlay { display: flex; }

#share-dismiss {
  padding: 8px 12px;
  color: var(--muted);
}

/* --- diagnostics -------------------------------------------------------- */

.link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

.link:hover { color: var(--accent); }

#diagnostics {
  max-width: 34rem;
  padding: 24px;
  width: calc(100% - 2rem);
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  color: var(--ink);
}

#diagnostics::backdrop { background: rgba(0, 0, 0, .6); }
#diagnostics h2 { margin: 0 0 14px; font-size: 16px; }

#diagnostics dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 16px;
  margin: 0 0 16px;
  font: 12px/1.5 var(--mono);
}

#diagnostics dt { color: var(--muted); }

#diagnostics dd {
  margin: 0;
  min-width: 0;
  /* Values here are origins, worker paths and magnets: long, unbreakable
     tokens. On a phone they were simply clipped at the edge, so the one place
     a reader goes when something is wrong could not be read on the device it
     was wrong on. Reported from an iPhone, with the right-hand half missing. */
  overflow-wrap: anywhere;
}
#diagnostics dd.bad { color: var(--danger); }
#diagnostics dd.good { color: var(--accent); }

.dialog-head {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  justify-content: space-between;
}

.dialog-head h2 { flex: 1; }

.dismiss {
  flex: none;
  padding: 2px 8px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--muted);
  font: inherit;
  line-height: 1.2;
  cursor: pointer;
}

.dismiss:hover { border-color: var(--line); color: var(--ink); }

.dialog-actions {
  display: flex;
  flex-wrap: wrap;          /* three buttons do not fit a phone in one row */
  gap: 8px;
  justify-content: flex-end;
  margin-top: 16px;
}

/* --- phones -------------------------------------------------------------- */

/* Everything above is written for a window with room to spare. These are the
   places where that assumption showed: a status bar wide enough to drag the
   page sideways, and dialogs sized in rem that a small screen cannot honour. */
@media (max-width: 560px) {
  .statusbar { column-gap: 12px; }

  /* Two columns of monospace do not fit a phone. Stacked, each value gets the
     full width and nothing is cut off. */
  #diagnostics dl { grid-template-columns: 1fr; gap: 2px 0; }
  #diagnostics dt { margin-top: 10px; }

  /* The site's name gets its own line, so the controls beside it stay
     reachable instead of being pushed past the edge. */
  .statusbar > span:first-child { flex-basis: 100%; }

  .dialog-actions { justify-content: stretch; }
  .dialog-actions button { flex: 1; }
  .dialog-actions button.link { flex: 0 0 auto; }
}

/* A dialog taller than the window is unusable: on a phone the on-screen
   keyboard takes half of it, and the buttons end up below the fold with no way
   to scroll to them. Every dialog scrolls its own content instead. */
#signin-dialog,
#author-dialog,
#diagnostics {
  max-height: calc(100dvh - 2rem);
  overflow-y: auto;
}

/* --- the missing-site page ---------------------------------------------- */

/* A site nobody is seeding is a normal outcome, so it gets a page rather than
   an error banner — the same courtesy a web server extends to a missing URL. */

.error {
  margin: 0 auto;
  padding: 60px 20px;
  max-width: 34rem;
  text-align: center;
}

.error-code {
  margin: 0;
  color: var(--line);
  font: 700 72px/1 var(--mono);
  letter-spacing: .05em;
}

.error h1 {
  margin: 8px 0 12px;
  font-size: 20px;
}

.error-detail {
  margin: 0 0 20px;
  color: var(--muted);
  text-align: left;
}

.error-ref {
  margin: 0 0 24px;
  overflow-wrap: anywhere;
  text-align: left;
}

.error-ref code {
  display: block;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--muted);
  font-size: 12px;
}

.error-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
}

/* --- a torrent that is not a website ------------------------------------ */

.listing {
  margin: 0 auto;
  padding: 40px 20px 60px;
  max-width: 44rem;
}

.listing h1 {
  margin: 0 0 4px;
  overflow-wrap: anywhere;
  font-size: 22px;
}

.listing p { margin: 0 0 14px; }

.listing-files {
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
}

.listing-files li + li { border-top: 1px solid var(--line); }

.listing-files button {
  display: flex;
  gap: 14px;
  align-items: baseline;
  width: 100%;
  padding: 10px 14px;
  border: 0;
  border-radius: 0;
  background: var(--panel);
  color: var(--ink);
  font: 13px/1.5 var(--mono);
  text-align: left;
  cursor: pointer;
}

.listing-files button:hover { background: var(--line); }

.listing-files .path {
  flex: 1;
  overflow-wrap: anywhere;
}

.listing-files .size {
  color: var(--muted);
  white-space: nowrap;
}
