/* Portal stylesheet. Hand-written, no build step.
   Loaded AFTER Bootstrap 5.3.8 (see base.html) and layered on top of it: this
   file owns the colours and the look of .card/.btn/.pill/.msg, Bootstrap owns
   the reset, the grid utilities and the collapsing navbar. Load order is the
   whole mechanism -- most rules here beat Bootstrap only because they come
   second, so nothing in this file may be moved into <head> above the CDN link.
   Rules that exist purely to undo Bootstrap are marked "reset:" below. */
:root {
    --bg: #f6f7f9; --card: #fff; --ink: #14161a; --muted: #5c6570;
    --line: #e3e6ea; --accent: #2f6fed; --accent-ink: #fff;
    --ok: #1a7f4b; --warn: #9a6700; --bad: #b42318; --bad-bg: #fef3f2;
    --radius: 10px;
  }
  * { box-sizing: border-box; }
  body {
    margin: 0; background: var(--bg); color: var(--ink);
    font: 15px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  }
  a { color: var(--accent); }
  .wrap { max-width: 940px; margin: 0 auto; padding: 0 20px; }

  header.site {
    background: var(--card); border-bottom: 1px solid var(--line);
    padding: 14px 0; margin-bottom: 28px;
  }
  /* reset: .navbar brings its own padding and a flex row we do not want at the
     header level -- the .wrap inside it is what centres the content. */
  header.site.navbar { padding: 14px 0; display: block; }
  header.site .wrap { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
  .brand { font-weight: 650; letter-spacing: -0.01em; }
  .spacer { margin-left: auto; }
  .who { color: var(--muted); font-size: 13px; }

  /* Collapsed nav (below the navbar-expand-* breakpoint): the toggler shows and
     the links become a stacked block under the brand. .spacer's margin-left:auto
     is meaningless once stacked, so it is neutralised here. */
  .navbar-collapse { flex-basis: 100%; }
  .navbar-collapse.show, .navbar-collapse.collapsing {
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 12px; padding: 14px 0 4px;
  }
  .navbar-collapse.show .spacer, .navbar-collapse.collapsing .spacer { margin-left: 0; }
  /* Expanded (wide): restore the single flex row the header always had. */
  @media (min-width: 768px) {
    header.site.navbar-expand-md .navbar-collapse {
      display: flex; align-items: center; gap: 16px; flex-basis: auto;
    }
  }
  @media (min-width: 992px) {
    header.site.navbar-expand-lg .navbar-collapse {
      display: flex; align-items: center; gap: 16px; flex-basis: auto;
    }
  }

  h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: -0.02em; }
  h2 { font-size: 16px; margin: 0 0 12px; }
  .lede { color: var(--muted); margin: 0 0 24px; }

  /* reset: Bootstrap's .card is `display:flex; flex-direction:column` with no
     padding of its own. Ours is a plain padded box -- without display:block the
     children become flex items, margins stop collapsing and widths change. */
  .card {
    display: block;
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 18px; margin-bottom: 16px;
  }
  .card h2 { display: flex; align-items: baseline; gap: 10px; }

  table { width: 100%; border-collapse: collapse; font-size: 14px; }
  th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--line); }
  th { color: var(--muted); font-weight: 550; font-size: 12px;
       text-transform: uppercase; letter-spacing: 0.04em; }
  tr:last-child td { border-bottom: 0; }
  td.num { text-align: right; font-variant-numeric: tabular-nums; }
  /* Row-action cell: keeps its buttons on one line on desktop. The stacked
     media query below undoes both properties. */
  td.actions { text-align: right; white-space: nowrap; }

  /* overflow-wrap:anywhere, not break-word: a base64 public key and an invite
     URL are single tokens with no break opportunity at all, and break-word will
     not break inside one if the line is otherwise empty-ish. `anywhere` also
     lets the token shrink min-content, which is what stops a table cell or card
     from being forced wider than the viewport. */
  code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px;
                overflow-wrap: anywhere; }
  .key { user-select: all; }
  /* Emails and license keys land in all of these. */
  .msg, h1, nav.crumbs, td, th { overflow-wrap: anywhere; }

  .meter { background: var(--line); border-radius: 999px; height: 7px; overflow: hidden; }
  .meter > i { display: block; height: 100%; background: var(--accent); }
  .meter.full > i { background: var(--warn); }

  .pill { display: inline-block; padding: 1px 8px; border-radius: 999px;
          font-size: 12px; font-weight: 550; }
  .pill.ok { background: #e7f6ee; color: var(--ok); }
  .pill.warn { background: #fdf3d7; color: var(--warn); }
  .pill.bad { background: var(--bad-bg); color: var(--bad); }

  .btn {
    display: inline-block; padding: 8px 14px; border-radius: 8px; border: 1px solid var(--line);
    background: var(--card); color: var(--ink); font: inherit; font-size: 14px;
    cursor: pointer; text-decoration: none;
  }
  .btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
  .btn.danger { color: var(--bad); border-color: #f3c2bd; background: var(--bad-bg); }
  .btn.link { border: 0; background: none; padding: 0; color: var(--accent); }

  /* reset: Bootstrap's `.btn:hover` / `:focus-visible` are more specific than
     our `.btn` and resolve against --bs-btn-hover-bg etc., which a bare .btn
     never sets -- so without these, hovering blanks the button out. These must
     restate the colours rather than rely on inheritance. */
  .btn:hover, .btn:focus-visible {
    background: var(--bg); border-color: var(--line); color: var(--ink);
  }
  .btn.primary:hover, .btn.primary:focus-visible {
    background: #2560d4; border-color: #2560d4; color: var(--accent-ink);
  }
  .btn.danger:hover, .btn.danger:focus-visible {
    background: #fde7e4; border-color: #f3c2bd; color: var(--bad);
  }
  .btn.link:hover, .btn.link:focus-visible {
    background: none; border: 0; color: var(--accent); text-decoration: underline;
  }
  .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: none; }

  form.inline { display: inline; }
  label { display: block; font-weight: 550; margin: 14px 0 5px; font-size: 14px; }
  input[type=text], input[type=email], input[type=password], input[type=number], select {
    width: 100%; padding: 9px 11px; border: 1px solid var(--line);
    border-radius: 8px; font: inherit; background: var(--card);
  }
  .helptext, .help { color: var(--muted); font-size: 13px; margin: 5px 0 0; }
  ul.errorlist { margin: 6px 0 0; padding-left: 18px; color: var(--bad); font-size: 13px; }

  .msg { padding: 11px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 14px; }
  .msg.success { background: #e7f6ee; color: var(--ok); }
  .msg.warning { background: #fdf3d7; color: var(--warn); }
  .msg.error { background: var(--bad-bg); color: var(--bad); }

  .narrow { max-width: 420px; margin: 48px auto; }
  .empty { color: var(--muted); text-align: center; padding: 28px 0; }
  footer.site { color: var(--muted); font-size: 13px; padding: 32px 0; text-align: center; }

  /* Rendered from base.html rather than per-page, so it is structurally
     impossible to show a portal page while impersonating without this banner. */
  .impersonating {
    background: #7a2e0e; color: #fff; padding: 9px 0; font-size: 14px;
    position: sticky; top: 0; z-index: 10;
  }
  .impersonating .wrap { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
  .impersonating .btn { background: rgba(255,255,255,.15); border-color: rgba(255,255,255,.3);
                        color: #fff; padding: 4px 10px; font-size: 13px; }
  .impersonating .btn:hover, .impersonating .btn:focus-visible {
    background: rgba(255,255,255,.28); border-color: rgba(255,255,255,.45); color: #fff;
  }
  /* Sticky + wrapping: on a phone this banner is three lines, so cap how much
     of the viewport it can pin. */
  @media (max-width: 767.98px) {
    .impersonating .wrap { row-gap: 8px; }
    .impersonating .spacer { margin-left: 0; }
  }

  /* Wide tables become one labelled card per row below Bootstrap's md
     breakpoint. Bootstrap has no equivalent -- .table-responsive is horizontal
     scroll -- so this is ours. The label comes from each cell's data-label,
     which must match that column's <th>; thead is hidden, so a wrong or missing
     data-label silently mislabels the value rather than failing visibly.
     Note this drops the row/cell roles for screen readers, the known trade-off
     of this pattern. */
  @media (max-width: 767.98px) {
    .table-stack, .table-stack tbody, .table-stack tr, .table-stack td { display: block; }
    .table-stack thead { display: none; }
    .table-stack tr {
      border: 1px solid var(--line); border-radius: var(--radius);
      margin-bottom: 12px; padding: 4px 0;
    }
    .table-stack tr:last-child { margin-bottom: 0; }
    .table-stack td {
      display: grid; grid-template-columns: 92px 1fr; gap: 10px; align-items: baseline;
      border-bottom: 0; padding: 6px 12px;
    }
    .table-stack td::before {
      content: attr(data-label);
      color: var(--muted); font-size: 12px; font-weight: 550;
      text-transform: uppercase; letter-spacing: 0.04em;
    }
    /* Right-alignment and nowrap are desktop-column concerns; stacked, they
       only push the card wider than the screen. */
    .table-stack td.num, .table-stack td.actions { text-align: left; white-space: normal; }
    /* A header-less column (data-label="") gets no label gutter -- otherwise an
       action cell is indented 92px against nothing. */
    .table-stack td[data-label=""] { display: block; }
    .table-stack td[data-label=""]::before { content: none; }
  }
