/* ============================================================
   layout.css
   Shared app shell. Loaded after tokens.css on every page so
   the body, the .app phone frame, the desktop centering rules,
   and the universal grain overlay live in exactly one place.
   Page-specific bottom padding (to clear the tab bar) lives on
   modifier classes: .app--list / .app--detail / .app--immersive.
   Pages with their own bespoke layout (flame, landing) can opt
   out by skipping the .app class.
   ============================================================ */

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; }

body {
  font-family: var(--font-ui);
  font-weight: var(--fw-ui-regular);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-charcoal);
  background-color: var(--paper-warm);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.3s ease;
  /* iOS safe-area. The Capacitor WebView runs edge-to-edge (contentInset:
     never) so pages can extend under the Dynamic Island when they want to
     (e.g. the flame hero). Pages that DON'T want that opt in to this floor
     by using the default body. Pages that DO want edge-to-edge add
     .no-safe-top to the body to cancel the inset. */
  padding-top: env(safe-area-inset-top);
}
body.no-safe-top {
  padding-top: 0;
}

/* The phone frame. Mobile first, fills the screen. On desktop a
   430px column is centered with a soft drop shadow so the app
   feels like a printed booklet rather than a browser page. */
.app {
  max-width: 430px;
  margin: 0 auto;
  min-height: 100vh;
  position: relative;
  padding: 0 0 120px 0;
}

/* Bottom padding modifiers. Default .app already clears a 5-tab
   bar with breathing room. Detail pages have a sticky action bar
   that needs more clearance. Immersive pages (flame, landing)
   should skip .app entirely. */
.app--list   { padding-bottom: 140px; }
.app--detail { padding-bottom: 180px; }

@media (min-width: 520px) {
  body::before {
    content: '';
    position: fixed; inset: 0;
    background: radial-gradient(ellipse at center, transparent 0%, rgba(30, 26, 20, 0.08) 100%);
    pointer-events: none;
    z-index: 0;
  }
  .app {
    background-color: var(--paper-warm);
    box-shadow: 0 0 0 1px rgba(58, 51, 48, 0.08), 0 40px 80px -20px rgba(30, 26, 20, 0.25);
    border-radius: 0;
  }
}

/* Universal grain overlay. Apply .grain to any container that
   should pick up a faint paper-noise multiply. The pseudo
   element fills the parent and inherits its border radius so
   it works on cards, buttons, and full-bleed sections. */
.grain::before {
  content: '';
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' seed='7'/><feColorMatrix values='0 0 0 0 0.17  0 0 0 0 0.12  0 0 0 0 0.08  0 0 0 0.5 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  opacity: 0.06;
  mix-blend-mode: multiply;
  pointer-events: none;
  border-radius: inherit;
}

/* ----------------------------------------------------------
   Touch target floor. Any anchor or button that doesn't opt
   out (.tap-sm) gets a 44x44 invisible hit area via padding.
   This prevents accidental misses on tiny SEE ALL links,
   filter chips, and inline icons. The visual size of the
   element is unchanged because we use padding, not min size.
   ---------------------------------------------------------- */
button, a {
  position: relative;
}
.see-all,
.assist-chip,
.filter-chip,
.starter-chip,
.cat-pill,
.ambience-btn,
.tab-link,
.inline-action {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
@media (hover: none) {
  .see-all::before,
  .nav .circle::before,
  .icon-btn::before {
    content: '';
    position: absolute;
    inset: -8px;
    pointer-events: auto;
  }
}

/* ----------------------------------------------------------
   Micro-interactions. Warm, consistent feedback on every
   interactive element. These are the details that make a
   good app feel premium.
   ---------------------------------------------------------- */

/* Input focus: warm glow instead of default browser outline.
   Works on text inputs, textareas, and contenteditable. The
   focus-visible rule in theme.css handles keyboard outlines;
   this adds a warm ambient glow on all focus. */
input[type="text"]:focus,
input[type="search"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
textarea:focus,
[contenteditable="true"]:focus {
  box-shadow: 0 0 0 3px rgba(11, 114, 114, 0.12), 0 0 16px rgba(11, 114, 114, 0.06);
  border-color: var(--teal-seaglass) !important;
  transition: box-shadow var(--dur-focus, 180ms) var(--ease-organic),
              border-color var(--dur-focus, 180ms) var(--ease-organic);
}
[data-theme="candlelight"] input[type="text"]:focus,
[data-theme="candlelight"] input[type="search"]:focus,
[data-theme="candlelight"] input[type="email"]:focus,
[data-theme="candlelight"] textarea:focus,
[data-theme="candlelight"] [contenteditable="true"]:focus {
  box-shadow: 0 0 0 3px rgba(111, 184, 180, 0.15), 0 0 16px rgba(111, 184, 180, 0.06);
  border-color: rgba(111, 184, 180, 0.4) !important;
}

/* Button press: consistent tactile scale on all buttons.
   Pages can override with their own active states. */
button:active:not(.tab):not(.meet-btn):not(.held-btn) {
  transform: scale(0.97);
  transition: transform 80ms var(--ease-ink);
}

/* Links and interactive text: smooth color transitions */
a {
  transition: color var(--dur-focus, 180ms) var(--ease-organic),
              opacity var(--dur-focus, 180ms) var(--ease-organic);
}

/* Card and container hover/active: subtle lift or press */
.grain {
  transition: box-shadow var(--dur-tap, 220ms) var(--ease-organic),
              transform var(--dur-tap, 220ms) var(--ease-organic);
}

/* Smooth opacity for images and media loading */
img, video {
  transition: opacity 0.4s var(--ease-gentle, ease);
}

/* ----------------------------------------------------------
   Bottom tab bar. Lives on every primary page (Home, Journal,
   Library, You). Immersive screens (flame, held, landing,
   onboarding) opt out by omitting the markup. Pages must also
   add .app--list or .app--detail so content clears the bar.
   ---------------------------------------------------------- */
.tabbar {
  position: fixed;
  bottom: 0; left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 430px;
  padding: var(--s-3) var(--s-5) calc(var(--s-3) + env(safe-area-inset-bottom));
  background: var(--paper-parchment);
  border-top: 1px solid rgba(58, 51, 48, 0.15);
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--s-2);
  z-index: 100;
  box-shadow: 0 -8px 30px -12px rgba(30, 26, 20, 0.18);
}
.tab {
  background: none;
  border: none;
  padding: var(--s-2) 0 var(--s-1);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  cursor: pointer;
  font-family: inherit;
  color: var(--ink-graphite);
  position: relative;
}
.tab .icon-wrap {
  width: 64px; height: 64px;
  display: grid; place-items: center;
  position: relative;
  border-radius: 50%;
}
.tab .icon-wrap img {
  width: 56px; height: 56px;
  object-fit: contain;
}
.tab .label {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.tab.active { color: var(--teal-deep); }
.tab.active .icon-wrap::before {
  content: '';
  position: absolute; inset: 0;
  background-image: url('assets/textures/washes/wash-teal-bloom.jpg');
  background-size: cover;
  mix-blend-mode: multiply;
  opacity: 0.55;
  border-radius: 50%;
}
.tab.center .icon-wrap {
  width: 56px; height: 56px;
  background: var(--paper-vellum);
  border: 1px solid rgba(58, 51, 48, 0.15);
  transform: translateY(-18px);
  box-shadow: 0 8px 20px -10px rgba(30, 26, 20, 0.25), inset 0 0 20px rgba(242, 192, 96, 0.18);
}
.tab.center .icon-wrap img { width: 44px; height: 44px; }
.tab.center .label { transform: translateY(-14px); color: var(--amber-warm); }

/* Narrow viewports (Samsung S20 = 360px). The fixed 64px icon-wrap plus
   gaps and tabbar padding totals 392px on a 360px screen, clipping the
   rightmost tab ("RHYTHM" -> "RHYTH"). At <=400px we tighten padding,
   gap, and icon-wrap so all five labels render. */
@media (max-width: 400px) {
  .tabbar {
    padding-left: var(--s-2);
    padding-right: var(--s-2);
    gap: var(--s-1);
  }
  .tab .icon-wrap { width: 56px; height: 56px; }
  .tab .icon-wrap img { width: 48px; height: 48px; }
  .tab.center .icon-wrap { width: 50px; height: 50px; }
  .tab.center .icon-wrap img { width: 38px; height: 38px; }
}

/* Candlelight (dark) mode. Token overrides in tokens.css handle
   most theming via CSS variables. Below are structural overrides
   for hardcoded colors and shadows. */
[data-theme="candlelight"] .tabbar {
  background: #0a0a0a;
  border-top: 1px solid rgba(237, 228, 210, 0.08);
  box-shadow: none;
}
[data-theme="candlelight"] .tab .icon-wrap {
  background: rgba(255, 255, 255, 0.04);
}
[data-theme="candlelight"] .tab .label { color: rgba(237, 228, 210, 0.5); }
[data-theme="candlelight"] .tab.active .icon-wrap {
  background: rgba(111, 184, 180, 0.10);
}
[data-theme="candlelight"] .tab.active .label { color: #6FB8B4; }
[data-theme="candlelight"] .branch-btn {
  border-color: rgba(237, 228, 210, 0.15);
  color: var(--ink-graphite);
}
[data-theme="candlelight"] .branch-btn:hover { background: rgba(111, 184, 180, 0.08); }
[data-theme="candlelight"] .gentle-rule { background: rgba(237, 228, 210, 0.15); }
[data-theme="candlelight"] .daily-gift {
  background: rgba(34, 26, 15, 0.85);
  border-color: rgba(237, 228, 210, 0.08);
  box-shadow: inset 0 0 40px rgba(242, 192, 96, 0.04), 0 1px 0 rgba(0, 0, 0, 0.2);
}
[data-theme="candlelight"] .grain::before { opacity: 0.03; }
@media (min-width: 520px) {
  [data-theme="candlelight"] body::before {
    background: radial-gradient(ellipse at center, transparent 0%, rgba(0, 0, 0, 0.3) 100%);
  }
  [data-theme="candlelight"] .app {
    box-shadow: 0 0 0 1px rgba(237, 228, 210, 0.05), 0 40px 80px -20px rgba(0, 0, 0, 0.5);
  }
}

/* ----------------------------------------------------------
   Page transitions. Every page fades in on arrival and fades
   out when the user navigates. The body starts transparent via
   the pageEnter animation. The .page-exit class triggers a
   quick fade + slight scale before the browser navigates.
   ---------------------------------------------------------- */
body:not(.no-page-enter) {
  animation: pageEnter var(--dur-page, 340ms) var(--ease-gentle, ease) both;
}
body.page-exit {
  animation: pageExit calc(var(--dur-page, 340ms) * 0.7) var(--ease-ink, ease) both;
}
@keyframes pageEnter {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes pageExit {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* ----------------------------------------------------------
   Stagger-reveal utility. Apply .reveal to any element that
   should fade + rise into view on page load. Set
   --reveal-i (0, 1, 2...) on each child for stagger timing.
   The 4px blur-to-sharp transition is Jakub Krehel's "materializing"
   recipe: opacity + translateY + filter combined feels like the
   element comes into focus rather than just sliding in.
   ---------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(10px);
  filter: blur(4px);
  animation: revealUp var(--dur-reveal, 500ms) var(--ease-gentle, ease) forwards;
  animation-delay: calc(var(--reveal-i, 0) * var(--dur-stagger, 60ms) + 200ms);
}
@keyframes revealUp {
  to { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* ---------- Accessibility: screen-reader-only ---------- */
.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;
}
