/* Octet brand basics for the customer-facing licence pages.
 *
 * SCOPE, deliberately small. This is fonts, colour and box treatment only. The
 * visual system also carries illuminated drop caps, seeded chronograph bands and
 * a motion vocabulary. None of that is here. Those are per-document signatures
 * for outbound material, and a licence dashboard is a tool someone uses, not a
 * document we send them.
 *
 * Tokens are lifted from octet-brand-guidelines: paper and stage neutrals from
 * octet-render-recipes.md, the font stacks from fonts.md, the four gradients
 * from visual-system-card.md.
 */

:root {
  color-scheme: light;

  /* Neutrals. `paper` is the warm ground the system sets everything on; the
     black `stage` is for outbound artwork, not for a page of forms. */
  --paper: #f5f4f0;
  --ink: #111111;
  --ink-soft: #5b5750;
  --ink-faint: #8b867c;
  --card: #ffffff;
  --line: #e2ded4;

  --font-head: 'ABC Daily Slab Mono', 'IBM Plex Mono', 'Courier New', monospace;
  --font-body: 'Stack Sans Text', 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* The four gradients carry meaning, so status colour is not decoration.
     Forest is "proof, the yes". Bloom is "signal, the no". Sunset is "human,
     the who", which is the right register for a claim still waiting on a
     person's app to launch. Surface is "environment, the where". */
  --forest-a: #a0b80a; --forest-b: #4e5d02;
  --bloom-a:  #e18ea3; --bloom-b:  #cf2f1e;
  --sunset-a: #e44d43; --sunset-b: #f9cf80;
  --surface-a: #645139; --surface-b: #5ca6cd;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.55;
}

h1, h2, h3 { font-family: var(--font-head); font-weight: 400; letter-spacing: -0.01em; }
h1 { font-size: 1.75rem; margin: 0 0 0.35rem; }

/* The gradient bar is the system's structural primitive, and bars run alongside
   rather than across. One hairline under the page title is the smallest honest
   use of it: it signs the page without becoming ornament. */
.octet-rule {
  height: 2px; border: 0; margin: 0 0 22px;
  background: linear-gradient(90deg, var(--surface-a), var(--surface-b));
}

code, .mono, .licence-id { font-family: var(--font-mono); }

/* Cards sit as paper-on-paper: white lifted off the warm ground by a hairline,
   no drop shadow. The system prefers a hairline to a shadow. */
.card, form.add { background: var(--card); border: 1px solid var(--line); border-radius: 10px; }

/* The table carries long opaque strings: package names, team ids, 64-char
   certificate digests. Left to itself it either overflows the page or wraps a
   short label like "octet-sdk" mid-word, which reads as broken. So: keep the
   type small, let the identifier column do the wrapping, and let the whole
   table scroll inside its own box on a narrow screen rather than pushing the
   page sideways.

   The identifier column's own wrapping is set per page, not here: /apps
   inserts a <wbr> at every dot and pairs it with overflow-wrap:anywhere, so
   `td.wrap`'s break-all below is the fallback for pages that do not. */
.table-wrap { overflow-x: auto; margin: 18px 0 0; }
table { border-collapse: collapse; width: 100%; font-size: 13.5px; }
th { font-family: var(--font-head); font-weight: 400; font-size: 11px;
     letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-soft);
     white-space: nowrap; }
th, td { border-bottom: 1px solid var(--line); text-align: left; padding: 9px 12px 9px 0; }
td { vertical-align: top; }
/* Everything except the identifier stays on one line. */
td:not(.wrap) { white-space: nowrap; }
td.wrap { white-space: normal; word-break: break-all; }

.pill { display: inline-block; padding: 2px 9px; border-radius: 999px;
        font-size: 12px; font-family: var(--font-mono); letter-spacing: 0.02em; }
.pill.verified { background: #eef3d6; color: var(--forest-b); }
.pill.pending  { background: #fdf0dc; color: #8a5a12; }
.pill.disputed { background: #fbe4e4; color: var(--bloom-b); }
/* Waiting on the CUSTOMER, not on the app (#225). Its own colour because it is
   not a step in the pending -> verified story: an Android prod row with no
   release digest will refuse the release build until someone pastes one in. */
.pill.needs-cert { background: #fdeadb; color: #8a4a12; }

/* Licence state (`license_status`: active | revoked | disabled). The customer
   dashboard used to print this as small grey text beside two real pills, so
   the one status that can stop everything working was the quietest thing in
   the row. Same three palettes again — no new colours. */
.pill.active   { background: #eef3d6; color: var(--forest-b); }
.pill.disabled { background: #efefea; color: #6b6b66; }
/* Sandbox-token state (#197). Same three palettes as the app-status pills above
   so the page stays one system: no new tokens and no new faces. */
.pill.live    { background: #eef3d6; color: var(--forest-b); }
.pill.lapsed  { background: #efefea; color: #6b6b66; }
.pill.revoked { background: #fbe4e4; color: var(--bloom-b); }

button, .btn {
  font-family: var(--font-body); background: var(--ink); color: #fff;
  border: 1px solid var(--ink); border-radius: 7px; padding: 9px 18px;
  font-size: 14px; cursor: pointer;
}
button:hover, .btn:hover { background: #2b2b2b; }

input, select {
  font-family: var(--font-body); background: #fff; color: var(--ink);
  border: 1px solid #cbc6bb; border-radius: 7px; padding: 9px 11px; font-size: 14px;
}
input:focus, select:focus {
  outline: 2px solid var(--surface-b); outline-offset: -1px; border-color: var(--surface-b);
}
input::placeholder { color: var(--ink-faint); }

/* Platform marks. Inline SVG inheriting currentColor, so they sit in text and
   in table cells without a second colour decision. Optically nudged down a
   fraction: both marks read as heavier than the cap height beside them. */
.mark { vertical-align: -0.14em; }
/* The platform mark and its label must not split, but the identifier beside
   them has to be allowed to wrap. A bundle id like com.octetproof.bootstraptest
   is long enough to push a table past its container, and with
   `.table-wrap { overflow-x: auto }` that silently clipped the last column,
   which is where the Revoke button lives (#197). So nowrap applies to the mark
   only, not to the whole cell. */
.plat { white-space: normal; }
.plat .mark { flex: 0 0 auto; }
.plat .wrap { white-space: normal; word-break: break-all; }
.plat .mark { margin-right: 5px; color: var(--ink-soft); }
.with-mark { display: flex; align-items: center; gap: 9px; }
.with-mark select { flex: 1; max-width: 420px; }
.mark-slot { display: inline-flex; width: 15px; justify-content: center; color: var(--ink-soft); }

/* Sandbox token output. Monospace and wrapping, because the token is long and a
   developer has to be able to see they copied all of it. */
.token { font-family: var(--font-mono); font-size: 12px; width: 100%; max-width: 560px;
         border: 1px solid #cbc6bb; border-radius: 7px; padding: 10px; background: #fff;
         color: var(--ink); word-break: break-all; resize: vertical; }
.mint { padding: 20px; margin-top: 24px; }
.mint h3 { margin: 0 0 6px; }

/* Under its own header, not shoved against the table's outer edge. Every `th`
   is left-aligned, so right-aligning the action cell put the only control in
   the table a long way from the word naming it — and `padding-right: 0` pushed
   it a further 12px out, past where every other column ends. It was pinned
   there so an overflow could not hide it; the identifier column wraps now, so
   the tables no longer overflow and it does not need to hide at the edge. */
td.act { white-space: nowrap; }
