/* ===== forms_html (HTML form, scoped) =====
   The Forms screen. Loaded eagerly from anvil.yaml native_deps.head_html.

   SCOPE. .fm-page is the form's own adopted root — it was already the only
   top-level element in the template, so no wrapper was added. Screen rules are
   wrapped :where(.fm-page), which contributes zero specificity and so cannot
   change which rule wins.

   WHAT STAYS BARE, AND WHY.
   * The three rules whose SUBJECT is .fm-page: the root rule and its two
     @media padding steps. :where(.fm-page) .fm-page would need a .fm-page
     inside a .fm-page and would match nothing, silently, leaving the page
     padding unable to respond to the window width.
   * .fm-page, .fm-summary and its [data-theme="dark"] twin: half the selector
     is the root, half is portaled out of it.
   * .fm-summary, .fm-summary-row, .fm-summary-label, .fm-summary-value: the
     summary node is NEVER inside .fm-page. fmBuildSummary creates a detached
     div.fm-summary and Python hands it to px_form_alert_dom, which mounts it
     in #px-modal-portal, a sibling of main's content slot. A :where(.fm-page)
     ancestor would silently unstyle every discrepancy and conversation review
     dialog, and no test would catch it.

   HEAD-LINK ORDER. This asset is a head <link>, so it loads BEFORE the
   dependency's theme, which px_theme appends to <head> at startup. Two rules
   would lose a specificity tie on document order and are written one class
   heavier so they win: .fm-card against .px-card's box-shadow, and .fm-card-body against
   .px-card-body's padding. The .fm-card-body @media (max-width: 600px) copy is
   doubled IDENTICALLY — a media query adds no specificity of its own, so a
   doubled base rule would otherwise beat an undoubled phone copy at every
   width and a phone would render the desktop padding.

   NO DESIGNER GATE. Nothing here hides content until JavaScript runs: every
   initially-hidden block uses the HTML `hidden` attribute in the markup, and
   .fm-card[hidden] / .fm-section[hidden] only restore `display: none` against
   `display: flex`. .fm-select-wrap { display: none } is a width rule, revealed
   by the @media (max-width: 700px) block. So this screen carries no live class.
   The one place the canvas and the browser differ is the three form panels: the
   template ships all three WITHOUT `hidden` so each one's anvil:name intro
   block is selectable and draggable, and bootstrap's first statement
   (fmSelectForm) hides the two that are not selected. The canvas therefore
   shows all three stacked, which is what makes them editable.

   theme/assets/theme.css is not edited by this rollout, and no rule is written
   for .themed-scrollbar — that class is the shared dependency's. */

/* Forms screen.

   PRIMITIVES COME FROM THE SHARED DEPENDENCY. The buttons (px-btn), the
   text boxes and dropdowns (px-input / px-select), the busy overlay
   (px-loading-*) and the page title (px-page-title / px-subtitle) are all
   painted by the estate theme, which loads before this block. What is left
   here is only what this screen genuinely adds: the accent contract, the
   directory tabs, the card, the tappable check rows and the layout.

   ACCENT. Sky #0369a1. Rose was the suggested pick, but this screen puts
   danger red on every field error and on the refusal banner, and an accent
   a shade away from the colour that means "this is wrong" is the one thing
   an audit form cannot afford. Sky is unclaimed by any other screen's
   --accent and sits well clear of both the red errors and the green
   success toast. */
/* The summary rides along because it is portaled into the px modal,
   outside .fm-page, where the contract would otherwise not reach. */
.fm-page,
.fm-summary {
  --accent: #0369a1;
  --accent-hover: #075985;
  --accent-subtle: rgba(3, 105, 161, 0.12);
  --px-loading-accent: #0369a1;
}

[data-theme="dark"] .fm-page,
[data-theme="dark"] .fm-summary {
  --accent: #38bdf8;
  /* Dark ink on a light-blue fill; white on #38bdf8 is unreadable. */
  --accent-text: #0f172a;
  --accent-hover: #7dd3fc;
  --accent-subtle: rgba(56, 189, 248, 0.15);
  --px-loading-accent: #38bdf8;
}

.fm-page {
  width: 100%;
  display: flex;
  flex-direction: column;
  padding: 24px 32px;
  /* .fm-page IS the flex item of main's content mount: without
     flex: 1 0 auto it shrinks inside that scrolling column. position: relative is what pxEnsureOverlayAnchor would
     otherwise write inline at the first pxShowLoading. */
  position: relative;
  flex: 1 0 auto;
}

/* theme.css gives .px-screen-root height: 100% and overflow-y: auto. main's
   content mount has a definite height, so those would make .fm-page its own
   scroller instead of the mount, changing which element scrolls, which
   scrollbar is themed, and where the pinned loading overlay sits. Two classes
   beat theme.css's one, so the mount stays the scroller. */
.fm-page.px-screen-root {
  height: auto;
  overflow-y: visible;
}

/* One readable column, centred. A data-entry form spread across a wide
   monitor is harder to check than one that stays the width of the eye. */
:where(.fm-page) .fm-shell {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* --- Header --- */
:where(.fm-page) .fm-title-block {
  display: flex;
  flex-direction: column;
}

/* --- Form directory: underline tabs on wide screens, a dropdown on narrow
   ones ---
   Both controls are always in the DOM and always carry the same options;
   exactly one is ever displayed, and a single JS function keeps the two in
   step so the screen behaves identically whichever one the operator used.
   The switch itself is at 700px and is pinned there by the suite. */
:where(.fm-page) .fm-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  border-bottom: 2px solid var(--px-border);
}

:where(.fm-page) .fm-tab {
  appearance: none;
  background: transparent;
  border: none;
  border-bottom: 3px solid transparent;
  margin-bottom: -2px;
  padding: 11px 20px;
  font-family: var(--px-font);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--px-text-muted);
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}

:where(.fm-page) .fm-tab:hover {
  color: var(--px-text-primary);
}

:where(.fm-page) .fm-tab:focus-visible {
  outline: none;
  color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: var(--px-radius-sm);
}

:where(.fm-page) .fm-tab[aria-selected="true"] {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

:where(.fm-page) .fm-select-wrap {
  display: none;
  flex-direction: column;
  gap: 6px;
}

:where(.fm-page) .fm-select-label {
  font-family: var(--px-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--px-text-muted);
}

/* --- Card ---
   Surface comes from the shared .px-card / .px-card-body; local rules keep
   only this card's extra lift, its padding, and the accent-washed head. */
:where(.fm-page) .px-card.fm-card {
  box-shadow: var(--px-shadow-md);
}

:where(.fm-page) .fm-card[hidden] {
  display: none;
}

:where(.fm-page) .fm-card-head {
  padding: 1.1rem 1.5rem;
  border-bottom: 1px solid var(--px-border);
  background: var(--accent-subtle);
}

:where(.fm-page) .fm-card-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  color: var(--px-text-primary);
}

:where(.fm-page) .fm-card-intro {
  margin: 5px 0 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--px-text-secondary);
}

:where(.fm-page) .px-card-body.fm-card-body {
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

:where(.fm-page) .fm-block {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

:where(.fm-page) .fm-sec-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--px-text-primary);
  margin: 0;
}

:where(.fm-page) .fm-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

:where(.fm-page) .fm-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 200px;
  min-width: 0;
}

:where(.fm-page) .fm-row-single .fm-field {
  flex: 0 1 320px;
}

:where(.fm-page) .fm-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--px-text-primary);
}

/* Extras only. The border, radius, background and focus ring all come from
   the shared .px-input / .px-select. */
:where(.fm-page) .fm-input,
:where(.fm-page) .fm-select {
  min-height: 44px;
}

:where(.fm-page) .fm-textarea {
  min-height: 116px;
  line-height: 1.5;
  resize: vertical;
  /* The operator's line breaks are part of the report. */
  white-space: pre-wrap;
}

:where(.fm-page) .fm-input:disabled,
:where(.fm-page) .fm-select:disabled,
:where(.fm-page) .fm-textarea:disabled {
  background: var(--px-bg-elevated);
  color: var(--px-text-muted);
  cursor: not-allowed;
}

/* The auditor is not an answer, it is who is answering: a chip, not a box
   the operator can mistake for something they are meant to fill in.
   Self-contained on purpose — it is readonly and skipped by the keyboard
   flow, so it does not borrow the shared input skin or its focus ring. */
:where(.fm-page) .fm-chip {
  width: 100%;
  border: 1px solid var(--px-border);
  border-radius: var(--px-radius-pill);
  background: var(--px-bg-elevated);
  font-family: var(--px-mono);
  font-size: 12.5px;
  color: var(--px-text-secondary);
  padding: 10px 16px;
  min-height: 44px;
  cursor: default;
  outline: none;
}

:where(.fm-page) .fm-help {
  font-family: var(--px-mono);
  font-size: 0.7rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--px-text-muted);
}

:where(.fm-page) .fm-error {
  font-size: 12px;
  font-weight: 600;
  color: var(--px-danger);
}

:where(.fm-page) .fm-error:empty {
  display: none;
}

/* --- Attestation + discrepancy categories ---
   Both are tappable rows: the whole row toggles, and a ticked row is tinted
   so what has been ticked is readable at a glance rather than by hunting
   for a small box. Hover darkens the border only — the category tiles sit
   on the elevated panel, where a background change would be invisible. */
:where(.fm-page) .fm-check-row,
:where(.fm-page) .fm-category {
  border: 1px solid var(--px-border);
  border-radius: var(--px-radius-sm);
  background: var(--px-bg-card);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

:where(.fm-page) .fm-check-row:hover:not(:has(input:disabled)),
:where(.fm-page) .fm-category:hover:not(:has(input:disabled)) {
  border-color: var(--px-border-strong);
}

:where(.fm-page) .fm-check-row:has(input:disabled),
:where(.fm-page) .fm-category:has(input:disabled) {
  cursor: not-allowed;
}

:where(.fm-page) .fm-check-row:has(input:checked),
:where(.fm-page) .fm-category:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-subtle);
}

:where(.fm-page) .fm-check-row input[type="checkbox"],
:where(.fm-page) .fm-category input[type="checkbox"] {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  accent-color: var(--accent);
}

:where(.fm-page) .fm-check-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
}

:where(.fm-page) .fm-check-row input[type="checkbox"] {
  margin: 1px 0 0 0;
}

:where(.fm-page) .fm-check-text {
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--px-text-primary);
}

:where(.fm-page) .fm-category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 10px;
}

:where(.fm-page) .fm-category {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 10px 14px;
  font-size: 13.5px;
  color: var(--px-text-primary);
}

/* The discrepancy branch is a deliberate step, not an afterthought: it is
   set apart on its own panel with an accent edge. */
:where(.fm-page) .fm-section {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  border: 1px solid var(--px-border);
  border-left: 3px solid var(--accent);
  border-radius: var(--px-radius-sm);
  background: var(--px-bg-elevated);
}

:where(.fm-page) .fm-section[hidden] {
  display: none;
}

/* --- Footer --- */
:where(.fm-page) .fm-footer {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  padding-top: 20px;
  border-top: 1px solid var(--px-border);
}

/* Inline spinner while the write is in flight, on the shared button. The
   keyframes are the estate's own pxSpin. */
:where(.fm-page) .fm-submit.is-busy::before {
  content: '';
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: pxSpin 0.7s linear infinite;
}

:where(.fm-page) .fm-form-error {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--px-danger);
  background: var(--px-danger-wash);
  border: 1.5px solid var(--px-danger);
  border-radius: var(--px-radius);
  padding: 12px 16px;
}

:where(.fm-page) .fm-form-error:empty {
  display: none;
}

/* Sit beside the buttons on a wide footer, wrap under them on a narrow
   one; min-width instead of flex-basis so the same rule is right whether
   the footer is a row or, on phones, a column. */
:where(.fm-page) .fm-footer .fm-form-error {
  flex: 1 1 auto;
  min-width: min(260px, 100%);
}

@media (max-width: 900px) {
  .fm-page {
    padding: 16px;
  }
}

@media (max-width: 700px) {
  :where(.fm-page) .fm-tabs {
    display: none;
  }

  :where(.fm-page) .fm-select-wrap {
    display: flex;
  }
}

/* Phone layout: one column, full-width controls, nothing to reach for. */
@media (max-width: 600px) {
  .fm-page {
    padding: 12px 8px;
  }

  :where(.fm-page) .fm-card-head {
    padding: 1rem 1.1rem;
  }

  :where(.fm-page) .px-card-body.fm-card-body {
    padding: 1.1rem;
    gap: 22px;
  }

  :where(.fm-page) .fm-field,
  :where(.fm-page) .fm-row-single .fm-field {
    flex: 1 1 100%;
  }

  :where(.fm-page) .fm-category-grid {
    grid-template-columns: 1fr;
  }

  :where(.fm-page) .fm-section {
    padding: 16px;
  }

  :where(.fm-page) .fm-footer {
    flex-direction: column;
    align-items: stretch;
  }

  :where(.fm-page) .fm-footer .px-btn {
    width: 100%;
    justify-content: center;
  }
}

/* --- Pre-submit discrepancy summary (rendered into a px modal) ---
   Accent comes from the widened contract at the top of this sheet. */
.fm-summary {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 18px;
  border-left: 3px solid var(--accent);
  border-radius: var(--px-radius-sm);
  background: var(--px-bg-elevated);
  font-family: var(--px-font);
  font-size: 13.5px;
  color: var(--px-text-primary);
}

.fm-summary-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.fm-summary-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--px-text-muted);
}

.fm-summary-value {
  /* Notes keep the line breaks the operator typed. */
  white-space: pre-wrap;
  word-break: break-word;
  line-height: 1.5;
}

/* --- Signature pad (Staff Conversation) ---
   A raw canvas, because a signature is drawn, not typed. Everything
   around it is the existing field furniture; only the pad itself and
   its action row are new. */
:where(.fm-page) .fm-sig-wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

:where(.fm-page) .fm-sig-pad {
  display: block;
  width: 100%;
  height: 180px;
  border: 1px solid var(--px-border-strong);
  border-radius: var(--px-radius-sm);
  background: var(--px-bg-card);
  cursor: crosshair;
  /* A finger drag must DRAW, not scroll the screen out from under it. */
  touch-action: none;
}

/* The pad has no disabled attribute of its own, so the lock is a class:
   it must go inert while a write is in flight exactly as the inputs do. */
:where(.fm-page) .fm-sig-locked {
  pointer-events: none;
  opacity: 0.55;
  cursor: not-allowed;
}

:where(.fm-page) .fm-sig-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}

/* --- Evidence files (Staff Conversation) ---
   Each attached file is a chip carrying its name in Drive and its own
   remove button, so a mis-picked file is undone without retyping the
   conversation. */
:where(.fm-page) .fm-file-wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

:where(.fm-page) .fm-file-input {
  font-family: var(--px-font);
  font-size: 13px;
  color: var(--px-text-secondary);
}

:where(.fm-page) .fm-file-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

:where(.fm-page) .fm-file-chips:empty {
  display: none;
}

:where(.fm-page) .fm-file-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 6px 8px 6px 12px;
  border: 1px solid var(--px-border);
  border-radius: var(--px-radius-pill);
  background: var(--px-bg-elevated);
  font-family: var(--px-mono);
  font-size: 12px;
  color: var(--px-text-secondary);
}

:where(.fm-page) .fm-file-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 260px;
}

:where(.fm-page) .fm-file-chip-remove {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--px-text-muted);
  font-size: 15px;
  line-height: 1;
  min-width: 24px;
  min-height: 24px;
  cursor: pointer;
}

:where(.fm-page) .fm-file-chip-remove:hover {
  color: var(--px-danger);
}

:where(.fm-page) .fm-file-chip-remove:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
