/*
 * Boise Civic Trust — shared interface components.
 * Borders over shadows; restraint over decoration.
 */

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--button-pad-y) var(--button-pad-x);
  border-radius: var(--button-radius);
  border: 1px solid transparent;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  background: none;
  transition:
    background-color var(--motion-fast) var(--ease-standard),
    border-color var(--motion-fast) var(--ease-standard),
    color var(--motion-fast) var(--ease-standard);
}

/* The press: buttons physically give, one pixel down. Instant — a
   state, not an animation. */
.btn:active:not(:disabled) {
  transform: translateY(1px);
}

.btn-primary {
  background: var(--bct-deep-green);
  color: var(--bct-warm-ivory);
  border-color: var(--bct-deep-green);
}

/* Hover asserts a rule, never a color swap alone: an inner Ivory
   hairline inside the raised green. */
.btn-primary:hover:not(:disabled) {
  background: var(--bct-green-raised);
  box-shadow: inset 0 0 0 1px rgba(230, 224, 213, 0.4);
}

.btn-secondary {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-border-strong);
}

/* The border thickens to a 2px rule without moving the label. */
.btn-secondary:hover:not(:disabled) {
  border-color: currentColor;
  box-shadow: inset 0 0 0 1px currentColor;
}

/* High-significance moments only. Not the default donation button. */
.btn-accent {
  background: var(--bct-civic-gold);
  color: var(--bct-deep-green);
  border-color: var(--bct-civic-gold);
}

/* Gold stays gold; the ink asserts around it. */
.btn-accent:hover:not(:disabled) {
  border-color: var(--bct-deep-green);
  box-shadow: inset 0 0 0 1px var(--bct-deep-green);
}

.btn-quiet {
  background: transparent;
  color: var(--color-text-secondary);
  border-color: transparent;
  text-transform: none;
  letter-spacing: var(--tracking-normal);
  padding: var(--space-1) var(--space-2);
}

.btn-quiet:hover:not(:disabled) {
  color: var(--color-text);
}

/* On dark (Deep Green) surfaces. */
.on-dark .btn-primary,
.btn-primary.on-dark {
  background: var(--bct-warm-ivory);
  color: var(--bct-deep-green);
  border-color: var(--bct-warm-ivory);
}

.on-dark .btn-primary:hover:not(:disabled),
.btn-primary.on-dark:hover:not(:disabled) {
  background: var(--bct-warm-ivory);
  box-shadow: inset 0 0 0 1px rgba(28, 43, 36, 0.4);
}

.on-dark .btn-secondary,
.btn-secondary.on-dark {
  color: var(--color-dark-text);
  border-color: var(--color-dark-border);
}

.on-dark .btn-secondary:hover:not(:disabled),
.btn-secondary.on-dark:hover:not(:disabled) {
  border-color: currentColor;
  box-shadow: inset 0 0 0 1px currentColor;
}

/* Disabled keeps its label legible — text labels for every state.
   The dashed rule reads "not currently available", never "broken". */
.btn:disabled {
  cursor: not-allowed;
  background: var(--color-surface);
  border: 1px dashed var(--color-border-strong);
  color: var(--color-text-secondary);
  box-shadow: none;
}

.on-dark .btn:disabled {
  background: transparent;
  border-color: var(--color-dark-border);
  color: var(--color-dark-text-secondary);
}

/* ---- Status chips ----
   Compact, pill-shaped, always textual. Never color-only. */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: var(--chip-pad);
  border-radius: var(--chip-radius);
  border: 1px solid var(--color-border);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-text-secondary);
  background: transparent;
  white-space: nowrap;
}

.chip-neutral {
  background: var(--status-neutral-bg);
}

.chip-active {
  background: var(--status-active-bg);
  color: var(--color-success);
  border-color: rgba(53, 95, 73, 0.4);
}

.chip-attention {
  background: var(--status-attention-bg);
  color: var(--color-accent-strong);
  border-color: rgba(142, 115, 62, 0.45);
}

.chip-danger {
  background: var(--status-danger-bg);
  color: var(--color-danger);
  border-color: rgba(122, 56, 47, 0.4);
}

.chip-idea {
  border-style: dashed;
}

/* Interactive chips (map filters, amount presets, scope tabs):
   fine-bordered pills with room under the finger. Pressed state is a
   Deep Green fill with an Ivory label — polarity, not hue, carries
   the state. Hover/press behavior lives in interactions.css. */
.filter-chip,
.amount-chip {
  cursor: pointer;
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: 0.375rem 0.875rem;
}

.filter-chip.is-active,
.amount-chip.is-active {
  background: var(--bct-deep-green);
  border-color: var(--bct-deep-green);
  color: var(--bct-warm-ivory);
}

/* ---- Panels and rules ---- */

.panel {
  background: var(--panel-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.panel-pad {
  padding: var(--panel-pad);
}

.frame {
  border: var(--rule-strong);
  border-radius: var(--radius-sm);
}

.rule-above {
  border-top: var(--rule);
  padding-top: var(--space-4);
}

.rule-gold {
  border: 0;
  border-top: 2px solid var(--color-accent);
  width: var(--space-8);
  margin: var(--space-4) 0;
}

/* ---- Forms ---- */

.field {
  margin-bottom: var(--space-5);
}

.field > label {
  display: block;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-institutional);
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin-bottom: var(--space-2);
}

.field .field-help {
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
  margin: var(--space-1) 0 var(--space-2);
}

/* Inline field error: exact, adjacent, announced (set through
   setFieldError; linked to its control via aria-describedby). */
.field .field-error {
  font-size: var(--text-sm);
  color: var(--color-danger);
  margin: var(--space-1) 0 0;
}

.field [aria-invalid='true'] {
  border-color: var(--color-danger);
}

.field input[type='text'],
.field input[type='search'],
.field input[type='email'],
.field input[type='password'],
.field input[type='number'],
.field input[type='date'],
.field input[type='datetime-local'],
.field input[type='url'],
.field select,
.field textarea {
  width: 100%;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: var(--input-radius);
  padding: var(--input-pad);
  font-family: var(--font-ui);
  color: var(--color-text);
}

.field ::placeholder {
  color: var(--color-text-faint);
  opacity: 1;
}

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

/* Selects drop the browser chrome; the caret is a fine Deep Green
   stroke drawn from the brand's geometry. */
.field select {
  appearance: none;
  padding-right: 2.25rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%231C2B24' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 10px 6px;
}

/* Focus is a 2px Deep Green rule asserted inside the field — the
   border plus a matching inner hairline. No glow. */
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-color: var(--bct-deep-green);
  box-shadow: inset 0 0 0 1px var(--bct-deep-green);
}

.field-error {
  color: var(--color-danger);
  font-size: var(--text-sm);
  margin-top: var(--space-1);
}

fieldset {
  border: var(--rule);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
  margin: 0 0 var(--space-5);
}

legend {
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-institutional);
  text-transform: uppercase;
  color: var(--color-text-secondary);
  padding: 0 var(--space-2);
}

.choice-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.choice-row label {
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
}

/* Checks and radios sit on the label's first text line, in brand ink. */
input[type='checkbox'],
input[type='radio'] {
  accent-color: var(--bct-deep-green);
}

.choice-row input[type='checkbox'],
.choice-row input[type='radio'] {
  flex: none;
  width: 1.0625rem;
  height: 1.0625rem;
  margin: 2px 0 0;
}

/* ---- Toast / notice ---- */

.notice {
  border: var(--rule-strong);
  border-left: 3px solid var(--color-text);
  background: var(--color-surface);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
}

.notice-danger {
  border-left-color: var(--color-danger);
}

.notice-success {
  border-left-color: var(--color-success);
}

.notice-attention {
  border-left-color: var(--color-accent-strong);
}

/* Notices settle in from below and leave by fading (toast.ts adds
   .is-leaving before removal). Reduced motion collapses both to
   instant via the global rule in base.css. */
@media (prefers-reduced-motion: no-preference) {
  .notice {
    animation: notice-in var(--motion-medium) var(--ease-entrance);
    transition:
      opacity var(--motion-medium) var(--ease-standard),
      transform var(--motion-medium) var(--ease-standard);
  }

  .notice.is-leaving {
    opacity: 0;
    transform: translateY(4px);
  }

  @keyframes notice-in {
    from {
      opacity: 0;
      transform: translateY(8px);
    }
  }
}

.toast-region {
  position: fixed;
  bottom: var(--space-4);
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(28rem, calc(100vw - 2rem));
}

/* Persistent live regions inside the stack; empty ones take no room. */
.toast-region .toast-live {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* ---- Progress (funding) ----
   A measured line, not a gamified bar. */

.progress-line {
  position: relative;
  height: 4px;
  background: var(--color-surface-strong);
  border-radius: 0;
}

.progress-line > span {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--bct-deep-green);
}

.progress-line.progress-complete > span {
  background: var(--color-accent-strong);
}

/* ---- Definition rows (records) ---- */

.record-row {
  display: grid;
  grid-template-columns: 11rem 1fr;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-2) 0;
  border-bottom: var(--rule);
  font-size: var(--text-sm);
}

.record-row dt {
  color: var(--color-text-secondary);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  font-size: var(--text-xs);
  padding-top: 2px;
}

.record-row dd {
  margin: 0;
}

@media (max-width: 40rem) {
  .record-row {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }
}

/* ---- Form error summary (audit F-023) ----
   A focusable role="alert" panel: the heading states the job, each
   entry links to its field. Rendered by core/form-summary. */

.form-summary-host:empty {
  display: none;
}

.form-summary {
  border: var(--rule-strong);
  border-left: 3px solid var(--color-danger);
  background: var(--color-surface);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-5);
}

.form-summary:focus {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

.form-summary-heading {
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-institutional);
  text-transform: uppercase;
  color: var(--color-danger);
  margin: 0 0 var(--space-2);
}

.form-summary-list {
  margin: 0;
  padding-left: var(--space-5);
  font-size: var(--text-sm);
}

.form-summary-list li {
  margin-bottom: var(--space-1);
}

.form-summary-list a {
  color: var(--color-danger);
  text-decoration: underline;
}

/* ---- Report flow: remembered evidence + geolocation (F-012, F-002) ---- */

.report-remembered-list {
  margin: var(--space-2) 0 0;
  padding-left: var(--space-5);
  font-size: var(--text-sm);
}

.report-locate-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.evidence-progress {
  margin: var(--space-2) 0 var(--space-4);
}

/* ---- Drawer snap states (audit F-005) ----
   Desktop never sees the control; the side panel is unchanged. On
   narrow screens the bottom sheet holds two states — full (the
   existing sheet) and peek (title and summary over the map) — toggled
   by the handle button, which also accepts a vertical swipe. */

.drawer-snap {
  display: none;
}

@media (max-width: 760px) {
  .drawer-snap {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 44px;
    padding: var(--space-2);
    border: 0;
    border-bottom: var(--rule);
    background: transparent;
    cursor: pointer;
    touch-action: none;
  }

  .drawer-snap-bar {
    width: var(--space-8);
    height: 4px;
    border-radius: var(--radius-pill);
    background: var(--color-border-strong);
  }

  .drawer.is-peek {
    height: clamp(9rem, 42vh, 16rem);
    align-self: flex-end;
  }

  /* Touch targets in the drawer meet 44px (audit F-017). */
  .drawer-close {
    min-width: 44px;
    min-height: 44px;
  }

  .drawer .btn {
    min-height: 44px;
  }

  .drawer input[type='file'] {
    min-height: 44px;
  }

  .drawer .choice-row input[type='checkbox'],
  .drawer .choice-row input[type='radio'] {
    width: 1.375rem;
    height: 1.375rem;
  }

  .drawer .choice-row label {
    display: flex;
    min-height: 44px;
    align-items: center;
  }

  .form-summary-list a {
    display: inline-block;
    padding: var(--space-2) 0;
  }
}

/* ---- Forced colors (Windows High Contrast) ----
   Active states and primary actions keep a system-color identity
   instead of resisting the user's palette. */

@media (forced-colors: active) {
  .chip.is-active,
  .filter-chip.is-active {
    background: SelectedItem;
    color: SelectedItemText;
    border-color: SelectedItemText;
    forced-color-adjust: none;
  }

  .btn-primary {
    background: ButtonFace;
    color: ButtonText;
    border: 1px solid ButtonText;
    forced-color-adjust: none;
  }

  .btn-primary:focus-visible {
    outline: 2px solid Highlight;
  }
}

/* ---------------------------------------------------------------------------
   Help tooltips (core/tooltip.ts): plain-language hints that a
   non-technical operator can reach by hover or keyboard focus.
   --------------------------------------------------------------------------- */

.help-tooltip {
  position: absolute;
  z-index: 80;
  max-width: 20rem;
  padding: 0.45rem 0.6rem;
  border-radius: 6px;
  background: #1c2b24;
  color: #f4efe5;
  font-size: 0.82rem;
  line-height: 1.35;
  box-shadow: 0 6px 18px rgb(28 43 36 / 0.28);
  pointer-events: none;
}

.help-tooltip::after {
  content: '';
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
}

.help-tooltip[data-placement='above']::after {
  top: 100%;
  border-top-color: #1c2b24;
}

.help-tooltip[data-placement='below']::after {
  bottom: 100%;
  border-bottom-color: #1c2b24;
}

.help-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15rem;
  height: 1.15rem;
  margin-left: 0.35rem;
  padding: 0;
  border: 1px solid #b9c6bc;
  border-radius: 50%;
  background: #fdfbf7;
  color: #4a4c47;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  cursor: help;
  vertical-align: middle;
}

.help-hint:hover,
.help-hint:focus-visible {
  border-color: #b89a5a;
  color: #1c2b24;
}

@media (prefers-reduced-motion: no-preference) {
  .help-tooltip {
    animation: help-tooltip-in 0.12s ease-out;
  }
}

@keyframes help-tooltip-in {
  from {
    opacity: 0;
  }
}
