/* Niadirect Space: the control vocabulary.
 *
 * Every control here exists in exactly one form. A second variant of a button, a
 * second card treatment, a second way to show a status, is how an institutional
 * interface becomes a generic one, so the set below is deliberately small and
 * nothing outside it is used.
 *
 * VII-3 bans the outlined button and names its replacement directly:
 *   primary   filled accent
 *   secondary filled neutral, from the interactive step of the ramp
 *   tertiary  text with a rule beneath it
 * That trio is the whole affordance ladder. There is no fourth.
 *
 * Two constraints from VII-7 shape how this is written. The floor is Chrome 80
 * at 320px, so no colour function newer than that appears here: a hover state is
 * a translucent white wash laid over whatever the token happens to be, which
 * works on any browser and stays correct when the Operator changes the token.
 * And horizontal rows are grid rather than flex, because grid carried gap four
 * versions before flex did.
 */

/* --------------------------------------------------------------------------
 * Buttons
 * ---------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;             /* 44px: a thumb target, not a mouse target. */
  padding: 0 var(--s4);
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface-interactive);
  color: var(--text-primary);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  text-align: center;
  transition: box-shadow var(--step), opacity var(--step);
  -webkit-tap-highlight-color: transparent;
}

.btn:hover { box-shadow: inset 0 0 0 99rem rgba(255, 255, 255, 0.07); text-decoration: none; }
.btn:active { box-shadow: inset 0 0 0 99rem rgba(0, 0, 0, 0.16); }

/* A disabled control is still a control, and has to look like one.
 *
 * This used to fall back to the card surface, which is the surface most of
 * these buttons sit on: the primary action on the earnings screen became text
 * floating in the middle of a panel, with nothing to say it was a button at
 * all. Unavailable is a state of a thing, not the absence of it, so the shape
 * stays and only the fill and the label lose their strength. */
.btn:disabled,
.btn[aria-disabled="true"] {
  background: var(--surface-elevated);
  color: var(--text-disabled);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
  cursor: not-allowed;
}

.btn-primary { background: var(--accent); color: var(--text-inverse); }
.btn-primary:disabled,
.btn-primary[aria-disabled="true"] {
  background: var(--surface-elevated);
  color: var(--text-disabled);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
}

/* The confirming button inside a dialog, and nowhere else. Solid, in the
 * critical colour, with the dark inverse text the palette carries for exactly
 * this: a colour used at full strength reads as a decision, while the same
 * colour whispered on a dark field reads as an alarm nobody can act on. */
.btn-critical { background: var(--critical-fg); color: var(--text-inverse); }

/* The destructive action as it appears on a page: stated, in its own colour,
 * and deliberately not competing with the work. */
.btn-quiet-critical {
  min-height: 2.75rem;
  padding: 0;
  background: none;
  border: 0;
  color: var(--critical-fg);
  font-size: 0.9375rem;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
}
.btn-quiet-critical:hover { text-decoration: underline; text-underline-offset: 0.2em; }

/* border: 0 first, and it matters. A button carries a border on all four sides
 * from the browser itself, so setting only the bottom one left the other three
 * drawn in the user agent's own colour: the tertiary action appeared inside a
 * rectangle on every screen it was used on. VII-3 bans the outlined button, and
 * this was accidentally shipping one. */
.btn-text {
  min-height: 2.25rem;
  padding: 0 0 0.0625rem 0;
  background: none;
  color: var(--accent);
  border: 0;
  border-radius: 0;
  border-bottom: 1px solid var(--accent);
}
.btn-text:hover { box-shadow: none; opacity: 0.8; }
.btn-text:active { box-shadow: none; }
.btn-text:disabled { background: none; color: var(--text-disabled); border-bottom-color: transparent; }

.btn-block { width: 100%; }
.btn-sm { min-height: 2.25rem; padding: 0 var(--s3); font-size: 0.875rem; }

/* Sized for the pointer, not for the page.
 *
 * The compact button and the language switch are comfortable under a mouse and
 * too small under a thumb: measured at 36px and 32px against the 44px this
 * platform uses everywhere else. "Delete my information" is not a control to
 * make people aim at. Coarse pointer catches a touch laptop as well as a phone;
 * the width condition catches a phone whose browser does not report one. */
@media (max-width: 55.999rem), (pointer: coarse) {
  .btn-sm { min-height: 2.75rem; padding: 0 var(--s4); }
  .switch button { min-height: 2.5rem; padding: 0 var(--s4); }
  .icon-btn { width: 2.75rem; height: 2.75rem; }
}

.btn-busy { color: transparent !important; pointer-events: none; position: relative; }
.btn-busy::after {
  content: "";
  position: absolute;
  width: 1.0625rem;
  height: 1.0625rem;
  border-radius: 50%;
  border: 2px solid var(--text-primary);
  border-top-color: transparent;
  animation: spin 700ms linear infinite;
}
.btn-primary.btn-busy::after { border-color: var(--text-inverse); border-top-color: transparent; }
@keyframes spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
 * Surfaces
 *
 * VII-4: depth is a luminance step, a defined edge and one shadow. The card is
 * attached to the page, never floating above it on nothing.
 * ---------------------------------------------------------------------- */

.card {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: var(--r-lg);
  padding: var(--s4);
  box-shadow: var(--emboss);
}

@media (min-width: 40rem) {
  .card { padding: 1.25rem; }
}

.card-tight { padding: var(--s4); }

.card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
  margin-bottom: var(--s4);
}
.card-head > .btn-text { white-space: nowrap; }

.panel {
  background: var(--surface-elevated);
  border: 1px solid var(--edge);
  border-radius: var(--r-md);
  padding: var(--s4);
  box-shadow: var(--emboss);
}

.rule { height: 1px; background: var(--edge); border: 0; margin: var(--s4) 0; }

/* --------------------------------------------------------------------------
 * Statistics
 *
 * The number is the content. The caption above names it, the line below
 * qualifies it. Nothing else belongs in this block.
 * ---------------------------------------------------------------------- */

.stat { min-width: 0; }
.stat-value {
  font-variant-numeric: tabular-nums;
  font-size: 1.75rem;
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -0.024em;
}
.stat-note { margin-top: var(--s1); }

/* --------------------------------------------------------------------------
 * Badges
 *
 * IV-12: no enum ever reaches a person. Every badge carries wording resolved
 * from the language pack, never a status value with the underscores taken out.
 * ---------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.1875rem 0.5rem 0.1875rem 0.4375rem;
  border-radius: var(--r-sm);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: -0.003em;
  white-space: nowrap;
  background: var(--surface-interactive);
  color: var(--text-primary);
}

/* The mark carries the state; the chip stays neutral. A dot is an indicator
 * rather than text, so it answers to the 3:1 floor, and every one of these
 * clears it against the chip it sits on. */
.badge .dot { margin-right: 0.4375rem; width: 0.375rem; height: 0.375rem; }
.badge-live    .dot { background: var(--success-fg); }
.badge-hold    .dot { background: var(--warning-fg); }
.badge-stopped .dot { background: var(--critical-fg); }
.badge-info    .dot { background: var(--info-fg); }

/* The live dot is the one place the accent reads as a state rather than an
 * action, which VII-2 names explicitly. */
.dot { width: 0.4375rem; height: 0.4375rem; border-radius: 50%; background: currentColor; flex: none; }

/* --------------------------------------------------------------------------
 * Banners
 * ---------------------------------------------------------------------- */

.banner {
  padding: var(--s4);
  border-radius: var(--r-md);
  border: 1px solid var(--edge);
}
.banner-info     { background: var(--info-bg); color: var(--info-fg); }
.banner-warning  { background: var(--warning-bg); color: var(--warning-fg); }
.banner-critical { background: var(--critical-bg); color: var(--critical-fg); }
.banner-success  { background: var(--success-bg); color: var(--success-fg); }
.banner strong { display: block; margin-bottom: var(--s1); }
.banner p { color: inherit; }
.banner .btn-text { color: inherit; border-bottom-color: currentColor; }

/* --------------------------------------------------------------------------
 * Fields
 * ---------------------------------------------------------------------- */

.field { display: block; }
.field + .field { margin-top: var(--s4); }
.field > .t-label { display: block; margin-bottom: var(--s2); }

.input,
.select,
.textarea {
  display: block;
  width: 100%;
  min-height: 2.75rem;
  padding: var(--s2) var(--s3);
  background: var(--surface-interactive);
  color: var(--text-primary);
  border: 1px solid var(--edge);
  border-radius: var(--r-md);
  transition: border-color var(--step);
}

/* text_secondary, not the label colour. The label colour measures 3.37:1 on the
 * control surface and the floor is 4.5; this measures 4.83. A placeholder is
 * read by someone deciding what to type, which is the worst moment to make text
 * hard to see. Gate 26 checks the pair rather than trusting this note. */
.input::placeholder,
.textarea::placeholder { color: var(--text-secondary); opacity: 1; }

.input:focus,
.select:focus,
.textarea:focus { border-color: var(--accent); outline: none; }

.textarea { min-height: 6rem; resize: vertical; line-height: 1.5; }

.select {
  -webkit-appearance: none;
  appearance: none;
  padding-right: var(--s6);
  /* The caret, drawn as a shape rather than assembled from two gradients.
   * VII-3 bans gradients outright and a technique that happens to be a common
   * way of drawing a triangle is still a gradient to the scanner that enforces
   * it. A shape is also what this actually is. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23C8CFDA' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-position: right 1rem center;
  background-size: 0.625rem 0.375rem;
  background-repeat: no-repeat;
}

.field-help  { margin-top: var(--s2); color: var(--text-secondary); font-size: 0.875rem; }
.field-error { margin-top: var(--s2); color: var(--critical-fg); font-size: 0.875rem; }
.input-invalid, .textarea-invalid { border-color: var(--critical-fg); }

/* A number with a hard floor and ceiling, shown beside the box rather than
 * discovered on save. VIII-3: the guardrail protects the Founder from a
 * fat-fingered edit, so it has to be visible before the finger moves. */
.bounds {
  display: flex;
  justify-content: space-between;
  margin-top: var(--s2);
  font-size: 0.8125rem;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

.switch {
  display: inline-grid;
  grid-auto-flow: column;
  background: var(--surface-interactive);
  border-radius: var(--r-md);
  padding: 0.1875rem;
}

.switch button {
  min-height: 2rem;
  padding: 0 var(--s3);
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text-secondary);
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--step), color var(--step);
}
.switch button[aria-pressed="true"] { background: var(--surface-chrome); color: var(--text-primary); }

/* --------------------------------------------------------------------------
 * Lists and tables
 *
 * A list row on a phone becomes a table row on a desk. Both carry the same
 * fields in the same order, so nobody has to relearn the screen.
 * ---------------------------------------------------------------------- */

.list { border-top: 1px solid var(--edge); }

.list-row {
  display: block;
  width: 100%;
  padding: 0.8125rem var(--s3);
  border: 0;
  border-bottom: 1px solid var(--edge);
  background: none;
  text-align: left;
  color: inherit;
}

button.list-row, a.list-row {
  cursor: pointer;
  transition: box-shadow var(--step), background var(--step);
}
button.list-row:hover, a.list-row:hover {
  background: var(--surface-elevated);
  text-decoration: none;
}
button.list-row:active, a.list-row:active { background: var(--surface-chrome); }

/* The current row is stated twice and quietly: a solid accent edge where the
 * eye tracks down the list, and a lift of one step on the ramp. Neither alone
 * survives a glance on a phone in daylight. */
.list-row[aria-current="true"] {
  background: var(--surface-elevated);
  box-shadow: inset 2px 0 0 var(--accent);
}

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.table th {
  padding: var(--s3);
  text-align: left;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  border-bottom: 1px solid var(--edge);
  white-space: nowrap;
}

.table td { padding: var(--s3); border-bottom: 1px solid var(--edge); vertical-align: top; }
.table .right, .right { text-align: right; }
.table tbody tr:last-child td { border-bottom: 0; }

/* --------------------------------------------------------------------------
 * Progress
 *
 * One use only: how much of a campaign's pool is left. It is a proportion of a
 * known total, which is the only thing a bar can honestly say.
 * ---------------------------------------------------------------------- */

.meter { height: 0.375rem; border-radius: var(--r-pill); background: var(--surface-interactive); overflow: hidden; }
.meter > span { display: block; height: 100%; background: var(--accent); width: var(--fill, 0%); transition: width var(--step); }
.meter-low > span { background: var(--warning-fg); }

/* --------------------------------------------------------------------------
 * Empty states
 *
 * One sentence saying what would be here, and one action that would put it
 * there. Never an illustration, never an apology.
 * ---------------------------------------------------------------------- */

.empty { padding: var(--s7) var(--s4); text-align: center; color: var(--text-secondary); }
.empty p { max-width: 26rem; margin: 0 auto var(--s4); }

/* --------------------------------------------------------------------------
 * Dialog
 * ---------------------------------------------------------------------- */

dialog {
  width: min(34rem, calc(100vw - 2rem));
  max-height: calc(100vh - 4rem);
  padding: 0;
  border: 1px solid var(--edge-strong);
  border-radius: var(--r-lg);
  background: var(--surface-elevated);
  color: var(--text-primary);
  box-shadow: var(--shadow);
  overflow: auto;
}
dialog::backdrop { background: rgba(6, 9, 14, 0.72); }
.dialog-body { padding: var(--s5); }
.dialog-actions {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-top: 1px solid var(--edge);
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  flex: none;
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface-interactive);
  color: var(--text-primary);
  cursor: pointer;
  transition: box-shadow var(--step);
}
.icon-btn:hover { box-shadow: inset 0 0 0 99rem rgba(255, 255, 255, 0.07); }

/* --------------------------------------------------------------------------
 * Toast
 *
 * Confirmation of something the person just did, and nothing else. It never
 * carries an error that a screen should be showing in place.
 * ---------------------------------------------------------------------- */

#toast {
  position: fixed;
  left: 50%;
  bottom: 5.5rem;
  z-index: 70;
  max-width: min(30rem, calc(100vw - 2rem));
  padding: var(--s3) var(--s4);
  border-radius: var(--r-md);
  background: var(--surface-elevated);
  border: 1px solid var(--edge-strong);
  box-shadow: var(--shadow);
  transform: translate(-50%, 0.5rem);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--step), transform var(--step);
}
#toast[data-open="true"] { opacity: 1; transform: translate(-50%, 0); }

@media (min-width: 56rem) {
  #toast { bottom: var(--s5); }
}

/* --------------------------------------------------------------------------
 * Photography
 *
 * VII-4: a photograph sits in a defined container at a fixed ratio with no
 * treatment applied. In the reviewer queue it is evidence, and evidence is
 * never tinted, cropped to flatter, or overlaid.
 * ---------------------------------------------------------------------- */

.photo {
  position: relative;
  width: 100%;
  background: var(--surface-chrome);
  border: 1px solid var(--edge-strong);
  border-radius: var(--r-md);
  overflow: hidden;
}
.photo::before { content: ""; display: block; padding-top: 125%; }   /* 4:5, without aspect-ratio */
.photo > * { position: absolute; inset: 0; top: 0; right: 0; bottom: 0; left: 0; }
.photo img { width: 100%; height: 100%; object-fit: cover; }
.photo-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--s4);
  color: var(--text-tertiary);
  font-size: 0.8125rem;
}
