/* Licence manager / purchase / checkout / sign-in pages - split out of style.css. */

.text-warning {
  margin: 1px;
    margin-top: 5px;
    padding: 5px;
    border: 1px dashed #f89a2d;
    background-color: #f89a2d12;
}
/* ----------------------
   ---- Payments page 
   ---------------------- 
*/

#licenceagreement {
	padding: 5px;
}


body.light .card {
    background: #c1c1c1;
}


.card {
	background: #222;
	max-width: 550px;
  padding: 15px;
  margin: 20px auto;
}

.card-body {
  flex: none;
  padding: 0.5rem;
}

.licence-ops {
  margin: 40px auto;
}

.licence-ops .card-body {
    min-height: 100px;
}

.licence-ops .card-footer {
	margin: 10px;
  min-height: 0;
	vertical-align: middle;
}

.licence-ops .card-footer div {
	padding-bottom:15px;
	font-size:24px;
}

.licence-ops ul {
    padding-left: 6.5rem;
    font-size: 18px;
    text-align: left;
}

.licence-ops .small {
    margin-top: -10px;
    margin-bottom: 30px;
    height: 10px;
}

/* Styling for small print */
.licence-ops .card-body p {
	text-align: left;
	font-size: 90%;
	padding-left: 1.5rem;
	padding-top: 1.5rem;
}



/* Licence Manager - each licence is its own direct child of #licence, so it
   gets the existing .tab > div green-bordered-card treatment and takes part
   in #licence.selected's responsive 1/2/3-column grid automatically. The
   label/value pairs inside each card use CSS grid instead of a table
   (stacks on mobile, two columns from 600px up). */
.licence-details {
	display: grid;
	grid-template-columns: 1fr;
	row-gap: 8px;
	margin: 15px 0;
}

.licence-details > div:nth-child(odd) {
	font-weight: bold;
}

.licence-details a {
  word-wrap: anywhere;
}

@media (min-width: 600px) {
	.licence-details {
		grid-template-columns: 135px minmax(0, 1fr);
		column-gap: var(20px);
		row-gap: var(--gridspacing);
	}
}

/* "Using this key with the API" - folded away so a licence card stays the
   size of its neighbours in the grid, but on the page rather than behind a
   docs link, since it is what a customer needs straight after collecting
   their key. */
.api-example {
	margin: 15px 0;
	font-size: 90%;
}

.api-example summary {
	cursor: pointer;
	font-weight: bold;
}

.api-example pre {
	overflow-x: auto;
	padding: 8px 10px;
	margin: 8px 0 4px;
	background: rgba(0, 0, 0, 0.25);
	border-radius: 4px;
}

.api-example code {
	white-space: pre;
	word-break: normal;
}

/* Choosing a Professional size. The same control appears on the pricing
   page's Professional card and again at checkout, so it is styled once. */
.band-picker {
	margin: 10px 0;
}

.band-picker label,
.licence-ops label {
	display: block;
	font-size: 90%;
	opacity: 0.85;
	margin-bottom: 4px;
}

.band-picker select,
.licence-ops select {
	width: auto;
	margin-bottom: 6px;
}


/* ---- Website / App toggle (checkout) ----
   Two large, clearly-separate options rather than a dropdown - this decides
   which of two entirely different fields is asked for next, so it should
   read as a fork in the form, not a setting inside it. */
.platform-toggle {
	display: flex;
	gap: 10px;
	margin: 10px 0 16px;
}

.platform-option {
	position: relative;
	flex: 1 1 0;
	display: block;
	padding: 10px 36px 10px 14px;
	border: 1px solid var(--d-rule, #e6e9ee);
	border-radius: 6px;
	cursor: pointer;
	font-weight: 600;
}

/* The radio itself - stretched invisibly over the whole card rather than
   display:none, so it stays clickable and keyboard-focusable, and clicking
   anywhere on the card (not just the tick) selects it. Not drawn: the tick
   below stands in for it. */
.platform-option input {
	position: absolute;
	inset: 0;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}

.platform-option-text {
	display: block;
}

.platform-option small {
	display: block;
	font-weight: 400;
	opacity: 0.75;
}

/* An empty ring until checked, then a filled tick - one indicator, in one
   place, rather than a browser's own radio dot sitting wherever normal flex
   flow put it. */
.platform-option-tick {
	position: absolute;
	top: 12px;
	right: 12px;
	width: 18px;
	height: 18px;
	border: 1.5px solid var(--d-rule, #e6e9ee);
	border-radius: 50%;
	background: var(--d-bg, #fff);
	box-sizing: border-box;
}

.platform-option:has(input:checked) {
	border-color: var(--d-accent, #1f8b57);
	background: var(--d-accent-wash, rgba(31, 139, 87, .08));
}

.platform-option:has(input:checked) .platform-option-tick {
	border-color: var(--d-accent, #1f8b57);
	background: var(--d-accent, #1f8b57);
}

.platform-option:has(input:checked) .platform-option-tick::after {
	content: "";
	position: absolute;
	left: 5px;
	top: 2px;
	width: 5px;
	height: 9px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

/* The input carries focus but is invisible, so its own default outline
   would land on nothing anyone could see - drawn on the card instead. */
.platform-option:has(input:focus-visible) {
	outline: 2px solid var(--d-accent, #1f8b57);
	outline-offset: 2px;
}

/* A one-line explanation under a label - what the field asks for, without
   putting it in the placeholder where it disappears the moment you type. */
.field-note {
	font-size: 90%;
	opacity: 0.85;
	margin: 2px 0 8px;
}

/* Usage chart card - a direct child of #licence like the licence/buy-another
   cards above, but spans the full row at the 2/3-column breakpoints since a
   chart needs more than a third of the width to be legible. */
.usage-chart-card {
	grid-column: 1 / -1;
}

.usage-chart {
	width: 100%;
}

.usage-chart svg {
	display: block;
	width: 100%;
	height: auto;
}

.usage-chart-empty {
	color: #aaa;
	font-size: 90%;
}

.usage-chart-legend {
	display: flex;
	flex-wrap: wrap;
	gap: var(--gridspacing);
	margin-top: 8px;
	font-size: 90%;
}

.usage-chart-legend-item {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.usage-chart-legend-swatch {
	display: inline-block;
	width: 12px;
	height: 12px;
	border-radius: 2px;
}

/* Super Manager dashboard - a compact card per licence, much denser than
   the licence-manager cards so many fit on screen at once. */
.usage-rank-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
	gap: var(--gridspacing);
	margin: var(--spacing) 0;
}

.usage-rank-card {
	border: 1px solid var(--green);
	border-radius: 8px;
	background-color: #111;
	padding: 8px 10px;
	font-size: 90%;
}

.usage-rank-card a {
	display: block;
	font-weight: bold;
	margin-bottom: 4px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.usage-rank-figures.exceeded {
	color: red;
}

.pagination {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--gridspacing);
	margin: var(--spacing) 0;
}

#licenceagreement {
    border: 1px solid #aaa;
    font-size: 12px;
    overflow-y: scroll;
    height: 350px;
    background-color: #222;
    padding: 10px;
}

body.light #licenceagreement {
    background-color: beige;
}

#licenceagreement h3 {
    font-size: 14px;
}

#licenceagreement h2 {
    font-size: 15px;
}



/* --------------------
   - Licence manager  -
   -------------------- */

.loader {
  display: none;
  border: 10px solid #222; /* Light grey */
  border-top: 10px solid #28a745; /* Blue */
  border-radius: 50%;
  width: 40px;
  height: 40px;
  margin: 20px auto;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

#free-signup {
  margin-bottom: 40px;
}

#licence.selected {
  display: grid;
  grid-template-columns: 100%;
  grid-column-gap: var(--gridspacing);
  grid-row-gap: var(--gridspacing);
}

/* Moved here from style.css - has to live in the same file as the bare #licence.selected/
   .licence-ops rules it overrides. Equal specificity resolves by which file loads last on
   the page, not by which one is wrapped in a media query - see the same note in api.css. */
@media (min-width: 768px) {
  #licence.selected {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 990px) {
  .licence-ops {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    column-gap: 25px;
    row-gap: 25px;
  }

  /* .card carries `margin: 20px auto`, and an auto inline margin on a grid
     item makes it shrink to its content and centre in the track instead of
     filling it. The effect is invisible on a card whose text happens to be
     wide and obvious on one whose text is not, so a column of cards ends up
     with ragged edges - Essential came out 327px against fxTeX's 383px in the
     same column. The track already does the positioning here. */
  .licence-ops > .card {
    margin-inline: 0;
  }

  /* The plan being argued for across the top, the rest in a row beneath.

       [============ Professional ============]
       [ fxTeX ] [ Essential ] [ Enterprise ]

     Professional is not one of four comparable things, so it does not stand
     in the row as though it were: it has twice the feature list of any
     other card and reads far better across the width than down a column.
     The three below are then genuinely comparable - one free, two paid.

     The trial is a link in the banner rather than a fourth card. As a card
     it competed with fxTeX for "the free one": two boxes, both FREE, both
     saying GET STARTED, going to different places.

     Keyed on fxTeX rather than a plan, because fxTeX is the card that is
     absent for signed-in visitors - they see the three plans only, which
     auto-placement already handles. */
  .licence-ops:has(#fxtex-card) #professional-card { grid-column: 1 / span 3; grid-row: 1; }
  .licence-ops:has(#fxtex-card) #fxtex-card        { grid-column: 1; grid-row: 2; }
  .licence-ops:has(#fxtex-card) #essential-card    { grid-column: 2; grid-row: 2; }
  .licence-ops:has(#fxtex-card) #enterprise-card   { grid-column: 3; grid-row: 2; }

  /* The free-signup form replaces the plans when the trial link is clicked,
     so it takes the columns they vacate. fxTeX stays: it is the one thing
     on the page that needs no sign-up. .card caps at 550px, which is right
     for one column and would leave this one stopping short of the two it
     spans. */
  .licence-ops:has(#fxtex-card) #free-signup {
    grid-column: 2 / span 2;
    grid-row: 2;
    max-width: none;
  }

  .licence-ops ul {
    padding-left: 1.5rem;
  }

  #licence.selected {
    grid-template-columns: repeat(3, 1fr);
  }
}

#licence table {
  margin-bottom: var(--spacing);
}

#licence > div > button, #licence form > button {
  display: block;
  width: fit-content;
  margin-top: 5px;
  margin-left: 0;
}

.input-group > input {
  width:250px;
  display: inline-block !important;
}

.input-group > button {
  display: inline-block;
  color:red;
  white-space: nowrap;
  font-size: 140%;
  padding: 0px 7px 4px 7px;
  vertical-align: middle;
}

.licagree {
    display:grid;
    grid-template-columns: 1fr 1fr;
    grid-column-gap: var(--spacing);
    grid-row-gap: var(--gridpacing);
}

/* ============================================================================
   ---- The shared system on the account pages ----
   ============================================================================
   Login, purchase, checkout. They take body.ui - the tokens, type scale, links,
   tables and notes above - and add the pieces the documentation has no use for:
   cards, forms and buttons. Everything these restate was written for the dark
   ground the pages used to sit on: a #222 card is invisible under #262D36 text.
   ============================================================================ */

/* ---- Cards ---- */

body.ui .card {
  background: var(--d-bg);
  border: 1px solid var(--d-rule);
  border-radius: 8px;
  padding: 4px 8px 12px;
  display: flex;
  flex-direction: column;
}

/* The plan you are most likely to want, and the one the page is arguing for. */
body.ui .card#professional-card { border-color: var(--d-accent); }

/* ============================================================================
   ---- Licence manager ----
   The page a customer lands on from their sign-in link. It used to be dark
   with an orange-bordered box; it now takes the same ground, type and table
   treatment as the documentation and the purchase page either side of it.
   ============================================================================ */

/* A red, used only for a licence that has stopped. Deliberately muted - it
   marks something as over, it is not an error. */
body.ui {
  --d-danger:       #b4232a;
  --d-danger-deep:  #8c1a20;
  --d-danger-wash:  rgba(180, 35, 42, .06);
  --d-danger-rule:  rgba(180, 35, 42, .28);
}

body.ui .manager-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 26px;
}

body.ui .manager-head h2 { margin: 0 0 4px; }
body.ui .manager-head p  { margin: 0; color: var(--d-ink-soft); }

/* Reference, not a task: the account number and the organisation it belongs
   to, set quietly at the top right rather than in a bordered box competing
   with the licences. */
body.ui .account-block {
  flex: 0 0 auto;
  text-align: right;
  padding-left: 20px;
  border-left: 2px solid var(--d-rule);
}

body.ui .account-block .account-id {
  margin: 0;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--d-ink-faint);
}

body.ui .account-block .account-id strong {
  font-variant-numeric: tabular-nums;
  color: var(--d-ink);
}

body.ui .account-block .account-org {
  margin: 2px 0 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--d-ink);
}

/* ---- The licence card ---- */
body.ui .licence-card {
  background: var(--d-bg);
  border: 1px solid var(--d-rule);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

body.ui .licence-head {
  padding: 14px 16px 12px;
  background: var(--d-panel);
  border-bottom: 1px solid var(--d-rule);
}

body.ui .licence-head h3 {
  margin: 0;
  font-size: 18px;
  border-bottom: none;
  padding-bottom: 0;
}

body.ui .licence-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 7px 0 0;
}

body.ui .plan-badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 3px;
  background: var(--d-accent-wash);
  color: var(--d-accent-deep);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}

body.ui .licence-status {
  font-size: 13px;
  color: var(--d-ink-soft);
}

/* The facts. A plain table, so it inherits the documentation's row rules and
   label column instead of carrying a grid of its own. */
body.ui .licence-facts {
  width: 100%;
  max-width: none;
  margin: 0;
  font-size: 14px;
}

body.ui .licence-facts th {
  width: 38%;
  background: transparent;
  color: var(--d-ink-soft);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  vertical-align: top;
  padding: 10px 10px 10px 16px;
  white-space: normal;
}

body.ui .licence-facts td {
  padding: 10px 16px 10px 0;
  vertical-align: top;
  word-break: break-word;
}

body.ui .licence-facts tr + tr th,
body.ui .licence-facts tr + tr td { border-top: 1px solid var(--d-rule-soft); }

body.ui .licence-facts code {
  font-size: 13px;
  background: var(--d-rule-soft);
  padding: 2px 6px;
  border-radius: 3px;
  word-break: break-all;
}

body.ui .licence-facts .domain-name { font-weight: 600; }
body.ui .licence-facts .domain-note {
  display: block;
  font-size: 12px;
  color: var(--d-ink-faint);
}

body.ui .licence-facts button.small {
  margin: 4px 0 0 6px;
  padding: 3px 10px;
  font-size: 11.5px;
  border-radius: 3px;
  border: 1px solid var(--d-rule);
  background: var(--d-bg);
  color: var(--d-ink-soft);
  cursor: pointer;
}

body.ui .licence-facts button.small:hover {
  border-color: var(--d-accent);
  color: var(--d-accent-deep);
}

/* "Get licence key" is the one primary action inside the table, and the
   neutral rule above was painting it white-on-white with a hairline border -
   invisible until hovered. Four classes to outrank that rule. */
body.ui .licence-facts button.small.blue {
  background: #1b4b8f;
  border-color: #1b4b8f;
  color: #fff;
}

body.ui .licence-facts button.small.blue:hover {
  background: #163c72;
  border-color: #163c72;
  color: #fff;
}

/* ---- Expired ---- */
body.ui .licence-card.is-expired {
  border-color: var(--d-danger-rule);
  background: var(--d-danger-wash);
}

body.ui .licence-card.is-expired .licence-head {
  background: var(--d-danger-wash);
  border-bottom-color: var(--d-danger-rule);
}

body.ui .licence-card.is-expired .plan-badge {
  background: rgba(180, 35, 42, .1);
  color: var(--d-danger-deep);
}

body.ui .licence-status.is-expired {
  color: var(--d-danger);
  font-weight: 600;
}

/* Where the licence key used to be. Set as prose, not as a value, so it does
   not read like a key that happens to be unusually long. */
body.ui .key-withdrawn {
  color: var(--d-ink-soft);
  font-size: 13px;
  font-style: italic;
}

/* The key row's buttons - "Get licence key" on its own, or "Renew licence
   key" sitting after the key and its Copy. Inline so they sit on the row
   rather than starting a new block under it. */
body.ui .licence-facts form { display: inline; margin: 0; }

/* ---- "Get licence key" failure transcript ----
   Diagnostic, not part of the card's design: plain, monospaced, full width,
   and only present after a failed attempt. */
body.ui .key-debug {
  display: block;
  margin: 10px 0 0;
  border: 1px solid var(--d-rule);
  border-radius: 5px;
  background: var(--d-panel);
  padding: 10px 12px;
}

body.ui .key-debug > summary {
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--d-ink-soft);
}

body.ui .key-debug p {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--d-danger);
}

body.ui .key-debug h6 {
  margin: 10px 0 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--d-ink-faint);
}

body.ui .key-debug pre {
  margin: 0;
  max-width: none;
  padding: 8px 10px;
  background: var(--d-bg);
  font-size: 11.5px;
  line-height: 1.5;
}

body.ui .key-debug pre code { white-space: pre; }
body.ui .key-debug button.small { margin: 8px 6px 0 0; }

/* So it is never mistaken for something the customer is being shown. */
body.ui .admin-only {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 3px;
  background: var(--d-danger-wash);
  color: var(--d-danger);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}

/* ---- Example Key Usage ----
   One subsection per product, so the three do not run together. */
body.ui .api-example h5 {
  margin: 18px 0 6px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--d-ink-soft);
}

body.ui .api-example h5:first-of-type { margin-top: 0; }
body.ui .api-example p { margin: 0 0 8px; font-size: 13.5px; }

/* The section sat flush against the card's edges. Inset it, and give the
   summary the same gutter so the two line up. */
body.ui .api-example > summary { padding: 0 16px; }
body.ui .api-example-body { padding: 14px 16px 4px; }

/* Each snippet in its own positioning context, so the copy button can float
   over the top-right corner rather than sitting on its own line underneath -
   the button acts on the block it sits over, so it reads better attached to
   it than following it. */
body.ui .api-example .code-box {
  position: relative;
  margin: 0 0 6px;
}

body.ui .api-example .code-box pre {
  margin: 0;
  max-width: none;
  /* Room for the button so it never sits over the first line of code. */
  padding-right: 66px;
}

/* A distinct class rather than the site's own .code-copy (used on the
   documentation pages, floating bottom-right): that rule sets "bottom" and
   not "height", so combining it with a "top" here left the button stretched
   to fill the whole box - a 185px-tall button rather than a small one. */
body.ui .api-example .code-copy-key {
  position: absolute;
  top: 8px;
  right: 8px;
  bottom: auto;
  left: auto;
  width: auto;
  height: auto;
  margin: 0;
  padding: 3px 10px;
  border: 1px solid var(--d-rule);
  border-radius: 4px;
  background: var(--d-bg);
  color: var(--d-ink-soft);
  font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: none;
  cursor: pointer;
  transition: background-color .12s ease-in-out, color .12s ease-in-out, border-color .12s ease-in-out;
}

body.ui .api-example .code-copy-key:hover {
  background: var(--d-accent-deep);
  border-color: var(--d-accent-deep);
  color: #fff;
}

/* A line to the fuller write-up, directly under the example it belongs to
   rather than bundled at the end where it would stop naming which snippet it
   was for. */
body.ui .api-example .doc-link {
  margin: 0 0 4px;
  font-size: 12.5px;
}

body.ui .api-example .doc-link a {
  color: var(--d-accent-deep);
  text-decoration: none;
}

body.ui .api-example .doc-link a:hover { text-decoration: underline; }


/* The card's own trailing actions (Renew, Upgrade) need the same gutter -
   they were sitting flush against the edge too. */
body.ui .licence-card > button {
  margin: 14px 16px 16px;
  align-self: flex-start;
}

/* The card puts its last element hard against the bottom edge; the details
   summary is a click target, so give it room to be one. */
body.ui .api-example { margin: 0; padding: 14px 0 16px; border-top: 1px solid var(--d-rule); }


/* ---- Archive ---- */
body.ui .licence-archive {
  grid-column: 1 / -1;
  margin-top: 26px;
  border-top: 1px solid var(--d-rule);
  padding-top: 16px;
}

body.ui .licence-archive > summary {
  cursor: pointer;
  font-size: 14px;
  color: var(--d-ink-soft);
  list-style-position: outside;
}

body.ui .archive-tag {
  display: inline-block;
  margin-right: 6px;
  padding: 2px 9px;
  border-radius: 3px;
  background: var(--d-rule-soft);
  color: var(--d-ink-soft);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}

body.ui .archive-list {
  display: grid;
  gap: 22px;
  margin-top: 18px;
}

@media (min-width: 990px) {
  body.ui .archive-list { grid-template-columns: repeat(3, 1fr); }
}

body.ui .licence-empty {
  grid-column: 1 / -1;
  color: var(--d-ink-soft);
}

/* ---- Tab chrome ----
   The legacy rule ".tab > div, .tab > table" gives every tab panel a black
   ground and a green border - the dark treatment this page has left behind.
   Undo it here, and let each panel carry its own frame instead. */
body.ui .tab > div:not(.data-panel),
body.ui .tab > table:not(.data-table),
body.ui .tab > section:not(.data-panel) {
  border: none;
  border-radius: 0;
  background: none;
  padding: 0;
}

/* Real tabs, not a row of links: each one is a tab-shaped box sitting on a
   rule, and the selected one is cut out of that rule so it joins the panel
   below it. Hovering an unselected tab shows the same shape tinted, which is
   what makes the row readable as tabs before anything is clicked. The green
   "Buy a licence" stays a button - it is the one thing here that is an action
   rather than a view - and sits at the far end, away from the tabs it is not
   one of. */
body.ui .tab-bar {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  text-align: left;
  margin: 0 0 24px;
  border-bottom: 1px solid var(--d-rule);
}

/* :not(.green):not(.blue) is not decoration - it matches the specificity of
   the site-wide "body.ui button:not(.green):not(.blue)" outlined-button rule
   further down this file, which would otherwise repaint every tab as a plain
   button and flatten the selected one. */
body.ui .tab-bar > button:not(.green):not(.blue) {
  margin: 0 0 -1px;   /* sits ON the rule, so it can break it */
  padding: 8px 17px 9px;
  border: 1px solid transparent;
  border-radius: 6px 6px 0 0;
  background: transparent;
  color: var(--d-ink-soft);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
}

body.ui .tab-bar > button:not(.green):not(.blue):hover {
  background: var(--d-rule-soft);
  border-color: var(--d-rule);
  border-bottom-color: transparent;
  color: var(--d-ink-strong);
}

body.ui .tab-bar > button.selected:not(.green):not(.blue) {
  background: var(--d-bg);
  border-color: var(--d-rule);
  /* The notch: same colour as the ground, drawn over the container's rule. */
  border-bottom-color: var(--d-bg);
  color: var(--d-accent-deep);
  /* An accent cap along the top edge, inside the border. */
  box-shadow: inset 0 2px 0 0 var(--d-accent);
}

body.ui .tab-bar > a.button {
  margin: 0 0 6px auto;
  padding: 7px 16px;
  font-size: 14px;
}

/* ---- Panels of records ----
   Transactions and passkeys are both lists of rows, so they get one
   treatment: a framed panel holding a documentation-style table. */
body.ui .data-panel {
  border: 1px solid var(--d-rule);
  border-radius: 8px;
  padding: 18px 20px 20px;
  background: var(--d-bg);
}

body.ui .data-panel > h3 {
  margin: 0 0 4px;
  font-size: 18px;
  border-bottom: none;
  padding-bottom: 0;
}

body.ui .data-lead {
  max-width: var(--d-measure);
  margin: 0 0 16px;
  color: var(--d-ink-soft);
  font-size: 14.5px;
}

body.ui .data-panel > h3 + .data-table,
body.ui .data-panel > h3 + .data-empty { margin-top: 16px; }

body.ui .data-empty {
  margin: 12px 0 16px;
  color: var(--d-ink-soft);
  font-size: 14.5px;
}

body.ui .data-never { color: var(--d-ink-faint); }

/* Full width of its panel - these are ledgers, not the reading-measure
   parameter tables the bare "body.ui table" rule is sized for. */
body.ui .data-table {
  width: 100%;
  max-width: none;
  margin: 0;
}

body.ui .data-table th {
  padding: 9px 14px;
  font-size: 11.5px;
  text-transform: uppercase;
}

body.ui .data-table td {
  padding: 11px 14px;
  vertical-align: middle;
  font-size: 14px;
}

body.ui .data-table tbody tr + tr td { border-top: 1px solid var(--d-rule-soft); }
body.ui .data-table tbody tr:hover td { background: var(--d-rule-soft); }

body.ui .data-table .nowrap { white-space: nowrap; }

/* Money, right-aligned on the decimal point. */
body.ui .data-table th.num,
body.ui .data-table td.num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* The last column is a control, not a value: no label, hugging the edge. */
body.ui .data-table th:last-child,
body.ui .data-table td.row-action {
  width: 1%;
  text-align: right;
  white-space: nowrap;
}

body.ui .data-table .row-action .small,
body.ui .data-table .row-action a.small {
  display: inline-block;
  margin: 0;
  padding: 4px 11px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
  border-radius: 3px;
  border: 1px solid var(--d-rule);
  background: var(--d-bg);
  color: var(--d-ink-soft);
  text-decoration: none;
  cursor: pointer;
}

body.ui .data-table .row-action .small:hover {
  border-color: var(--d-accent);
  color: var(--d-accent-deep);
  background: var(--d-bg);
}

body.ui .data-panel > .button.green {
  display: inline-block;
  margin: 18px 0 0;
}

/* Two panels stacked in one tab - you, then your organisation. */
body.ui #contact .data-panel + .data-panel { margin-top: 22px; }

/* ---- Contact / organisation forms ----
   Fields pair up on a wide screen and stack on a narrow one, inside the same
   measure the rest of the page reads at. */
body.ui .detail-form {
  max-width: 640px;
  margin-top: 16px;
}

body.ui .detail-form .field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 18px;
}

body.ui .detail-form .field {
  flex: 1 1 240px;
  display: flex;
  flex-direction: column;
  margin: 0 0 14px;
}

body.ui .detail-form .field-short { max-width: 220px; }

body.ui .detail-form label {
  margin-bottom: 5px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--d-ink-soft);
}

body.ui .detail-form input,
body.ui .detail-form textarea {
  width: 100%;
  font-size: 14.5px;
}

body.ui .detail-form textarea { min-height: 96px; line-height: 1.5; resize: vertical; }

/* Read-only, and it should look it rather than looking broken: the field note
   underneath says who to ask. */
body.ui .detail-form input:disabled {
  background: var(--d-panel);
  color: var(--d-ink-soft);
  border-color: var(--d-rule);
  cursor: not-allowed;
}

body.ui .detail-form .field-note {
  margin: -4px 0 16px;
  font-size: 12.5px;
  color: var(--d-ink-soft);
}

body.ui .detail-form > button { margin-top: 4px; }

@media (max-width: 680px) {
  /* The header stacks, so the account block is no longer in a right-hand
     column and should stop pretending to be. */
  body.ui .account-block {
    text-align: left;
    padding: 0 0 0 14px;
    margin-top: 6px;
  }

  body.ui .data-panel { padding: 16px 14px 18px; }

  body.ui .data-table th,
  body.ui .data-table td { padding-left: 8px; padding-right: 8px; }

  body.ui .data-table .row-action .small,
  body.ui .data-table .row-action a.small { padding: 4px 8px; }

  /* Five columns do not fit a phone. The organisation is already named at
     the top of the page, and on the ledger it is the same value in every
     row, so it is the one that goes. */
  body.ui .data-table.ledger th:nth-child(2),
  body.ui .data-table.ledger td:nth-child(2) { display: none; }

  /* Rather than shrink the labels until they are unreadable. */
  body.ui .tab-bar { overflow-x: auto; }
}

/* ---- Plan cards ----
   A tinted header band carrying the plan's name and the product it is about,
   a list of what you get, and the price pinned to the bottom. Scoped to
   cards that have a head, so the free-signup form sharing this grid keeps
   the plain card treatment. */
body.ui .licence-ops .card:has(.card-head) {
  padding: 0;
  position: relative;
}

body.ui .licence-ops .card-head {
  /* Rounds its own top corners, rather than the card clipping them with
     overflow:hidden - which would also have clipped any tooltip that needs
     to escape the card. Inset by the card's 1px border so the tint does not
     show outside it. */
  border-radius: 7px 7px 0 0;
  background: var(--d-panel);
  border-bottom: 1px solid var(--d-rule);
  padding: 16px 14px 13px;
}

body.ui .licence-ops .card-head h2 {
  margin: 0 0 3px;
}

body.ui .licence-ops .card:has(.card-head) .card-body {
  padding: 15px 16px 6px;
  min-height: 0;
}

/* The footer is three fixed rows - price, note, button - rather than a stack
   that closes up when a part is missing. Without it the four cards align
   only by accident: Essential carries a VAT line and the others do not, Sandbox
   adds "/ 30 days" to its price, so every card put its button at a
   different height. The rows are placed explicitly, so a card with no note
   leaves row two empty instead of pulling its button up into it. */
body.ui .licence-ops .card:has(.card-head) .card-footer {
  margin: auto 0 0;
  padding: 6px 16px 18px;
  display: grid;
  grid-template-rows: minmax(46px, auto) minmax(26px, auto) auto;
  align-content: end;
}

/* The price, sitting on the baseline of its row so a one-line price and a
   two-line one still start their buttons at the same height. */
body.ui .licence-ops .card:has(.card-head) .card-footer > div {
  grid-row: 1;
  align-self: end;
  padding-bottom: 0;
}

body.ui .licence-ops .card:has(.card-head) .card-footer > p {
  grid-row: 2;
  margin: 0;
}

body.ui .licence-ops .card:has(.card-head) .card-footer > .button {
  grid-row: 3;
  /* Capped and centred rather than full width. These cards went from a
     quarter of the page to a third when Sandbox left, and a button that
     fills one is 350px of green - louder than the price above it. All
     three take the same width so the row still reads as a set. */
  width: 100%;
  max-width: 200px;
  justify-self: center;
  margin: 0;
}

/* Ticks rather than squares: every line in these lists is something you get,
   and a tick says that where a bullet only separates. Overrides the site's
   orange square marker. */
body.ui .licence-ops ul li:before {
  content: "\2713";
  color: var(--d-accent);
  font-weight: 700;
  font-size: 1em;
  width: 1.3em;
  margin-left: -1.3em;
  padding-top: 0;
}

body.ui .licence-ops ul { padding-left: 1.5rem; }

body.ui .licence-ops ul li ul li:before {
  content: "\25aa";
}

/* ---- The recommended plan, across the top ----
   Four bands: what it is, two columns of what you get, and what it costs.
   The last is sized to its content and the feature columns share what is
   left, so the price never wraps and the bullets take the slack. */
body.ui .licence-ops .plan-banner {
  /* .card caps at 550px, which is a column's worth. This one is the page. */
  max-width: none;
  display: grid;
  grid-template-columns: minmax(180px, 0.9fr) minmax(0, 1.25fr) minmax(0, 1.35fr) minmax(175px, auto);
  gap: 0 26px;
  align-items: start;
  padding: 20px 22px;
  background: var(--d-accent-wash);
  border-color: var(--d-accent);
}

body.ui .licence-ops .plan-banner h2 {
  margin: 10px 0 2px;
  font-size: 30px;
}

body.ui .licence-ops .plan-banner .card-strapline {
  margin: 0 0 8px;
  font-size: 15px;
}

/* The intro column stretches so the trial link can sit on the banner's
   bottom-left corner, diagonally opposite the price. */
body.ui .licence-ops .plan-banner-intro {
  display: flex;
  flex-direction: column;
  align-self: stretch;
}

body.ui .licence-ops .plan-banner-trial {
  margin: auto 0 0;
  padding-top: 12px;
  font-size: 13.5px;
}

body.ui .licence-ops .plan-banner-trial a {
  color: var(--d-accent-deep);
  font-weight: 600;
}

body.ui .licence-ops .plan-banner-tagline {
  margin: 0;
  font-size: 14px;
  color: var(--d-ink-soft);
}

/* A pill, not the full-width bar it was when this card stood in a column. */
body.ui .licence-ops .plan-banner .card-ribbon {
  display: inline-block;
  /* The intro is a flex column so the trial link can sit at its foot, and a
     flex child stretches by default - which turned this pill into a bar the
     width of the column. It hugs its text. */
  align-self: flex-start;
  margin: 0;
  padding: 5px 12px;
  border-radius: 4px;
  background: var(--d-accent-deep);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The whole banner reads left, as the mockup has it: the title block, the
   two feature lists and the trial link all share one left edge, so the eye
   runs straight down it. Only the price column on the far right centres.

   It was previously half and half - the heading and strapline forced left
   while the tagline and trial link inherited the page's `center` class - so
   nothing in the column lined up with anything else. */
body.ui .licence-ops .plan-banner-intro,
body.ui .licence-ops .plan-banner-intro h2,
body.ui .licence-ops .plan-banner-intro p,
body.ui .licence-ops .plan-banner-features,
body.ui .licence-ops .plan-banner-features p { text-align: left; }

body.ui .licence-ops .plan-banner-features ul { margin: 0; }

/* The authors picker. Its label inherited body type and a 23.8px
   line-height into a box that rendered 10px tall, which left 3px between
   the label and the select and 6px of the select's own margin hanging below
   the column. Sized and spaced explicitly: clear of the note above, close
   to the control it names, and nothing trailing underneath. */
body.ui .licence-ops .plan-banner-features label {
  display: block;
  margin: 16px 0 6px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--d-ink-soft);
}

body.ui .licence-ops .plan-banner-features select {
  margin: 0;
}

/* The education exemption sits in the list but is a caveat, not a feature,
   so it loses the tick and takes the small print's weight. */
body.ui .licence-ops .plan-banner-features li.is-note {
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--d-ink-soft);
}

body.ui .licence-ops .plan-banner-features li.is-note:before {
  content: "*";
  color: var(--d-ink-soft);
}

/* Right-hand band: the price at the top, its button at the foot of the
   banner - diagonally opposite the trial link, so the two things you can
   act on sit on the same line at the bottom of the box. The column has to
   stretch for that; .plan-banner aligns its children to the start. */
body.ui .licence-ops .plan-banner .card-footer {
  margin: 0;
  padding: 0;
  text-align: center;
  align-self: stretch;
  display: flex;
  flex-direction: column;
}

body.ui .licence-ops .plan-banner .card-footer .button {
  display: block;
  width: 100%;
  margin: auto 0 0;
}

@media (max-width: 1100px) {
  body.ui .licence-ops .plan-banner {
    grid-template-columns: 1fr 1fr;
    gap: 16px 26px;
  }
}

/* ---- Tooltips ----
   A term whose detail is not worth a line of its own: the trigger carries
   the text in data-tooltip and this draws it. Pure CSS, shown on hover and
   on keyboard focus, so it is not mouse-only.

   Two attribute names because both are in use in the markup. */
[data-tooltip],
[data-tooltip-html] {
  position: relative;
  cursor: help;
  border-bottom: 1px dotted var(--d-ink-faint);
}

[data-tooltip]::after,
[data-tooltip-html]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;

  width: max-content;
  max-width: 240px;
  padding: 8px 10px;
  border-radius: 6px;

  background: var(--d-ink-strong);
  color: #fff;
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  white-space: normal;

  opacity: 0;
  visibility: hidden;
  transition: opacity .12s ease;
  pointer-events: none;   /* never steals the pointer from what is underneath */
}

[data-tooltip-html]::after { content: attr(data-tooltip-html); }

/* The little arrow, drawn as a rotated corner of the same colour. */
[data-tooltip]::before,
[data-tooltip-html]::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 4px);
  left: 50%;
  z-index: 20;
  width: 10px;
  height: 10px;
  transform: translateX(-50%) rotate(45deg);
  background: var(--d-ink-strong);
  opacity: 0;
  visibility: hidden;
  transition: opacity .12s ease;
  pointer-events: none;
}

[data-tooltip]:hover::after,    [data-tooltip]:focus-visible::after,
[data-tooltip]:hover::before,   [data-tooltip]:focus-visible::before,
[data-tooltip-html]:hover::after,  [data-tooltip-html]:focus-visible::after,
[data-tooltip-html]:hover::before, [data-tooltip-html]:focus-visible::before {
  opacity: 1;
  visibility: visible;
}


/* ---- Help bar ----
   Full width under the plans, for anyone the four cards have not decided
   for. */
body.ui .plan-help {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 28px 0 10px;
  padding: 14px 18px;
  background: var(--d-accent-wash);
  border: 1px solid var(--d-rule);
  border-radius: 8px;
  text-align: left;
}

body.ui .plan-help p {
  margin: 0;
  flex: 1 1 auto;
  font-size: 14px;
  color: var(--d-ink-soft);
}

body.ui .plan-help p strong { color: var(--d-ink); }

body.ui .plan-help .plan-help-icon {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--d-accent);
  color: #fff;
  font-weight: 700;
  font-style: italic;
  font-size: 15px;
  line-height: 26px;
  text-align: center;
}

body.ui .plan-help .button { flex: 0 0 auto; margin: 0; }

@media (max-width: 700px) {
  body.ui .plan-help { flex-wrap: wrap; }
}

/* Under each plan's name, the product it is actually about - "fxTeX Server",
   "fxTeX Server + fxEditor". The tiers are a ladder of products rather than
   sizes of one thing, and the h2 alone cannot say which is which. */
body.ui .card .card-strapline {
  margin: 0 0 10px;
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--d-accent);
}

body.ui .card h2 {
  font-size: 19px;
  margin: 14px 0 4px;
  padding-bottom: 0;
  border-bottom: none;
  text-align: center;
}

/* Pushes the price and its button to the bottom edge, so a row of plans lines
   its calls to action up however uneven the feature lists above them are. */
body.ui .card .card-body { flex: 1 1 auto; }
body.ui .card .card-footer { margin-top: auto; }

body.ui .licence-ops ul {
  padding-left: 1.4rem;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--d-ink);
}
body.ui .licence-ops ul li { margin-bottom: 5px; }
body.ui .licence-ops ul li:before { color: var(--d-accent); }

body.ui .licence-ops .card-body p {
  font-size: 14px;
  padding-left: 0;
  color: var(--d-ink-soft);
}

/* An exemption or caveat under a plan's feature list, tied to a * in one of
   the bullets. Quieter than the list and not a bullet itself, so it reads as
   a note on the plan rather than another thing you get. */
/* `.card-body p` above is more specific than a bare .card-footnote would be,
   so the class is qualified to out-weigh it - otherwise the note inherits the
   body's 14px and stops reading as small print. */
body.ui .licence-ops .card-body p.card-footnote {
  margin: 12px 0 4px;
  padding: 0 2px;
  font-size: 12.5px;
  line-height: 1.5;
  text-align: left;
  color: var(--d-ink-soft);
}

/* The price. Tabular figures so a column of plans aligns on the decimal. */
body.ui .licence-ops .card-footer div {
  font-size: 27px;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--d-ink-strong);
  font-variant-numeric: tabular-nums;
  padding-bottom: 12px;
}

body.ui .licence-ops .card-footer p {
  font-size: 12.5px;
  color: var(--d-ink-soft);
  margin-top: 12px;
}

/* Footnote markers are the smallest text on the page, so they need the most
   contrast, not the least: --d-ink-faint is 2.8:1 on white. */
body.ui sup { color: var(--d-ink-soft); }
body.ui .text-warning {
  border: 1px solid #e3b778;
  background-color: #fdf6ec;
  color: #7a4c12;
  border-radius: 5px;
  padding: 8px 12px;
}

/* The licence text sits in a scrolling panel that was given a #222 fill for the
   dark page. On a light one it is dark ink on a dark ground. Same panel, light. */
body.ui #licenceagreement {
  background-color: var(--d-panel);
  border: 1px solid var(--d-rule);
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.6;
  padding: 18px 22px;
}
body.ui #licenceagreement h2 {
  font-size: 15px;
  margin: 20px 0 6px;
  padding-bottom: 0;
  border-bottom: none;
}
body.ui #licenceagreement h2:first-child { margin-top: 0; }

/* ---- Sign-in ---- */
/* Its own grid rather than .licence-ops, which is the pricing layout: three
   columns with min-heights sized for plan feature lists. */

body.ui .auth-lede { color: var(--d-ink-soft); margin-bottom: 26px; }

body.ui .auth-ops {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
  /* min() rather than max-width: the section has no horizontal padding of its
     own, so on a narrow screen the cards otherwise run edge to edge. */
  width: min(100% - 32px, 720px);
  margin: 0 auto 48px;
}

@media (min-width: 720px) {
  body.ui .auth-ops { grid-template-columns: 1fr 1fr; gap: 22px; }
}

body.ui .auth-ops .card {
  max-width: none;
  margin: 0;
  padding: 22px 24px 20px;
}

/* The form is the card's only child, so it has to carry the column layout for
   the body/footer split inside it to behave like the other card's. */
body.ui .auth-form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}

body.ui .auth-ops .card-body {
  padding: 0;
  min-height: 0;
  flex: 1 1 auto;
}

body.ui .auth-ops .card-footer {
  padding: 0;
  margin: 18px 0 0;
  min-height: 0;
}

body.ui .auth-ops h2 {
  margin: 0 0 6px;
  font-size: 18px;
  text-align: left;
}

body.ui .auth-ops p {
  margin: 0 0 14px;
  font-size: 14.5px;
  color: var(--d-ink-soft);
  text-align: left;
}

body.ui .auth-ops label {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--d-ink-soft);
  margin-bottom: 5px;
}

body.ui .auth-ops input { max-width: none; margin: 0; }

body.ui .auth-ops .button { width: 100%; }

/* Rendered on every load and usually empty; without this it is an outlined
   blank box taking up a line of the card. */
body.ui .text-warning:empty { display: none; }

