/* ============================================================================
 * Stylesheet for the hand-authored HTMX calculator templates.
 *
 * Plain CSS on purpose. It is served verbatim by Spring from
 * src/main/resources/static, so changing calculator styling needs no frontend
 * build and no Node toolchain, the same way static/vendor/chart.umd.min.js is
 * vendored. The HTMX experiment stays self-contained in the backend.
 *
 * Bootstrap's UTILITY layer is loaded separately from the webjar:
 *   /webjars/bootstrap/5.3.8/dist/css/bootstrap-utilities.min.css
 * Bootstrap's Reboot and component layers are deliberately NOT loaded: these
 * templates render as a fragment inside a Magnolia page shell, so any top-level
 * element selector (html, body, h1-h6, a, table) would restyle the host page.
 * The handful of component classes we actually use are defined below instead,
 * keeping the same class names Bootstrap would have used.
 *
 * Every rule below is either class-based or nested under .ffp-htmx-scope, so
 * nothing here can reach the host page.
 * ==========================================================================*/

/* --- Brand tokens ----------------------------------------------------------
 * Aliased from the Ramsey Design System custom properties, with the literal
 * value as a fallback. When Magnolia's page shell already defines the --rds-*
 * tokens these follow the live design system; standalone (and in local dev)
 * they still render correctly. Declared on the scope class rather than :root
 * so they cannot bleed into the host page.
 * ------------------------------------------------------------------------ */
.ffp-htmx-scope {
  --ffp-white: var(--rds-color-base-white, #ffffff);
  --ffp-gray-10: var(--rds-color-base-gray-10, #f5f7f8);
  --ffp-gray-20: var(--rds-color-base-gray-20, #e8eced);
  --ffp-gray-30: var(--rds-color-base-gray-30, #d5d9db);
  --ffp-gray-40: var(--rds-color-base-gray-40, #b6bec2);
  --ffp-gray-50: var(--rds-color-base-gray-50, #8e999e);
  --ffp-gray-60: var(--rds-color-base-gray-60, #69757a);
  --ffp-gray-70: var(--rds-color-base-gray-70, #495257);
  --ffp-gray-90: var(--rds-color-base-gray-90, #1f2426);
  --ffp-blue-5: var(--rds-color-base-blue-5, #ebf4fa);
  --ffp-blue-8: var(--rds-color-base-blue-8, #d8f1fc);
  --ffp-blue-10: var(--rds-color-base-blue-10, #ade9ff);
  --ffp-blue-30: var(--rds-color-base-blue-30, #00b2f6);
  --ffp-blue-50: var(--rds-color-base-blue-50, #0073b9);
  --ffp-blue-60: var(--rds-color-base-blue-60, #005b98);
  --ffp-blue-80: var(--rds-color-base-blue-80, #003561);
  --ffp-red-5: var(--rds-color-base-red-5, #fcedeb);
  --ffp-red-40: var(--rds-color-base-red-40, #f26552);
  --ffp-red-50: var(--rds-color-base-red-50, #e64b40);
  --ffp-red-60: var(--rds-color-base-red-60, #cc392f);
  --ffp-green-5: var(--rds-color-base-green-5, #eaf8ee);
  --ffp-green-8: var(--rds-color-base-green-8, #d9fae1);
  --ffp-green-50: var(--rds-color-base-green-50, #35bd59);
  --ffp-green-60: var(--rds-color-base-green-60, #24a344);

  --ffp-font: var(--rds-font-family-gibson, canada-type-gibson, Arial, sans-serif);
  --ffp-radius: var(--rds-size-radius-control, 4px);
  --ffp-radius-lg: var(--rds-size-radius-lg, 16px);
  --ffp-ease: cubic-bezier(0.19, 1, 0.22, 1);

  --ffp-shadow-sm: 0 2px 4px 0 rgba(31, 36, 38, 0.08);
  --ffp-shadow-md: 0 4px 16px 0 rgba(31, 36, 38, 0.12);
}

/* ============================================================================
 * Scope root
 * ==========================================================================*/
.ffp-htmx-scope {
  container-type: inline-size;
  font-family: var(--ffp-font);
  color: var(--ffp-gray-90);
}

/* Minimal resets, safely contained by the scope class. These recover the few
 * Reboot behaviours the templates depend on without touching the host page. */
.ffp-htmx-scope *,
.ffp-htmx-scope *::before,
.ffp-htmx-scope *::after {
  box-sizing: border-box;
}

.ffp-htmx-scope h1,
.ffp-htmx-scope h2,
.ffp-htmx-scope h3,
.ffp-htmx-scope h4,
.ffp-htmx-scope p {
  margin: 0;
}

.ffp-htmx-scope button {
  font-family: inherit;
}

.ffp-htmx-scope img {
  max-width: 100%;
  height: auto;
}

.ffp-htmx-scope hr {
  margin: 0;
  border: 0;
}

/* ============================================================================
 * Component layer (same class names Bootstrap would provide)
 * ==========================================================================*/

/* --- Buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  white-space: nowrap;
  padding: 0.75rem 1.25rem;
  border: 1px solid transparent;
  border-radius: var(--ffp-radius);
  background-color: transparent;
  font-family: var(--ffp-font);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 0.3s var(--ffp-ease),
    border-color 0.3s var(--ffp-ease),
    color 0.3s var(--ffp-ease);
}

.btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--ffp-white), 0 0 0 4px var(--ffp-blue-50);
}

.btn:disabled,
.btn.disabled {
  opacity: 0.4;
  pointer-events: none;
}

.btn-primary {
  background-color: var(--ffp-blue-50);
  color: var(--ffp-white);
}
.btn-primary:hover {
  background-color: var(--ffp-blue-60);
  color: var(--ffp-white);
}

.btn-outline-primary {
  border-color: var(--ffp-blue-50);
  color: var(--ffp-blue-50);
}
.btn-outline-primary:hover {
  background-color: rgba(0, 115, 185, 0.1);
  color: var(--ffp-blue-50);
}

/* Transparent until hover, for destructive row actions. */
.btn-ghost-danger {
  color: var(--ffp-red-50);
}
.btn-ghost-danger:hover {
  background-color: rgba(230, 75, 64, 0.1);
  color: var(--ffp-red-50);
}

/* Square icon-only button, sized to match the 42px control height. */
.ffp-btn-icon {
  padding: 13px;
  font-size: 0.875rem;
  line-height: 1;
}

/* Text-only action that reads as a link. */
.ffp-link-btn {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font-family: var(--ffp-font);
  font-size: 1rem;
  font-weight: 400;
  color: var(--ffp-blue-50);
  text-decoration: none;
  cursor: pointer;
}
.ffp-link-btn:hover,
.ffp-link-btn:focus,
.ffp-link-btn:active {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* Bare button used purely as a layout row. */
.ffp-bare-btn {
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: inherit;
  cursor: pointer;
}

/* --- Form controls -------------------------------------------------------- */
.form-control {
  display: block;
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--ffp-gray-60);
  border-radius: var(--ffp-radius);
  background-color: var(--ffp-white);
  color: var(--ffp-gray-90);
  font-family: inherit;
  font-size: 1rem;
}
.form-control::placeholder {
  color: var(--ffp-gray-60);
}
.form-control:focus {
  border-color: var(--ffp-blue-50);
  box-shadow: inset 0 0 0 1px var(--ffp-blue-50);
  outline: none;
}

/* --- Card / surface ------------------------------------------------------- */
.card {
  border-radius: var(--ffp-radius-lg);
  background-color: var(--ffp-white);
  color: var(--ffp-gray-90);
}

/* Bootstrap's shadow utilities live in the utility webjar, but its scale does
 * not match RDS, so the calculator surfaces use the RDS box shadows. */
.shadow-sm {
  box-shadow: var(--ffp-shadow-sm) !important;
}
.shadow {
  box-shadow: var(--ffp-shadow-md) !important;
}

/* --- Alert ---------------------------------------------------------------- */
.ffp-alert {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1rem;
  margin-bottom: 1.5rem;
  border-left: 4px solid;
  border-radius: var(--ffp-radius);
  color: var(--ffp-gray-90);
}
.ffp-alert--danger {
  border-left-color: var(--ffp-red-50);
  background-color: rgba(242, 101, 82, 0.1);
}
.ffp-alert--success {
  border-left-color: var(--ffp-green-50);
  background-color: rgba(53, 189, 89, 0.1);
}

/* ============================================================================
 * Typography
 * ==========================================================================*/
.ffp-title {
  font-family: var(--ffp-font);
  font-weight: 600;
  color: var(--ffp-gray-90);
}
.ffp-title--display {
  font-size: 42px;
  line-height: 1.1;
}
.ffp-title--xxl {
  font-size: 28px;
}
.ffp-title--xl {
  font-size: 1.5rem;
}
.ffp-title--lg {
  font-size: 1.25rem;
}
.ffp-title--md {
  font-size: 1.125rem;
}

.ffp-text {
  font-family: var(--ffp-font);
  font-weight: 400;
  line-height: 1.25;
}
.ffp-text--lg {
  font-size: 1.125rem;
}
.ffp-text--sm {
  font-size: 0.875rem;
}
.ffp-text--muted {
  color: var(--ffp-gray-70);
}
.ffp-text-success {
  color: var(--ffp-green-60);
}

/* ============================================================================
 * Calculator shell
 * ==========================================================================*/
.ffp-shell {
  /* Also a query container, so descendant @container rules measure the form
   * rather than the outer scope div. */
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  max-width: 48rem;
  margin-inline: auto;
  border-radius: var(--ffp-radius-lg);
  background-color: var(--ffp-white);
  color: var(--ffp-gray-90);
}

.ffp-startover-row {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  margin-bottom: 0.5rem;
}

.ffp-section {
  margin: 1rem;
}

/* ============================================================================
 * Category card
 * ==========================================================================*/
.ffp-cat-card {
  border-radius: var(--ffp-radius-lg);
  background-color: var(--ffp-white);
  color: var(--ffp-gray-90);
  padding: 1.5rem;
}

.ffp-cat-card__header {
  display: flex;
  flex-flow: row wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.ffp-cat-card__chevron {
  width: 1rem;
  color: var(--ffp-gray-70);
}

/* ============================================================================
 * Line item row
 * ==========================================================================*/
.ffp-line-item {
  display: flex;
  flex-flow: row wrap;
  gap: 0.25rem;
  align-items: center;
  justify-content: flex-start;
}

/* Hover target that reveals the edit affordance, replacing Tailwind group-hover. */
.ffp-name {
  display: flex;
  flex-flow: row nowrap;
  gap: 0.25rem;
  align-items: center;
  min-width: 0;
  cursor: pointer;
}

.ffp-name__label {
  font-family: var(--ffp-font);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.25;
  text-transform: capitalize;
  min-width: 0;
  overflow-wrap: break-word;
}

.ffp-name__icon {
  flex-shrink: 0;
  padding: 0;
  border: 0;
  background: transparent;
  pointer-events: none;
  color: var(--ffp-gray-50);
}

.ffp-name:hover .ffp-name__icon {
  color: var(--ffp-blue-50);
}

.ffp-name__input {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 15rem;
  border: 0;
  border-bottom: 1px solid var(--ffp-gray-40);
  background: transparent;
  color: var(--ffp-gray-70);
  outline: none;
  cursor: text;
}

.ffp-name__save {
  flex-shrink: 0;
  padding: 0;
  margin-right: 0.5rem;
  border: 0;
  background: transparent;
  color: var(--ffp-green-60);
  cursor: pointer;
}

/* Currency input with a leading dollar glyph. */
.ffp-amount {
  position: relative;
  width: 6rem;
  flex-shrink: 0;
  margin-left: auto;
}

.ffp-amount__icon {
  position: absolute;
  top: 50%;
  left: 0.75rem;
  width: 1rem;
  height: 1rem;
  transform: translateY(-50%);
  pointer-events: none;
  color: var(--ffp-gray-60);
}

.ffp-amount__input {
  height: 42px;
  padding-left: 2.25rem;
}

/* Nested under .ffp-htmx-scope so this beats the ".ffp-htmx-scope hr" reset
 * above (a bare ".ffp-divider" class selector loses that specificity fight,
 * so the border/margin below silently never rendered). */
.ffp-htmx-scope .ffp-divider {
  border-top: 1px solid var(--ffp-gray-40);
  margin-block: 1rem;
}

/* ============================================================================
 * Radio tile
 * ==========================================================================*/
.ffp-radio-tile {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  border: 1px solid var(--ffp-gray-60);
  border-radius: var(--ffp-radius);
  background-color: var(--ffp-white);
  cursor: pointer;
  transition:
    background-color 0.2s var(--ffp-ease),
    border-color 0.2s var(--ffp-ease);
}
.ffp-radio-tile:hover {
  background-color: rgba(0, 115, 185, 0.05);
}

.ffp-radio-tile--selected {
  border-color: var(--ffp-blue-50);
  background-color: rgba(0, 115, 185, 0.05);
}

.ffp-radio-tile__marker {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid var(--ffp-gray-60);
  border-radius: 50%;
  transition: border-color 0.2s var(--ffp-ease);
}
.ffp-radio-tile--selected .ffp-radio-tile__marker {
  border-color: var(--ffp-blue-50);
}

.ffp-radio-tile__dot {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background-color: var(--ffp-blue-50);
  opacity: 0;
  transition: opacity 0.2s var(--ffp-ease);
}
.ffp-radio-tile--selected .ffp-radio-tile__dot {
  opacity: 1;
}

.ffp-radio-tile__label {
  font-size: 1.125rem;
  color: var(--ffp-gray-90);
}

/* ============================================================================
 * Result hero
 * ==========================================================================*/
.ffp-hero {
  border-radius: var(--ffp-radius-lg);
  padding: 1.5rem;
}

.ffp-hero__inner {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: center;
}

.ffp-hero__body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.5rem;
  align-items: center;
  text-align: center;
}

.ffp-hero--positive {
  background-color: var(--ffp-blue-5);
}
.ffp-hero--positive .ffp-hero__amount {
  color: var(--ffp-blue-50);
}
.ffp-hero--negative {
  background-color: var(--ffp-red-5);
}
.ffp-hero--negative .ffp-hero__amount {
  color: var(--ffp-red-60);
}
.ffp-hero--balanced {
  background-color: var(--ffp-green-5);
}
.ffp-hero--balanced .ffp-hero__amount {
  color: var(--ffp-green-60);
}

/* Status pill */
.ffp-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.5rem;
  border-radius: 9999px;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1;
}
.ffp-tag--positive {
  background-color: var(--ffp-blue-5);
  color: var(--ffp-blue-60);
}
.ffp-tag--negative {
  background-color: var(--ffp-red-5);
  color: var(--ffp-red-60);
}
.ffp-tag--balanced {
  background-color: var(--ffp-green-5);
  color: var(--ffp-green-60);
}

.ffp-next-steps__inner {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: center;
}

/* ============================================================================
 * Layout helpers the Bootstrap utility layer does not cover
 * ==========================================================================*/
.ffp-intro-copy {
  max-width: 500px;
  margin-inline: auto;
}

.ffp-img-150 {
  width: 150px;
  height: 150px;
}

.ffp-img-200 {
  width: 200px;
  height: 200px;
}

.ffp-icon-1em {
  width: 1em;
  height: 1em;
}

.ffp-icon-12 {
  width: 12px;
  height: 12px;
}

.ffp-icon-16 {
  width: 1rem;
  height: 1rem;
}

.ffp-question-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
}

.ffp-action-btn {
  width: 100%;
}

/* ============================================================================
 * Spacing / sizing on the original 0.25rem-per-step scale
 *
 * Bootstrap's own spacing utilities stop at .25/.5/1/1.5/3rem, so 0.75rem,
 * 2rem and 2.5rem have no equivalent. These keep ported values exact instead
 * of drifting to the nearest Bootstrap step. Naming mirrors the container
 * layer below, minus the breakpoint infix: .at-gap-8 / .at-md-gap-8.
 * ==========================================================================*/
.at-gap-0 { gap: 0 !important; }
.at-gap-1 { gap: 0.25rem !important; }
.at-gap-2 { gap: 0.5rem !important; }
.at-gap-3 { gap: 0.75rem !important; }
.at-gap-4 { gap: 1rem !important; }
.at-gap-6 { gap: 1.5rem !important; }
.at-gap-8 { gap: 2rem !important; }
.at-gap-12 { gap: 3rem !important; }

.at-p-6 { padding: 1.5rem !important; }
.at-p-8 { padding: 2rem !important; }
.at-p-10 { padding: 2.5rem !important; }
.at-p-12 { padding: 3rem !important; }

.at-mb-0 { margin-bottom: 0 !important; }
.at-mb-1 { margin-bottom: 0.25rem !important; }
.at-mb-2 { margin-bottom: 0.5rem !important; }
.at-mb-4 { margin-bottom: 1rem !important; }
.at-mb-6 { margin-bottom: 1.5rem !important; }
.at-mb-8 { margin-bottom: 2rem !important; }
.at-mb-12 { margin-bottom: 3rem !important; }

.at-mt-0 { margin-top: 0 !important; }
.at-mt-2 { margin-top: 0.5rem !important; }
.at-mt-6 { margin-top: 1.5rem !important; }
.at-mt-8 { margin-top: 2rem !important; }
.at-mt-12 { margin-top: 3rem !important; }

.at-my-2 { margin-block: 0.5rem !important; }
.at-my-4 { margin-block: 1rem !important; }
.at-my-8 { margin-block: 2rem !important; }

.at-w-13 { width: 3.25rem !important; }
.at-w-56 { width: 14rem !important; }
.at-w-72 { width: 18rem !important; }
.at-h-13 { height: 3.25rem !important; }
.at-h-56 { height: 14rem !important; }

/* ============================================================================
 * Container-query responsive layer
 *
 * Bootstrap's responsive utilities (.d-md-none) key off the VIEWPORT, which is
 * wrong here: these calculators are embedded by Magnolia at a width the page
 * decides, not the browser. So the responsive layer is container-driven,
 * using Bootstrap's infix convention: .at-md-d-none.
 *
 * Breakpoints mirror the RDS --breakpoint-* scale: 37.5em / 56.25em / 75em.
 * ==========================================================================*/

/* --- at-sm: 600px -------------------------------------------------------- */
@container (width >= 600px) {
  .at-sm-d-flex { display: flex !important; }
  .at-sm-d-grid { display: grid !important; }
  .at-sm-d-none { display: none !important; }
  .at-sm-flex-row { flex-direction: row !important; }
  .at-sm-flex-row-reverse { flex-direction: row-reverse !important; }
  .at-sm-align-items-start { align-items: flex-start !important; }
  .at-sm-grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .at-sm-grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  .at-sm-col-span-2 { grid-column: span 2 / span 2 !important; }
  .at-sm-col-span-3 { grid-column: span 3 / span 3 !important; }
  .at-sm-gap-6 { gap: 1.5rem !important; }
  .at-sm-mb-4 { margin-bottom: 1rem !important; }
  .at-sm-ms-auto { margin-left: auto !important; }
  .at-sm-w-auto { width: auto !important; }
  .at-sm-text-start { text-align: left !important; }
  .at-sm-fs-3xl { font-size: 1.875rem !important; }

  /* Component responses that were @sm: variants on the Tailwind side. */
  .ffp-section { margin: 2rem; }
  .ffp-title--display { font-size: 60px; }
  .ffp-hero__inner { flex-direction: row-reverse; }
  .ffp-hero__body { align-items: flex-start; text-align: left; }
  .ffp-next-steps__inner { flex-direction: row; }
  .ffp-question-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ffp-action-btn { width: auto; margin-left: auto; }
}

/* --- at-md: 900px -------------------------------------------------------- */
@container (width >= 900px) {
  .at-md-d-flex { display: flex !important; }
  .at-md-d-none { display: none !important; }
  .at-md-flex-row { flex-direction: row !important; }
  .at-md-flex-row-reverse { flex-direction: row-reverse !important; }
  .at-md-flex-nowrap { flex-wrap: nowrap !important; }
  .at-md-flex-fill { flex: 1 1 0% !important; }
  .at-md-flex-shrink-0 { flex-shrink: 0 !important; }
  .at-md-align-items-center { align-items: center !important; }
  .at-md-align-items-start { align-items: flex-start !important; }
  .at-md-justify-content-start { justify-content: flex-start !important; }
  .at-md-col-span-1 { grid-column: span 1 / span 1 !important; }
  .at-md-gap-2 { gap: 0.5rem !important; }
  .at-md-gap-3 { gap: 0.75rem !important; }
  .at-md-gap-6 { gap: 1.5rem !important; }
  .at-md-gap-8 { gap: 2rem !important; }
  .at-md-gap-12 { gap: 3rem !important; }
  .at-md-p-10 { padding: 2.5rem !important; }
  .at-md-p-12 { padding: 3rem !important; }
  .at-md-mb-0 { margin-bottom: 0 !important; }
  .at-md-mb-8 { margin-bottom: 2rem !important; }
  .at-md-mb-12 { margin-bottom: 3rem !important; }
  .at-md-mt-12 { margin-top: 3rem !important; }
  .at-md-my-8 { margin-block: 2rem !important; }
  .at-md-w-72 { width: 18rem !important; }
  .at-md-h-56 { height: 14rem !important; }
}

/* --- at-lg: 1200px ------------------------------------------------------- */
@container (width >= 1200px) {
  .at-lg-d-flex { display: flex !important; }
  .at-lg-d-none { display: none !important; }
  .at-lg-flex-row { flex-direction: row !important; }
  .at-lg-flex-nowrap { flex-wrap: nowrap !important; }
  .at-lg-flex-fill { flex: 1 1 0% !important; }
  .at-lg-flex-none { flex: none !important; }
  .at-lg-flex-shrink-0 { flex-shrink: 0 !important; }
  .at-lg-align-items-start { align-items: flex-start !important; }
  .at-lg-col-span-1 { grid-column: span 1 / span 1 !important; }
  .at-lg-my-8 { margin-block: 2rem !important; }
  .at-lg-w-13 { width: 3.25rem !important; }
  .at-lg-w-56 { width: 14rem !important; }
  .at-lg-h-13 { height: 3.25rem !important; }
}

/* ============================================================================
 * Student Loan Payoff calculator
 * Only the pieces the shared layer above has no equivalent for.
 * ==========================================================================*/

/* Centered column the whole calculator lives in. Not .ffp-shell: this one stays
 * transparent, because the cards inside carry their own white surface and the
 * gaps between them show the host page through. Also the query container the
 * at-sm/at-md/at-lg utilities in the template measure against.
 * 75rem is what the Tailwind build resolved max-w-lg to, because RDS overrides
 * --container-lg to 1200px (it does NOT use Tailwind's stock 32rem). */
.ffp-sl-shell {
  container-type: inline-size;
  max-width: 75rem;
  margin-inline: auto;
}

/* One loan. Also the hook the list's delegated click/input/blur handlers use to
 * map an event target back to its index in the loans array. */
.ffp-sl-row {
  min-width: 0;
}

/* Short blue accent rule under a section heading. */
.ffp-sl-rule {
  width: 3rem;
  border-top: 4px solid var(--ffp-blue-50);
}

/* Round tinted badge holding the graduation-cap glyph on each loan row. */
.ffp-sl-badge {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: var(--ffp-blue-5);
}

.ffp-sl-badge__icon {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--ffp-blue-50);
}

/* Lets a flex child shrink below its content width so a long loan name wraps
 * instead of stretching the row. Bootstrap ships no min-width utility. */
.ffp-sl-min-w-0 {
  min-width: 0;
}

/* Loan name, inline-edit state. .ffp-name__input is sized for a body-copy
 * label; this replaces a 24px blue heading, so it inherits the field behaviour
 * and overrides the type. */
.ffp-sl-name-input {
  max-width: 16rem;
  font-weight: 600;
  font-size: 1.5rem;
  color: var(--ffp-blue-50);
}

/* Pencil affordance next to the loan name. Not .ffp-name__icon: that sets
 * pointer-events: none because its wrapper is the click target, whereas here
 * the button itself is what the delegated click handler looks for. */
.ffp-sl-name-edit {
  flex-shrink: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ffp-gray-40);
  cursor: pointer;
}
.ffp-sl-name-edit:hover {
  color: var(--ffp-blue-50);
}

/* Confirm-rename button: blue here, rather than the shared green check. */
.ffp-sl-name-save {
  flex-shrink: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ffp-blue-50);
  cursor: pointer;
}

/* Invalid field outline. Bootstrap's .is-invalid validation styles are not part
 * of the component layer this sheet defines. */
.ffp-sl-input--error {
  border-color: var(--ffp-red-60);
}

/* Small gray caption sitting above or beside a result metric. Deliberately
 * gray-60, not .ffp-text--muted (gray-70). */
.ffp-sl-caption {
  font-size: 0.875rem;
  color: var(--ffp-gray-60);
}

/* The debt-free date headline: 48px, between the --xxl and --display steps. */
.ffp-sl-date {
  font-weight: 600;
  font-size: 3rem;
  line-height: 1;
}

/* Accent green for the accelerated scenario. Not .ffp-text-success: that is
 * green-60, and the accelerated figures use the brighter green-50. */
.ffp-sl-text-green {
  color: var(--ffp-green-50);
}

/* Scenario compare pills. .ffp-tag--positive / --balanced carry the resting
 * colors; these add the neutral family plus the pressed state, which is one
 * tint step darker within each family. */
.ffp-sl-tag--neutral {
  background-color: var(--ffp-gray-10);
  color: var(--ffp-gray-70);
}
.ffp-tag--positive.ffp-sl-tag--active {
  background-color: var(--ffp-blue-8);
}
.ffp-tag--balanced.ffp-sl-tag--active {
  background-color: var(--ffp-green-8);
}
.ffp-sl-tag--neutral.ffp-sl-tag--active {
  background-color: var(--ffp-gray-30);
}

/* Next-steps CTA: a soft-tinted pill. Every .btn variant here is solid or
 * outlined, so there is nothing to extend. text-decoration is reset explicitly
 * because Reboot is not loaded and the host page styles links. */
.ffp-sl-next-step {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  border: 1px solid var(--ffp-blue-10);
  border-radius: 9999px;
  background-color: var(--ffp-blue-8);
  font-family: var(--ffp-font);
  color: var(--ffp-blue-50);
  text-align: center;
  text-decoration: none;
}
.ffp-sl-next-step:hover {
  background-color: var(--ffp-blue-10);
}

/* 2px heading gap (Tailwind's mb-0.5); no spacing scale has a half step. */
.ffp-sl-mb-half {
  margin-bottom: 0.125rem;
}

/* ============================================================================
 * Debt Snowball calculator
 * ==========================================================================*/

/* 75rem: what the Tailwind build resolved max-w-lg to (RDS --container-lg is
 * 1200px). Has to stay above the @md 900px container breakpoint or the
 * two-column results layout could never engage. */
.ffp-ds-shell {
  container-type: inline-size;
  max-width: 75rem;
  margin-inline: auto;

  /* The Chart.js code resolves its palette at draw time by reading these off
   * the canvas's computed style (see resolveColors), which is how the real Vue
   * component stays in sync with the design tokens. Declared here so the chart
   * keeps working now that Tailwind's token layer is no longer loaded. */
  --color-blue-5: #ebf4fa;
  --color-blue-8: #d8f1fc;
  --color-blue-50: #0073b9;
  --color-blue-80: #003561;
  --color-gray-20: #e8eced;
  --color-gray-30: #d5d9db;
  --color-gray-50: #8e999e;
  --color-green-5: #eaf8ee;
  --color-green-8: #d9fae1;
  --color-green-50: #35bd59;
  --color-green-60: #24a344;

  /* Bootstrap's .text-primary/.bg-primary/.border-primary utilities read
   * --bs-primary-rgb (an R,G,B triple, not a hex value) via rgba(). Override
   * scoped to this calculator only -- Bootstrap's default #0d6efd otherwise
   * bleeds through since htmx-calculators.css doesn't redefine it globally. */
  --bs-primary: #0073b9;
  --bs-primary-rgb: 0, 115, 185;
}

/* Currency and rate fields render their own affordances, so the browser's
 * number spinners are redundant. Scoped to this calculator's shell. */
.ffp-ds-shell input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}
.ffp-ds-shell input[type="number"]::-webkit-outer-spin-button,
.ffp-ds-shell input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Short blue underline used beneath the section headings. */
.ffp-ds-rule {
  width: 3rem;
  border-top: 4px solid var(--ffp-blue-50);
}

.ffp-ds-min-w-0 {
  min-width: 0;
}

/* One debt. Also the hook the list's delegated handlers use to map an event
 * target back to its index in `debts`. */
.ffp-ds-row {
  min-width: 0;
}

/* Label + control + error message, stacked. Doubles as the element
 * refreshRowValidation walks up to when it needs somewhere to put an error. */
.ffp-ds-field > * + * {
  margin-top: 0.25rem;
}

.ffp-ds-label {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-family: var(--ffp-font);
  font-size: 1rem;
  font-weight: 600;
}

.ffp-ds-text-60 {
  color: var(--ffp-gray-60);
}

/* Invalid control. Bootstrap's .is-invalid also paints a background warning
 * icon on the right, which would collide with these fields' leading $ / %
 * glyphs. !important because it overrides .form-control's border. */
.ffp-ds-invalid {
  border-color: var(--ffp-red-60) !important;
}

/* Round badge holding the debt-type icon. */
.ffp-ds-type-badge {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: var(--ffp-blue-5);
}

.ffp-ds-name-input {
  flex: 1 1 0%;
  min-width: 0;
  max-width: 18.75rem;
  border: 0;
  border-bottom: 1px solid var(--ffp-gray-40);
  background: transparent;
  font-family: var(--ffp-font);
  font-size: 24px;
  font-weight: 600;
  color: var(--ffp-blue-50);
  cursor: text;
}
.ffp-ds-name-input:focus {
  outline: none;
}

/* Pencil affordance next to a debt name. */
.ffp-ds-edit-btn {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ffp-gray-40);
  cursor: pointer;
}
.ffp-ds-edit-btn:hover {
  color: var(--ffp-blue-50);
}

/* Native <select> dressed to match the RDS combobox trigger: the chevron is a
 * sibling span, so the browser's own arrow has to go. */
.ffp-ds-select {
  height: 42px;
  padding-right: 2rem;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}
.ffp-ds-select::-ms-expand {
  display: none;
}

.ffp-ds-select-chevron {
  position: absolute;
  top: 50%;
  right: 0.75rem;
  transform: translateY(-50%);
  pointer-events: none;
  color: var(--ffp-gray-60);
}

.ffp-ds-icon-20 {
  width: 1.25rem;
  height: 1.25rem;
}

.ffp-ds-icon-32 {
  width: 2rem;
  height: 2rem;
}

/* The remove-debt button collapses to an icon-only square at @lg, where the
 * glyph steps up to match the larger hit area. */
.ffp-ds-del-icon {
  width: 1rem;
  height: 1rem;
}

/* The debt-free date itself: the largest figure on the page. */
.ffp-ds-figure {
  font-family: var(--ffp-font);
  font-size: 3rem;
  font-weight: 600;
}

/* Accent for the accelerated scenario. Blue is covered by .text-primary. */
.ffp-ds-accent-green {
  color: var(--ffp-green-50);
}

/* Compare chips reuse .ffp-tag. The "minimum payments only" chip needs a
 * neutral variant .ffp-tag has none of, and the selected chip in each family
 * deepens its background one step. */
.ffp-ds-tag-neutral {
  background-color: var(--ffp-gray-10);
  color: var(--ffp-gray-70);
}
.ffp-tag--positive.ffp-ds-tag-on {
  background-color: var(--ffp-blue-8);
}
.ffp-tag--balanced.ffp-ds-tag-on {
  background-color: var(--ffp-green-8);
}
.ffp-ds-tag-neutral.ffp-ds-tag-on {
  background-color: var(--ffp-gray-30);
}

/* Fixed-height frame the responsive canvas draws into, and the anchor the
 * trophy marker is absolutely positioned against. */
.ffp-ds-chart-box {
  height: 12rem;
}

/* Debt-free-date marker, positioned onto the chart's x-axis from JS. */
.ffp-ds-trophy {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--ffp-blue-5);
  color: var(--ffp-blue-50);
  cursor: pointer;
}

.ffp-ds-trophy--accel {
  background-color: var(--ffp-green-5);
}

/* 0.125rem: hairline gap between a heading and its blue underline. */
.ffp-ds-mb-half {
  margin-bottom: 0.125rem;
}

/* 1.25rem: falls between the at-gap-4 (1rem) and at-gap-6 (1.5rem) steps. */
.ffp-ds-gap-5 {
  gap: 1.25rem;
}

/* --- Extra-payment range slider -------------------------------------------
 * Ported from the library's RangeSlider.vue scoped styles: the track fills
 * green up to the current value (--range-progress, set inline from JS) over a
 * translucent gray remainder, with a white circular thumb. All pseudo-element
 * rules, so no utility layer can express it. The gray uses a literal rgba
 * because rgba() cannot take a custom property as its color argument.
 * ------------------------------------------------------------------------ */
.ffp-ds-range {
  -webkit-appearance: none;
  appearance: none;
  --range-progress: 0%;
  height: 20px;
  padding: 0;
  border: none;
  background: none;
  outline: none;
  cursor: pointer;
}
.ffp-ds-range::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 9999px;
  background: linear-gradient(
    to right,
    var(--ffp-green-50) var(--range-progress),
    rgba(213, 217, 219, 0.8) var(--range-progress)
  );
}
.ffp-ds-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -7px;
  border: 1px solid var(--ffp-gray-50);
  border-radius: 50%;
  background: var(--ffp-white);
  cursor: pointer;
}
.ffp-ds-range::-moz-range-track {
  height: 6px;
  border: none;
  border-radius: 9999px;
  background: rgba(213, 217, 219, 0.8);
}
.ffp-ds-range::-moz-range-progress {
  height: 6px;
  border-radius: 9999px;
  background: var(--ffp-green-50);
}
.ffp-ds-range::-moz-range-thumb {
  box-sizing: border-box;
  width: 20px;
  height: 20px;
  border: 1px solid var(--ffp-gray-50);
  border-radius: 50%;
  background: var(--ffp-white);
  cursor: pointer;
}

/* --- Ask Ramsey ----------------------------------------------------------- */

/* Intro column: centered while the results card is single-column, left-aligned
 * once it splits in two at @md. */
.ffp-ds-ask-intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* Question field: it sits inside the gradient pill, so it drops the border and
 * background a .form-control would bring. */
.ffp-ds-ask-input {
  flex: 1 1 0%;
  min-width: 0;
  padding-block: 0.75rem;
  border: 0;
  background: transparent;
  font-family: var(--ffp-font);
  font-size: 1rem;
  color: var(--ffp-gray-90);
}
.ffp-ds-ask-input::placeholder {
  color: var(--ffp-gray-60);
}
.ffp-ds-ask-input:focus {
  outline: none;
}

.ffp-ds-ask-send {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ffp-blue-50);
  cursor: pointer;
}
.ffp-ds-ask-send:hover {
  background-color: var(--ffp-blue-8);
}

/* Suggested-prompt pill linking into an Ask Ramsey chat. */
.ffp-ds-prompt-card {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.5rem;
  border: 1px solid var(--ffp-blue-30);
  border-radius: 9999px;
  background-color: var(--ffp-white);
  font-family: var(--ffp-font);
  font-size: 0.875rem;
  color: var(--ffp-blue-50);
  text-align: center;
  text-decoration: none;
}
.ffp-ds-prompt-card:hover {
  background-color: var(--ffp-blue-8);
}

/* --- Calculator-specific container responses ------------------------------ */
@container (width >= 900px) {
  .ffp-ds-ask-intro {
    align-items: flex-start;
    text-align: left;
  }
}

@container (width >= 1200px) {
  .ffp-sl-del-icon {
    width: 1.5rem;
    height: 1.5rem;
  }
  .ffp-ds-del-icon {
    width: 1.5rem;
    height: 1.5rem;
  }
}
