/* ============================================================================
   base.css — resets, layout skeleton, typography. No component classes here
   (those live in components.css) and no colour literals (tokens.css only).
   ============================================================================ */

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none; /* a swipe-to-turn-page gesture must not also bounce the whole document */
}

.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;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--surface); color: var(--ink); padding: var(--space-2) var(--space-4);
  border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus { left: 0; }

/* Cloak the shell until app.js has filled it — see index.html boot script. */
html.booting .app-shell { visibility: hidden; }

.splash {
  position: fixed; inset: 0; display: none; align-items: center; justify-content: center;
  flex-direction: column; gap: var(--space-3); background: var(--bg); z-index: 300;
}
html.booting .splash { display: flex; }
.splash-mark { font-size: 48px; animation: sway 2.4s var(--ease) infinite; }
.splash-word { color: var(--ink-soft); font-size: 15px; letter-spacing: 0.02em; }
@keyframes sway {
  0%, 100% { transform: rotate(-6deg); }
  50% { transform: rotate(6deg); }
}
@media (prefers-reduced-motion: reduce) { .splash-mark { animation: none; } }

.noscript-card {
  max-width: 420px; margin: 15vh auto; padding: var(--space-5);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
  text-align: center;
}

/* App shell layout: sidebar (tablet landscape) collapses to a bottom tab bar
   on narrow viewports. Mobile-first, widened with min-width queries. */
.app-shell {
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.brand { display: flex; align-items: center; gap: var(--space-2); background: none; border: 0; cursor: pointer; }
.brand-mark { font-size: 22px; }
.brand-text strong { display: block; font-size: 15px; color: var(--ink); }
.brand-text small { display: block; font-size: 11px; color: var(--ink-faint); }
.topbar-actions { margin-left: auto; display: flex; gap: var(--space-2); }

.app-body { flex: 1; display: flex; min-height: 0; }

.nav-rail {
  display: none; /* shown from tablet width up */
  flex-direction: column; gap: var(--space-1);
  width: 220px; padding: var(--space-4) var(--space-2);
  border-right: 1px solid var(--line); background: var(--surface);
  overflow-y: auto;
}
@media (min-width: 768px) {
  .nav-rail { display: flex; }
}

.page-host {
  flex: 1; min-width: 0; overflow-y: auto;
  padding: var(--space-5) var(--space-4) calc(var(--space-6) + 64px);
}
@media (min-width: 1024px) {
  .page-host { padding: var(--space-6) var(--space-6); }
}

.tab-bar {
  display: flex; justify-content: space-around; align-items: center;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: var(--surface); border-top: 1px solid var(--line);
  padding: var(--space-2) var(--space-1) max(var(--space-2), env(safe-area-inset-bottom));
}
@media (min-width: 768px) { .tab-bar { display: none; } }

.no-print { }
@media print { .no-print { display: none !important; } }

/* A save that silently fails is the one failure mode a "years of daily
   entries" product cannot afford to hide — see app.js's
   updateSaveErrorBanner. Persistent (no auto-dismiss timer) and always
   above page content, since scrolling past it must not make it disappear. */
.save-error-banner {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  background: var(--danger-soft, var(--surface-3)); color: var(--danger, var(--ink));
  border-bottom: 1px solid var(--danger, var(--line-strong));
  font-size: 13px;
}

/* A gentle same-day nudge, not a real push notification — see store.js's
   setReminderEnabled comment for why. Reuses .save-error-banner's layout
   (flex row, dismiss button on the right) with the sakura accent instead of
   the danger one, so the two never read as the same severity of message. */
.reminder-banner {
  background: var(--sakura-soft); color: var(--ink);
  border-bottom: 1px solid var(--sakura);
}

/* Ambient falling sakura petals (js/decor.js). Purely decorative: fixed,
   z-index 0 so it always paints BEHIND the app shell's own content rather
   than needing pointer-events:none to merely LOOK non-interactive (it also
   has pointer-events:none, belt and suspenders — a decoration must never be
   able to eat a tap meant for the page under it). Two nested animations
   because a single one can't combine a slow one-shot fall with a fast
   repeating side-to-side sway without one silently overriding the other's
   timing. */
.decor-petals { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.decor-petal-fall {
  position: absolute; top: -20px;
  animation-name: decor-fall; animation-timing-function: linear; animation-iteration-count: infinite;
}
.decor-petal-sway {
  animation-name: decor-sway; animation-timing-function: ease-in-out;
  animation-iteration-count: infinite; animation-direction: alternate;
}
.decor-petal { background: var(--sakura); opacity: 0.5; border-radius: 100% 0 100% 0; transform: rotate(45deg); }
@keyframes decor-fall { from { transform: translateY(-20px) rotate(0deg); } to { transform: translateY(110vh) rotate(360deg); } }
@keyframes decor-sway { from { transform: translateX(-16px); } to { transform: translateX(16px); } }
@media (prefers-reduced-motion: reduce) {
  .decor-petal-fall, .decor-petal-sway { animation: none; }
}
@media print { .decor-petals { display: none; } }
html[data-printing] .decor-petals { display: none; }
