/* Funding Metrics components. Loaded after tokens.css. Every color, space, radius, shadow and size is a
   token; type sizes and weights come from the type scale, which the static checks hold them to; what is
   left is structural (a border width, a scale, an opacity). No color is written here directly. */

.fm { font-family: var(--font-sans); font-size: 17px; line-height: 1.47; color: var(--fg); -webkit-font-smoothing: auto; }
.fm *, .fm *::before, .fm *::after { box-sizing: border-box; }
.fm-tnum { font-variant-numeric: tabular-nums; }
/* The components set display; keep the hidden attribute stronger than that. */
.fm [hidden], .fm[hidden] { display: none !important; }
/* Words only a screen reader hears, such as the pause between an alert's title and its detail. */
.fm-visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* The keyboard focus ring on everything focusable. is-focus forces it in previews. */
.fm :focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Page: one centered column inside the side gutters. A single-task page (a form, an upload, an offer)
   adds fm-page--task to hold the column to the running-text measure. */
.fm-page { width: 100%; max-width: var(--container-max); margin: 0 auto; padding: var(--space-12) var(--space-6); }
.fm-page--task { max-width: calc(var(--measure) + 2 * var(--space-6)); }
/* A row of actions. Below the one breakpoint its buttons stack at full width. */
.fm-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }

/* Button */
.fm-btn {
  font-family: var(--font-sans); font-size: 17px; font-weight: 500; line-height: 1.2;
  min-height: var(--control-height); padding: 0 var(--space-5);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  border-radius: var(--radius-sm); border: 1px solid transparent; cursor: pointer;
  text-decoration: none; white-space: normal; text-align: center;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 150ms cubic-bezier(0.28, 0, 0.22, 1), border-color 150ms cubic-bezier(0.28, 0, 0.22, 1), transform 150ms cubic-bezier(0.28, 0, 0.22, 1);
}
.fm-btn--primary { background: var(--accent); color: var(--accent-on); }
.fm-btn--secondary { background: var(--bg); color: var(--fg); border-color: var(--border-control); }
.fm-btn--link { background: none; color: var(--fg); padding: 0 var(--space-1); margin-inline-start: calc(-1 * var(--space-1)); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
/* The negative margin lines the link's text up with the text above it; the padding keeps room for the focus ring. */
.fm-btn--block { display: flex; width: 100%; }
/* Compact: a secondary action inside a row (Replace, Remove). Smaller text, the same 44px target. */
.fm-btn--compact { font-size: 14px; padding: 0 var(--space-4); }
/* Hover only where a pointer can hover: after a tap on a phone it would stay stuck. */
@media (hover: hover) and (pointer: fine) {
  .fm-btn--primary:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--accent-hover); }
  .fm-btn--secondary:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--surface); border-color: var(--accent); }
  .fm-btn--link:hover:not(:disabled):not([aria-disabled="true"]) { text-decoration-thickness: 2px; }
}
.fm-btn--primary.is-hover { background: var(--accent-hover); }
.fm-btn--secondary.is-hover { background: var(--surface); border-color: var(--accent); }
.fm-btn--primary:active:not(:disabled):not([aria-disabled="true"]), .fm-btn--primary.is-active { background: var(--accent-active); }
.fm-btn.is-focus { outline: 2px solid var(--focus); outline-offset: 2px; }
.fm-btn:disabled, .fm-btn[aria-disabled="true"] { opacity: 0.4; cursor: not-allowed; }
/* Busy: the request is on its way. The label says what is happening, a bar runs along the bottom edge,
   and taps pass through so the request cannot go twice. Pair it with aria-disabled="true" and a
   role="status" line; a busy button keeps its full strength. */
.fm-btn[aria-busy="true"] { position: relative; overflow: hidden; opacity: 1; pointer-events: none; }
.fm-btn[aria-busy="true"]::after { content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 2px; background: currentColor; opacity: 0.35; }
/* Motion only for people who have not asked for less: the press scale and the moving busy bar.
   Color changes stay for everyone. */
@media (prefers-reduced-motion: no-preference) {
  .fm-btn--primary:active:not(:disabled):not([aria-disabled="true"]), .fm-btn--primary.is-active,
  .fm-btn--secondary:active:not(:disabled):not([aria-disabled="true"]), .fm-btn--secondary.is-active { transform: scale(0.98); }
  .fm-btn[aria-busy="true"]::after { width: 40%; opacity: 0.7; animation: fm-busy 1100ms linear infinite; }
}
@keyframes fm-busy { from { transform: translateX(-100%); } to { transform: translateX(250%); } }

/* A secondary line under a control: the reason next to a disabled button, the status of a busy one. */
.fm-help { margin: 0; font-size: 14px; line-height: 1.45; color: var(--muted); }

/* Link inside running text (a note, a footer). A button that navigates uses fm-btn--link. */
.fm-link { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
@media (hover: hover) and (pointer: fine) {
  .fm-link:hover { text-decoration-thickness: 2px; }
}

/* Field (text and amount inputs) */
.fm-field { display: grid; gap: var(--space-2); align-content: start; }
.fm-field__label { font-size: 14px; font-weight: 500; line-height: 1.35; color: var(--fg); }
.fm-field__input {
  font-family: var(--font-sans); font-size: 17px; line-height: 1.3; color: var(--fg);
  min-height: var(--control-height); padding: 0 var(--space-3); width: 100%;
  border: 1px solid var(--border-control); border-radius: var(--radius-sm); background: var(--bg);
}
.fm-field__input--amount { font-variant-numeric: tabular-nums; }
.fm-field__input.is-focus { outline: 2px solid var(--focus); outline-offset: 2px; }
/* Locked: a value under review stays readable and focusable, and cannot be edited. */
.fm-field__input[readonly] { background: var(--surface); }
.fm-field__input:disabled { opacity: 0.4; cursor: not-allowed; background: var(--surface); }
.fm-field__help { font-size: 14px; line-height: 1.45; color: var(--muted); }
.fm-field--error .fm-field__input { border: 2px solid var(--danger); padding: 0 calc(var(--space-3) - 1px); }
.fm-field--error .fm-field__help { color: var(--danger-ink); }

/* Alert */
/* Alert: a white card with neutral words. The status lives in a round badge around its icon, whose shape
   also differs by status, so the color never carries the meaning alone. */
.fm-icon { display: block; width: var(--icon-size); height: var(--icon-size); flex: none; }
.fm-alert { display: grid; grid-template-columns: var(--badge-size) minmax(0, 1fr); column-gap: var(--space-3); padding: var(--space-4) var(--space-5) var(--space-4) var(--space-4); background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-md); font-size: 14px; line-height: 1.45; color: var(--fg-2); }
.fm-alert__badge { width: var(--badge-size); height: var(--badge-size); border-radius: var(--radius-pill); border: 1px solid transparent; display: grid; place-items: center; }
/* The words start level with the badge: half the badge less half a line. Where 1lh is unknown, they align to its top. */
.fm-alert__body { display: grid; gap: var(--space-1); padding-top: calc((var(--badge-size) - 1lh) / 2); }
.fm-alert__title { font-weight: 600; color: var(--fg); }
/* An action sits inside the detail sentence and never breaks across lines. */
.fm-alert .fm-link { white-space: nowrap; }
.fm-alert--info .fm-alert__badge { background: var(--accent-soft); border-color: var(--border); color: var(--fg); }
.fm-alert--success .fm-alert__badge { background: var(--success-soft); border-color: var(--success-line); color: var(--success-ink); }
.fm-alert--warning .fm-alert__badge { background: var(--warning-soft); border-color: var(--warning-line); color: var(--warning-ink); }
.fm-alert--danger .fm-alert__badge { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger-ink); }

/* Pill */
.fm-pill { display: inline-flex; align-items: center; gap: var(--space-1); font-size: 12px; font-weight: 500; line-height: 1.4; padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill); border: 1px solid transparent; white-space: nowrap; font-variant-numeric: tabular-nums; }
.fm-pill--term { color: var(--highlight-ink); background: var(--highlight-soft); border-color: var(--highlight-line); }
.fm-pill--success { color: var(--success-ink); background: var(--success-soft); border-color: var(--success-line); }
.fm-pill--warning { color: var(--warning-ink); background: var(--warning-soft); border-color: var(--warning-line); }
/* Neutral: a figure that is not a state, such as the ISO's commission. */
.fm-pill--neutral { color: var(--fg); background: var(--bg); border-color: var(--border); }
.fm-pill strong { font-weight: 600; }

/* Offer card. The card is a size container so the hero amount can step down on a card too narrow for
   a seven-figure amount at 40px; everywhere else it stays 40px. */
.fm-offer { background: var(--surface); border-radius: var(--radius-md); padding: var(--space-5); display: grid; gap: var(--space-3); container-type: inline-size; }
.fm-offer__top { display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.fm-offer__kicker { font-size: 12px; font-weight: 500; line-height: 1.4; color: var(--muted); }
.fm-offer__amount { margin: 0; font-size: 40px; font-size: min(40px, 13.5cqi); font-weight: 600; line-height: 1.05; letter-spacing: -0.015em; color: var(--fg); }
.fm-offer__payback { margin: 0; font-size: 14px; line-height: 1.45; color: var(--fg-2); }
.fm-offer__payback strong { font-weight: 600; color: var(--fg); font-variant-numeric: tabular-nums; }
.fm-offer__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--border-soft); margin: 0; }
.fm-offer__grid--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.fm-offer__grid dt { font-size: 12px; font-weight: 500; line-height: 1.4; color: var(--muted); }
.fm-offer__grid dd { margin: var(--space-1) 0 0; font-size: 17px; font-weight: 500; line-height: 1.3; font-variant-numeric: tabular-nums; }
.fm-offer__fee { font-size: 14px; line-height: 1.45; color: var(--muted); font-variant-numeric: tabular-nums; margin: 0; }
.fm-offer__actions { display: grid; gap: var(--space-3); margin-top: var(--space-2); }

/* File upload: one slot per document. The native file input is stretched over the drop zone, so a
   click, a tap, the keyboard and a dropped file all reach it with no script; the zone paints the
   state and the focus ring. Replace and Remove sit after the zone, never inside it. */
.fm-upload-note { margin: 0; font-size: 14px; line-height: 1.45; color: var(--fg-2); max-width: var(--measure); }
.fm-upload { display: grid; gap: var(--space-2); align-content: start; }
.fm-upload__head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.fm-upload__title { font-size: 14px; font-weight: 500; line-height: 1.35; color: var(--fg); }
.fm-upload__optional { font-size: 12px; font-weight: 500; line-height: 1.4; color: var(--muted); }
.fm-upload__zone {
  position: relative; display: grid; align-content: center; justify-items: center; gap: var(--space-1);
  min-height: calc(var(--control-height) * 2); padding: var(--space-4); text-align: center;
  border: 1px dashed var(--border-control); border-radius: var(--radius-sm); background: var(--bg); color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  transition: border-color 150ms cubic-bezier(0.28, 0, 0.22, 1), background-color 150ms cubic-bezier(0.28, 0, 0.22, 1);
}
/* inset -1px covers the zone's border too, so the whole painted box is the target. */
.fm-upload__input { position: absolute; inset: -1px; margin: 0; opacity: 0; cursor: pointer; }
.fm-upload__prompt { display: grid; gap: var(--space-1); }
.fm-upload__action { font-size: 14px; font-weight: 500; line-height: 1.35; }
.fm-upload__choose { text-decoration: underline; text-underline-offset: 3px; }
.fm-upload__touch { display: none; }
.fm-upload__hint { font-size: 14px; line-height: 1.45; color: var(--muted); }
.fm-upload__file { font-size: 14px; font-weight: 500; line-height: 1.35; color: var(--success-ink); overflow-wrap: anywhere; }
.fm-upload__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.fm-upload__error, .fm-upload__help { margin: 0; font-size: 14px; line-height: 1.45; }
.fm-upload__error { color: var(--danger-ink); }
.fm-upload__help { color: var(--muted); }
/* No drag promise on a touch screen: the zone reads "Choose a file". */
@media (pointer: coarse) {
  .fm-upload__fine { display: none; }
  .fm-upload__touch { display: inline; }
}
@media (hover: hover) and (pointer: fine) {
  .fm-upload__zone:hover { border-color: var(--accent); }
}
/* Drag over: the page's script adds it on dragenter and removes it on dragleave and drop. */
.fm-upload__zone.is-dragover { border-style: solid; border-color: var(--accent); background: var(--accent-soft); }
/* Keyboard focus lands on the transparent input; the zone draws the ring. is-focus forces it in previews. */
.fm-upload__zone:has(.fm-upload__input:focus-visible), .fm-upload__zone.is-focus { outline: 2px solid var(--focus); outline-offset: 2px; }
@supports not selector(:has(*)) {
  .fm-upload__zone:focus-within { outline: 2px solid var(--focus); outline-offset: 2px; }
}
/* Attached (the browser has the file) and Uploaded (the server confirmed it) look the same; the pill's
   word tells them apart. */
.fm-upload--attached .fm-upload__zone {
  border-style: solid; border-color: var(--success-line); background: var(--success-soft);
  min-height: var(--control-height); padding: var(--space-3) var(--space-4); justify-items: start; text-align: left;
}
.fm-upload--error .fm-upload__zone { border: 2px solid var(--danger); padding: calc(var(--space-4) - 1px); }
.fm-upload--error .fm-upload__input { inset: -2px; }
.fm-upload--disabled .fm-upload__zone { opacity: 0.4; }
.fm-upload--disabled .fm-upload__input { cursor: not-allowed; }
/* Several files in one slot (supporting documents): each attached file on its own row. */
.fm-upload__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.fm-upload__item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
  border: 1px solid var(--success-line); border-radius: var(--radius-sm); background: var(--success-soft);
}
.fm-upload__item .fm-upload__file { min-width: 0; }

/* The one breakpoint. Media queries cannot read custom properties, so 640px is written here. */
@media (max-width: 639px) {
  .fm-page { padding: var(--space-8) var(--space-4); }
  .fm-page--task { max-width: none; }
  .fm-actions { flex-direction: column; width: 100%; }
  .fm-actions > .fm-btn { width: 100%; }
}
