/* ── Design tokens ─────────────────────────────────────────────────────────── */
:root {
  /* ── Colour palette ── */
  --bg:           #ede0e2;
  --bg-frame:     #d4c4c8;  /* desktop frame behind the contained shell */
  --surface:      #fdf7f8;
  --surface-warm: #faeef0;
  --border:       #d6c4c8;
  --border-soft:  #e4d4d8;
  --text:      #1e0c10;
  --text-soft: #7a4a54;  /* secondary labels, meta text */
  --text-dim:  #a07880;  /* timestamps, placeholders, tertiary */

  --accent:        #b5446a;
  --accent-bright: #d05482;
  --accent-hover:  #9a3759;
  --accent-dark:   #7c3d52;  /* pressed/active state for primary button */
  --accent-bg:     #fce8ef;
  --accent-rgb:    181, 68, 106;

  --green:       #1a5c3a;
  --green-light: #d1fae5;
  --green-rgb:   26, 92, 58;

  --danger:       #b91c1c;
  --danger-light: #fee2e2;
  --danger-rgb:   185, 28, 28;

  --income:     #16a34a;  /* WCAG AA only at large/bold sizes (~3.1:1 on --surface) */
  --income-rgb: 22, 163, 74;
  --done-text: #b09098;  /* intentionally below AA — decorative de-emphasis on completed items */
  --white:     #fff;


  /* Calendar event colours — prevents hardcoded hex proliferation */
  --cal-wish:      #f59e0b;
  --cal-wish-bg:   #fef3c7;
  --cal-wish-text: #b45309;  /* ≈5.7:1 on --cal-wish-bg (WCAG AA) */
  --cal-gcal:      #4285f4;
  --cal-gcal-bg:   #e8f0fe;
  --cal-gcal-text: #1a56db;  /* darkened from #4285f4 — was 3.6:1, now ≈6:1 on --cal-gcal-bg */

  /* ── Layout ── */
  --tab-h:           64px;
  --safe-b:          env(safe-area-inset-bottom, 0px); /* iPhone home indicator */
  --radius:          6px;
  --radius-sm:       4px;   /* small elements: tags, badges, source chips */
  --radius-full:     9999px;
  --border-accent-w: 3px;   /* accent left-stripe width on list cards */

  /* ── Elevation ── */
  --shadow-rgb: 80, 30, 40;  /* shared base for all shadow colours */
  --shadow:    0 1px 3px rgba(var(--shadow-rgb),.10), 0 4px 16px rgba(var(--shadow-rgb),.14);
  --shadow-md: 0 2px 6px rgba(var(--shadow-rgb),.10), 0 12px 32px rgba(var(--shadow-rgb),.18);

  /* ── Overlay colours ── */
  --overlay:       rgba(0,0,0,.50);  /* modal backdrops */
  --overlay-light: rgba(0,0,0,.35);  /* sheet backdrops */

  /* ── Z-index stack ── */
  --z-header:        10;
  --z-add-form:      15;
  --z-tabbar:        20;
  --z-sheet:         50;   /* backdrops + floating menus */
  --z-sheet-content: 51;
  --z-toast:         100;
  --z-modal:         200;

  /* ── Motion ── */
  --transition:       .15s;  /* snappy UI feedback (hover, active) */
  --transition-md:    .25s;  /* panel entrances (add form, filter sheet) */
  --transition-bloom: .55s;  /* phulkari bloom keyframe — decorative only */
  --ease:             ease;
  --ease-out:         cubic-bezier(0, 0, .2, 1);  /* decelerate into resting state */
  --ease-in-out:      cubic-bezier(.4, 0, .2, 1); /* standard material motion */

  /* ── Typography scale (rem at 16px base) ── */
  --text-xs:    .6875rem;  /* 11px — tab labels, micro (floor for accessibility) */
  --text-sm:    .75rem;    /* 12px — tags, chips, captions, meta  */
  --text-md:    .875rem;   /* 14px — secondary body, meta         */
  --text-base:  .9375rem;  /* 15px — primary body                 */
  --text-input: 1rem;      /* 16px — inputs/selects: prevents iOS Safari zoom   */
  --text-lg:    1.125rem;  /* 18px — subheadings                  */
  --text-xl:    1.25rem;   /* 20px — section titles               */
  --text-header: 1.5rem;   /* 24px — app header h1                */
  --text-2xl:   1.875rem;  /* 30px — login title                  */

  /* ── Line height ── */
  --lh-tight:  1.35;
  --lh-normal: 1.5;

  /* ── Font weight system ──
     400  body text (inputs, display headings)
     500  toast, slightly emphasised body
     600  btn, summary-label, login label, modal-label — semibold
     700  tags, chips, group-headers, tab labels — bold/uppercase elements  */

  /* ── Letter spacing ── */
  --ls-tight:   .05em;   /* tags, chips */
  --ls-caps:    .07em;   /* uppercase labels */
  --ls-heading: -.01em;  /* serif display headings */
  --ls-display: -.02em;  /* large login title */

  /* ── Spacing scale (4px base) ── */
  --sp-1: .25rem;   /*  4px */
  --sp-2: .5rem;    /*  8px */
  --sp-3: .75rem;   /* 12px */
  --sp-4: 1rem;     /* 16px */
  --sp-5: 1.25rem;  /* 20px */
  --sp-6: 1.5rem;   /* 24px */
  --sp-7: 1.75rem;  /* 28px */
  --sp-8: 2rem;     /* 32px */

  /* ── Derived layout tokens ── */
  --add-form-h:       4.25rem;  /* collapsed add form: .75rem pad×2 + input (~2.75rem) */
  --card-pad:         .75rem 1rem;     /* standard list card padding */
  --card-pad-sm:      .5rem .75rem;    /* compact card padding */

  /* ── Select chevron — shared by all <select> elements ── */
  --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E");

  /* ── Dark mode — override these 10 tokens in a prefers-color-scheme: dark block:
     --bg, --bg-frame, --surface, --surface-warm, --border, --border-soft,
     --text, --text-soft, --text-dim, --done-text                              */

  /* ── Tricolor stripe — saffron | forest | sindoor ──
     Fixed colours: represents the Indian flag palette.
     Intentionally does NOT adapt to dark mode.          */
  --stripe: linear-gradient(90deg, #e07b0a 0% 33%, #1a5c3a 33% 66%, #b91c1c 66% 100%);
}


/* ── Reset ─────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; -webkit-text-size-adjust: 100%; }
body {
  font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: var(--lh-normal);
}
input:not([type="checkbox"]):not([type="radio"]), button, select, textarea { -webkit-appearance: none; appearance: none; font: inherit; }
input[type="checkbox"], input[type="radio"] { font: inherit; }
button { cursor: pointer; border: none; background: none; border-radius: 0; padding: 0; }
a { color: var(--accent); }

/* ── Accessibility utilities ───────────────────────────────────────────────── */

/* Visually hidden but available to screen readers */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Focus ring — shown only on keyboard navigation, not on mouse click */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Item text used as an edit trigger — make it clear it's interactive */
.item-text[role="button"] {
  cursor: pointer;
  border-radius: var(--radius);
}
.item-text[role="button"]:focus-visible {
  outline-offset: -2px;
}

/* ── Material Symbols Outlined ─────────────────────────────────────────────── */
/* Variable font: FILL=0 (outlined), wght=400, GRAD=0, opsz=24 (default axes). */
.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  font-weight: normal;
  font-style: normal;
  line-height: 1;
  display: inline-block;
  vertical-align: middle;
  white-space: nowrap;
  -webkit-font-smoothing: antialiased;
}

.login-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100dvh;
  padding: 1.5rem;
  background: var(--bg);
}

.app-content {
  flex: 1;
  overflow-y: auto;
  padding: 1.25rem 1rem calc(var(--tab-h) + var(--safe-b) + 1.5rem);
}

.section-title {
  font-family: 'DM Serif Display', Georgia, serif;
  font-size: var(--text-xl);
  font-weight: 400;
  letter-spacing: var(--ls-heading);
  margin-bottom: var(--sp-4);
  color: var(--text);
}


.finance-summary {
  background: var(--surface-warm);
  border: 1px solid var(--border-soft);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 1rem;
  margin-bottom: 1.25rem;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: .5rem;
  text-align: center;
  box-shadow: var(--shadow);
}

/* ══════════════════════════════════════════════════════════════════════════════
   MOTIF 4 — PHULKARI ACTIVE-TAB INDICATOR (Punjab)
   In phulkari, colorful beads and knots mark intersections of the lattice.
   The active tab glows in the accent colour — like a thread tightening into a knot.
══════════════════════════════════════════════════════════════════════════════ */

.tab-btn[aria-selected="true"] { color: var(--accent); }


/* ── Login page ────────────────────────────────────────────────────────────── */
.login-container {
  position: relative;
  width: 100%;
  max-width: 360px;
  background: var(--surface);
  border-radius: var(--radius);
  padding: 2.25rem 2rem;
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.login-container::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: var(--stripe);
  pointer-events: none;
}

.login-title {
  font-family: 'DM Serif Display', Georgia, serif;
  font-size: var(--text-2xl);
  font-weight: 400;
  text-align: center;
  margin-bottom: .25rem;
  color: var(--text);
  letter-spacing: var(--ls-display);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
}
.login-title .material-symbols-outlined { font-size: var(--text-header); color: var(--accent); }

.login-subtitle {
  font-size: var(--text-md);
  text-align: center;
  color: var(--text-soft);
  margin-bottom: 1.75rem;
}

.login-form {
  display: flex;
  flex-direction: column;
  gap: .75rem;
}
.login-form label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  margin-bottom: -.25rem;
}
.form-error {
  color: var(--danger);
  font-size: var(--text-md);
  margin: 0;
}

/* ── App shell ─────────────────────────────────────────────────────────────── */
.app-shell {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

.app-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--surface-warm);
  border-bottom: 1px solid var(--border);
  border-top: 3px solid var(--accent);
  padding: max(.75rem, env(safe-area-inset-top)) 1.125rem .75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  box-shadow: 0 2px 12px rgba(var(--shadow-rgb),.12); /* downward — lifts header above content; direction-specific, not a --shadow token */
}

.app-header h1 {
  font-family: 'DM Serif Display', Georgia, serif;
  font-size: var(--text-header);
  font-weight: 400;
  letter-spacing: var(--ls-heading);
  color: var(--accent);
  display: flex;
  align-items: center;
  gap: .375rem;
}
.app-header h1 .material-symbols-outlined { font-size: var(--text-header); }

.app-header .user-chip {
  display: flex;
  align-items: center;
  gap: .25rem;
  position: relative;
}
/* User menu dropdown */
.user-menu-dropdown {
  position: absolute;
  top: calc(100% + .5rem);
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  min-width: 9rem;
  z-index: var(--z-sheet);
  overflow: hidden;
}
.user-menu-item {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
  padding: .625rem 1rem;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-soft);
  text-align: left;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.user-menu-item:hover {
  background: var(--surface-warm);
  color: var(--text);
}
/* Sign out is destructive — red on hover */
#logout-btn:hover {
  background: var(--danger-light);
  color: var(--danger);
}
.user-menu-item .material-symbols-outlined { font-size: var(--text-base); }

/* ── Bottom tab bar ────────────────────────────────────────────────────────── */
.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: var(--z-tabbar);
  height: calc(var(--tab-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  background: var(--surface-warm);
  border-top: 1px solid var(--border);
  box-shadow: 0 -4px 16px rgba(var(--shadow-rgb),.14); /* upward — lifts tab bar above content; direction-specific, not a --shadow token */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(3rem, 1fr));
}

.tab-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-1);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-soft);
  transition: color var(--transition);
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + .6rem);
  position: relative;
}

.tab-btn .tab-icon { font-size: 1.375rem; line-height: 1; }
.tab-btn:disabled { opacity: .35; cursor: not-allowed; }

/* Centre home button — slightly larger icon */
#tab-home .tab-icon { font-size: 1.7rem; }


/* ── Tab panels ────────────────────────────────────────────────────────────── */
.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* ── Inline form row (expense form) ──────────────────────────────────────── */
.form-row {
  display: flex;
  gap: .5rem;
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}
.form-row input, .form-row select {
  flex: 1;
  min-width: 0;
}

/* ── Inputs ────────────────────────────────────────────────────────────────── */
input[type="text"],
input[type="number"],
input[type="date"],
input[type="password"],
input[type="url"],
select {
  display: block;
  width: 100%;
  padding: .625rem .875rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  outline: none;
  transition: border-color var(--transition), box-shadow var(--transition);
}
select {
  padding-right: 2rem;
  background-image: var(--select-arrow);
  background-repeat: no-repeat;
  background-position: right .5rem center;
  background-size: 8px;
  cursor: pointer;
}
/* iOS Safari collapses empty date inputs to nothing — lock in the same
   height as other inputs and a minimum width that holds the date string. */
input[type="date"] {
  min-height: calc(1.5rem + 1.25rem); /* line-height + top+bottom padding */
  min-width: clamp(7rem, 50%, 9rem);  /* 9rem max; shrinks on narrow screens */
  box-sizing: border-box;
}
input:focus-visible, select:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18);  /* more visible than --accent-bg on white */
}
/* Fallback for browsers without :focus-visible (Safari <15.4).
   Covers inputs, selects, buttons, anchors, and any custom tabindex element. */
@supports not selector(:focus-visible) {
  input:focus,
  select:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18);
  }
  button:focus,
  a:focus,
  [tabindex]:focus {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
}

/* ── Buttons ───────────────────────────────────────────────────────────────── */
.btn {
  padding: .625rem 1.125rem;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: var(--text-base);
  transition: background var(--transition), color var(--transition), border-color var(--transition), opacity var(--transition);
  white-space: nowrap;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-soft);
}
.btn:hover  { background: var(--surface-warm); border-color: var(--border); }
.btn:active { background: var(--border-soft); }
.btn-primary {
  background: var(--accent);
  color: var(--white);
  border-color: transparent;  /* prevent .btn border showing if both classes applied */
}
.btn-primary:hover { background: var(--accent-hover); }
.btn-primary:active { background: var(--accent-dark); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; pointer-events: none; }

.btn-icon {
  font-size: var(--text-input);
  color: var(--text-soft);
  padding: .25rem .375rem;
  min-width: 44px;   /* WCAG 2.5.5 minimum touch target */
  min-height: 44px;
  border-radius: var(--radius);
  transition: color var(--transition);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.btn-icon:hover { color: var(--accent); }  /* default hover — accent, not danger */
/* Delete/close actions turn red on hover */
[data-action*="delete"] .btn-icon:hover,
.btn-icon[data-action*="delete"]:hover,
.list-item > .btn-icon:hover { color: var(--danger); }
.item-link.btn-icon {
  min-width: unset; /* intentional — inline link icon, not a standalone touch target */
  min-height: unset;
  padding: 0 .1rem;
  vertical-align: middle;
  font-size: var(--text-sm);
}
.item-link .material-symbols-outlined { font-size: var(--text-md); }

/* ── List items ────────────────────────────────────────────────────────────── */
.list { display: flex; flex-direction: column; gap: var(--sp-2); }

.list-item {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: var(--card-pad);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  box-shadow: var(--shadow);
  border-left: var(--border-accent-w) solid var(--border);
  transition: border-left-color var(--transition);
}
/* ══════════════════════════════════════════════════════════════════════════════
   MOTIF 8 — PHULKARI COLOUR BLOOM (Punjab)
   On hover, the left border cycles through saffron → forest green → sindoor
   before settling on the accent — like a thread tightening into a stitch.
══════════════════════════════════════════════════════════════════════════════ */
.list-item:not(.done) { will-change: border-left-color; }
.list-item:not(.done):hover {
  animation: phulkari-bloom var(--transition-bloom) var(--ease-out) forwards;
}
@keyframes phulkari-bloom {
  0%   { border-left-color: var(--border); }        /* smooth start from resting state */
  20%  { border-left-color: var(--accent-bright); }
  45%  { border-left-color: var(--green); }
  75%  { border-left-color: var(--danger); }
  100% { border-left-color: var(--accent); }
}
.list-item.done {
  border-left-color: var(--border);
}
/* Selectively mute done card text — avoid blanket opacity which tanks contrast for all children */
.list-item.done .item-text,
.list-item.done .item-meta,
.list-item.done .todo-due,
.list-item.done .todo-meta-assignee {
  color: var(--done-text);
}
.list-item.done .item-text {
  text-decoration: line-through;
}

.item-text { flex: 1; font-size: var(--text-base); }
.item-meta { font-size: var(--text-sm); color: var(--text-soft); }


.item-check {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* ── Finance specifics ─────────────────────────────────────────────────────── */
.expense-amount {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.expense-amount.income { color: var(--income); }
.expense-amount.expense { color: var(--danger); }

.summary-label {
  font-size: var(--text-xs);
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  font-weight: 600;
}
.summary-value {
  font-size: var(--text-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin-top: .125rem;
}
.balance-positive { color: var(--income); }
.balance-negative { color: var(--danger); }

/* ── Home / Calendar ───────────────────────────────────────────────────────── */
.cal-greeting {
  font-family: 'DM Serif Display', Georgia, serif;
  font-size: var(--text-xl);
  font-weight: 400;
  letter-spacing: var(--ls-heading);
  color: var(--text);
  margin-bottom: var(--sp-4);
}
.cal-card {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--sp-4) var(--sp-4) var(--sp-4);
  margin-bottom: var(--sp-4);
}
.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: .75rem;
  margin-bottom: .5rem;
  border-bottom: 1px solid var(--border-soft);
}
.cal-month-label {
  font-family: 'DM Serif Display', Georgia, serif;
  font-size: var(--text-lg);
  font-weight: 400;
  letter-spacing: var(--ls-heading);
}
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.cal-weekday {
  text-align: center;
  font-size: var(--text-xs);
  color: var(--text-soft);
  padding: .25rem 0 .375rem;
  font-weight: 700;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}
.cal-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: .25rem .125rem .3rem;
  border-radius: var(--radius);
  cursor: pointer;
  min-height: 2.75rem; /* increased from 2.625rem for better tap surface */
  min-width: 2rem;     /* prevents cells collapsing below tap-worthy width on narrow screens */
}
.cal-day:hover:not(.cal-day-empty)  { background: var(--surface-warm); }
.cal-day:active:not(.cal-day-empty) { background: var(--accent-bg); }
.cal-day-empty { cursor: default; }
.cal-day-num {
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
}
.cal-day.today .cal-day-num {
  background: var(--accent);
  color: var(--white);
  font-weight: 700;
}
.cal-day.selected:not(.today) .cal-day-num {
  outline: 2px solid var(--accent);
}
.cal-day-dots {
  display: flex;
  gap: 3px;
  margin-top: 3px;
  height: .3rem;
  align-items: center;
}
.cal-dot {
  width: .3rem;
  height: .3rem;
  border-radius: 50%;
  flex-shrink: 0;
}
.cal-dot--todo    { background: var(--accent); }
.cal-dot--expense { background: var(--income); }
.cal-dot--wish    { background: var(--cal-wish); }
.cal-dot--gcal    { background: var(--cal-gcal); }

/* Events panel */
.cal-events { margin-top: .25rem; }
.cal-events-date {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-soft);
  display: flex;
  align-items: center;
  gap: .5rem;
  padding-bottom: .375rem;
  margin-bottom: .625rem;
}
.cal-events-date::after {
  content: '';
  flex: 1;
  height: 1px;
  background: repeating-linear-gradient(
    90deg,
    var(--border) 0, var(--border) 4px,
    transparent 4px, transparent 8px
  );
}
.cal-events-list {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.cal-event-row {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: var(--card-pad-sm);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  border-left-width: var(--border-accent-w);
}
.cal-event-row--todo    { border-left-color: var(--accent); }
.cal-event-row--expense { border-left-color: var(--income); }
.cal-event-row--wish    { border-left-color: var(--cal-wish); }
.cal-event-row--gcal    { border-left-color: var(--cal-gcal); }
.cal-event-body { flex: 1; min-width: 0; }
.cal-event-title {
  font-size: var(--text-base);
  line-height: var(--lh-tight);
}
.cal-event-title.done {
  color: var(--done-text);
  text-decoration: line-through;
}
.cal-event-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  flex-wrap: wrap;
  font-size: var(--text-sm);
  color: var(--text-soft);
  margin-top: .25rem;
}
.cal-event-source {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  padding: .125rem .375rem;
  border-radius: var(--radius-sm);
}
.cal-event-row--todo    .cal-event-source { background: var(--accent-bg);    color: var(--accent);        }
.cal-event-row--expense .cal-event-source { background: var(--green-light);  color: var(--income);        }
.cal-event-row--wish    .cal-event-source { background: var(--cal-wish-bg);  color: var(--cal-wish-text); }
.cal-event-row--gcal    .cal-event-source { background: var(--cal-gcal-bg);  color: var(--cal-gcal-text); }
.cal-allday-row {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-1) var(--sp-3);
  border-left: 2px solid var(--cal-gcal);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--cal-gcal-bg);  /* fallback for Safari <16.2 */
  background: color-mix(in srgb, var(--cal-gcal-bg) 60%, transparent);
  font-size: var(--text-sm);
  color: var(--text-soft);
  overflow: hidden;
}
.cal-allday-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--cal-gcal-text);
  flex-shrink: 0;
}
.cal-allday-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-event-time {
  font-size: var(--text-sm);
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}

/* ── Empty state ───────────────────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════════════════════
   MOTIF 9 — GIDDHA DOT RINGS (Punjab)
   Giddha dancers form concentric circles. Empty states carry three dashed
   rings in saffron, forest green, and sindoor red as a faint watermark.
   Note: SVG data URL — CSS custom properties cannot be used inside data: URIs.
══════════════════════════════════════════════════════════════════════════════ */
.empty {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 5rem 1rem;
  color: var(--text-soft);
  font-size: var(--text-base);
  position: relative;
}
.empty::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 160px;
  height: 160px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 160'%3E%3Ccircle cx='80' cy='80' r='35' fill='none' stroke='rgba(194,105,10,.16)' stroke-width='1.5' stroke-dasharray='4 4'/%3E%3Ccircle cx='80' cy='80' r='55' fill='none' stroke='rgba(26,92,58,.11)' stroke-width='1.5' stroke-dasharray='5 5'/%3E%3Ccircle cx='80' cy='80' r='73' fill='none' stroke='rgba(185,28,28,.07)' stroke-width='1.5' stroke-dasharray='6 6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 160px 160px;
  pointer-events: none;
}
.empty--compact {
  padding: 1rem 0;
}
.empty--compact::before {
  display: none;
}

/* ══════════════════════════════════════════════════════════════════════════════
   MOTIF 7 — NAKSHI KANTHA FISH (Bengal)
   The maach (fish) is the most auspicious Bengali motif — prosperity,
   abundance. A stylized fish watermark behind the grocery empty state.
   Note: SVG data URL — CSS custom properties cannot be used inside data: URIs.
══════════════════════════════════════════════════════════════════════════════ */
#grocery-list .empty::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 140 80'%3E%3Cellipse cx='60' cy='40' rx='38' ry='24' fill='none' stroke='rgba(194,105,10,.13)' stroke-width='2'/%3E%3Cpolygon points='98,40 118,22 118,58' fill='none' stroke='rgba(194,105,10,.13)' stroke-width='2'/%3E%3Ccircle cx='34' cy='36' r='3.5' fill='rgba(194,105,10,.15)'/%3E%3Cpath d='M48,16 Q68,5 82,24' fill='none' stroke='rgba(194,105,10,.1)' stroke-width='1.5'/%3E%3Cpath d='M52,52 Q64,62 78,56' fill='none' stroke='rgba(194,105,10,.08)' stroke-width='1.5'/%3E%3C/svg%3E");
  background-size: 180px 100px;
  width: 180px;
  height: 100px;
}

/* ══════════════════════════════════════════════════════════════════════════════
   MOTIF 8 — PADMA (Lotus / পদ্ম, Bengal)
   The lotus symbolises beauty, aspiration and purity — fitting for a wishlist.
   Five petals rise from water ripples; accent pink at low opacity.
   Note: SVG data URL — CSS custom properties cannot be used inside data: URIs.
══════════════════════════════════════════════════════════════════════════════ */
#wishlist-list .empty::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 140 110'%3E%3Cpath d='M70,82 C63,68 63,48 70,34 C77,48 77,68 70,82' fill='none' stroke='rgba(181,68,106,.15)' stroke-width='1.5'/%3E%3Cpath d='M70,82 C59,72 52,52 58,37 C67,47 70,66 70,82' fill='none' stroke='rgba(181,68,106,.12)' stroke-width='1.5'/%3E%3Cpath d='M70,82 C81,72 88,52 82,37 C73,47 70,66 70,82' fill='none' stroke='rgba(181,68,106,.12)' stroke-width='1.5'/%3E%3Cpath d='M70,82 C55,76 41,60 46,43 C58,53 67,69 70,82' fill='none' stroke='rgba(181,68,106,.09)' stroke-width='1.5'/%3E%3Cpath d='M70,82 C85,76 99,60 94,43 C82,53 73,69 70,82' fill='none' stroke='rgba(181,68,106,.09)' stroke-width='1.5'/%3E%3Cpath d='M70,82 C56,86 40,84 38,78 C50,77 62,80 70,82' fill='none' stroke='rgba(181,68,106,.08)' stroke-width='1'/%3E%3Cpath d='M70,82 C84,86 100,84 102,78 C90,77 78,80 70,82' fill='none' stroke='rgba(181,68,106,.08)' stroke-width='1'/%3E%3Cpath d='M30,92 Q50,88 70,92 Q90,96 110,92' fill='none' stroke='rgba(181,68,106,.07)' stroke-width='1'/%3E%3Cpath d='M42,100 Q56,97 70,100 Q84,103 98,100' fill='none' stroke='rgba(181,68,106,.05)' stroke-width='1'/%3E%3C/svg%3E");
  background-size: 160px 125px;
  width: 160px;
  height: 125px;
}

/* ── Form layout helpers ───────────────────────────────────────────────────── */
#expense-form { flex-wrap: wrap; }
#expense-desc     { flex: 1 1 140px; }
#expense-amount   { flex: 0 1 100px; }
#expense-type     { flex: 0 1 100px; }
#expense-category { flex: 1 1 120px; }



/* ── Skeleton loaders ───────────────────────────────────────────────────────── */
@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}
/* Base shimmer block — applied to each placeholder shape */
.sk {
  background: linear-gradient(
    90deg,
    var(--surface-warm) 0%,
    var(--border)       50%,
    var(--surface-warm) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s linear infinite;
  border-radius: var(--radius-sm);
}
/* Card shell — matches .list-item dimensions exactly */
.skeleton-card {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-left: var(--border-accent-w) solid var(--border);
  border-radius: var(--radius);
  padding: var(--card-pad);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  box-shadow: var(--shadow);
}
/* Checkbox-sized circle */
.sk--check  { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; }
/* Title and meta bars */
.sk-body    { flex: 1; display: flex; flex-direction: column; gap: .4rem; }
.sk--line   { height: .875rem; width: 65%; }
.sk--meta   { height: .75rem;  width: 38%; }
/* Delete-button-sized circle */
.sk--action { width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0; }
/* Vary card widths so they don't look identical */
.skeleton-card:nth-child(1) .sk--line { width: 72%; }
.skeleton-card:nth-child(2) .sk--line { width: 55%; }
.skeleton-card:nth-child(3) .sk--line { width: 68%; }
.skeleton-card:nth-child(4) .sk--line { width: 44%; }
.skeleton-card:nth-child(5) .sk--line { width: 71%; }

/* ── Toast notifications ───────────────────────────────────────────────────── */
.toast {
  position: fixed;
  bottom: calc(var(--tab-h) + var(--safe-b) + 1rem);
  left: 50%;
  transform: translateX(-50%);
  max-width: calc(430px - 2rem); /* contained within mobile shell on desktop */
  background: var(--text);
  color: var(--bg);
  padding: .5rem 1.25rem;
  border-radius: var(--radius);
  font-size: var(--text-md);
  font-weight: 500;
  z-index: var(--z-toast);
  white-space: nowrap;
  pointer-events: none;
  animation: toast-in var(--transition-md) var(--ease-out);
}
.toast-error { background: var(--danger); }

/* ── Modal ─────────────────────────────────────────────────────────────────── */
.modal-backdrop {
  position: fixed; inset: 0;
  background: var(--overlay);
  display: flex; align-items: center; justify-content: center;
  z-index: var(--z-modal);
  padding: 1rem;
}
.modal-backdrop[hidden] { display: none; }
.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
  width: 100%; max-width: 24rem;
  box-shadow: var(--shadow-md);
}
.modal-title { font-family: 'DM Serif Display', Georgia, serif; font-size: var(--text-lg); font-weight: 400; letter-spacing: var(--ls-heading); margin-bottom: 1rem; }
.modal-label { display: block; font-size: var(--text-sm); font-weight: 600; margin-bottom: .25rem; margin-top: .75rem; }
.modal-label:first-of-type { margin-top: 0; }
.modal-input { width: 100%; font-size: var(--text-input); }
.modal-error { color: var(--danger); font-size: var(--text-sm); margin-top: .5rem; }
.modal-actions { display: flex; gap: .5rem; margin-top: 1rem; justify-content: flex-end; }
.pw-field { position: relative; }
.pw-field .modal-input { padding-right: 2.75rem; box-sizing: border-box; }
.pw-toggle { position: absolute; right: .25rem; top: 50%; transform: translateY(-50%); color: var(--text-soft); }

@keyframes toast-in {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0);   }
}

/* ── Tags ──────────────────────────────────────────────────────────────────── */
.tag {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-tight);
  padding: 0.125rem 0.4375rem;
  border-radius: var(--radius-sm);
  background: var(--accent-bg);
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .2);
}

.tag-assignee {
  background: var(--green-light);
  color: var(--green);
  border-color: rgba(var(--green-rgb), .2);
}

/* ── Filter bar ────────────────────────────────────────────────────────────── */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}

/* ── Filter toggle button + active chips ──────────────────────────────────── */
/* a11y: JS should set aria-label="Filter (N active)" on .filter-toggle-btn when filters are active */
.filter-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--text-sm);
  font-weight: 700;
  line-height: var(--lh-tight);   /* matches .todo-sort-select so both render the same height */
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  padding: var(--sp-1) var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-soft);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.filter-toggle-btn .material-symbols-outlined { font-size: var(--text-input); line-height: 1; }
.filter-toggle-btn:hover  { border-color: var(--accent); color: var(--accent); }
.filter-toggle-btn:active { background: var(--surface-warm); }
.filter-toggle-btn--active {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-bg);  /* fallback for Safari <16.2 */
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.filter-toggle-btn--active:hover {
  background: var(--accent-bg);  /* fallback for Safari <16.2 */
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}

.filter-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.1rem;
  height: 1.1rem;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--white);
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 0 .2rem;
  line-height: 1;
}

.active-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: var(--lh-tight);   /* matches filter toggle + sort select height */
  padding: var(--sp-1) var(--sp-2);
  background: var(--accent-bg);  /* fallback for Safari <16.2 */
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  color: var(--accent);
  cursor: pointer;
  transition: background var(--transition);
}
.active-filter-chip:hover { background: var(--accent-bg); }
.active-filter-chip:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.active-filter-chip span  { font-size: var(--text-input); line-height: 1; opacity: .7; }

/* ── Filter bottom sheet ──────────────────────────────────────────────────── */
.filter-sheet-backdrop {
  position: fixed;
  inset: 0;
  background: var(--overlay-light);
  z-index: var(--z-sheet);
}
.filter-sheet {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  max-width: 430px;             /* cap width within mobile shell on desktop */
  margin-inline: auto;          /* centre within the body */
  z-index: var(--z-sheet-content);
  background: var(--surface);
  border-radius: var(--radius) var(--radius) 0 0;
  border-top: 2px solid var(--accent);
  padding: var(--sp-4) var(--sp-5) max(var(--sp-8), env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  transform: translateY(100%);
  transition: transform var(--transition-md) var(--ease-out);
  max-height: min(70vh, 420px);
  overflow-y: auto;
}
.filter-sheet--open { transform: translateY(0); }
.filter-sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.filter-sheet-title {
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-soft);
}
.filter-sheet-done {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--accent);
  background: none;
  border: none;
  cursor: pointer;
  padding: .25rem .5rem;
  transition: opacity var(--transition);
}
.filter-sheet-done:active { opacity: .7; }
.filter-sheet-section {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.filter-sheet-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-soft);
}
.filter-sheet-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
}

/* ── Unified add form (always visible above tab bar) ────────────────────────── */
#add-form {
  display: flex;
  flex-direction: column-reverse;   /* details panel sits visually below input row (column-reverse: first DOM child = bottom) */
  position: fixed;
  bottom: calc(var(--tab-h) + var(--safe-b));
  left: 0;
  right: 0;
  z-index: var(--z-add-form);
  background: var(--surface);
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  box-shadow: 0 -4px 16px rgba(var(--shadow-rgb),.12); /* upward shadow lifts form above tab bar */
  /* No padding here — each child row carries its own padding for independent alignment */
}
#add-form.expanded {
  border-top: var(--border-accent-w) solid var(--accent); /* accent stripe at the card's curved top edge when adding */
}

/* Show only on tabs that have an add form (home + finance tabs hide it).
   Triple-negation avoids repeating the display: flex declaration on three selectors. */
body:not(.todos-active):not(.groceries-active):not(.wishlist-active) #add-form {
  display: none;
}

.add-form-main {
  display: flex;
  gap: var(--sp-2);
  align-items: stretch;
  padding: var(--card-pad);  /* owns its own padding — aligned with details' horizontal padding */
}
.add-form-main #add-input { flex: 3 1 0; min-width: 0; } /* grow:3 — gives qty sibling (#add-qty-inline, grow:1) 1/4 of space on groceries tab */

/* Add button hidden until form is expanded — fix #2: max-width animates, width:auto doesn't */
.add-submit-btn {
  max-width: 0;
  padding-left: 0;
  padding-right: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-width var(--transition-md) var(--ease-out), opacity var(--transition) var(--ease-out), padding var(--transition-md) var(--ease-out);
}
#add-form.expanded .add-submit-btn {
  max-width: 6rem;
  padding-left: 1rem;
  padding-right: 1rem;
  opacity: 1;
}

/* Details panel — full-bleed warm section above the main input row */
.add-form-details {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4) var(--sp-2);  /* horizontal matches .add-form-main for alignment */
  background: var(--surface-warm);
  border-bottom: 1px solid var(--border-soft);  /* subtle divider between warm details and input row above (column-reverse) */
  animation: details-panel-in var(--transition-md) var(--ease-out);
}
.add-form-details[hidden] { display: none; }

/* Field groups inside the details panel — fix #4: labelled sections */
.add-field-group        { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1 1 auto; min-width: 0; }
.add-field-group--full  { flex-basis: 100%; }
/* Inline group: For + Due side-by-side */
.add-field-group--inline { flex-direction: row; align-items: flex-end; gap: var(--sp-2); flex-basis: 100%; }
.add-inline-field        { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1 1 0; min-width: 0; }

/* Edit card field groups — mirrors add-form structure so labels and layout match */
.edit-field-group        { display: flex; flex-direction: column; gap: var(--sp-1); }
.edit-field-group--inline { flex-direction: row; align-items: flex-end; gap: var(--sp-2); }
.edit-inline-field       { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1 1 0; min-width: 0; }
.add-field-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-soft);
  line-height: 1;
}

/* Inline qty field — shown only when groceries add form is expanded */
#add-qty-inline { display: none; flex: 1 1 0; min-width: 0; }
body.groceries-active #add-form.expanded #add-qty-inline { display: block; }

#add-url:not(:placeholder-shown):invalid { border-color: var(--danger); }

/* Shared date-input wrapper — used in both add form and edit card */
.due-wrap  { position: relative; min-width: 0; }
.due-wrap input { width: 100%; min-width: 0; padding-right: 2.25rem; box-sizing: border-box; }
.due-wrap .btn-icon {
  position: absolute;
  right: .375rem;
  top: 50%;
  transform: translateY(-50%);
  padding: .25rem;
  font-size: var(--text-input);
  line-height: 1;
  color: var(--text-soft);
  min-width: unset;   /* intentional — overlaid inside date input, not a standalone touch target */
  min-height: unset;
}
/* .todo-add-due-wrap — removed; templates now use .due-wrap */

/* Extra bottom padding so content isn't hidden behind the fixed form.
   Derived from --add-form-h + --tab-h + breathing room. */
body.todos-active #panel-todos,
body.wishlist-active #panel-wishlist   { padding-bottom: calc(var(--tab-h) + var(--safe-b) + var(--add-form-h) + 2.5rem); }
body.groceries-active #panel-groceries { padding-bottom: calc(var(--tab-h) + var(--safe-b) + var(--add-form-h) + 1rem); }

/* iOS Safari: prevent zoom on focus — 1rem = var(--text-input) */
#add-form input,
#add-form select { font-size: var(--text-input); }

@keyframes details-panel-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Todo controls row (filter bar + sort) ─────────────────────────────────── */
.todo-controls,
.grocery-controls {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}

/* filter-bar margin is handled by .filter-bar globally; zero it inside controls */
.todo-controls .filter-bar,
.grocery-controls .filter-bar { margin-bottom: 0; }

.todo-sort-select {
  margin-left: auto;
  width: auto;
  padding: var(--sp-1) 1.5rem var(--sp-1) var(--sp-3);  /* vertical matches .filter-toggle-btn; right = arrow room */
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  line-height: var(--lh-tight);
  color: var(--text-soft);
}
/* .todo-sort-select:focus — border-color inherited from input:focus, select:focus global rule */

/* ── Overdue due date tag variant ──────────────────────────────────────────── */
.tag-overdue {
  background: var(--danger-light);
  color: var(--danger);
  border-color: rgba(var(--danger-rgb), .2);
}

/* ── Todo card layout ──────────────────────────────────────────────────────── */

/* Assignee avatar — circular letter badge */
.todo-avatar {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-transform: uppercase;
}
.todo-avatar--accent {
  background: var(--accent-bg);
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .25);
}
.todo-avatar--green {
  background: var(--green-light);
  color: var(--green);
  border: 1px solid rgba(var(--green-rgb), .25);
}

/* Date + tag on one line below the title */
.todo-meta-row {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  flex-wrap: wrap;
  margin-top: var(--sp-1);
}
.todo-due {
  font-size: var(--text-sm);
  color: var(--text-soft);
}
.todo-due.overdue {
  color: var(--danger);
  font-weight: 600;
}
.todo-meta-sep {
  font-size: var(--text-xs);
  color: var(--text-dim);
  user-select: none;
}
.todo-meta-assignee {
  font-size: var(--text-sm);
  font-weight: 600;
}
.todo-meta-assignee.todo-avatar--accent { color: var(--accent); }
.todo-meta-assignee.todo-avatar--green  { color: var(--green); }

/* Strikethrough on title text only */
.list-item.done .todo-title {
  text-decoration: line-through;
  color: var(--done-text);
}

/* ── Group-by section headers ──────────────────────────────────────────────── */
.todo-group-header {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-soft);
  padding-bottom: .375rem;
  display: flex;
  align-items: center;
  gap: .5rem;
}
/* Kantha-stitch dashed rule extending to the right */
.todo-group-header::after {
  content: '';
  flex: 1;
  height: 1px;
  background: repeating-linear-gradient(
    90deg,
    var(--border) 0, var(--border) 4px,
    transparent 4px, transparent 8px
  );
}
.todo-group-header--gap { margin-top: var(--sp-5); }

/* Completed section header — slightly muted vs regular group headers */
.todo-done-header { color: var(--text-dim); }

/* "Show / Hide completed" toggle link */
.todo-done-toggle {
  display: block;
  width: 100%;
  margin-top: var(--sp-4);
  padding: var(--sp-2) 0;
  font-size: var(--text-sm);
  color: var(--text-soft);
  text-align: center;
  border-top: 1px solid var(--border-soft);
  background: none;
  cursor: pointer;
  transition: color var(--transition);
}
.todo-done-toggle:hover  { color: var(--accent); }
.todo-done-toggle:active { color: var(--accent-dark); }

/* ── Tag selector ──────────────────────────────────────────────────────────── */
.tag-selector {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  align-items: center;
}
.tag-chip {
  /* fix #3: larger touch targets — was 0.2rem 0.5rem (~20px tall) */
  padding: .45rem .75rem;
  min-height: 2.25rem;
  display: inline-flex;
  align-items: center;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-tight);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-soft);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.tag-chip:hover  { border-color: var(--accent); color: var(--accent); }
.tag-chip:active { background: var(--accent-bg); border-color: var(--accent); }
.tag-chip.selected {
  background: var(--accent);
  color: var(--white);
  border-color: var(--accent);
}
.tag-chip--green:hover { border-color: var(--green); color: var(--green); }
.tag-chip--green.selected { background: var(--green); color: var(--white); border-color: var(--green); }
.tag-chip-add {
  /* extends .tag-chip — only overrides differ */
  border-style: dashed;
}
.tag-chip-input {
  width: 5rem;   /* ~80px; em-based so it scales with font */
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--text-input);
  border: 1px solid var(--accent);
}
/* tag selector inside edit-field-group — gap from parent handles spacing */

/* ── Grocery inline edit ───────────────────────────────────────────────────── */
.todo-edit-meta .grocery-edit-name { flex: 3 1 0; min-width: 0; }
.todo-edit-meta .grocery-edit-qty  { flex: 1 1 0; min-width: 0; }

/* ── Keyboard open: hide tab bar and snap add form to screen bottom ─────────── */
/* body.keyboard-open is set immediately on focusin (app.js) — before the async
   visualViewport resize event fires. This ensures the tab bar disappears the
   instant an input is focused so it never lingers behind the keyboard.
   The add form snaps to bottom:0 immediately; _onVP refines it to the exact
   keyboard height once the viewport resize event fires.                         */
body.keyboard-open .tab-bar { display: none; }
body.keyboard-open #add-form { bottom: 0; }

/* ── Hide add form + tab bar while a list item is being edited ─────────────── */
/* body.is-editing is toggled by JS (more reliable on iOS than CSS :has() with
   dynamically added classes). The keyboard takes that space instead.           */
body.is-editing #add-form,
body.is-editing .tab-bar { display: none; }

body.is-editing.todos-active     #panel-todos,
body.is-editing.groceries-active #panel-groceries,
body.is-editing.wishlist-active  #panel-wishlist { padding-bottom: 1.5rem; }

/* ── Todo inline edit ──────────────────────────────────────────────────────── */
.list-item.editing {
  align-items: stretch;
  cursor: default;
  border-left-color: var(--accent);
  background: var(--surface-warm);
}
.todo-edit-form {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
}
.todo-edit-title {
  font-size: var(--text-input);
  font-weight: 400;
  width: 100%;
}
.todo-edit-url {
  font-size: var(--text-input);
  width: 100%;
  color: var(--text-soft);
}
/* .todo-edit-meta — grocery name + qty row only */
.todo-edit-meta {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
}
.todo-edit-actions {
  display: flex;
  gap: .5rem;
  justify-content: flex-end;
}
.todo-edit-actions .btn {
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--text-sm);
}


/* ── Activity log ───────────────────────────────────────────────────────────── */
.activity-section { margin-top: var(--sp-5); }
.activity-list { display: flex; flex-direction: column; gap: .375rem; }
.activity-item {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  font-size: var(--text-sm);
  color: var(--text-soft);
  padding: .375rem .5rem;
  border-left: 2px solid var(--border);
}
.activity-avatar {
  flex-shrink: 0;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: var(--ls-caps);
  width: 1.25rem; height: 1.25rem;
  border-radius: var(--radius-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent);
  color: var(--white);
}
.activity-avatar--green { background: var(--green); }
.activity-detail { flex: 1; min-width: 0; }
.activity-entity { font-weight: 600; color: var(--text); }
.activity-time { flex-shrink: 0; font-size: var(--text-xs); color: var(--text-dim); }
.activity-item--link {
  cursor: pointer;
  border-left-color: var(--accent);
  transition: background var(--transition);
}
.activity-item--link:hover,
.activity-item--link:focus-visible {
  background: var(--accent-bg);
  outline: none;
}

@keyframes item-flash {
  0%   { background: var(--accent-bg); box-shadow: inset 3px 0 0 var(--accent); }
  60%  { background: var(--accent-bg); box-shadow: inset 3px 0 0 var(--accent); }
  100% { background: transparent;      box-shadow: none; }
}
.activity-flash {
  animation: item-flash 1.4s var(--ease-out) forwards;
}

/* ── Landscape orientation: reduce fixed chrome height ────────────────────── */
@media (orientation: landscape) and (max-height: 500px) {
  :root { --tab-h: 48px; }
  .tab-btn .tab-icon { font-size: 1.125rem; }
  #tab-home .tab-icon { font-size: 1.3rem; }
}

/* ── Desktop containment ───────────────────────────────────────────────────── */
/* App is designed for mobile; on wide viewports, centre and constrain. */
@media (min-width: 480px) {
  body { background: var(--bg-frame); }
  .app-shell {
    max-width: 430px;
    margin-inline: auto;
    box-shadow: 0 0 40px rgba(var(--shadow-rgb),.25);
    min-height: 100dvh;
  }
  /* Note: position:sticky + transform creates a stacking context — known to cause
     layout bugs in older Safari. Test on Safari desktop if sticky header misbehaves. */
  .app-header,
  .tab-bar,
  #add-form {
    max-width: 430px;
    left: 50%;
    transform: translateX(-50%);
  }
}

/* ── Reduced motion ────────────────────────────────────────────────────────── */
/* Respect system preference — disables all animations/transitions. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration:       .01ms !important;
    animation-iteration-count: 1    !important;
    transition-duration:      .01ms !important;
  }
}
