/* Component/layout rules. Brand tokens live in tokens.css (loaded first);
   this file should reference var(--...) only, never a raw hex. */

* { box-sizing: border-box; }

/* Author rules always beat the UA [hidden]{display:none} rule regardless of
   specificity, so any class that also sets `display` (badges/pills toggled
   via el.hidden in JS) would otherwise stay visible even while hidden. */
[hidden] { display: none !important; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font: var(--body);
  background: var(--bg);
  color: var(--fg);
}

a, a:visited, a:focus, a:hover, a:active { color: inherit; }
a:visited.link { text-decoration: underline dashed; text-decoration-thickness: 50%; }
a:focus.link, a:hover.link, a:active.link {
  text-decoration: underline wavy;
  text-underline-offset: 2px;
}
.link {
  text-decoration: underline dotted;
  text-underline-offset: 4px;
  text-decoration-thickness: 2.75px;
}
a:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

button, a, [role="button"] { -webkit-tap-highlight-color: transparent; }

/* ---------- Accessibility helpers ---------- */

.skip-link {
  position: absolute;
  top: -3rem;
  left: var(--space-3);
  background: var(--bg-elevated);
  color: var(--fg);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  z-index: 100;
  text-decoration: none;
  transition: top var(--duration-base) var(--ease-standard);
}
.skip-link:focus {
  top: var(--space-3);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Navbar ---------- */

.topbar {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
}

.topbar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  max-width: 640px;
  margin: 0 auto;
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

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

.topbar h1 {
  font: var(--h3);
  letter-spacing: var(--tracking-heading);
  margin: 0;
}

.brand-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.brand-btn:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.brand-mark { flex-shrink: 0; }

/* Home/theme/language icon buttons use the secondary button treatment:
   no background, only a border, per brand guideline §24. */
.home-btn, .icon-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--fg);
  cursor: pointer;
  text-decoration: none;
  font-size: 18px;
}
/* Invisible expanded hit area (32px visible box -> 44px tap target,
   WCAG 2.2 2.5.5 Target Size Enhanced), without growing the visible
   button. Neighbors in the top bar/calendar-nav sit --space-3 (12px)
   apart, so a 6px inset on each side meets in the middle without
   overlapping an adjacent target. */
.home-btn::after, .icon-btn::after {
  content: "";
  position: absolute;
  inset: -6px;
}
.home-btn:hover, .icon-btn:hover { background: var(--lock-bg); }
.home-btn:focus-visible, .icon-btn:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.account-status { font: var(--caption); color: var(--fg-muted); display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; position: relative; }
.account-switcher-btn {
  display: inline-flex;
  align-items: center;
  height: 32px;
  background: none;
  border: 1px solid var(--border-strong);
  color: inherit;
  font: inherit;
  cursor: pointer;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
}
.account-switcher-btn:hover { background: var(--lock-bg); }
.account-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  min-width: 14rem;
  z-index: 10;
}
.account-dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.account-dropdown-item button.account-switch-btn {
  flex: 1;
  display: block;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-xs);
  padding: var(--space-2);
  font: var(--body);
  color: var(--fg);
  cursor: pointer;
}
.account-dropdown-item button.account-switch-btn:hover { background: var(--lock-bg); }
.account-dropdown-item.active button.account-switch-btn { font-weight: 600; }
.account-remove-btn {
  position: relative;
  background: none;
  border: none;
  color: var(--fg-muted);
  cursor: pointer;
  padding: var(--space-1);
  border-radius: var(--radius-xs);
  line-height: 1;
}
/* Deliberately modest expansion, not a full 44px: this button sits right
   next to the large flex:1 account-switch-btn (a "remove this saved
   account" action beside a "switch to it" one) with rows stacked tightly
   above/below in the dropdown, so maximizing the hit area risks turning a
   mis-aimed "switch" click into a "remove" click. */
.account-remove-btn::after {
  content: "";
  position: absolute;
  inset: -4px;
}
.account-remove-btn:hover { background: var(--lock-bg); color: var(--fg); }
.account-dropdown-divider { border: none; border-top: 1px solid var(--border); margin: var(--space-1) 0; }
.account-dropdown button.account-add-btn,
.account-dropdown button.account-signout-btn {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-xs);
  padding: var(--space-2);
  font: var(--body);
  color: var(--fg);
  cursor: pointer;
}
.account-dropdown button.account-add-btn:hover,
.account-dropdown button.account-signout-btn:hover { background: var(--lock-bg); }

.lang-switcher { position: relative; }
.lang-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  min-width: 8rem;
  z-index: 10;
}
.lang-dropdown button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-xs);
  padding: var(--space-2);
  font: var(--body);
  color: var(--fg);
  cursor: pointer;
}
.lang-dropdown button:hover { background: var(--lock-bg); }
.lang-dropdown button[aria-current="true"] { font-weight: 700; }

.domain-input-wrap { position: relative; }
.domain-suggest-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  max-height: 16rem;
  overflow-y: auto;
  z-index: 10;
}
.domain-suggest-label {
  font: var(--caption);
  color: var(--fg-muted);
  padding: var(--space-2) var(--space-2) var(--space-1);
}
.domain-suggest-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-xs);
  padding: var(--space-2);
  font: var(--body);
  color: var(--fg);
  cursor: pointer;
}
.domain-suggest-item:hover { background: var(--lock-bg); }
.domain-suggest-item .domain-suggest-meta {
  font: var(--caption);
  color: var(--fg-muted);
  flex-shrink: 0;
}
.domain-suggest-divider { border: none; border-top: 1px solid var(--border); margin: var(--space-1) 0; }

/* ---------- Layout ---------- */

#app {
  max-width: 640px;
  margin: 0 auto;
  padding: var(--space-4);
  flex: 1 0 auto;
  width: 100%;
}
#app:focus-visible { outline: none; }

.site-footer {
  max-width: 640px;
  margin: var(--space-8) auto var(--space-6);
  padding: var(--space-4);
  display: flex;
  gap: var(--space-5);
  font: var(--caption);
  color: var(--fg-muted);
}

.loading, .empty-state { color: var(--fg-muted); }

/* ---------- Typography ---------- */

h2 {
  font: var(--h2);
  letter-spacing: var(--tracking-heading);
  color: var(--fg-strong);
}

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

button {
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-4);
  font: 600 0.95rem/1 var(--font-body);
}

.btn-primary,
button:not([class*="btn-"]):not(.icon-btn):not(.brand-btn):not(.icon-info-btn):not(.account-switcher-btn):not(.account-dropdown button):not(.lang-dropdown button):not(.domain-suggest-dropdown button) {
  background: var(--button-bg);
  color: var(--button-fg);
}

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

.btn-ghost {
  background: transparent;
  color: var(--fg);
}

.btn-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--cta-bg);
  color: var(--cta-fg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-5);
  font: 600 0.95rem/1 var(--font-body);
  text-decoration: none;
  cursor: pointer;
}

button:hover, .btn-cta:hover        { filter: brightness(0.94); }
button:active, .btn-cta:active      { filter: brightness(0.86); transform: translateY(1px); }
button:focus-visible, .btn-cta:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
button:disabled { cursor: default; filter: none; }

/* Small inline spinner, appended at the end of a button's label while an
   awaited action (e.g. login's OAuth handshake) is in flight. */
.btn-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-left: var(--space-2);
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  opacity: 0.7;
  animation: btn-spin 1s linear infinite;
  vertical-align: -2px;
}
@keyframes btn-spin {
  to { transform: rotate(360deg); }
}

/* ---------- Form fields ---------- */

input:not([type="checkbox"]):not([type="radio"]), textarea, select {
  width: 100%;
  padding: var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  color: var(--fg);
  font: var(--body);
  margin: var(--space-1) 0 var(--space-3);
}

input:not([type="checkbox"]):not([type="radio"]):focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--focus-ring);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 18%, transparent);
}

input[type="checkbox"], input[type="radio"] {
  width: auto;
  margin: 0;
}

/* The native datetime-local control's calendar icon renders dark and
   becomes invisible against the dark theme, so invert it. WebKit/Blink-only
   pseudo-element; Firefox's control already follows color-scheme. */
:root[data-theme="dark"] input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  filter: invert(1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
  }
}

label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: var(--space-1);
}

/* ---------- Banners ---------- */

/* Solid --danger fill + --danger-fg text, not the --danger-bg tint: only
   the solid pairing is a documented AAA combination (joram.eu/design §09,
   "On Madder: Baby Powder only, 7.10:1"); text on the 12% tint measures
   only ~5.7:1. */
.error {
  background: var(--danger);
  color: var(--danger-fg);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  margin: var(--space-3) 0;
}

/* Warning has no brand color; the guideline's palette defines none, so
   this amber stays a locally-scoped exception outside the brand tokens. */
.warning {
  background: var(--warn-bg);
  color: var(--warn);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  margin: var(--space-3) 0;
}

/* ---------- List screen ---------- */

.list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding-top: var(--space-2);
  margin-top: var(--space-8);
  margin-bottom: 0;
}

.list-header h2 { margin: 0; }

.list-header-actions { display: flex; align-items: center; gap: var(--space-2); margin-bottom: 0; }
.list-header-actions .btn-primary {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 var(--space-4);
}

/* overflow:hidden used to do the rounded-corner clipping here, but that
   also clipped the icon-btn::after hit-area expansion below, so the
   corner rounding now lives on the end buttons themselves instead. */
.view-toggle {
  display: flex;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
}
.view-toggle .icon-btn { border-radius: 0; border: none; width: 34px; height: 34px; }
.view-toggle .icon-btn:first-child { border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); }
.view-toggle .icon-btn:last-child { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); }
.view-toggle .icon-btn + .icon-btn { border-left: 1px solid var(--border-strong); }
.view-toggle .icon-btn[aria-pressed="true"] { background: var(--lock-bg); }
/* The two buttons sit flush against each other (only a 1px border, no
   gap), so the shared inner edge can't expand without overlapping the
   neighbor's target; only the outer edge and top/bottom grow toward
   44px; the inner-edge dimension stays at the visible 34px. */
.view-toggle .icon-btn::after { inset: -5px 0; }
.view-toggle .icon-btn:first-child::after { left: -5px; }
.view-toggle .icon-btn:last-child::after { right: -5px; }

.list-filters {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.list-filters input[type="search"] { flex: 1; margin: 0; }

.list-items { list-style: none; margin: 0; padding: 0; }

/* ---------- Calendar view ---------- */

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

.calendar-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.calendar-nav-controls { display: flex; align-items: center; gap: var(--space-1); }
.calendar-month-label { font: var(--h3); margin: 0; }

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.calendar-day-header {
  background: var(--bg-elevated);
  padding: var(--space-2);
  text-align: center;
  font: var(--caption);
  color: var(--fg-muted);
  font-weight: 600;
}

.calendar-day-cell {
  background: var(--bg-elevated);
  min-height: 6rem;
  min-width: 0;
  padding: var(--space-1);
  display: flex;
  flex-direction: column;
  gap: 2px;
  transition: background var(--duration-base) var(--ease-standard);
}
.calendar-day-cell.other-month { opacity: 0.45; }
.calendar-day-cell.drag-over { background: var(--lock-bg); }

.calendar-day-number {
  font: var(--caption);
  color: var(--fg-muted);
  width: 1.5rem;
  height: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
}
.calendar-day-cell.today .calendar-day-number {
  background: var(--accent);
  color: var(--accent-fg);
  font-weight: 600;
}

.calendar-day-trigger {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.calendar-day-trigger:hover { background: var(--lock-bg); }

/* 0.65rem below here is intentionally off the --caption (0.75rem) floor;
   these are calendar/list micro-labels where density matters more than
   scale adherence. */
.calendar-post-pill {
  font-size: 0.65rem;
  border-radius: var(--radius-xs);
  padding: 1px 4px;
  background: var(--button-bg);
  color: var(--button-fg);
  display: flex;
  gap: 3px;
  overflow: hidden;
  cursor: grab;
}
.calendar-post-pill.locked { background: var(--lock-bg); color: var(--fg-muted); border: 1px dashed var(--border-strong); cursor: default; }
.calendar-post-pill .pill-time { flex-shrink: 0; font-weight: 700; opacity: 0.85; }
.calendar-post-pill .pill-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.calendar-more { font-size: 0.65rem; color: var(--fg-muted); padding-left: 2px; }

.calendar-empty-hint { color: var(--fg-muted); }

.calendar-day-popover {
  position: fixed;
  z-index: 20;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-3);
  width: 18rem;
  max-height: 60vh;
  overflow-y: auto;
}
.calendar-day-popover h3 {
  font: var(--body-emph);
  margin: 0 0 var(--space-2);
}
.calendar-day-popover-item {
  display: block;
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-1);
  color: inherit;
  text-decoration: none;
}
.calendar-day-popover-item:hover { background: var(--lock-bg); }
.calendar-day-popover-item .popover-item-time { font: var(--caption); color: var(--fg-muted); }
.calendar-day-popover-item .popover-item-text { font-size: 0.85rem; margin-top: 2px; white-space: pre-wrap; }

/* ---------- Toast (shared: undo-delete + save-done) ---------- */
/* One component for both timed notices; see js/toast.js. Both need the
   same controls (optional action, timer+pause, close) so they share this
   markup/style rather than duplicating it per call site. */

.toast {
  position: fixed;
  bottom: var(--space-5);
  background: var(--fg-strong);
  color: var(--bg);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-lg);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  z-index: 30;
  opacity: 1;
  transition: opacity var(--duration-base) var(--ease-standard);
}
.toast--center { left: 50%; transform: translateX(-50%); }
.toast--right { right: var(--space-5); }
/* Fade in on insertion, fade out before removal; see js/toast.js, which
   toggles these around the transition rather than snapping in/out. */
.toast.toast--enter, .toast.toast--leave { opacity: 0; }

.toast-message { font: var(--body); }

.toast-action {
  background: none;
  border: none;
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
  padding: 0;
  cursor: pointer;
}

/* Timer+pause: one control, not two; its label doubles as the live
   countdown so the pause affordance sits exactly where the eye already
   goes to check the remaining time. Any contact (hover, focus, click, or
   pressing "p" while focused inside the toast) pins it permanently; see
   js/toast.js. */
.toast-timer {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  background: none;
  border: 1px solid color-mix(in oklch, var(--bg) 35%, transparent);
  color: inherit;
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font: var(--caption);
  cursor: pointer;
}
.toast-timer:hover { background: color-mix(in oklch, var(--bg) 12%, transparent); }
.toast-timer:focus-visible {
  outline: 2px solid var(--bg);
  outline-offset: 2px;
}
.toast-timer:disabled {
  cursor: default;
  opacity: 0.85;
  border-color: color-mix(in oklch, var(--bg) 20%, transparent);
}
.toast-timer:disabled:hover { background: none; }

/* Ghost dismiss button per joram.eu/design's Dismiss Button spec: no
   background, no border at rest; overrides .icon-btn's default bordered
   secondary-button treatment. */
.toast-close.icon-btn {
  border: none;
  color: inherit;
  font-size: 20px;
}
.toast-close.icon-btn:hover { background: color-mix(in oklch, var(--bg) 12%, transparent); }
.toast-close.icon-btn:focus-visible { outline-color: var(--bg); }

@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; }
}

/* ---------- Post rows (card treatment) ---------- */

.post-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  margin-bottom: var(--space-2);
  transition: box-shadow var(--duration-base) var(--ease-standard);
}

.post-row:hover { box-shadow: var(--shadow-sm); }

.post-row.locked {
  background: var(--lock-bg);
  opacity: 0.75;
}

.post-row-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: 0.85rem;
  color: var(--fg-muted);
}

.post-time { white-space: nowrap; }

.post-lock-badge { font: var(--caption); }

.post-visibility { margin-left: auto; }

.post-cw {
  font-size: 0.8rem;
  color: var(--fg-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.15rem 0.4rem;
  display: inline-block;
  align-self: flex-start;
}

.post-text { margin: 0; white-space: pre-wrap; word-break: break-word; }

.post-media { display: flex; gap: var(--space-1); }
.post-media img { width: 48px; height: 48px; object-fit: cover; border-radius: var(--radius-sm); }

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

.post-row-badges { display: flex; align-items: center; gap: var(--space-1); }

.post-alttext-badge {
  background: var(--danger);
  color: var(--danger-fg);
  border-radius: var(--radius-pill);
  font-size: 0.65rem;
  padding: 0.05rem 0.5rem;
  cursor: help;
}

.post-hashtag-badge {
  border: 1px solid var(--border);
  color: var(--fg-muted);
  border-radius: var(--radius-pill);
  font-size: 0.65rem;
  padding: 0.05rem 0.5rem;
  cursor: help;
}

.post-row-actions { display: flex; gap: var(--space-2); margin-left: auto; }
.post-row-actions button { font-size: 0.8rem; padding: 0.3rem 0.6rem; }

/* ---------- Edit / compose screen ---------- */

.media-list { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3); }
.media-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2);
  width: 140px;
}
.media-item img { width: 100%; height: 80px; object-fit: cover; border-radius: var(--radius-sm); }
.media-item input { margin: 0.35rem 0 0; font: var(--caption); padding: 0.3rem; }
.media-item .media-status { font-size: 0.7rem; color: var(--fg-muted); }
.media-item .media-status-error { color: var(--danger); }

.form-actions { display: flex; gap: var(--space-2); margin-top: var(--space-4); }

#edit-fieldset { border: 0; padding: 0; margin: 0; }
#edit-fieldset:disabled { opacity: 0.6; }

/* Small inline loader, appended after the Save button's label while a save
   is in flight. Design per joram.eu/design's small loader spec. */
.btn-loader {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin-left: var(--space-2);
  border: 3px solid #fff;
  border-top-color: #0a1137;
  border-radius: 50%;
  animation: btn-loader-spin 1s linear infinite;
  vertical-align: -5px;
}
.btn-loader[hidden] { display: none; }
@keyframes btn-loader-spin {
  to { transform: rotate(360deg); }
}

.save-toast {
  position: fixed;
  right: var(--space-5);
  bottom: var(--space-5);
  background: var(--fg-strong);
  color: var(--bg);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-lg);
  z-index: 30;
  max-width: 20rem;
}
.save-toast[hidden] { display: none; }

.saving-checklist { list-style: none; margin: 0; padding: 0; text-align: left; }
.saving-checklist-item { padding: var(--space-1) 0; opacity: 0.6; }
.saving-checklist-item.active { opacity: 1; font-weight: 600; }
.saving-checklist-item.done { opacity: 1; }
.saving-checklist-item.done::before { content: "✓ "; }

.recovery-banner {
  background: var(--warn-bg);
  color: var(--warn);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.char-counter { font: var(--caption); color: var(--fg-muted); margin: -0.5rem 0 var(--space-3); }
.char-counter.over-limit { color: var(--danger); font-weight: 600; }
.hint { font: var(--caption); color: var(--fg-muted); margin: -0.5rem 0 var(--space-3); }

.list-count-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-1);
  margin-top: 0;
  margin-bottom: var(--space-7);
}
.list-count-row .hint { margin: 0; }
#list-count-text.over-limit { color: var(--danger); font-weight: 600; }

.icon-info-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  padding: 0;
  border: none;
  background: none;
  color: var(--fg-muted);
  font-size: 0.9rem;
  line-height: 1;
  cursor: help;
  border-radius: var(--radius-sm);
  -webkit-tap-highlight-color: transparent;
}
/* 20px visible box -> ~44px tap target. */
.icon-info-btn::after {
  content: "";
  position: absolute;
  inset: -12px;
}
.icon-info-btn:hover,
.icon-info-btn:focus-visible { color: var(--fg); }

/* ---------- Custom tooltip (instant, replaces slow native title) ---------- */

.tooltip-bubble {
  position: absolute;
  z-index: 50;
  max-width: 18rem;
  background: var(--fg-strong);
  color: var(--bg);
  font: var(--caption);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  transition: none;
}

/* ---------- Confirm modal ---------- */

.confirm-overlay {
  position: fixed;
  inset: 0;
  background: color-mix(in oklch, var(--color-ink-black) 55%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: 40;
}
.confirm-modal {
  background: var(--bg-elevated);
  color: var(--fg);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: var(--space-5) var(--space-4);
  max-width: 26rem;
}
.confirm-modal h3 { font: var(--h3); margin: 0 0 var(--space-2); }
.confirm-modal p { margin: 0 0 var(--space-4); color: var(--fg-muted); }
.confirm-modal-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }

/* ---------- Danger zone (edit screen) ---------- */

.danger-zone { margin-top: var(--space-6); }
.danger-zone summary {
  color: var(--fg-muted);
  font-size: 0.85rem;
  cursor: pointer;
  user-select: none;
}
.danger-zone summary:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.danger-btn {
  display: block;
  margin-top: var(--space-3);
  background: transparent;
  border: 1px solid var(--border);
  color: var(--fg-muted);
}
/* Solid --danger fill, same reasoning as .error above: the tinted
   --danger-bg + --danger text combo only clears AA, not AAA. */
.danger-btn:hover, .danger-btn:focus-visible {
  color: var(--danger-fg);
  border-color: var(--danger);
  background: var(--danger);
}

/* ---------- Filter popup ---------- */

.filter-popup-wrap { position: relative; }
#filter-toggle-btn { display: inline-flex; align-items: center; gap: var(--space-2); height: 100%; }
.filter-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.3rem;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 0.65rem;
  font-weight: 700;
}
.filter-popup {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: var(--space-3);
  width: 18rem;
  max-height: 70vh;
  overflow-y: auto;
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.filter-popup label {
  font-weight: 400;
  font-size: 0.85rem;
  margin-bottom: 0;
}
.filter-fieldset {
  border: none;
  padding: 0;
  margin: 0 0 var(--space-1);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.filter-fieldset legend {
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0;
  margin-bottom: var(--space-1);
}
.filter-date-range { display: flex; flex-direction: column; gap: var(--space-1); }
.filter-date-range input { margin: var(--space-1) 0 0; }
.filter-popup-actions { display: flex; justify-content: flex-end; margin-top: var(--space-1); }

/* ---------- Landing screen ---------- */

.landing-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-5);
  padding: var(--space-9) 0 var(--space-8);
}

.landing-eyebrow {
  font: var(--overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--accent);
  margin: 0;
}

.landing-heading {
  font: var(--display-1);
  letter-spacing: var(--tracking-heading);
  color: var(--fg-strong);
  margin: 0;
}
.landing-heading:focus-visible { outline: none; } /* programmatic focus target, not a real interactive control */

.landing-subhead {
  font: var(--body-lg);
  color: var(--fg-muted);
  max-width: 42ch;
  margin: 0;
}

.landing-cta-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  justify-content: center;
  margin-top: var(--space-2);
}

.landing-features {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  margin: var(--space-9) 0 var(--space-9);
  padding: 0;
}

.landing-feature-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-6);
}

.landing-feature-card i {
  flex: none;
  font-size: 1.5rem;
  color: var(--accent);
  line-height: 1.3;
}

.landing-feature-card h3 {
  font: 700 1rem/1.3 var(--font-body);
  color: var(--fg-strong);
  margin: 0 0 var(--space-2);
}

.landing-feature-card p {
  font: var(--caption);
  color: var(--fg-muted);
  margin: 0;
}

.landing-cta-hint {
  font: var(--caption);
  color: var(--fg-muted);
  /* .landing-hero applies a uniform flex gap between all children; pull
     this one closer to the button above it so it reads as a caption for
     the CTA, not just another evenly-spaced block. */
  margin-top: calc(var(--space-3) * -1);
}

.landing-noscript-note {
  font: var(--caption);
  color: var(--fg-muted);
  margin: var(--space-2) 0 0;
}

.landing-trust {
  margin: 0 0 var(--space-10);
  padding-top: var(--space-10);
  border-top: 1px solid var(--border);
}

.landing-trust-heading {
  font: var(--h3);
  color: var(--fg-strong);
  text-align: center;
  margin: 0 0 var(--space-6);
}

.landing-trust-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  margin: 0;
  padding: 0;
  max-width: 46ch;
  margin-inline: auto;
}

.landing-trust-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  text-align: left;
}

.landing-trust-item i {
  flex: none;
  font-size: 1.5rem;
  color: var(--accent);
  line-height: 1.3;
}

.landing-trust-item h4 {
  font: 700 0.95rem/1.3 var(--font-body);
  color: var(--fg-strong);
  margin: 0 0 var(--space-1);
}

.landing-trust-item p {
  font: var(--caption);
  color: var(--fg-muted);
  margin: 0;
}

.landing-faq {
  margin: 0 0 var(--space-10);
  padding-top: var(--space-9);
  border-top: 1px solid var(--border);
}

.landing-faq-heading {
  font: var(--h3);
  color: var(--fg-strong);
  text-align: center;
  margin: 0 0 var(--space-6);
}

.faq-item {
  border-bottom: 1px solid var(--border);
  padding: var(--space-3) 0;
}
.faq-item:first-of-type { border-top: 1px solid var(--border); }

.faq-item summary {
  font: var(--body-emph);
  color: var(--fg-strong);
  cursor: pointer;
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  float: right;
  color: var(--fg-muted);
}
.faq-item[open] summary::after { content: "\2212"; } /* minus sign */

.faq-item p {
  font: var(--body);
  color: var(--fg-muted);
  margin: var(--space-2) 0 0;
}

.landing-closing-cta {
  text-align: center;
  padding-top: var(--space-9);
  padding-bottom: var(--space-9);
}

.landing-closing-cta h3 {
  font: var(--h2);
  letter-spacing: var(--tracking-heading);
  color: var(--fg-strong);
  margin: 0 0 var(--space-2);
}

.landing-closing-cta p {
  font: var(--body-lg);
  color: var(--fg-muted);
  max-width: 42ch;
  margin: 0 auto var(--space-5);
}

/* Killing the flash: js/app.js is about to replace #app's static
   markup, but only once it's booted. The has-session class is set
   synchronously (index.html, before first paint) whenever a session
   already exists, so a returning signed-in visitor sees this neutral
   loading state instead of the marketing landing page for a moment. */
html.has-session #landing-screen { display: none; }
html.has-session #app-loading { display: block; }
