@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --nordea-blue: #0000a0;
  --nordea-blue-dark: #00007a;
  --nordea-blue-light: #e6e6f5;
  --nordic-green: #00965e;
  --nordic-red: #d42a2a;
  --nordic-amber: #f5a623;
  --gray-900: #1a1a1a;
  --gray-700: #4a4a4a;
  --gray-500: #7a7a7a;
  --gray-300: #c4c4c4;
  --gray-100: #f5f5f5;
  --white: #ffffff;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-8: 48px;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 9999px;

  --shadow-1: 0 1px 3px rgba(0, 0, 0, 0.1);
  --shadow-2: 0 4px 6px rgba(0, 0, 0, 0.1);
  --shadow-3: 0 10px 20px rgba(0, 0, 0, 0.15);

  /* Series colours. Six, because the seventh series wraps rather than inventing one,
     and every one of them is paired with a label so colour is never the only signal. */
  --chart-1: #0000a0;
  --chart-2: #00965e;
  --chart-3: #d4761a;
  --chart-4: #7b4bc4;
  --chart-5: #d42a2a;
  --chart-6: #5a7184;
  /* What surrounds the series on a plot. The ECharts option names these tokens and
     the component resolves them just before painting (visuals/echarts.md). */
  --chart-text: var(--gray-900);
  --chart-muted: var(--gray-500);
  --chart-rule: var(--gray-300);
  --chart-surface: var(--white);

  --transition-fast: 100ms ease-out;
  --transition-normal: 200ms ease-in-out;
  --transition-slow: 300ms ease-in-out;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: "Nordea Sans", "Segoe UI", system-ui, sans-serif;
  color: var(--gray-900);
  background: linear-gradient(180deg, var(--nordea-blue-light), var(--white));
}

a {
  color: var(--nordea-blue);
  text-decoration: none;
}

a:hover {
  color: var(--nordea-blue-dark);
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--space-6);
}

.page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.page-content {
  flex: 1;
  padding: var(--space-6) 0;
}

.app-header {
  background: var(--white);
  border-bottom: 1px solid var(--gray-300);
  box-shadow: var(--shadow-1);
  /* Full width on every page, and above the dock, which starts below it. */
  position: sticky;
  top: 0;
  z-index: 30;
}

.header-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 64px;
}

.header-brand {
  font-weight: 700;
  font-size: 18px;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.header-user {
  color: var(--gray-700);
}

.app-footer {
  background: var(--gray-100);
  border-top: 1px solid var(--gray-300);
  padding: var(--space-4) 0;
  color: var(--gray-700);
  font-size: 12px;
}

.footer-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.footer-links {
  display: flex;
  gap: var(--space-3);
}

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

.helper-text {
  color: var(--gray-500);
  font-size: 12px;
  margin-top: var(--space-3);
}

.card {
  background: var(--white);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-1);
}

.card-hover:hover {
  box-shadow: var(--shadow-2);
}

.card-padding-none { padding: 0; }
.card-padding-sm { padding: var(--space-3); }
.card-padding-md { padding: var(--space-4); }
.card-padding-lg { padding: var(--space-5); }

.card-header {
  border-bottom: 1px solid var(--gray-300);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
}

.card-footer {
  border-top: 1px solid var(--gray-300);
  padding-top: var(--space-3);
  margin-top: var(--space-3);
}

.loan-application-grid,
.loan-status-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: var(--space-6);
}

.loan-form-column,
.loan-status-column {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.loan-summary-column,
.loan-offer-column {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.loan-status-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.loan-guid {
  font-size: 12px;
  color: var(--gray-500);
}

.btn {
  border: none;
  border-radius: var(--radius-sm);
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition-normal);
}

.btn-full {
  width: 100%;
}

.btn-sm { padding: var(--space-2) var(--space-3); font-size: 12px; }
.btn-md { padding: var(--space-3) var(--space-4); font-size: 14px; }
.btn-lg { padding: var(--space-4) var(--space-5); font-size: 16px; }

.btn-primary { background: var(--nordea-blue); color: var(--white); }
.btn-primary:hover { background: var(--nordea-blue-dark); }
.btn-secondary { background: var(--gray-100); color: var(--gray-900); }
.btn-secondary:hover { background: var(--gray-300); }
.btn-ghost { background: transparent; color: var(--nordea-blue); }
.btn-ghost:hover { background: var(--nordea-blue-light); }
.btn-danger { background: var(--nordic-red); color: var(--white); }

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.stepper {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin: var(--space-4) 0;
}

.stepper-step {
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-full);
  padding: 6px 12px;
  background: var(--white);
  font-size: 12px;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  transition: var(--transition-fast);
}

.stepper-step-current {
  border-color: var(--nordea-blue);
  color: var(--nordea-blue);
  background: var(--nordea-blue-light);
}

.stepper-step-done {
  border-color: var(--nordic-green);
  color: var(--nordic-green);
}

.stepper-step-upcoming {
  color: var(--gray-500);
}

.stepper-index {
  font-weight: 700;
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
}

.badge-success { background: rgba(0, 150, 94, 0.15); color: var(--nordic-green); }
.badge-warning { background: rgba(245, 166, 35, 0.2); color: var(--nordic-amber); }
.badge-error { background: rgba(212, 42, 42, 0.15); color: var(--nordic-red); }
.badge-neutral { background: var(--gray-100); color: var(--gray-700); }

.loan-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

/* --- Loan application wizard --------------------------------------------- */

.loan-wizard {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.loan-wizard-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  gap: var(--space-5);
  align-items: start;
}

.loan-wizard-steps {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  min-width: 0;
}

/* Back sits left, Continue right, so the primary action is always in the same place. */
.loan-wizard-actions {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  border-top: 1px solid var(--gray-300);
  padding-top: var(--space-4);
}

.loan-wizard-actions > :only-child {
  margin-left: auto;
}

.loan-wizard-summary {
  position: sticky;
  top: var(--space-5);
  padding: var(--space-4);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-md);
  background: var(--gray-100);
}

.loan-wizard-summary h3 {
  margin: 0 0 var(--space-3);
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gray-700);
}

/* Provenance, said quietly but said. The colour is a hint, never the only signal —
   the text carries the meaning on its own. */
.derived-hint {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: calc(var(--space-2) * -1) 0 var(--space-2);
  font-size: 12px;
}

.derived-hint-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  flex: none;
}

.derived-hint-observed {
  color: var(--nordic-green);
}

.derived-hint-observed .derived-hint-dot {
  background: var(--nordic-green);
}

.derived-hint-fallback {
  color: var(--nordic-amber);
}

.derived-hint-fallback .derived-hint-dot {
  background: var(--nordic-amber);
}

.debt-row {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-3);
}

@media (max-width: 900px) {
  .loan-wizard-body {
    grid-template-columns: minmax(0, 1fr);
  }

  .loan-wizard-summary {
    position: static;
    order: -1;
  }
}

.form-section {
  display: grid;
  gap: var(--space-3);
}

/* The class was referenced but never defined, so these fields stacked with no gap and
   each label sat on the control above it. Visible once they moved onto Review beside
   properly spaced sections. */
.co-applicant-fields {
  display: grid;
  gap: var(--space-3);
}

.form-section h3 {
  margin: 0 0 var(--space-2);
  font-size: 16px;
}

.form-checkbox {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 14px;
  color: var(--gray-700);
}

.form-actions {
  display: flex;
  justify-content: flex-end;
}

.form-error-list {
  border: 1px solid var(--nordic-red);
  background: rgba(212, 42, 42, 0.08);
  color: var(--nordic-red);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-3);
  display: grid;
  gap: var(--space-2);
  font-size: 12px;
}

.form-error-item {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
}

.profile-summary {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: var(--gray-100);
  margin-bottom: var(--space-3);
}

.profile-row {
  display: flex;
  justify-content: space-between;
  font-size: 14px;
}

.loan-summary-row {
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  padding: 6px 0;
  border-bottom: 1px dashed var(--gray-300);
}

.loan-summary-label {
  color: var(--gray-700);
}

.loan-summary-value {
  font-weight: 600;
}

.loan-offer-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.loan-offer-title {
  font-weight: 700;
  font-size: 16px;
}

.loan-offer-row {
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  color: var(--gray-700);
}

.loan-offer-actions {
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
}

.status-timeline {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.timeline-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  border: 1px solid var(--gray-300);
  font-size: 13px;
}

.timeline-item-done {
  border-color: var(--nordic-green);
  background: rgba(0, 150, 94, 0.08);
}

.timeline-item-current {
  border-color: var(--nordea-blue);
  background: var(--nordea-blue-light);
}

.timeline-item-upcoming {
  color: var(--gray-500);
}

.timeline-label {
  font-weight: 600;
}

.timeline-timestamp {
  color: var(--gray-500);
  font-size: 12px;
}

@media (max-width: 960px) {
  .loan-application-grid,
  .loan-status-grid {
    grid-template-columns: 1fr;
  }
}

.spinner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.spinner-circle {
  border: 3px solid var(--gray-300);
  border-top: 3px solid var(--nordea-blue);
  border-radius: 50%;
  width: 32px;
  height: 32px;
  animation: spin 1s linear infinite;
}

.spinner-inline .spinner-circle { width: 16px; height: 16px; }
.spinner-page { min-height: 200px; }

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.login-container {
  max-width: 420px;
}

.login-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  text-align: center;
}

.login-title { font-size: 32px; font-weight: 700; }
.login-subtitle { color: var(--gray-700); }
.login-legal { font-size: 12px; color: var(--gray-500); }

.accounts-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

.accounts-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Unreachable banks: a partial view must announce itself, so this sits above the
   account grid rather than being tucked away. */
.bank-warnings {
  display: flex;
  flex-direction: column;
  gap: var(--space-2, 0.5rem);
  margin-bottom: var(--space-4, 1rem);
}

.bank-warning {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2, 0.5rem);
  padding: 0.75rem 1rem;
  border: 1px solid var(--color-warning, #b45309);
  border-left-width: 4px;
  border-radius: var(--radius-md, 0.375rem);
  background: var(--color-warning-bg, #fffbeb);
  color: var(--color-warning-text, #78350f);
  font-size: 0.875rem;
}

.bank-warning-text {
  flex: 1 1 auto;
  min-width: 0;
}

.bank-warning-action {
  flex: 0 0 auto;
  font-weight: 600;
  text-decoration: underline;
  color: inherit;
}

.accounts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-4);
}

.account-card {
  background: var(--white);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  cursor: pointer;
  position: relative;
}

.account-card .btn {
  align-self: flex-end;
}

.account-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
}

.account-title {
  font-size: 18px;
  font-weight: 600;
}

.account-number {
  font-family: "JetBrains Mono", "Fira Code", monospace;
  color: var(--gray-700);
}

.account-balances {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--space-3);
}

.balance-label {
  font-size: 12px;
  color: var(--gray-500);
}

.account-meta {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--gray-500);
}

.currency {
  display: inline-flex;
  gap: 6px;
  align-items: baseline;
}

.currency-sm { font-size: 12px; }
.currency-md { font-size: 14px; }
.currency-lg { font-size: 18px; }
.currency-positive { color: var(--nordic-green); }
.currency-negative { color: var(--nordic-red); }

.error-message {
  border: 1px solid var(--nordic-red);
  background: rgba(212, 42, 42, 0.1);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.error-title { font-weight: 700; }
.error-actions { display: flex; gap: var(--space-3); }

.empty-state {
  border: 1px dashed var(--gray-300);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.empty-title { font-size: 18px; font-weight: 600; }

.form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--gray-700);
}

.form-input,
.form-select {
  height: 40px;
  padding: 0 var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--gray-900);
}

.form-input-error {
  border-color: var(--nordic-red);
}

.form-error {
  font-size: 12px;
  color: var(--nordic-red);
}

.form-helper {
  font-size: 12px;
  color: var(--gray-500);
}

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3);
}

.form-static {
  height: 40px;
  padding: 0 var(--space-3);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-sm);
  background: var(--gray-100);
  color: var(--gray-800);
  display: flex;
  align-items: center;
}

.tab-row {
  display: flex;
  gap: var(--space-2);
}

.tab-button {
  border: 1px solid var(--gray-300);
  border-radius: 999px;
  padding: 6px 12px;
  background: var(--white);
  color: var(--gray-700);
  font-weight: 600;
  font-size: 12px;
  cursor: pointer;
}

.tab-button-active {
  background: var(--gray-900);
  color: var(--white);
  border-color: var(--gray-900);
}

.form-actions {
  display: flex;
  justify-content: flex-end;
}

.form-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: var(--gray-100);
}

.toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.toggle input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.toggle-track {
  width: 44px;
  height: 24px;
  background: var(--gray-300);
  border-radius: 999px;
  position: relative;
  transition: background 150ms ease;
}

.toggle-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
  transition: transform 150ms ease;
}

.toggle input:checked + .toggle-track {
  background: var(--nordea-blue);
}

.toggle input:checked + .toggle-track .toggle-thumb {
  transform: translateX(20px);
}

.recurring-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  border: 1px dashed var(--gray-300);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  background: var(--white);
}

.transfer-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.transfer-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.transfer-item-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  background: var(--white);
}

.transfer-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex: 1;
}

.transfer-item-main {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.transfer-item-title {
  font-weight: 600;
}

.transfer-item-sub {
  font-size: 12px;
  color: var(--gray-500);
}

.transaction-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  align-items: end;
}

.filter-actions {
  display: flex;
  gap: var(--space-2);
}

.transaction-summary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: center;
}

.summary-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.summary-label {
  font-size: 12px;
  color: var(--gray-500);
}

.summary-range {
  font-size: 12px;
  color: var(--gray-700);
}

.transaction-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--white);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.transaction-table th,
.transaction-table td {
  padding: var(--space-3);
  border-bottom: 1px solid var(--gray-300);
  text-align: left;
  font-size: 12px;
}

.transaction-table th {
  background: var(--gray-100);
  font-weight: 600;
  cursor: pointer;
}

.transaction-row:hover {
  background: var(--nordea-blue-light);
}

.transaction-amount,
.transaction-balance {
  white-space: nowrap;
}

.account-id {
  font-size: 12px;
  color: var(--gray-500);
}

.pagination {
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
  margin-top: var(--space-4);
}

/* ── Header nav ─────────────────────────────────────────────────────────── */

.header-nav {
  display: flex;
  gap: var(--space-5);
  align-items: center;
}

.header-nav-link {
  color: var(--gray-700);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  padding: var(--space-1) 0;
  border-bottom: 2px solid transparent;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.header-nav-link:hover {
  color: var(--nordea-blue);
  border-bottom-color: var(--nordea-blue);
}

/* ── Chat page ───────────────────────────────────────────────────────────── */

.chat-container {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 130px);
  max-width: 800px;
}

.chat-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: var(--space-4);
  flex-shrink: 0;
}

.chat-header h1 {
  margin: 0 0 var(--space-1) 0;
}

.chat-header-subtitle {
  color: var(--gray-500);
  font-size: 14px;
  margin: 0;
}

.chat-panel {
  display: flex;
  flex-direction: column;
  flex: 1;
  background: var(--white);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  scroll-behavior: smooth;
}

.chat-empty {
  color: var(--gray-500);
  font-size: 14px;
  text-align: center;
  margin-top: var(--space-8);
}

.chat-message-row {
  display: flex;
}

.chat-message-row-user {
  justify-content: flex-end;
}

.chat-message-row-assistant {
  justify-content: flex-start;
}

.chat-bubble {
  max-width: 75%;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

.chat-bubble-user {
  background: var(--nordea-blue);
  color: var(--white);
  border-bottom-right-radius: var(--radius-sm);
}

.chat-bubble-assistant {
  background: var(--gray-100);
  color: var(--gray-900);
  border-bottom-left-radius: var(--radius-sm);
}

.chat-bubble-thinking {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
}

.chat-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--gray-500);
  animation: chat-dot-bounce 1.2s infinite ease-in-out;
}

.chat-dot:nth-child(1) { animation-delay: 0s; }
.chat-dot:nth-child(2) { animation-delay: 0.2s; }
.chat-dot:nth-child(3) { animation-delay: 0.4s; }

@keyframes chat-dot-bounce {
  0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
  40% { transform: scale(1.2); opacity: 1; }
}

.chat-error {
  padding: var(--space-2) var(--space-5);
  color: var(--nordic-red);
  font-size: 13px;
  background: #fef2f2;
  border-top: 1px solid #fecaca;
}

.chat-input-area {
  border-top: 1px solid var(--gray-300);
  padding: var(--space-3) var(--space-4);
  flex-shrink: 0;
}

.chat-input-row {
  display: flex;
  gap: var(--space-3);
  align-items: flex-end;
}

.chat-textarea {
  flex: 1;
  resize: none;
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  font-size: 14px;
  font-family: inherit;
  color: var(--gray-900);
  background: var(--white);
  line-height: 1.5;
  transition: border-color var(--transition-fast);
  outline: none;
}

.chat-textarea:focus {
  border-color: var(--nordea-blue);
}

.chat-textarea:disabled {
  background: var(--gray-100);
  color: var(--gray-500);
  cursor: not-allowed;
}

.chat-send-btn {
  flex-shrink: 0;
  align-self: flex-end;
}

@media (max-width: 768px) {
  .container { padding: 0 var(--space-4); }
  .footer-content { flex-direction: column; align-items: flex-start; }
  .account-meta { flex-direction: column; gap: var(--space-2); }
  .transaction-table { display: block; overflow-x: auto; }
  .accounts-actions { flex-direction: column; align-items: flex-end; }
  .chat-container { height: calc(100vh - 110px); }
  .header-nav { gap: var(--space-3); }
}

/* ---------------------------------------------------------------------------
 * Client authorisation and approval
 *
 * Both pages are reached by redirect rather than navigation, and both ask the user to
 * decide something. They are deliberately narrow and plain: the decision is the content.
 * ------------------------------------------------------------------------- */

.narrow-page {
  max-width: 560px;
}

.connect-title,
.approve-title {
  font-size: var(--font-size-xl, 20px);
  font-weight: 600;
  margin: 0 0 var(--space-3);
  color: var(--gray-900);
}

.connect-lead,
.approve-summary {
  margin: 0 0 var(--space-4);
  color: var(--gray-700);
}

.approve-summary {
  font-size: var(--font-size-lg, 17px);
  font-weight: 500;
  color: var(--gray-900);
}

.connect-scopes {
  margin: 0 0 var(--space-4);
  padding-left: var(--space-5);
  color: var(--gray-800);
}

.connect-scopes li {
  margin-bottom: var(--space-2);
}

/* The line that stops a user believing an agent can move their money. It is the point of
 * the page, so it is not styled as fine print. */
.connect-note,
.approve-note {
  margin: var(--space-4) 0;
  padding: var(--space-3);
  border-radius: var(--radius-md, 8px);
  background: var(--gray-100, #f3f4f6);
  border: 1px solid var(--gray-300);
  color: var(--gray-700);
  font-size: var(--font-size-sm, 13px);
}

.connect-actions,
.approve-actions {
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
  margin-top: var(--space-5);
}

.approve-link {
  display: inline-block;
  margin-top: var(--space-3);
  color: var(--primary-600, #1d4ed8);
}

@media (max-width: 480px) {
  .connect-actions,
  .approve-actions {
    flex-direction: column-reverse;
  }
}

/* ── the chat dock ─────────────────────────────────────────────────────────────
   Always there on a wide screen, to the right of whatever the user is doing.
   Fixed rather than a grid column because every page renders its own header and
   footer: a column would have to be threaded through all of them, and a page added
   later would quietly not have one.

   It begins below the header, so the header bar still runs the width of the page.

   Width: wide enough that a reply reads as prose rather than as a column of two or
   three words, and that enough of the history stays on screen to be worth glancing at.
   It grows with the viewport between those bounds so a large monitor gives the
   conversation more room without a laptop handing over its whole screen. */
:root {
  --chat-dock-width: clamp(600px, 42vw, 880px);
  --app-header-height: 65px; /* the 64px bar plus its rule */
}

.chat-dock {
  display: none;
}

@media (min-width: 1280px) {
  .chat-dock {
    position: fixed;
    top: var(--app-header-height);
    right: 0;
    bottom: 0;
    width: var(--chat-dock-width);
    display: flex;
    flex-direction: column;
    background: var(--white);
    border-left: 1px solid var(--gray-300);
    z-index: 20;
  }

  .chat-dock-header {
    padding: var(--space-4);
    border-bottom: 1px solid var(--gray-300);
    font-weight: 600;
    font-size: 14px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--gray-700);
  }

  /* The dock owns the right edge, so the page stops before it — but only where the
     dock is actually up. The header and footer bars themselves still run the full
     width; it is what they hold that lines up with the content below. */
  .shell-docked .page-content,
  .shell-docked .app-header > .container,
  .shell-docked .app-footer > .container {
    margin-right: var(--chat-dock-width);
  }

  .chat-dock .chat-panel {
    flex: 1;
    min-height: 0;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }
}

/* Where the assistant offered to take the user. An offer, not a jump: it sits inside the
   answer and waits to be pressed. */
.chat-destination {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--nordea-blue);
  border-radius: var(--radius-full);
  background: var(--white);
  color: var(--nordea-blue);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.chat-destination:hover,
.chat-destination:focus-visible {
  background: var(--nordea-blue);
  color: var(--white);
}

.chat-destination-icon {
  font-size: 14px;
  line-height: 1;
}

/* ── charts ───────────────────────────────────────────────────────────────────

   A `ChartSpec` arrives fully resolved: the figures, the labels, the order and
   the choice of chart were all made in Rust. Plots are painted by ECharts on a
   canvas from the shared option (visuals/echarts.md), which decides how the plot
   itself looks. Everything below is what surrounds it: the title, the notices,
   the summary and the table. */

.chart {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

.chart-title {
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--gray-900);
}

/* Never quiet, and never below the chart: figures drawn from three banks of
   four, presented as whole, read as underspending. */
.chart-incomplete {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--nordic-amber);
  border-radius: var(--radius-sm);
  background: #fdf6e7;
  color: var(--gray-700);
  font-size: 13px;
  line-height: 1.4;
}

.chart-body {
  min-width: 0;
}

/* An empty spec says why it is empty, and the reason is the content. */
.chart-reason {
  margin: 0;
  padding: var(--space-6) var(--space-4);
  border: 1px dashed var(--gray-300);
  border-radius: var(--radius-md);
  color: var(--gray-500);
  font-size: 14px;
  text-align: center;
}

/* The plot's box. Full width; its height is the option's, set inline. ECharts is
   resized whenever this box changes, so the plot is never stretched. */
.chart-canvas {
  width: 100%;
  min-width: 0;
}

/* ── labelled figures ── */

.chart-summary {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-3);
}

.chart-figure {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--gray-100);
}

.chart-figure dt {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-500);
}

.chart-figure dd {
  margin: var(--space-1) 0 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--gray-900);
  font-variant-numeric: tabular-nums;
}

/* ── the table, which is also what an unrecognised kind becomes ── */

.chart-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.chart-table th {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--gray-300);
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-500);
}

.chart-table td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--gray-100);
  color: var(--gray-700);
}

.chart-table tbody tr:last-child td {
  border-bottom: none;
}

.chart-table-value {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ── a composed chart ── */

.chart-caption {
  margin: 0;
  font-size: 13px;
  color: var(--gray-700);
}

/* Obi's own account of how the figures were computed. Always shown: the title is the
   assistant's words, and this is what actually ran. One line per table. */
.chart-method {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--gray-300);
  font-size: 12px;
  line-height: 1.5;
  color: var(--gray-700);
  white-space: pre-line;
}

.chart-method-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-500);
}

.chart-table-caption {
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  color: var(--gray-500);
  padding: var(--space-2) 0;
}

.insights-panel-composed {
  grid-column: 1 / -1;
}

.chart-note,
.chart-footnote {
  margin: 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--gray-500);
}

/* ── the spending page ── */

.insights-container {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.insights-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
}

.insights-header h1 {
  margin: 0;
  font-size: 28px;
  font-weight: 600;
  color: var(--gray-900);
}

.insights-period {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.insights-period .form-input {
  width: auto;
}

.insights-loading {
  display: flex;
  justify-content: center;
  padding: var(--space-8) 0;
}

.insights-panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: var(--space-4);
  align-items: start;
}

/* A plot and a row of figures are read across the whole width; the breakdowns sit side
   by side beside each other, where there is room. Which is which is decided by what the
   panel holds, not by where it sits, because a free-form chart can arrive at the top and
   push everything else down one. */
.insights-panel:has(.chart-canvas-wide),
.insights-panel:has(.chart-summary) {
  grid-column: 1 / -1;
}

.insights-panel {
  padding: var(--space-5);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-lg);
  background: var(--white);
  box-shadow: var(--shadow-1);
  min-width: 0;
}

