:root {
  color-scheme: light;
  --bg: #f5f7f8;
  --surface: #ffffff;
  --surface-soft: #eef4f2;
  --text: #172026;
  --muted: #65727b;
  --line: #d8e0e4;
  --nav: #22304a;
  --teal: #0f766e;
  --green: #18794e;
  --red: #c92a2a;
  --mod-blue: #2563eb;
  --mod-blue-bg: rgba(37, 99, 235, 0.12);
  --mod-green: #16a34a;
  --mod-green-bg: rgba(22, 163, 74, 0.13);
  --mod-amber: #d97706;
  --mod-amber-bg: rgba(217, 119, 6, 0.14);
  --mod-violet: #7c3aed;
  --mod-violet-bg: rgba(124, 58, 237, 0.13);
  --shadow: 0 16px 48px rgba(23, 32, 38, 0.07);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 75%;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
}

.shell {
  min-height: 100vh;
}

.sidebar {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 10;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
  padding: 8px;
  background: rgba(255, 255, 255, 0.94);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(16px);
}

.brand {
  display: none;
}

.nav {
  display: contents;
}

.nav-separator {
  display: none;
}

.nav-button {
  position: relative;
  display: grid;
  min-height: 44px;
  place-items: center;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: 6px;
}

.nav-button.is-active {
  color: #ffffff;
  background: var(--nav);
}

.nav-button::after {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  z-index: 20;
  padding: 6px 8px;
  color: #ffffff;
  background: var(--nav);
  border-radius: 6px;
  content: attr(aria-label);
  font-size: 0.78rem;
  font-weight: 800;
  opacity: 0;
  pointer-events: none;
  transform: translateX(-50%) translateY(3px);
  transition: opacity 120ms ease, transform 120ms ease;
  white-space: nowrap;
}

.nav-button:hover::after,
.nav-button:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.nav-icon {
  display: block;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2;
}

.app {
  width: min(100%, 1180px);
  margin: 0 auto;
  padding: 18px 14px 92px;
}

.view {
  display: none;
}

.view.is-active {
  display: block;
}

.topbar {
  display: flex;
  gap: 16px;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 18px;
}

.eyebrow,
.period {
  margin: 0;
  color: var(--nav);
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

h1 {
  margin-bottom: 0;
  font-size: 2rem;
  line-height: 1;
}

h2 {
  margin-bottom: 0;
  font-size: 1rem;
}

.summary {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  margin-bottom: 14px;
}

.metric,
.panel,
.module-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow);
}

.metric {
  display: flex;
  min-height: 76px;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
}

.metric span {
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 700;
}

.metric strong {
  font-size: 1.24rem;
}

.metric-balance {
  background: var(--surface-soft);
}

.module-grid {
  display: grid;
  gap: 10px;
}

.module-groups {
  display: grid;
  gap: 12px;
}

.module-group {
  display: grid;
  gap: 8px;
}

.module-card {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 4px 12px;
  align-items: center;
  padding: 14px;
  color: var(--text);
  text-align: left;
}

.module-card:hover {
  border-color: #b8c5cb;
  background: #fbfcfd;
}

.module-card .nav-icon {
  grid-row: span 2;
  color: var(--nav);
}

.module-card strong {
  font-size: 1rem;
}

.module-card small {
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.35;
}

.module-card--accent {
  grid-template-columns: 36px 1fr;
  gap: 4px 14px;
}

.module-icon {
  grid-row: span 2;
  display: inline-flex;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--module-tile-bg, var(--surface-soft));
  color: var(--module-tile-fg, var(--nav));
}

.module-icon .nav-icon {
  width: 20px;
  height: 20px;
  color: inherit;
}

.module-card[data-color="blue"] {
  --module-tile-bg: var(--mod-blue-bg);
  --module-tile-fg: var(--mod-blue);
}

.module-card[data-color="green"] {
  --module-tile-bg: var(--mod-green-bg);
  --module-tile-fg: var(--mod-green);
}

.module-card[data-color="amber"] {
  --module-tile-bg: var(--mod-amber-bg);
  --module-tile-fg: var(--mod-amber);
}

.module-card[data-color="violet"] {
  --module-tile-bg: var(--mod-violet-bg);
  --module-tile-fg: var(--mod-violet);
}

.meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  padding-top: 14px;
  margin-top: 4px;
  border-top: 1px solid var(--line);
}

.meta-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 600;
}

.meta-link:hover {
  color: var(--text);
}

.meta-link .nav-icon {
  width: 16px;
  height: 16px;
  color: currentColor;
}

@media (max-width: 719px) {
  .meta-link span {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
}

.changelog-list {
  display: grid;
  gap: 10px;
}

.changelog-item {
  display: grid;
  gap: 8px;
  padding: 12px;
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.changelog-meta {
  display: flex;
  gap: 8px;
  align-items: center;
}

.changelog-item time,
.changelog-item code {
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
}

.changelog-item code {
  padding: 2px 5px;
  background: #eef2f4;
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
  text-transform: none;
}

.changelog-item h3 {
  margin-bottom: 0;
  font-size: 1rem;
}

.changelog-item ul {
  display: grid;
  gap: 5px;
  padding-left: 18px;
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

.panel {
  padding: 16px;
  margin-top: 14px;
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(23, 32, 38, 0.28);
}

.modal[hidden] {
  display: none;
}

.modal-dialog {
  position: relative;
  width: min(100%, 940px);
  max-height: calc(100vh - 32px);
  overflow: auto;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow);
}

#close-movement-modal {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1;
}

.modal-dialog .section-heading {
  padding-right: 40px;
}

.section-heading {
  display: flex;
  min-height: 28px;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.section-heading p,
.section-heading span {
  margin: 0;
  color: var(--muted);
  font-size: 0.86rem;
}

.movement-form,
.filters,
.settings-form,
.config-toolbar {
  display: grid;
  gap: 12px;
}

label {
  display: grid;
  gap: 6px;
}

label span {
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
}

.toggle-field {
  display: flex;
  gap: 8px;
  align-items: center;
}

.toggle-field input {
  width: auto;
  min-height: auto;
}

.shared-fields {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.shared-fields[hidden] {
  display: none;
}

input,
select,
textarea {
  width: 100%;
  min-height: 46px;
  padding: 10px 12px;
  color: var(--text);
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 6px;
}

textarea {
  min-height: 74px;
  resize: vertical;
}

input:focus,
select:focus,
textarea:focus,
button:focus-visible {
  outline: 3px solid rgba(15, 118, 110, 0.22);
  outline-offset: 2px;
}

.primary-action {
  min-height: 48px;
  padding: 0 18px;
  color: #ffffff;
  background: var(--teal);
  border: 0;
  border-radius: 6px;
  font-weight: 800;
}

.primary-action:hover {
  background: #0b5f59;
}

.date-trigger {
  width: 100%;
  min-height: 46px;
  padding: 10px 12px;
  color: var(--text);
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 6px;
  text-align: left;
}

.date-picker {
  position: fixed;
  z-index: 50;
  width: min(300px, calc(100vw - 28px));
  padding: 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow);
}

.date-picker[hidden] {
  display: none;
}

.date-picker-header {
  display: grid;
  grid-template-columns: 34px 1fr 34px;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}

.date-picker-header strong {
  font-size: 0.92rem;
  text-align: center;
  text-transform: capitalize;
}

.icon-button {
  display: grid;
  width: 34px;
  height: 34px;
  place-items: center;
  color: var(--text);
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 1.2rem;
  font-weight: 900;
  line-height: 1;
}

.date-weekdays,
.date-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

.date-weekdays {
  margin-bottom: 4px;
}

.date-weekdays span {
  display: grid;
  height: 24px;
  place-items: center;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 900;
}

.date-spacer,
.date-day {
  width: 100%;
  aspect-ratio: 1;
}

.date-day {
  color: var(--text);
  background: #fbfcfd;
  border: 1px solid transparent;
  border-radius: 6px;
  font-size: 0.86rem;
  font-weight: 700;
}

.date-day:hover {
  border-color: var(--line);
}

.date-day.is-today {
  border-color: var(--teal);
}

.date-day.is-selected {
  color: #ffffff;
  background: var(--nav);
}

.movement-list,
.config-list {
  display: grid;
  margin-top: 14px;
}

.movement-list {
  gap: 8px;
}

.date-group {
  display: none;
}

.config-list {
  overflow: hidden;
  gap: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.movement-card,
.config-item {
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.movement-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 34px;
  gap: 10px;
  align-items: start;
  padding: 12px;
}

.movement-card.is-compact {
  grid-template-columns: minmax(0, 1fr) auto;
}

.movement-card h3 {
  margin-bottom: 5px;
  font-size: 1rem;
}

.movement-note {
  margin-bottom: 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

.tag {
  display: inline-flex;
  min-height: 24px;
  align-items: center;
  width: fit-content;
  padding: 0 9px;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 800;
}

.movement-main .tag {
  margin-bottom: 8px;
}

.movement-side {
  display: grid;
  gap: 4px;
  align-content: start;
  justify-items: end;
}

.amount {
  font-size: 1rem;
}

.amount.expense {
  color: var(--red);
}

.amount.income {
  color: var(--green);
}

.date {
  color: var(--muted);
  font-size: 0.82rem;
}

.movement-meta {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: 1fr;
  gap: 8px;
  margin: 0;
}

.movement-meta div {
  display: flex;
  gap: 8px;
  justify-content: space-between;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}

dt,
dd {
  margin: 0;
  font-size: 0.82rem;
}

dt {
  color: var(--muted);
  font-weight: 800;
}

.delete-action {
  display: grid;
  width: 34px;
  min-width: 34px;
  height: 34px;
  min-height: 34px;
  place-items: center;
  color: var(--red);
  background: transparent;
  border: 1px solid #f0b7b7;
  border-radius: 6px;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1;
}

.empty-state {
  padding: 24px;
  color: var(--muted);
  text-align: center;
  border: 1px dashed var(--line);
  border-radius: 8px;
}

/* Empty-state variant for hints que solo necesitan una línea horizontal,
   no un panel cuadrado que se coma altura. Mismas dashed-borders pero
   con padding y tipografía calibrados para leerse como un aviso, no
   como un placeholder de tarjeta. */
.empty-state--inline {
  padding: 12px 14px;
  font-size: 0.88rem;
  text-align: left;
  margin: 0;
}

.callout-panel {
  border-left: 3px solid var(--teal);
  background: linear-gradient(180deg, rgba(15, 118, 110, 0.045), var(--surface) 60%);
}

details.callout-panel {
  padding: 0;
  overflow: hidden;
}

details.callout-panel > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

details.callout-panel > summary::-webkit-details-marker {
  display: none;
}

details.callout-panel > summary:hover {
  background: rgba(15, 118, 110, 0.04);
}

details.callout-panel .callout-chevron {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--muted);
  transition: transform 0.18s ease;
}

details.callout-panel[open] .callout-chevron {
  transform: rotate(180deg);
}

details.callout-panel .callout-body {
  padding: 0 16px 16px;
}

.callout-panel h2 {
  margin: 0 0 12px;
  font-size: 1.05rem;
  color: var(--text);
}

.callout-panel p {
  margin: 0 0 10px;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--muted);
}

.callout-panel p:last-child {
  margin-bottom: 0;
}

.callout-panel strong {
  color: var(--text);
}

.callout-panel .callout-example {
  padding: 10px 12px;
  background: rgba(15, 118, 110, 0.07);
  border-radius: 6px;
  font-size: 0.93rem;
  color: var(--text);
}

.callout-panel .callout-example strong {
  color: var(--teal);
}

.callout-panel .callout-hint {
  font-size: 0.88rem;
  font-style: italic;
}

.info-button {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  margin-left: 8px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 0.78rem;
  font-weight: 700;
  font-style: italic;
  vertical-align: middle;
  cursor: help;
}

.info-button:hover,
.info-button:focus-visible {
  color: var(--teal);
  border-color: var(--teal);
}

.info-tooltip {
  position: absolute;
  z-index: 30;
  top: calc(100% + 8px);
  left: 50%;
  width: min(280px, 78vw);
  padding: 10px 12px;
  background: #1a242b;
  color: #ffffff;
  border-radius: 6px;
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.82rem;
  font-weight: 400;
  font-style: normal;
  line-height: 1.5;
  text-align: left;
  white-space: normal;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -4px);
  transition: opacity 0.15s ease, transform 0.15s ease;
  box-shadow: var(--shadow);
}

.info-button:hover .info-tooltip,
.info-button:focus-visible .info-tooltip,
.info-button[aria-expanded="true"] .info-tooltip {
  opacity: 1;
  transform: translate(-50%, 0);
  pointer-events: auto;
}

.feedback-status {
  margin: 4px 0 0;
  font-size: 0.88rem;
  color: var(--muted);
}

.feedback-status[data-state="success"] {
  color: var(--green);
}

.feedback-status[data-state="error"] {
  color: var(--red);
}

.feedback-status[data-state="loading"] {
  color: var(--teal);
}

.roadmap-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 12px;
}

.roadmap-list li {
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.roadmap-list li strong {
  font-size: 0.98rem;
  color: var(--text);
}

.roadmap-list li span {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--muted);
}

a.primary-action {
  display: inline-grid;
  place-items: center;
  text-decoration: none;
}

.config-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(110px, 0.8fr) 42px 34px;
  gap: 8px;
  align-items: center;
  min-height: 42px;
  padding: 7px 10px;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
}

.config-item:last-child {
  border-bottom: 0;
}

.config-item strong {
  overflow: hidden;
  font-size: 0.92rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.config-item input,
.config-item select {
  min-height: 32px;
  padding: 5px 8px;
  background: #ffffff;
  font-size: 0.9rem;
}

.config-item .tag {
  justify-self: start;
  margin: 0;
}

.category-list .config-item {
  grid-template-columns: minmax(0, 1fr) 34px 42px;
}

#contacts-list .config-item {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.3fr) auto 42px 34px;
}

.contact-invite-button {
  min-height: 32px;
  padding: 0 12px;
  font-size: 0.84rem;
  white-space: nowrap;
}

.contact-invite-button.is-linked {
  color: var(--green);
  border-color: rgba(24, 121, 78, 0.3);
  background: rgba(24, 121, 78, 0.06);
}

.contact-invite-button.is-linked:hover {
  /* No hover change when already linked — read-only state. */
  color: var(--green);
  border-color: rgba(24, 121, 78, 0.3);
  background: rgba(24, 121, 78, 0.06);
}

/* ==== Invitation modal (recibe el invitado al primer login) ==== */
.invitation-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.invitation-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.invitation-item-text {
  display: grid;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}

.invitation-item-text strong {
  font-size: 0.95rem;
}

.invitation-item-text small {
  color: var(--muted);
  font-size: 0.8rem;
}

.invitation-item .primary-action {
  flex: 0 0 auto;
  min-height: 36px;
  padding: 0 14px;
}

.invitation-feedback {
  margin: 12px 0 0;
  font-size: 0.88rem;
  color: var(--muted);
  min-height: 18px;
}

.invitation-feedback[data-state="error"] {
  color: var(--red);
}

.invitation-feedback[data-state="success"] {
  color: var(--green);
}

/* ==== History modal (registro de cambios por gasto compartido) ==== */
.history-list {
  display: grid;
  gap: 8px;
  margin-top: 12px;
}

.history-item {
  padding: 10px 12px;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.history-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 4px;
  flex-wrap: wrap;
}

.history-meta strong {
  font-size: 0.92rem;
}

.history-meta small {
  color: var(--muted);
  font-size: 0.8rem;
  white-space: nowrap;
}

.history-summary {
  margin: 0;
  color: var(--text);
  font-size: 0.9rem;
  line-height: 1.4;
}

.history-comment {
  margin: 6px 0 0;
  padding: 6px 10px;
  border-left: 2px solid var(--teal);
  color: var(--muted);
  font-size: 0.88rem;
  font-style: italic;
  line-height: 1.4;
}

/* Per-row history button (small clock icon) */
.shared-entry-history {
  display: grid;
  place-items: center;
  width: 26px;
  min-width: 26px;
  height: 26px;
  min-height: 26px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
}

.shared-entry-history:hover {
  color: var(--text);
  border-color: #b8c5cb;
}

/* Comment input shown only while editing a shared entry */
.edit-comment-field[hidden] {
  display: none;
}

.edit-comment-field input {
  font-size: 0.92rem;
}

.label-hint {
  color: var(--muted);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
}

.swatch {
  justify-self: end;
  width: 24px;
  height: 24px;
  border: 1px solid var(--line);
  border-radius: 999px;
}

.config-toolbar {
  grid-template-columns: 1fr 1fr;
  margin-top: 12px;
}

.settings-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-width: 860px;
  margin: 0 auto 8px;
}

.period-toolbar {
  display: grid;
  grid-template-columns: 34px 1fr 34px;
  gap: 8px;
  align-items: center;
  max-width: 360px;
  margin: 0 auto 10px;
}

.period-toolbar strong {
  text-align: center;
  text-transform: capitalize;
}

.compact-summary {
  margin-bottom: 10px;
}

.analysis-grid {
  display: grid;
  gap: 10px;
}

.breakdown-list {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.breakdown-header,
.breakdown-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 56px 60px 110px;
  gap: 8px;
  align-items: center;
  padding: 5px 10px;
}

.breakdown-header {
  min-height: 28px;
  background: #eef2f4;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 900;
  text-transform: uppercase;
}

.breakdown-header-cell {
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.breakdown-header-cell:not(:first-child) {
  justify-self: end;
  text-align: right;
}

.breakdown-header-cell:hover {
  color: var(--text);
}

.breakdown-header-cell.is-active {
  color: var(--nav);
}

.breakdown-row {
  min-height: 32px;
  background: #fbfcfd;
  border-bottom: 1px solid var(--line);
}

.breakdown-row:last-child {
  border-bottom: 0;
}

.breakdown-row strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.breakdown-row span {
  justify-self: end;
}

.balance-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
}

.balance-card {
  display: grid;
  gap: 8px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: 8px;
  text-align: left;
}

.balance-header {
  display: flex;
  gap: 8px;
  align-items: baseline;
  justify-content: space-between;
}

.balance-actions {
  display: grid;
  gap: 6px;
  margin-top: 4px;
}

.balance-action {
  display: grid;
  gap: 2px;
  padding: 8px 10px;
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 6px;
  text-align: left;
}

.balance-action strong {
  font-size: 0.85rem;
  font-weight: 800;
}

.balance-action small {
  color: var(--muted);
  font-size: 0.72rem;
  line-height: 1.25;
}

.balance-action.ghost {
  color: var(--muted);
  text-align: center;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.balance-action.settle {
  color: #ffffff;
  background: var(--nav);
  border-color: var(--nav);
}

.balance-action.settle small {
  color: rgba(255, 255, 255, 0.78);
}

.balance-action[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.balance-card.is-positive {
  border-left-color: var(--green);
}

.balance-card.is-negative {
  border-left-color: var(--red);
}

.balance-card.is-zero {
  opacity: 0.7;
}

.balance-card strong {
  font-size: 0.95rem;
}

.balance-hint {
  color: var(--muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.balance-amount {
  font-size: 1.2rem;
  font-weight: 800;
}

/* Resumen tappable de saldos en móvil cuando el filtro está en "Todos".
   Cada fila muestra nombre + dirección (te debe / le debes / saldado) +
   importe. Al tocar, el card detallado de ese contacto reemplaza el
   resumen y los movimientos compartidos abajo se filtran a su entrada. */
.balance-summary {
  display: grid;
  gap: 8px;
}

.balance-summary-title {
  margin: 0 0 4px;
  color: var(--muted);
  font-size: 0.82rem;
}

.balance-summary-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 6px;
}

.balance-summary-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: rgba(15, 118, 110, 0.08);
}

.balance-summary-row:hover {
  border-color: #b8c5cb;
}

.balance-summary-row.is-positive {
  border-left-color: var(--green);
}

.balance-summary-row.is-negative {
  border-left-color: var(--red);
}

.balance-summary-row.is-zero {
  opacity: 0.7;
}

.balance-summary-name {
  font-size: 0.95rem;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.balance-summary-direction {
  color: var(--muted);
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.balance-summary-amount {
  font-size: 0.98rem;
  font-weight: 800;
  white-space: nowrap;
}

.balance-summary-row.is-positive .balance-summary-amount {
  color: var(--green);
}

.balance-summary-row.is-negative .balance-summary-amount {
  color: var(--red);
}

.balance-card.is-positive .balance-amount {
  color: var(--green);
}

.balance-card.is-negative .balance-amount {
  color: var(--red);
}

/* Mobile-only contact picker en la cabecera del panel Saldos — no se ve
   en desktop. Su valor está sincronizado con el dropdown de la sección
   "Movimientos compartidos" para que ambos viewports compartan estado. */
.shared-mobile-picker {
  display: none;
}

@media (max-width: 719px) {
  .shared-mobile-picker {
    display: grid;
    gap: 4px;
    margin-bottom: 14px;
  }
}

.shared-toolbar {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin: 6px 0 10px;
}

.shared-toolbar label {
  flex: 0 0 220px;
}

.shared-entries {
  display: grid;
  gap: 6px;
}

.shared-entry {
  display: grid;
  /* date | main | amount | (settle) | (history) | (edit) | (delete) —
     up to 7 cols. Trailing "auto" tracks collapse to 0 when the button
     isn't rendered. */
  grid-template-columns: 82px minmax(0, 1fr) repeat(5, auto);
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.shared-entry[data-type="payment"] {
  background: #eef5fb;
  border-color: #cfdfeb;
}

.shared-entry-date {
  color: var(--muted);
  font-size: 0.82rem;
}

.shared-entry-main {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.shared-entry-main strong {
  font-size: 0.92rem;
  white-space: normal;
}

.shared-entry-note,
.shared-entry-breakdown {
  color: var(--muted);
  font-size: 0.78rem;
}

.shared-entry-amount {
  font-size: 0.95rem;
  font-weight: 800;
  white-space: nowrap;
}

.shared-entry-amount.income {
  color: var(--green);
}

.shared-entry-amount.expense {
  color: var(--red);
}

/* Settled rows: dim the whole row + strike the amount, so the user
   sees them in the list as historical / closed but the entry itself
   stays accessible (concept, breakdown, etc. remain readable). */
.shared-entry.is-settled {
  opacity: 0.55;
}

.shared-entry.is-settled .shared-entry-amount {
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
}

.shared-entry-settled-tag {
  display: inline-flex;
  align-items: center;
  margin-top: 2px;
  padding: 1px 7px;
  background: rgba(24, 121, 78, 0.12);
  color: var(--green);
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.shared-entry-settled-tag::before {
  content: "✓";
  margin-right: 3px;
  font-weight: 900;
}

.shared-entry-settle {
  min-height: 30px;
  padding: 0 10px;
  font-size: 0.82rem;
  white-space: nowrap;
}

.shared-entry.is-partner {
  /* A subtle accent on the left edge tells the user this row originated
     in their partner's account (read-only edits in v1). */
  border-left: 3px solid rgba(124, 58, 237, 0.4);
}

.month-group {
  margin-top: 12px;
  padding: 6px 4px 4px;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}

.month-group:first-child {
  margin-top: 0;
}

.shared-contact-control {
  display: flex;
  gap: 6px;
  align-items: stretch;
}

.shared-contact-control select {
  flex: 1 1 auto;
}

.shared-contact-control .icon-button {
  width: 36px;
  min-width: 36px;
  height: auto;
  align-self: stretch;
}

.shared-contact-field,
.shared-mode-field {
  grid-column: 1 / -1;
}

.shared-uneven {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.shared-uneven[hidden] {
  display: none;
}

.shared-uneven-feedback {
  grid-column: 1 / -1;
  margin: 0;
  padding: 6px 8px;
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  font-size: 0.82rem;
}

.shared-uneven-feedback[data-state="ok"] {
  color: var(--green);
  border-color: var(--green);
  background: #ebf5ec;
}

.shared-uneven-feedback[data-state="warn"] {
  color: var(--red);
  border-color: var(--red);
  background: #fbecec;
}

.settings-tab {
  min-height: 30px;
  padding: 0 10px;
  color: var(--muted);
  background: #fbfcfd;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 0.82rem;
  font-weight: 800;
}

.settings-tab.is-active {
  color: #ffffff;
  background: var(--nav);
  border-color: var(--nav);
}

.settings-panel {
  display: none;
}

.settings-panel.is-active {
  display: block;
}

.import-preview {
  white-space: pre-line;
  text-align: left;
}

.save-action {
  display: grid;
  width: 42px;
  min-width: 42px;
  height: 32px;
  min-height: 32px;
  place-items: center;
  color: #ffffff;
  background: var(--teal);
  border: 0;
  border-radius: 6px;
  font-size: 0.72rem;
  font-weight: 900;
  line-height: 1;
}

.config-group {
  margin: 0;
  padding: 8px 10px;
  color: var(--muted);
  background: #eef2f4;
  border-bottom: 1px solid var(--line);
  font-size: 0.78rem;
  font-weight: 900;
  text-transform: uppercase;
}

@media (min-width: 720px) {
  .summary {
    grid-template-columns: repeat(3, 1fr);
  }

  .module-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .analysis-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .movement-form {
    grid-template-columns: repeat(4, 1fr);
  }

  .field-wide {
    grid-column: span 3;
  }

  .primary-action {
    align-self: end;
  }

  .filters {
    grid-template-columns: 2fr 1fr 1fr;
  }

  .settings-form {
    grid-template-columns: 1.2fr 1fr auto;
    align-items: end;
  }

  .config-toolbar {
    grid-template-columns: 180px 180px;
  }

  .movement-card {
    grid-template-columns: minmax(230px, 1.25fr) minmax(110px, 0.55fr) minmax(230px, 1fr) 34px;
    align-items: center;
  }

  .movement-card.is-compact {
    grid-template-columns: minmax(230px, 1.25fr) minmax(110px, 0.55fr) minmax(230px, 1fr);
  }

  .movement-meta {
    grid-column: auto;
  }

  .movement-meta div {
    padding-top: 0;
    border-top: 0;
  }

  .delete-action {
    grid-column: auto;
  }

  .config-item {
    grid-template-columns: minmax(0, 1fr) 170px 42px 34px;
  }

  .category-list .config-item {
    grid-template-columns: minmax(0, 1fr) 34px 42px;
  }
}

@media (min-width: 980px) {
  .shell {
    display: grid;
    grid-template-columns: 76px 1fr;
  }

  .sidebar {
    position: sticky;
    top: 0;
    right: auto;
    bottom: auto;
    left: auto;
    display: flex;
    flex-direction: column;
    height: 100vh;
    padding: 18px 12px;
    background: var(--surface);
    border-top: 0;
    border-right: 1px solid var(--line);
  }

  .brand {
    display: grid;
    place-items: center;
    margin-bottom: 22px;
  }

  .brand-mark {
    display: grid;
    width: 42px;
    height: 42px;
    place-items: center;
    color: #ffffff;
    background: var(--nav);
    border-radius: 8px;
    font-weight: 900;
  }

  .brand div {
    display: none;
  }

  .nav {
    display: grid;
    gap: 10px;
    justify-items: center;
  }

  .nav-separator {
    display: block;
    width: 24px;
    height: 1px;
    background: var(--line);
    margin: 2px 0;
  }

  .nav-button {
    width: 44px;
    padding: 0;
  }

  .nav-button::after {
    top: 50%;
    bottom: auto;
    left: calc(100% + 10px);
    transform: translateY(-50%) translateX(-3px);
  }

  .nav-button:hover::after,
  .nav-button:focus-visible::after {
    transform: translateY(-50%) translateX(0);
  }

  .app {
    margin: 0;
    padding: 28px 28px 48px;
  }

  h1 {
    font-size: 2.6rem;
  }
}

/* Dense mode: FlowGrid prioritizes visible data over spacious cards. */
.sidebar {
  padding: 6px;
}

.nav-button {
  min-height: 34px;
}

.nav-icon {
  width: 16px;
  height: 16px;
}

.app {
  /* Bottom space large enough to clear the fixed mobile sidebar (nav row +
     session-footer row with the email/logout) so the last list item can
     be scrolled fully into view. Desktop overrides this further down. */
  padding: 12px 10px 140px;
}

.topbar {
  margin-bottom: 10px;
}

h1 {
  font-size: 1.65rem;
}

.summary {
  gap: 6px;
  margin-bottom: 8px;
}

.metric {
  min-height: 52px;
  padding: 10px;
}

.panel {
  padding: 10px;
  margin-top: 8px;
}

.section-heading {
  min-height: 22px;
  margin-bottom: 8px;
}

.movement-form,
.filters,
.settings-form,
.config-toolbar {
  gap: 8px;
}

label {
  gap: 4px;
}

input,
select,
textarea,
.date-trigger {
  min-height: 34px;
  padding: 6px 8px;
}

textarea {
  min-height: 52px;
}

.primary-action {
  min-height: 36px;
  padding: 0 12px;
}

.module-card {
  padding: 10px;
}

.movement-list {
  gap: 0;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.movement-header,
.movement-card {
  display: grid;
  grid-template-columns: 78px minmax(100px, 1fr) 84px minmax(120px, 1.3fr) minmax(100px, 0.9fr) minmax(80px, 96px) 76px minmax(70px, 0.6fr) 28px 28px 28px;
  gap: 6px;
  align-items: center;
}

.movement-actions {
  display: contents;
}

.movement-header {
  min-height: 28px;
  padding: 5px 8px;
  color: var(--muted);
  background: #eef2f4;
  border-bottom: 1px solid var(--line);
  font-size: 0.76rem;
  font-weight: 900;
  text-transform: uppercase;
}

.movement-header-cell {
  margin: 0;
  padding: 0;
  color: inherit;
  background: transparent;
  border: 0;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.movement-header-cell:hover {
  color: var(--text);
}

.movement-header-cell.is-active {
  color: var(--nav);
}

.movement-header-cell-static {
  cursor: default;
}

.movement-card {
  min-height: 34px;
  padding: 5px 8px;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
}

.movement-card:last-child {
  border-bottom: 0;
}

.movement-card.is-compact {
  grid-template-columns: 82px minmax(120px, 1fr) 92px minmax(160px, 1.4fr) minmax(130px, 1fr) 112px 88px;
}

.movement-main,
.movement-side,
.movement-meta,
.movement-meta div {
  display: contents;
}

.movement-card h3 {
  order: 2;
  margin: 0;
  overflow: hidden;
  font-size: 0.95rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.movement-note {
  order: 4;
  margin: 0;
  overflow: hidden;
  font-size: 0.84rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.movement-main .tag {
  order: 6;
  margin: 0;
}

.tag {
  min-height: 18px;
  padding: 0 6px;
}

.amount {
  order: 3;
  justify-self: end;
  font-size: 0.95rem;
}

.date,
dd {
  overflow: hidden;
  font-size: 0.82rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.date {
  order: 1;
}

.party {
  order: 5;
}

.recurrence {
  order: 7;
}

.shared-cell {
  order: 8;
  overflow: hidden;
  color: var(--muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.edit-action,
.duplicate-action {
  display: grid;
  place-items: center;
  width: 26px;
  min-width: 26px;
  height: 26px;
  min-height: 26px;
  padding: 0;
  color: var(--nav);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  line-height: 1;
}

.action-icon {
  display: block;
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2;
}

.edit-action {
  order: 9;
}

.duplicate-action {
  order: 10;
}

dt {
  display: none;
}

.movement-card .delete-action {
  order: 11;
  width: 26px;
  min-width: 26px;
  height: 26px;
  min-height: 26px;
}

.config-item {
  min-height: 32px;
  padding: 4px 8px;
}

.config-item input,
.config-item select {
  min-height: 26px;
  padding: 3px 6px;
}

.save-action {
  width: 34px;
  min-width: 34px;
  height: 26px;
  min-height: 26px;
}

.delete-action {
  width: 26px;
  min-width: 26px;
  height: 26px;
  min-height: 26px;
}

@media (min-width: 720px) {
  .movement-card,
  .movement-card.is-compact {
    align-items: center;
  }
}

@media (min-width: 980px) {
  .shell {
    grid-template-columns: 58px 1fr;
  }

  .sidebar {
    padding: 12px 8px;
  }

  .brand-mark {
    width: 32px;
    height: 32px;
  }

  .nav-button {
    width: 34px;
  }

  .app {
    margin: 0 auto;
    padding: 18px 18px 34px;
  }

  h1 {
    font-size: 2rem;
  }

  .topbar,
  .summary,
  .panel {
    max-width: 1040px;
    margin-right: auto;
    margin-left: auto;
  }

  #home-view .panel,
  #settings-view .panel,
  #news-view .panel {
    max-width: 860px;
  }

  #movements-view .panel[aria-labelledby="form-title"] {
    max-width: 940px;
  }

  #movements-view .panel[aria-labelledby="ledger-title"] {
    max-width: 100%;
  }
}

@media (max-width: 719px) {
  .modal {
    align-items: stretch;
    padding: 0;
  }

  .modal-dialog {
    width: 100%;
    max-height: 100vh;
    border-radius: 0;
  }

  /* Mobile-only redesign of the new-movement form: 2-column grid so
     Concepto + Recurrencia can sit side-by-side, plus reordering and
     enlarged inputs. The type-toggle CSS itself lives inline in <head>
     to survive a stale styles.css cache. */
  .movement-form {
    grid-template-columns: repeat(2, 1fr);
  }

  /* By default every direct child spans the full row; only Concepto and
     Recurrencia (which we want side-by-side) override this below. */
  .movement-form > * {
    grid-column: 1 / -1;
  }

  .movement-form .type-toggle           { order: 1; }
  .movement-form > label:nth-of-type(2) { order: 2; grid-column: span 1; } /* Fecha */
  .movement-form > label:nth-of-type(6) { order: 3; grid-column: span 1; } /* Recurrencia */
  .movement-form > label:nth-of-type(3) { order: 4; } /* Importe */
  .movement-form > label:nth-of-type(4) { order: 5; } /* Concepto */
  .movement-form > label:nth-of-type(5) { order: 6; } /* Emisor / receptor */
  .movement-form > label.field-wide     { order: 7; } /* Nota */
  .movement-form > label.toggle-field   { order: 8; } /* Gasto compartido */
  .movement-form > #shared-fields       { order: 9; }
  .movement-form > button[type="submit"]{ order: 10; }

  #date-trigger {
    min-height: 48px;
    padding: 6px 12px;
    font-size: 1.7rem;
    font-weight: 700;
  }

  /* Importe: keep the 3.2rem typography but tighten the box so it
     doesn't look like a billboard. Right padding is wider so the €
     suffix has its own room. */
  #movement-form #amount {
    min-height: 72px;
    padding: 6px 56px 6px 14px;
    font-size: 3.2rem;
    font-weight: 800;
    text-align: center;
  }

  #movement-form .amount-suffix {
    font-size: 2.4rem;
    right: 16px;
  }

  /* Recurrencia (paired with Fecha) and Concepto (full width below):
     same content typography as Fecha so the row reads as a unit. */
  #movement-form #concept,
  #movement-form #recurrence {
    min-height: 48px;
    padding: 4px 10px;
    font-size: 1.7rem;
    font-weight: 700;
  }

  /* Gasto compartido toggle: turn into a proper tappable strip with
     extra breathing room above the Anadir button so it can't be
     missed-tapped. */
  .movement-form .toggle-field {
    min-height: 56px;
    padding: 12px 14px;
    margin-top: 8px;
    background: #fbfcfd;
    border: 1px solid var(--line);
    border-radius: 8px;
  }

  .movement-form .toggle-field input[type="checkbox"] {
    width: 22px;
    height: 22px;
  }

  .movement-form .toggle-field span {
    font-size: 1rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    color: var(--text);
  }

  /* Floating square submit pinned to the bottom-center of the viewport.
     Removed from grid flow via position:fixed; the form gets bottom
     padding so the last in-flow field can't hide behind it. */
  #movement-form {
    padding-bottom: 120px;
  }

  #movement-form > button[type="submit"].movement-submit {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    width: 76px;
    height: 76px;
    min-height: 76px;
    margin: 0;
    padding: 0;
    border-radius: 18px;
    box-shadow: 0 12px 28px rgba(15, 118, 110, 0.32);
    z-index: 50;
  }

  .movement-submit .movement-submit-label {
    display: none;
  }

  .movement-submit .movement-submit-icon {
    display: block;
  }

  /* Title removed on mobile (the modal is unambiguous), and the heading
     row collapses to whatever the feedback line says. */
  #movement-modal #form-title {
    display: none;
  }

  #movement-modal .section-heading {
    min-height: 0;
    margin-bottom: 4px;
    padding-right: 0;
  }

  /* Close button: also fixed at the bottom, smaller than the submit,
     placed to the right of the submit with the same gap. */
  #movement-modal #close-movement-modal {
    position: fixed;
    bottom: 34px;
    left: calc(50% + 56px);
    top: auto;
    right: auto;
    width: 56px;
    height: 56px;
    min-width: 56px;
    min-height: 56px;
    padding: 0;
    border-radius: 14px;
    font-size: 1.6rem;
    font-weight: 700;
    background: rgba(255, 255, 255, 0.95);
    box-shadow: 0 8px 22px rgba(23, 32, 38, 0.14);
    z-index: 50;
  }

  .shared-fields {
    grid-template-columns: 1fr;
  }

  .shared-uneven {
    grid-template-columns: 1fr;
  }

  .shared-toolbar {
    /* Mobile: el dropdown del panel Movimientos compartidos queda oculto
       — la selección del contacto la lleva el picker que sale al inicio
       del panel Saldos (.shared-mobile-picker). Ambos están sincronizados
       vía estado, así que basta con uno visible. */
    display: none;
  }

  /* Móvil: la tarjeta de saldo del contacto se aplana a 2 filas para
     aprovechar el ancho del panel y reducir la altura. Antes era una
     pila vertical (cabecera, importe, dos botones apilados); ahora la
     cabecera + importe van en la primera fila y los dos botones
     comparten la segunda. La rejilla del panel pasa a 1 columna para
     que la card use todo el ancho disponible. */
  .balance-grid {
    grid-template-columns: 1fr;
  }

  .balance-card {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    grid-template-areas:
      "header   amount"
      "actions  actions";
    gap: 8px 12px;
    align-items: center;
    padding: 10px 12px;
  }

  .balance-card .balance-header {
    grid-area: header;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
  }

  .balance-card .balance-header strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
  }

  .balance-card .balance-amount {
    grid-area: amount;
    align-self: center;
    justify-self: end;
    font-size: 1.4rem;
    font-weight: 800;
    white-space: nowrap;
  }

  .balance-card .balance-actions {
    grid-area: actions;
    /* Solo una columna porque "Ver entradas" se oculta en móvil — el
       dropdown del Saldos ya filtra los movimientos abajo, así que el
       botón sería redundante (scrollear ≠ acción). Dejamos solo
       Liquidar saldo a ancho completo. */
    grid-template-columns: 1fr;
    gap: 8px;
    margin-top: 0;
  }

  .balance-card .balance-action {
    padding: 8px 10px;
    text-align: center;
  }

  .balance-card .balance-action.ghost {
    display: none;
  }

  /* En móvil, la subcadena "Raquel te paga / tú pagas a Raquel" se
     omite para no apilar dos líneas en cada botón. La intención del
     botón ya queda clara con el texto principal + el contexto del card. */
  .balance-card .balance-action small {
    display: none;
  }

  .balance-card .balance-action strong {
    font-size: 0.82rem;
  }

  .shared-entry {
    /* Mobile: 5 explicit columns. Amount on row 1 spans the three
       rightmost cells so col 5's width is only what the delete X
       button needs (26px) — otherwise the amount text would widen
       col 5 to ~70px and push the delete button visually away from
       the right edge of the card. With this span, the four action
       buttons in row 3 pack flush against the right edge, with the
       1fr col 1 absorbing all slack. */
    grid-template-columns: minmax(0, 1fr) auto auto auto auto;
    grid-template-areas:
      "date    .        amount   amount   amount"
      "main    main     main     main     main"
      ".       settle   history  edit     delete";
    align-items: center;
    gap: 6px;
  }

  .shared-entry-date { grid-area: date; }

  .shared-entry-amount {
    grid-area: amount;
    justify-self: end;
  }

  .shared-entry-main { grid-area: main; }

  .shared-entry .shared-entry-settle { grid-area: settle; }
  .shared-entry .shared-entry-history { grid-area: history; }
  .shared-entry .edit-action { grid-area: edit; }
  .shared-entry .delete-action { grid-area: delete; }

  .movement-list {
    gap: 8px;
    overflow-x: visible;
    background: transparent;
    border: 0;
  }

  .movement-header {
    display: none;
  }

  .date-group {
    display: block;
    margin: 6px 2px 0;
    color: var(--muted);
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
  }

  .date-group:first-child {
    margin-top: 0;
  }

  /* Simplified mobile card. Row 1: concepto (truncado) + importe.
     Row 2: badges inline (recurrencia si !puntual + compartido si aplica).
     La row 2 colapsa cuando no hay nada que mostrar. La card entera es
     tappable y abre el modal de detalle (gestionado en JS por viewport). */
  .movement-card {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    grid-template-areas:
      "concept amount"
      "meta    meta";
    /* Column-gap only — row spacing is delivered via margin-top on the
       meta row and the expanded section so a collapsed expansion doesn't
       leave a 4px ghost gap. */
    column-gap: 12px;
    row-gap: 0;
    align-items: center;
    min-width: 0;
    min-height: 0;
    padding: 10px 12px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 10px;
    box-shadow: var(--shadow);
    cursor: pointer;
    -webkit-tap-highlight-color: rgba(15, 118, 110, 0.08);
  }

  .movement-card:active {
    background: #fbfcfd;
  }

  /* Caso común (puntual + no compartido): segunda fila desaparece. */
  .movement-card[data-recurrence="puntual"][data-shared="false"] {
    grid-template-rows: auto;
    grid-template-areas: "concept amount";
  }

  .movement-card[data-recurrence="puntual"][data-shared="false"] .movement-meta {
    display: none;
  }

  .movement-card .movement-main {
    display: contents;
  }

  .movement-card .movement-side {
    grid-area: amount;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
  }

  .movement-card .movement-meta {
    grid-area: meta;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 8px;
    align-items: center;
    margin: 4px 0 0;
    min-width: 0;
  }

  .movement-card .movement-meta div {
    display: contents;
  }

  /* Datos que solo viven en el modal de detalle en mobile. */
  .movement-card .movement-note,
  .movement-card .party,
  .movement-card .movement-actions,
  .movement-card .tag,
  .movement-card .date,
  .movement-card dt {
    display: none;
  }

  .movement-card h3 {
    grid-area: concept;
    margin: 0;
    font-size: 0.98rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
  }

  .movement-card .amount {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    white-space: nowrap;
  }

  .movement-card .recurrence {
    display: inline-flex;
    align-items: center;
    padding: 1px 8px;
    color: var(--muted);
    background: rgba(101, 114, 123, 0.1);
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
  }

  .movement-card[data-recurrence="puntual"] .recurrence {
    display: none;
  }

  .movement-card .shared-cell {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 9px 1px 7px;
    color: #5b21b6;
    background: rgba(124, 58, 237, 0.1);
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 18ch;
  }

  .movement-card .shared-cell::before {
    content: "👥";
    font-size: 0.85em;
    margin-right: 1px;
    filter: grayscale(0.2);
  }

  .movement-card[data-shared="false"] .shared-cell {
    display: none;
  }

  /* Inline expansion: the section sits as a third row spanning both
     columns. Collapse uses grid-template-rows 0fr→1fr so the height
     transitions smoothly without measuring it. */
  .movement-card .movement-expanded {
    grid-column: 1 / -1;
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.28s ease-out;
  }

  .movement-card .movement-expanded-inner {
    overflow: hidden;
    min-height: 0;
    opacity: 0;
    transition: opacity 0.18s ease-out;
  }

  .movement-card.is-expanded .movement-expanded {
    grid-template-rows: 1fr;
  }

  .movement-card.is-expanded .movement-expanded-inner {
    opacity: 1;
    transition: opacity 0.22s ease-in 0.06s;
  }

  /* When expanded, the card behaves like a panel: drop the tap-pointer
     hint, slightly emphasise the border, and give the content room. */
  .movement-card.is-expanded {
    border-color: #b8c5cb;
  }

  .movement-card.is-expanded .movement-expanded-inner {
    padding-top: 12px;
    margin-top: 8px;
    border-top: 1px solid var(--line);
  }

  .movement-expanded-list {
    margin: 0;
    display: grid;
    gap: 0;
  }

  .movement-expanded-list > div {
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 8px;
    padding: 7px 0;
    border-bottom: 1px solid rgba(216, 224, 228, 0.6);
  }

  .movement-expanded-list > div:last-child {
    border-bottom: 0;
  }

  .movement-expanded-list > div[hidden] {
    display: none;
  }

  .movement-expanded-list dt {
    display: block;
    margin: 0;
    color: var(--muted);
    font-size: 0.82rem;
    font-weight: 600;
  }

  .movement-expanded-list dd {
    margin: 0;
    font-size: 0.92rem;
    word-break: break-word;
  }

  .movement-expanded-shared {
    margin: 12px 0 0;
    padding: 10px 12px;
    background: rgba(124, 58, 237, 0.06);
    border: 1px solid rgba(124, 58, 237, 0.18);
    border-radius: 8px;
  }

  .movement-expanded-shared[hidden] {
    display: none;
  }

  .movement-expanded-shared h4 {
    margin: 0 0 4px;
    font-size: 0.78rem;
    font-weight: 800;
    color: #5b21b6;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .movement-expanded-shared .movement-expanded-list > div {
    border-bottom: 1px solid rgba(124, 58, 237, 0.14);
  }

  .movement-expanded-shared .movement-expanded-list > div:last-child {
    border-bottom: 0;
  }

  .movement-expanded-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 14px;
  }

  .movement-expanded-actions .primary-action,
  .movement-expanded-actions .ghost-action {
    flex: 1 1 88px;
    min-height: 38px;
    padding: 0 12px;
    white-space: nowrap;
  }

  .movement-expanded-actions .exp-delete-action {
    color: var(--red);
  }

  .movement-expanded-actions .exp-delete-action:hover {
    color: #ffffff;
    background: var(--red);
    border-color: var(--red);
  }

  /* Hint that replaces the action row inside the expanded section for
     virtual movements (rows derived from a partner-owned shared_entry). */
  .movement-expanded-virtual-hint {
    margin: 0;
    padding: 10px 12px;
    color: var(--muted);
    font-size: 0.86rem;
    font-style: italic;
    background: var(--surface-soft);
    border: 1px solid var(--line);
    border-radius: 6px;
    line-height: 1.4;
  }
}

/* Virtual movements derived from a partner-owned shared_entry: the
   action buttons (edit/duplicate/delete) don't apply because the row
   doesn't live in this user's movements table — it's rendered from
   the linked shared_entry. Hide them in both viewports. visibility
   keeps the desktop grid columns intact so the row layout doesn't
   shift. */
.movement-card[data-virtual="true"] .edit-action,
.movement-card[data-virtual="true"] .duplicate-action,
.movement-card[data-virtual="true"] .delete-action {
  visibility: hidden;
}

/* ==== Importe with € suffix ==== */
.amount-input {
  position: relative;
}

.amount-suffix {
  position: absolute;
  top: 50%;
  right: 14px;
  transform: translateY(-50%);
  color: var(--muted);
  font-weight: 700;
  font-size: 1rem;
  pointer-events: none;
}

/* ==== Disabled toggle-field (e.g. Gasto compartido on income) ==== */
.toggle-field:has(input:disabled) {
  opacity: 0.2;
  pointer-events: none;
}

/* ==== Submit icon (visible only on mobile, when the button is square) ==== */
.movement-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.movement-submit-icon {
  display: none;
  width: 36px;
  height: 36px;
}

/* ==== Type toggle (movement form, mobile only) ==== */
.type-toggle {
  display: none;
}

.type-toggle-button {
  display: grid;
  place-items: center;
  min-height: 76px;
  padding: 12px;
  color: var(--muted);
  background: #fbfcfd;
  border: 2px solid var(--line);
  border-radius: 12px;
  font-size: 1.1rem;
  font-weight: 800;
}

.type-toggle-button[data-type-target="expense"].is-active {
  color: var(--red);
  background: rgba(201, 42, 42, 0.08);
  border-color: var(--red);
}

.type-toggle-button[data-type-target="income"].is-active {
  color: var(--green);
  background: rgba(24, 121, 78, 0.08);
  border-color: var(--green);
}

/* ==== Ledger header (panel de movimientos) ====
   Móvil: el header completo (top + filter-bar) queda sticky, así "N
   movimientos", el botón Filtrar y "Nuevo movimiento" siguen accesibles
   al hacer scroll por la lista. Desktop: header normal en flujo, con
   filter-bar permanente debajo (sin toggle). */
.ledger-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}

.ledger-header-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 28px;
}

.ledger-header-top h2 {
  margin: 0;
}

.ledger-actions {
  display: flex;
  gap: 8px;
}

/* ==== Filter bar inline ==== */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

/* The global `input, select { width: 100% }` rule would force each control
   onto its own row in this flex layout. Override so each shrinks to its
   natural width and the text input grows to fill the rest. */
.filter-bar > select,
.filter-bar > input {
  width: auto;
  flex: 0 0 auto;
}

.filter-bar .filter-text {
  flex: 1 1 200px;
  min-width: 0;
}

.filter-bar select {
  min-height: 36px;
}

/* Sticky header en ambos viewports: titulo + botones + filter-bar siguen
   al usuario al hacer scroll. Las medidas concretas se afinan dentro de
   los media queries (margenes negativos para que el bar se extienda
   flush con los bordes del panel, cuyo padding cambia). */
#movements-view .ledger-header {
  position: sticky;
  top: 0;
  z-index: 5;
  margin: -16px -16px 14px;
  padding: 16px 16px 12px;
  background: var(--surface);
  box-shadow: 0 6px 12px -10px rgba(23, 32, 38, 0.18);
}

/* Mobile: bar collapses by default; "Filtrar" toggles it. The desktop-only
   controls (concepto/categoría/tipo dropdowns) are hidden, and the bar's
   own X button moves up to the ledger actions row (left of Filtrar) so the
   bar stays at exactly one line when expanded. */
@media (max-width: 719px) {
  .filter-bar.is-collapsed-mobile {
    display: none;
  }

  .filter-bar .filter-concept-desktop,
  .filter-bar .filter-category-desktop,
  .filter-bar .filter-type-desktop {
    display: none;
  }

  .filter-bar .filter-field-mobile {
    flex: 0 0 auto;
    max-width: 42%;
  }

  /* The bar X is hidden on mobile; the top X (in .ledger-actions) takes
     over so toggling the filter never grows the panel by an extra row.
     Specificity is bumped via the parent class so this beats the global
     `.filter-clear-button { display: grid }` rule that sits later in the
     stylesheet. */
  .filter-bar .filter-clear-button--bar {
    display: none;
  }

  .ledger-actions .filter-clear-button--top {
    width: 32px;
    height: 32px;
    min-height: 32px;
    font-size: 0.92rem;
  }

  /* Tighten the gap on the actions row so X + Filtrar + Nuevo movimiento
     fit comfortably on phones at 360px. */
  .ledger-actions {
    gap: 6px;
  }

  /* En móvil el panel tiene padding 10px (override en línea 1648),
     así que ajustamos los márgenes negativos para que el sticky
     siga sentado flush con los bordes del panel. */
  #movements-view .ledger-header {
    margin: -10px -10px 10px;
    padding: 10px 10px 8px;
  }
}

/* Desktop: bar permanente (ignora cualquier toggle), Filtrar oculto, todos
   los dropdowns visibles + el text input multi-campo. La X del top no tiene
   sentido aquí (la X del bar es lo que usa) así que la ocultamos. */
@media (min-width: 720px) {
  .filter-bar.is-collapsed-mobile,
  .filter-bar {
    display: flex;
  }

  .filter-bar .filter-field-mobile {
    display: none;
  }

  .filter-bar select {
    flex: 0 0 auto;
  }

  .ledger-filter-toggle {
    display: none;
  }

  .ledger-actions .filter-clear-button--top {
    display: none;
  }

  /* Cabeceras de la lista congeladas en desktop:
     - .ledger-header (panel header) ya está sticky en top: 0, ~108px de alto.
     - .movement-header (titulos de columnas) sticky justo debajo.
     - .month-group sticky justo debajo del column-header, scopeado a su
       propia .month-section para que al pasar al siguiente mes el nuevo
       empuje al anterior fuera de la vista de forma natural.
     Para que sticky funcione hay que descartar el overflow-x: auto del list
     (creaba un scroll-container que rompía el sticky). En narrow desktops
     (~720-980px) la tabla puede causar scroll horizontal de la página; en
     anchos normales (≥980, donde el panel max-width: 1040 entra) cabe sin
     problema. */
  .movement-list {
    overflow-x: visible;
  }

  .movement-header {
    position: sticky;
    top: 108px;
    z-index: 4;
    /* Altura exacta = 148px (top de .month-group) - 108px (top propio).
       Sin esto el min-height: 28px deja un hueco transparente entre la
       cabecera de columnas y el separador de mes por el que se ven las
       filas scrolleando por detrás. */
    min-height: 40px;
  }

  /* Cada .month-section es el "containing block" del sticky de su propia
     .month-group: cuando la sección termina (siguiente mes empieza), el
     header se desadhiere de forma natural en lugar de quedar pegado
     indefinidamente y solapar con el siguiente. */
  .month-group {
    position: sticky;
    top: 148px;
    z-index: 3;
    margin-top: 0;
    background: var(--surface);
  }
}

.ghost-action {
  min-height: 36px;
  padding: 0 14px;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-weight: 700;
}

.ghost-action:hover {
  color: var(--text);
  border-color: #b8c5cb;
}

.filter-clear-button {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  min-height: 36px;
  padding: 0;
  color: #ffffff;
  background: var(--red);
  border: 0;
  border-radius: 6px;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1;
}

/* The HTML `hidden` attribute is the API used to toggle this button;
   without this rule the `display: grid` above wins and the button stays
   visible even when no filters are active. */
.filter-clear-button[hidden] {
  display: none;
}

.filter-clear-button:hover {
  background: #a82222;
}

/* ==== Danger zone (settings) ==== */
.danger-panel {
  border-color: #f0b7b7;
}

.danger-blurb {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.45;
}

.danger-blurb strong {
  color: var(--red);
}

.danger-action {
  min-height: 36px;
  padding: 0 14px;
  color: var(--red);
  background: transparent;
  border: 1px solid #f0b7b7;
  border-radius: 6px;
  font-weight: 800;
}

.danger-action:hover {
  color: #ffffff;
  background: var(--red);
  border-color: var(--red);
}

/* ==== Build version label (fixed, top-right) ==== */
.app-version {
  position: fixed;
  top: 4px;
  right: 6px;
  z-index: 60;
  padding: 1px 5px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.7);
  border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
  font-size: 0.66rem;
  opacity: 0.5;
  pointer-events: none;
  user-select: none;
}

/* ==== Auth gate ==== */
body.is-locked .shell {
  display: none;
}

.auth-gate {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--background, #f5f5f5);
  z-index: 100;
  padding: 24px;
}

/* The `hidden` attribute is the JS API we use to toggle the gate; without
   this rule the `display: grid` above wins and the gate stays visible. */
.auth-gate[hidden] {
  display: none;
}

.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--card, #fff);
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 12px;
  padding: 32px 28px;
  display: grid;
  gap: 16px;
}

.auth-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 18px;
}

.auth-card h1 {
  margin: 0;
  font-size: 22px;
}

.auth-blurb {
  margin: 0;
  color: var(--muted, #666);
  font-size: 14px;
  line-height: 1.5;
}

.auth-form {
  display: grid;
  gap: 12px;
}

.auth-form label {
  display: grid;
  gap: 4px;
  font-size: 13px;
  color: var(--muted, #666);
}

.auth-form input {
  font-size: 15px;
  padding: 10px 12px;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 8px;
}

#auth-feedback {
  margin: 0;
  font-size: 13px;
  color: var(--muted, #666);
  min-height: 18px;
}

/* ==== Session indicators in sidebar ====
   Email = chivato (no clickable). Logout = button.
   Mobile: each occupies one cell of the 5-col sidebar grid.
   Desktop: pushed to the bottom of the flex-column sidebar via margin-top:auto on email. */
.session-email {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  padding: 2px 4px;
  font-size: 10px;
  line-height: 1.15;
  color: var(--muted);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-all;
}

.session-email:empty {
  visibility: hidden;
}

.session-logout {
  display: grid;
  place-items: center;
  min-height: 34px;
  padding: 6px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
}

.session-logout:hover {
  color: var(--text);
  background: rgba(23, 32, 38, 0.05);
}

@media (min-width: 980px) {
  .session-email {
    width: 100%;
    margin-top: auto;
    padding: 6px 4px 2px;
  }

  .session-logout {
    width: 34px;
    align-self: center;
  }
}

/* ==== Movement card inline expansion (móvil; se abre al tocar la card) ====
   Hidden globally so desktop never paints it; the @media (max-width: 719px)
   block below enables the smooth expand/collapse animation via the
   grid-template-rows 0fr→1fr trick. */
.movement-expanded {
  display: none;
}
