/* KidsCompass — shared stylesheet
 *
 * Used across the site. Two visual registers live here:
 *   - "Entry" register — full-bleed night-sky scene with a single
 *     centered form card. Used by login.html and home.html (the gated
 *     role picker — formerly index.html). The marketing landing
 *     (index.html, formerly about.html) reuses the dark scene styling
 *     for its hero but inlines its own variant since it scrolls into
 *     ivory sections below.
 *   - "Reading" register — warm two-column layout for app.html and
 *     the activity pages.
 */

/* ==========================================================
   Shared tokens (used by app.html; entry page overrides below)
   ========================================================== */

:root {
  /* Reading stage — warm ivory, cozy, easy on the eyes. */
  --bg:           #FAF3E4;
  --bg-soft:      #F0E4C8;        /* sidebar — warmer amber, like firelight */
  --bg-soft-deep: #E8D6B0;        /* deeper amber for the sidebar's lower edge */
  --ink:          #2A2017;
  --ink-soft:     #6A574A;
  --rule:         #E2D4B6;
  --accent:       #1E5F5A;
  --accent-hover: #174945;
  --accent-soft:  #E0EDE8;
  --gold:         #B08A3E;
  --gold-soft:    #D4B36A;
  --label:        #8A6B2C;
  --shadow:       0 1px 0 rgba(42, 32, 23, 0.04), 0 8px 24px rgba(42, 32, 23, 0.06);
  --shadow-soft:  0 1px 0 rgba(42, 32, 23, 0.03), 0 4px 14px rgba(42, 32, 23, 0.04);
  --focus-ring:   0 0 0 3px rgba(30, 95, 90, 0.18);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Lexend', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
  font-size: 19px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* iOS Safari sometimes auto-inflates text on first paint when it
     decides the body font is "too small" — this scales up all text
     including the id-chip and ask button, which then overflow the
     viewport and visually clip on the right. Locking text-size-adjust
     to 100% keeps the layout at the size we authored. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Hard belt-and-braces: clip any accidental horizontal overflow at
     the page edge so nothing can ever push the visible content off
     the right. Desktop is unaffected because nothing on desktop
     exceeds the viewport in the first place. */
  max-width: 100vw;
  overflow-x: hidden;
}

button { font-family: inherit; }

:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: 6px;
}

/* ==========================================================
   ENTRY PAGES (home.html — gated role picker; login.html)
   ----------------------------------------------------------
   Full-bleed painted night-sky scene. The form sits over the
   right portion of the painting itself, with a soft local
   gradient only behind the form for text legibility. Used by
   home.html (formerly index.html) and login.html. The marketing
   landing (index.html) reuses these tokens inline for its hero.
   ========================================================== */

.entry-body {
  --night-ink:       #F8EFD8;
  --night-ink-soft:  #DCC9A0;
  --night-rule:      rgba(245, 220, 170, 0.30);
  --night-input-bg:  rgba(20, 14, 10, 0.55);
  --night-gold:      #E9B254;
  --night-gold-soft: #F2C572;
  background: #07090F;
  color: var(--night-ink);
  /* Only clip horizontal — the scene's breath animation occasionally
     pushes a few px sideways. Vertical scroll MUST stay enabled so
     long forms (login, role picker with 5+ kids) can reach their
     bottom content (incl. "Sign out of this account"). */
  overflow-x: hidden;
  overflow-y: auto;
}

/* The painted scene fills the whole viewport. No separate form column.
   A small brightness lift makes the night feel more inviting without
   washing out the lantern's warmth or the moon's contrast. */
.scene {
  position: fixed;
  inset: 0;
  z-index: 0;
  background-image: url('assets/lantern_in_night_sky.png');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-color: #0A0F18;
  filter: brightness(1.18) saturate(1.05);
  animation: scene-breath 14s ease-in-out infinite;
}

/*
  Soft local gradient behind the form area only. Keeps the right side
  readable without dividing the page. Lighter than before so the brighter
  scene shows through.
*/
.scene-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(
      ellipse 55% 75% at 80% 50%,
      rgba(14, 16, 21, 0.50) 0%,
      rgba(14, 16, 21, 0.30) 40%,
      rgba(14, 16, 21, 0.10) 70%,
      rgba(14, 16, 21, 0)    100%
    );
}

/* ==========================================================
   PER-PAGE SCENE VARIANTS (login vs. home)
   ----------------------------------------------------------
   .entry-body, .scene, and .scene-overlay above are SHARED by
   login.html and home.html so the painted lantern world feels
   continuous. To keep the two pages from reading as carbon
   copies, each page adds a body-level modifier (.is-login or
   .is-home) and these rules nudge the painting crop + overlay
   tint accordingly. Subtle but deliberate.

   index.html (the marketing landing) doesn't use .entry-body
   at all — it has its own .hero-scene + .hero-scene-overlay
   inline, treated as a warm-amber promotional variant of the
   same painting.
   ========================================================== */

/* ----- login.html — auth gate, "step through the door" -----
   The painting is cropped tighter (background-size lifted from
   the shared `cover` to 130%, anchored on the lantern itself)
   so the lantern reads bigger and the scene feels more focused.
   The overlay is deeper than the shared one, so the form-side
   night reads more intimate — a small dramatic shift from the
   marketing landing's brighter, more promotional treatment. */
.entry-body.is-login .scene {
  background-size: 130%;
  background-position: 35% 55%;
  /* Slightly less brightness lift than the shared scene — the
     login mood is contemplative, not promotional. The breath
     animation continues to play; it's defined on .scene above. */
  filter: brightness(1.10) saturate(1.05);
}
.entry-body.is-login .scene-overlay {
  /* Same shape as the shared overlay (radial behind the form
     on the right) but ~20% deeper at each stop, so the form
     side reads quieter and the lantern carries more of the
     visual weight. */
  background:
    radial-gradient(
      ellipse 55% 75% at 80% 50%,
      rgba(8, 10, 16, 0.62) 0%,
      rgba(8, 10, 16, 0.42) 40%,
      rgba(8, 10, 16, 0.16) 70%,
      rgba(8, 10, 16, 0)    100%
    );
}

/* ----- home.html — role picker, "you're inside now" --------
   Lift brightness, widen the crop (background-size pulled back
   to 100% so more of the painted household context shows), and
   warm the overlay toward dawn amber. The mood is welcoming and
   slightly brighter than login.html — the visitor has just
   crossed the threshold and is choosing who they are inside. */
.entry-body.is-home .scene {
  background-size: 100%;
  background-position: center 45%;
  filter: brightness(1.28) saturate(1.10);
}
.entry-body.is-home .scene-overlay {
  /* Warm amber wash at the form area instead of cold dark.
     Picks up the lantern's gold and translates it into a
     "household firelight" feeling at the right side of the
     page where the role picker sits. */
  background:
    radial-gradient(
      ellipse 55% 75% at 80% 50%,
      rgba(176, 138, 62, 0.22) 0%,
      rgba(176, 138, 62, 0.12) 40%,
      rgba(176, 138, 62, 0.04) 70%,
      rgba(176, 138, 62, 0)    100%
    ),
    radial-gradient(
      ellipse 100% 100% at 50% 100%,
      rgba(20, 14, 8, 0.30) 0%,
      rgba(20, 14, 8, 0)    60%
    );
}

@keyframes scene-breath {
  0%, 100% { transform: scale(1.00); filter: brightness(1.18) saturate(1.05); }
  50%      { transform: scale(1.015); filter: brightness(1.23) saturate(1.05); }
}

/* The form lives in the right portion of the painting. */
.entry {
  position: relative;
  z-index: 1;
  /* 100vh on iOS Safari includes the URL bar height initially, which
     hides content behind the bar until the user scrolls and the bar
     collapses. 100dvh tracks the dynamic viewport instead, so the
     form fits the visible area on first paint. Fallback line is
     kept for browsers that don't support dvh yet. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 40px clamp(32px, 6vw, 80px) 40px 0;
}

.entry-card {
  width: 100%;
  max-width: 460px;
  text-align: left;
}

.entry .greeting {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: clamp(40px, 4.4vw, 56px);
  color: var(--night-ink);
  margin: 0 0 18px;
  line-height: 1.15;
  letter-spacing: 0.005em;
  text-shadow: 0 2px 28px rgba(0, 0, 0, 0.55);
}

.entry .intro {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 17px;
  color: var(--night-ink-soft);
  margin: 0 0 24px;
  max-width: 40ch;
  line-height: 1.6;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.5);
}

.entry .subline {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 21px;
  color: var(--night-ink-soft);
  margin: 0 0 36px;
  max-width: 36ch;
  line-height: 1.5;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.5);
}

.entry .name-form {
  width: 100%;
  max-width: 400px;
  display: flex;
  flex-direction: column;
}

.entry .name-box {
  display: flex;
  align-items: stretch;
  background: var(--night-input-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--night-rule);
  border-radius: 14px;
  box-shadow:
    0 1px 0 rgba(245, 220, 170, 0.06) inset,
    0 10px 32px rgba(0, 0, 0, 0.40);
  overflow: hidden;
  transition: border-color 200ms ease, box-shadow 200ms ease, background 200ms ease;
  margin-bottom: 14px;
}

.entry .name-box:focus-within {
  border-color: rgba(233, 178, 84, 0.70);
  background: rgba(40, 26, 18, 0.65);
  box-shadow:
    0 0 0 3px rgba(233, 178, 84, 0.18),
    0 1px 0 rgba(245, 220, 170, 0.08) inset,
    0 10px 32px rgba(0, 0, 0, 0.40);
}

.entry .name-box input {
  flex: 1;
  min-width: 0;                  /* allow flex shrink — prevents button clip */
  border: none;
  outline: none;
  background: transparent;
  padding: 16px 20px;
  font-family: inherit;
  font-size: 19px;
  color: var(--night-ink);
  min-height: 52px;
}

.entry .name-box input::placeholder {
  color: rgba(245, 220, 170, 0.50);
  font-style: italic;
}

.entry .name-box button {
  flex-shrink: 0;                /* never let the button get squished */
  appearance: none;
  border: none;
  background: var(--night-gold);
  color: #2A1B0F;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 16px;
  font-weight: 600;
  padding: 0 22px;
  cursor: pointer;
  transition: background 160ms ease;
  min-height: 52px;
  white-space: nowrap;
}

.entry .name-box button:hover { background: var(--night-gold-soft); }

.entry .skip {
  background: transparent;
  border: none;
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 15px;
  color: var(--night-ink-soft);
  cursor: pointer;
  padding: 6px 4px;
  border-radius: 6px;
  text-decoration: underline;
  text-decoration-color: rgba(245, 220, 170, 0.30);
  text-underline-offset: 4px;
  transition: color 160ms ease;
  align-self: flex-start;
}

.entry .skip:hover { color: var(--night-ink); }

.entry .privacy-note {
  margin-top: 28px;
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  color: var(--night-ink-soft);
  opacity: 0.85;
  max-width: 38ch;
  line-height: 1.5;
}

/* On the entry (night) page, focus rings should be warm gold, not green. */
.entry-body :focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(233, 178, 84, 0.28);
  border-radius: 6px;
}

/* ==========================================================
   SITE NAV STRIP (index.html, login.html, future pricing.html)
   ----------------------------------------------------------
   The thin "KidsCompass · About · Pricing · Sign in" strip
   that lives in the top corners of any outer-site page. It's
   absolutely positioned so the page's centered hero / form
   doesn't have to budge to accommodate it, and pointer-events
   is none on the wrapper so clicks fall through to whatever's
   underneath — only the links themselves are interactive.

   Color comes from --night-ink / --night-ink-soft, which are
   painted by .entry-body (login.html, home.html). The marketing
   landing (index.html) isn't an .entry-body page, but its hero
   IS a dark band; index.html scopes the same two tokens onto
   the hero locally so this block resolves correctly there too.
   ========================================================== */

.site-nav {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px clamp(20px, 5vw, 56px);
  pointer-events: none;
}
.site-nav > * { pointer-events: auto; }

.site-nav-brand {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: 17px;
  color: var(--night-ink);
  letter-spacing: 0.01em;
  text-decoration: none;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.55);
}

.site-nav-links {
  display: flex;
  gap: clamp(14px, 3vw, 28px);
  align-items: center;
}

.site-nav-link {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 15px;
  color: var(--night-ink-soft);
  text-decoration: none;
  letter-spacing: 0.01em;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.55);
  transition: color 160ms ease;
}
.site-nav-link:hover { color: var(--night-ink); }
.site-nav-link.is-current {
  color: var(--night-ink);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: rgba(245, 220, 170, 0.45);
}

@media (max-width: 540px) {
  .site-nav { padding: 16px 18px; }
  .site-nav-brand { font-size: 15px; }
  .site-nav-link { font-size: 14px; }
}

/* ==========================================================
   APP / STORY PAGE (app.html)
   ----------------------------------------------------------
   Two-column warm-ivory reading surface. Sidebar carries
   amber tones from the entry's lantern. Reading stage stays
   light and easy on the eyes.
   ========================================================== */

.app {
  /* Dynamic viewport height for iOS Safari — see .entry note above. */
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 380px minmax(0, 1fr);
  background: var(--bg);
  /* Animate the column collapse when the kid toggles the sidebar.
     Modern Chrome / Safari / Firefox animate grid-template-columns
     natively; older engines just snap, which is the existing
     behaviour, so no regression. 560ms reads as a deliberate
     "settling" gesture rather than a snap. */
  transition: grid-template-columns 560ms cubic-bezier(.2, .7, .2, 1);
}

/* ---------- Sidebar ---------- */

/*
  Sidebar — the landing-page lantern scene is the background, with a dark
  ink wash on top to keep text readable. Top half = brand + section links.
  Bottom half (starts at midpoint) = "Your Stories" scrollable list.
*/
.sidebar {
  position: sticky;
  top: 0;
  /* Dynamic viewport height for iOS Safari — see .entry note above. */
  height: 100vh;
  height: 100dvh;
  background-color: #0A0F18;
  border-right: 1px solid rgba(176, 138, 62, 0.18);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
  overflow: hidden;
  isolation: isolate;
  color: #F4E8CD;
}

/* Top and bottom halves split evenly — "Your Stories" header lands at the midpoint. */
.sidebar-top {
  flex: 1 1 50%;
  min-height: 0;
  overflow-y: auto;
  padding: 32px 24px 16px;
  display: flex;
  flex-direction: column;
  scrollbar-width: thin;
  scrollbar-color: rgba(233, 178, 84, 0.20) transparent;
}

.sidebar-top::-webkit-scrollbar { width: 4px; }
.sidebar-top::-webkit-scrollbar-track { background: transparent; }
.sidebar-top::-webkit-scrollbar-thumb { background: rgba(233, 178, 84, 0.20); border-radius: 4px; }

.sidebar-bottom {
  flex: 1 1 50%;
  min-height: 0;
  padding: 18px 24px 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.sidebar-footer {
  flex-shrink: 0;
  border-top: 1px solid rgba(176, 138, 62, 0.18);
  padding: 14px 24px 18px;
  background: rgba(7, 9, 15, 0.78);
}

/*
  The landing-page lantern scene as the sidebar's own background, shifted
  so the moon and night sky dominate (the lantern itself is cropped out
  to the side). A lighter vignette keeps the cream sidebar text legible
  while still letting the moon and stars come through.
*/
.ambience {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image: url('assets/lantern_in_night_sky.png');
  background-size: cover;
  /* Shift right + slightly up — the lantern lives in the lower-left of
     the original image, so this composition shows the upper-right where
     the crescent moon and stars are. */
  background-position: 78% 22%;
  background-repeat: no-repeat;
  background-color: #0A0F18;
  filter: brightness(0.95) saturate(1.0);
}

.ambience::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      to bottom,
      rgba(7, 9, 15, 0.45) 0%,
      rgba(7, 9, 15, 0.30) 30%,
      rgba(7, 9, 15, 0.25) 65%,
      rgba(7, 9, 15, 0.50) 100%
    );
}

.sidebar > *:not(.ambience) { position: relative; z-index: 1; }

/* ----- Unified section headers (My Journal / Activities / Rewards / Your Stories) ----- */

.side-section-header {
  display: block;
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-style: normal;
  font-size: 18px;
  color: #F8EFD8;
  letter-spacing: 0.005em;
  text-decoration: none;
  padding: 10px 4px;
  margin: 0;
  line-height: 1.3;
  transition: color 120ms ease;
}

a.side-section-header:hover { color: #E9B254; }

a.side-section-header:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(233, 178, 84, 0.45);
  border-radius: 4px;
}

/* Nav wrapper for the three top-half section links. */
.sidebar-sections {
  display: flex;
  flex-direction: column;
  margin-top: 8px;
}

/* Continue entry (June 2026 IA round): a single resume line built by
   kc_sidebar.js from window.KCActivities. Sits just under the nav,
   styled as a quiet card so it reads as "pick up here" without
   competing with the section headers above it. */
.side-continue {
  margin: 14px 4px 2px;
  padding: 10px 12px;
  background: rgba(233, 178, 84, 0.08);
  border: 1px solid rgba(233, 178, 84, 0.18);
  border-left: 3px solid #E9B254;
  border-radius: 10px;
}
.side-continue-label {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 11px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #C9B894;
  margin: 0 0 4px;
}
.side-continue-link {
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-decoration: none;
}
.side-continue-name {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: 16px;
  color: #F8EFD8;
  line-height: 1.25;
  transition: color 120ms ease;
}
.side-continue-action {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  color: #DCC9A5;
  line-height: 1.3;
}
.side-continue-link:hover .side-continue-name,
.side-continue-link:focus-visible .side-continue-name { color: #E9B254; }
.side-continue-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(233, 178, 84, 0.45);
  border-radius: 4px;
}

/* ----- Section dividers ----- */

.side-divider {
  border: none;
  height: 1px;
  background: linear-gradient(to right,
    rgba(176, 138, 62, 0) 0%,
    rgba(176, 138, 62, 0.45) 50%,
    rgba(176, 138, 62, 0) 100%);
  /* June 2026 (4-link nav): hairlines inside the nav group sit
     tighter so the four links read as ONE compact group. */
  margin: 2px 0;
}

/* Stronger divider between top and bottom halves (the midpoint line). */
.side-divider--major {
  height: 1px;
  background: linear-gradient(to right,
    rgba(233, 178, 84, 0) 0%,
    rgba(233, 178, 84, 0.55) 50%,
    rgba(233, 178, 84, 0) 100%);
  /* June 2026: real air around the midpoint line. Pre-fix this was
     margin: 0, so "Stories" started CLOSER to the nav than the nav
     links sat to each other and the whole rail read as one crowded
     run. The asymmetric margin (more above than below) ties the
     line to the section it introduces. */
  margin: 18px 0 10px;
  position: relative;
  z-index: 1;
}

/* June 2026 (4-link nav): with a fourth link the 10px-tall rows
   read as a wall. Slightly tighter rows + one step down in size,
   scoped to the NAV group only — the "Stories" header below the
   major divider keeps its full 18px presence, which also helps
   the two groups read differently. */
.sidebar-sections .side-section-header {
  padding: 7px 4px;
  font-size: 17px;
}

.sidebar .brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 8px;
  padding-bottom: 4px;
  margin-bottom: 18px;
}

.sidebar .wordmark {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: 28px;
  color: #F8EFD8;
  margin: 0;
  letter-spacing: 0.005em;
}

.sidebar .tagline {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 16px;
  color: #DCC9A0;
  margin: 0;
  max-width: 28ch;
  line-height: 1.5;
}

/* Single rotating suggestion — sits below the ask box, not in the sidebar */
.single-suggestion {
  appearance: none;
  background: transparent;
  border: none;
  padding: 0;
  margin-top: 10px;
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 15px;
  color: var(--ink-soft);
  cursor: pointer;
  text-align: left;
  transition: color 120ms ease;
  line-height: 1.5;
  display: block;
  text-decoration: underline;
  text-decoration-color: rgba(106, 87, 74, 0.25);
  text-underline-offset: 3px;
}

.single-suggestion:hover { color: var(--accent); text-decoration-color: rgba(30, 95, 90, 0.35); }

/* ----- "Your Stories" history list (sidebar-bottom) ----- */

.history-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 2px 4px;
  scrollbar-width: thin;
  scrollbar-color: rgba(233, 178, 84, 0.30) transparent;
}

.history-list::-webkit-scrollbar { width: 5px; }
.history-list::-webkit-scrollbar-track { background: transparent; }
.history-list::-webkit-scrollbar-thumb { background: rgba(233, 178, 84, 0.30); border-radius: 4px; }

.history-empty {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  color: #DCC9A0;
  margin: 0;
  opacity: 0.7;
  padding: 6px 4px;
}

/*
  Each story card uses the warm parchment story-page background (--bg) so the
  list visually echoes the reading stage on the right.
*/
.history-entry {
  position: relative;
  display: flex;
  align-items: center;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 10px 36px 10px 12px; /* right padding reserves room for the × */
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
  outline: none;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.20);
}

.history-entry:hover {
  background: #FFFEFA;
  border-color: var(--gold-soft);
  transform: translateY(-1px);
}

.history-entry:focus-visible {
  box-shadow: 0 0 0 2px rgba(233, 178, 84, 0.55), 0 1px 2px rgba(0, 0, 0, 0.20);
  border-color: var(--gold-soft);
}

/* Tiny Islamic lantern (fanous) marker, sitting to the left of each
   stored story like a quiet little flame next to a remembered thing.
   Rendered via `mask-image` over `background-color: var(--gold)` so
   the silhouette automatically inherits the right warmth in both
   day and night mode — --gold is one of the variables that flips
   between the two themes (#B08A3E bronze by day, #E4C57A brass by
   night), so the single rule below carries both. On hover the
   lantern lifts to full opacity and a soft gold drop-shadow makes
   it read as "lit." The SVG is six small shapes — handle, top cap,
   octagonal body, bottom cap, finial — chosen for legibility at
   ~14×18 px rather than ornamental detail that would muddy at this
   size. */
.history-entry::before {
  content: "";
  flex: 0 0 auto;
  width: 14px;
  height: 18px;
  margin-right: 10px;
  background-color: var(--gold);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 16'><rect x='5.5' y='0.5' width='1' height='1.5'/><rect x='3' y='2' width='6' height='1.4' rx='0.3'/><path d='M3.5 3.4 L2 5 L2 10 L3.5 11.6 L8.5 11.6 L10 10 L10 5 L8.5 3.4 Z'/><rect x='3' y='11.6' width='6' height='1.1' rx='0.3'/><rect x='5.5' y='12.9' width='1' height='1.6'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 16'><rect x='5.5' y='0.5' width='1' height='1.5'/><rect x='3' y='2' width='6' height='1.4' rx='0.3'/><path d='M3.5 3.4 L2 5 L2 10 L3.5 11.6 L8.5 11.6 L10 10 L10 5 L8.5 3.4 Z'/><rect x='3' y='11.6' width='6' height='1.1' rx='0.3'/><rect x='5.5' y='12.9' width='1' height='1.6'/></svg>") center / contain no-repeat;
  opacity: 0.85;
  transition: opacity 160ms ease, filter 160ms ease;
}
.history-entry:hover::before,
.history-entry:focus-visible::before {
  opacity: 1;
  filter: drop-shadow(0 0 3px rgba(228, 197, 122, 0.45));
}

/* Single-line truncated story title (the child's question). */
.history-question {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.35;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}

/* Per-entry delete button. Faint until the entry is hovered/focused.
   min-width/height are bumped to 44px to meet iOS touch-target guidance
   — easy to mis-tap delete instead of opening the story otherwise. */
.history-entry-del {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  appearance: none;
  background: none;
  border: none;
  color: rgba(106, 87, 74, 0.45);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 4px;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 120ms ease, background 120ms ease;
}

.history-entry:hover .history-entry-del { color: rgba(106, 87, 74, 0.85); }
.history-entry-del:hover { color: #B0392B; background: rgba(176, 57, 43, 0.08); }
.history-entry-del:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(176, 57, 43, 0.40);
}

/* ----- Delete-confirm modal (shown when a history entry's × is clicked) ----- */

.confirm-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(7, 9, 15, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: confirm-in 160ms ease-out;
}
/* The shared confirm modal is currently added/removed from the DOM
   rather than toggled via .hidden, but author rules with `display:
   flex` and the UA's `[hidden] { display: none }` tie on specificity
   — author wins, so a future caller that wrote `overlay.hidden = true`
   would silently keep the modal visible. Match the explicit override
   the make-a-book.html custom-page modal uses so the smoke harness's
   [hidden]-guard passes for every overlay in one consistent style. */
.confirm-overlay[hidden] { display: none; }

@keyframes confirm-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.confirm-card {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 14px;
  padding: 28px 28px 22px;
  max-width: 380px;
  width: 100%;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
  text-align: center;
}

.confirm-message {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 18px;
  color: var(--ink);
  margin: 0 0 22px;
  line-height: 1.45;
}

.confirm-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
}

.confirm-cancel,
.confirm-delete {
  appearance: none;
  border: 1px solid var(--rule);
  background: #FFFEFA;
  border-radius: 8px;
  padding: 10px 22px;
  font-family: inherit;
  font-size: 15px;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.confirm-cancel { color: var(--ink); }
.confirm-cancel:hover { background: var(--bg); border-color: var(--ink-soft); }

.confirm-delete {
  background: #B0392B;
  border-color: #B0392B;
  color: #FFFEFA;
}
.confirm-delete:hover { background: #8E2D22; border-color: #8E2D22; }

/* ----- Activity example text ----- */

.activity-example {
  background: rgba(30, 95, 90, 0.06);
  border-left: 3px solid rgba(30, 95, 90, 0.25);
  border-radius: 0 8px 8px 0;
  padding: 10px 14px;
  margin-bottom: 16px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-soft);
}

.activity-example-label {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-weight: 500;
  color: var(--label);
}

/* ----- Sidebar footer (Hijri date only) ----- */
/* (The "Every answer comes from…" line and "For parents" link were moved
   off the sidebar — they now live on home.html and the parent page.) */

/* (The faint lantern+crescent watermark that used to sit behind the
   empty-state greeting has been removed — see the matching note in
   app.js. The .motif rules and the .empty-state .motif--watermark
   override below were removed along with it.) */

/* ---------- Right column: reading stage ---------- */

.content {
  position: relative;
  padding: 0;
  display: flex;
  flex-direction: column;
}

/*
  The "reading as Noah · switch" pill in the top-right of the content area.
  Three pieces: a gold initial-avatar, a stacked label + name, and a teal
  pill button for switching identity. Sits on a soft parchment background
  with a faint shadow so it reads as a proper UI element on the page.
*/
/* Identity chip — horizontal pill at top-right of every page:
   [avatar | reading as / Yousuf | switch]. Compact enough (~160px)
   to never reach the content's right edge on a 1440px viewport,
   given the content max-width of 860px and the 380px sidebar
   (1440 - 380 - 16 right offset - 160 chip - 24 gap = 860 fits).
   max-width: 200px is a hard ceiling in case a very long kid name
   would otherwise push the chip wider. */
.id-chip {
  position: fixed;
  top: 16px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #FFFEFA;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 4px 6px 4px 4px;
  max-width: 200px;
  z-index: 5;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.5) inset,
    0 2px 8px rgba(42, 32, 23, 0.08);
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

.id-chip:hover {
  border-color: var(--gold-soft);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.5) inset,
    0 4px 14px rgba(42, 32, 23, 0.12);
}

/* Avatar — kid's first initial inside a warm gold gradient. Smaller
   than before (32px) to keep the whole chip compact. */
.id-chip-avatar {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--gold-soft) 0%, var(--gold) 100%);
  color: #FFFEFA;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.30) inset,
    0 1px 2px rgba(42, 32, 23, 0.15);
}

/* Stacked label/name — italic "reading as" above bold name. The
   name truncates with ellipsis so a long kid name can't push the
   chip past its 200px cap. */
.id-chip-text {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.1;
  padding: 0 2px;
  min-width: 0;
  overflow: hidden;
}

.id-chip-label {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 9px;
  color: var(--ink-soft);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 1px;
}

.id-chip-text strong {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 600;
  font-style: normal;
  font-size: 13px;
  color: var(--ink);
  letter-spacing: 0.005em;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Switch — small teal pill, sits to the right of the name. */
.id-chip-switch {
  appearance: none;
  flex-shrink: 0;
  background: var(--accent-soft);
  border: none;
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 11px;
  color: var(--accent);
  padding: 4px 10px;
  border-radius: 999px;
  cursor: pointer;
  line-height: 1.3;
  transition: background 140ms ease, color 140ms ease, transform 140ms ease;
}

.id-chip-switch:hover {
  background: var(--accent);
  color: #FFFEFA;
  transform: translateY(-1px);
}

.id-chip-switch:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(30, 95, 90, 0.30);
}

.stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 64px 64px 40px;
}

.stage-inner {
  width: 100%;
  max-width: 640px;
}

/* Cross-fade for state transitions. */
.stage-inner > * {
  animation: stage-in 220ms ease-out both;
}

@keyframes stage-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.stage-inner > *[tabindex="-1"]:focus { outline: none; box-shadow: none; }

/* ----- Empty / greeting state ----- */

.empty-state {
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  position: relative;
}

/* (.empty-state .motif--watermark positioning rules were removed when
   the watermark itself was retired from app.js.) */

.empty-state > * { position: relative; z-index: 1; }

.empty-state .greeting {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 28px;
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 44px;
  line-height: 1.35;
  max-width: 22ch;
}

.empty-state .greeting .name {
  color: var(--ink);
  font-weight: 600;
}

.ask-form {
  width: 100%;
  max-width: 520px;
}

.ask-box {
  display: flex;
  align-items: stretch;
  background: #FFFEFA;
  border: 1px solid var(--rule);
  border-radius: 12px;
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

.ask-box:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(30, 95, 90, 0.12), var(--shadow);
}

.ask-box input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  padding: 18px 20px;
  font-family: inherit;
  font-size: 18px;
  color: var(--ink);
  min-height: 44px;
}

.ask-box input::placeholder {
  color: #A89E91;
  font-style: italic;
}

.ask-box button {
  flex-shrink: 0;
  appearance: none;
  border: none;
  background: var(--accent);
  color: #FFFEFA;
  font-size: 16px;
  font-weight: 500;
  padding: 0 26px;
  cursor: pointer;
  transition: background 120ms ease;
  min-height: 44px;
}

.ask-box button:hover { background: var(--accent-hover); }

/* Mic button — sits between the text input and the Ask button. */
.ask-box .mic-btn {
  flex-shrink: 0;
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-soft);
  width: 44px;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 120ms ease;
  border-left: 1px solid var(--rule);
  min-height: 44px;
}

.ask-box .mic-btn svg {
  width: 18px;
  height: 18px;
  display: block;
}

.ask-box .mic-btn:hover { color: var(--accent); }

/* Pulsing ring when actively listening */
.ask-box .mic-btn--listening {
  color: #C0392B;
  animation: mic-pulse 1.2s ease-in-out infinite;
}

@keyframes mic-pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.45; }
}

/* ----- Response state ----- */

/* Loading line shown under the question chip while the pipeline runs.
   Italic, soft color, gently animated opacity so the page feels alive
   without spinning anything. The kid sees their question echoed back
   immediately; this line acknowledges the wait. */
.response--loading .loading {
  text-align: center;
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 16px;
  color: var(--ink-soft);
  margin: 40px 0;
  animation: kc-loading-pulse 1.6s ease-in-out infinite;
}

@keyframes kc-loading-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

.response .question-bar { text-align: center; margin-bottom: 28px; }

.response .question-bar .label {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  margin-bottom: 8px;
}

.response .question-bar .question {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 24px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.3;
}

.response .block { margin-bottom: 24px; }

/* Bridge line between the brief answer and the story.
   Same font, size, and color as the surrounding answer and story bodies —
   it's just one more sentence in the same voice. */
.response .bridge {
  margin: 0 0 24px;
  max-width: 60ch;
}

.response .answer p {
  font-size: 19px;
  line-height: 1.55;
  color: var(--ink);
  margin: 0;
  max-width: 60ch;
}

.response .block-label {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-weight: 500;
  font-size: 14px;
  color: var(--label);
  margin-bottom: 8px;
}

.response .story p {
  margin: 0 0 1em;
  max-width: 62ch;
}
.response .story p:last-child { margin-bottom: 0; }

/* ----- Sources section (always visible, prominent heading) ----- */

.sources-section {
  margin: 28px 0 20px;
}

/* A soft closing line at the end of the story before the sources block.
   Centered ornamental hairline — feels like the end of a chapter. */
.story-end-line {
  width: 80px;
  height: 1px;
  margin: 0 auto 22px;
  background: linear-gradient(to right,
    rgba(176, 138, 62, 0) 0%,
    rgba(176, 138, 62, 0.55) 50%,
    rgba(176, 138, 62, 0) 100%);
}

.sources-heading {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 600;
  font-style: normal;
  font-size: 19px;
  color: var(--ink);
  margin: 0 0 14px;
  letter-spacing: 0.005em;
  text-align: center;
}

.sources-body {
  background: #FBF5E6;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--gold-soft);
  border-radius: 10px;
  padding: 16px 20px;
}

.sources-body ul {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 15px;
  color: var(--ink);
  line-height: 1.6;
}

.sources-body li { margin-bottom: 12px; }
.sources-body li:last-child { margin-bottom: 0; }
.sources-body .ref { color: var(--ink); font-weight: 600; }

/* Arabic verse beneath a Qur'an source citation — large, child-friendly.
   Scheherazade New is purpose-designed for clear Arabic reading (full
   harakat, open glyphs); Amiri / Noto Naskh kept as fallbacks. */
.source-arabic {
  font-family: 'Scheherazade New', 'Amiri', 'Noto Naskh Arabic', 'Traditional Arabic', serif;
  font-size: 28px;
  line-height: 2.1;
  font-weight: 500;
  color: var(--gold);
  margin: 14px 0 6px;
  text-align: right;
}

/* Plain-English child-friendly rendering shown directly under the Arabic. */
.source-translation {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
  margin: 4px 0 6px;
  padding: 8px 12px;
  background: rgba(176, 138, 62, 0.08);
  border-left: 2px solid var(--gold-soft);
  border-radius: 0 6px 6px 0;
}

.source-translation::before {
  content: "What it means: ";
  font-style: italic;
  font-weight: 600;
  color: var(--label);
  font-size: 14px;
  letter-spacing: 0.02em;
}

/* Lookup hint beneath each source item */
.source-lookup {
  display: block;
  font-size: 13px;
  color: var(--ink-soft);
  font-style: italic;
  margin-top: 8px;
}

/* ----- Dua block (response when the kid explicitly asks for a dua) ----- */

.dua {
  margin: 8px 0 20px;
}

.dua-eyebrow {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  color: var(--label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0 0 14px;
}

.dua-intro {
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 22px;
  max-width: 56ch;
}

/* The Arabic of the dua — same family/size as the Quran citations in the
   "Where this comes from" section. Slightly larger because here the dua
   IS the centerpiece. */
.dua-arabic {
  font-family: 'Scheherazade New', 'Amiri', 'Noto Naskh Arabic', 'Traditional Arabic', serif;
  font-size: 30px;
  line-height: 2.2;
  font-weight: 500;
  color: var(--gold);
  margin: 0 0 14px;
  text-align: right;
}

/* Kid-friendly translation — matches .source-translation styling so the
   visual vocabulary is consistent between the two places it appears. */
.dua-translation {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 18px;
  padding: 12px 16px;
  background: rgba(176, 138, 62, 0.08);
  border-left: 3px solid var(--gold-soft);
  border-radius: 0 8px 8px 0;
}

.dua-translation::before {
  content: "What it means: ";
  font-style: italic;
  font-weight: 600;
  color: var(--label);
  font-size: 14px;
  letter-spacing: 0.02em;
}

/* When and why to say this dua. */
.dua-context {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 18px;
  max-width: 60ch;
}

.dua-context::before {
  content: "When to say it: ";
  font-weight: 600;
  font-style: normal;
  color: var(--label);
  font-size: 14px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-right: 6px;
}

/* Citation row at the bottom of the dua block. */
.dua-source {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 14px;
  color: var(--ink-soft);
  padding-top: 14px;
  margin-top: 4px;
  border-top: 1px solid var(--rule);
}

.dua-source-ref {
  font-weight: 600;
  color: var(--ink);
}

.dua-source-lookup {
  font-style: italic;
  color: var(--ink-soft);
}
.response .sources .ref { color: var(--ink); font-weight: 500; }

/* ----- Muted text-link (used across multiple screens) ----- */

.next-link {
  appearance: none;
  background: none;
  border: none;
  padding: 4px 0;
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  color: var(--ink-soft);
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: rgba(106, 87, 74, 0.30);
  text-underline-offset: 3px;
  transition: color 120ms ease;
  /* iOS guidance: tap targets >= 44px. Bumped from 36px. */
  min-height: 44px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
}

.next-link:hover { color: var(--ink); }

/* ----- Story Continue button ----- */

.story-continue {
  display: block;
  margin: 28px 0 8px;
  appearance: none;
  background: var(--accent);
  border: none;
  border-radius: 10px;
  padding: 14px 32px;
  font-family: inherit;
  font-size: 17px;
  font-weight: 500;
  color: #FFFEFA;
  cursor: pointer;
  transition: background 120ms ease;
}

.story-continue:hover { background: var(--accent-hover); }

/* ----- Activity / Commitment / Check-in screens ----- */

.activity-state,
.checkin-state {
  max-width: 580px;
  padding-top: 40px;
}

.activity-heading {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: 26px;
  color: var(--ink);
  margin: 0 0 16px;
  line-height: 1.3;
}

.activity-prompt {
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 20px;
  max-width: 56ch;
}

.activity-textarea {
  width: 100%;
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 14px 16px;
  font-family: inherit;
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink);
  background: #FFFEFA;
  resize: vertical;
  transition: border-color 120ms ease, box-shadow 120ms ease;
  box-shadow: var(--shadow-soft);
}

.activity-textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(30, 95, 90, 0.10), var(--shadow-soft);
}

.activity-textarea::placeholder {
  color: #A89E91;
  font-style: italic;
}

.activity-btn-row {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: 16px;
}

.activity-continue {
  appearance: none;
  background: var(--accent);
  border: none;
  border-radius: 10px;
  padding: 12px 28px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 500;
  color: #FFFEFA;
  cursor: pointer;
  transition: background 120ms ease;
}

.activity-continue:hover { background: var(--accent-hover); }

.go-btn {
  padding: 14px 32px;
  font-size: 17px;
}

/* Check-in specific */

.checkin-greeting {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 20px;
  color: var(--ink);
  margin: 0 0 24px;
}

.checkin-commitment {
  background: #FBF5E6;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--gold-soft);
  border-radius: 10px;
  padding: 14px 18px;
  margin-bottom: 24px;
}

.checkin-label {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  color: var(--label);
  margin: 0 0 6px;
}

.checkin-text {
  font-size: 17px;
  color: var(--ink);
  line-height: 1.5;
  margin: 0;
}

.checkin-prompt {
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 16px;
  max-width: 52ch;
}

/* ----- Journal panel (sidebar) ----- */

.journal-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin-bottom: 16px;
}

.journal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.journal-title {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 15px;
  color: #E9B254;
  letter-spacing: 0.01em;
}

.journal-list {
  max-height: 120px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Subtle scrollbar on the dark sidebar */
  scrollbar-width: thin;
  scrollbar-color: rgba(233, 178, 84, 0.30) transparent;
}

.journal-list::-webkit-scrollbar { width: 4px; }
.journal-list::-webkit-scrollbar-track { background: transparent; }
.journal-list::-webkit-scrollbar-thumb { background: rgba(233, 178, 84, 0.30); border-radius: 4px; }

.journal-empty {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  color: #C9BFA8;
  margin: 0;
  opacity: 0.75;
}

.journal-entry {
  position: relative;
  background: rgba(248, 239, 216, 0.10);
  border: 1px solid rgba(176, 138, 62, 0.20);
  border-radius: 8px;
  padding: 8px 28px 8px 10px; /* right padding makes room for the × button */
  transition: background 120ms ease;
}

.journal-entry:hover { background: rgba(248, 239, 216, 0.16); }

.journal-entry-label {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 11px;
  color: #E9B254;
  margin-bottom: 2px;
  letter-spacing: 0.02em;
}

.journal-entry-text {
  font-size: 13px;
  color: #F4E8CD;
  line-height: 1.45;
}

.journal-entry-del {
  position: absolute;
  top: 6px;
  right: 6px;
  appearance: none;
  background: none;
  border: none;
  color: rgba(200, 180, 140, 0.50);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  transition: color 120ms ease;
}

.journal-entry-del:hover { color: #F4E8CD; }

/* ----- Hijri date (sidebar footer) — bigger + more visible ----- */

.hijri-date {
  text-align: center;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

/* June 2026: phase-of-the-month moon above the Hijri date. The
   sidebar is always night-styled, so the palette is fixed pale gold. */
.hijri-moon-wrap { line-height: 0; }
.hijri-moon { display: block; filter: drop-shadow(0 0 5px rgba(244, 232, 205, 0.30)); }
.hijri-moon-disc { fill: rgba(244, 232, 205, 0.10); stroke: rgba(244, 232, 205, 0.35); stroke-width: 0.8; }
.hijri-moon-lit { fill: #F4E8CD; }
@media (prefers-reduced-motion: no-preference) {
  .hijri-moon { animation: hijri-moon-breathe 9s ease-in-out infinite; }
}
@keyframes hijri-moon-breathe {
  0%, 100% { opacity: 0.82; }
  50%      { opacity: 1; }
}

.hijri-date-text {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: normal;
  font-weight: 500;
  font-size: 16px;
  color: #F4E8CD;
  margin: 0;
  opacity: 1;
  letter-spacing: 0.01em;
}

/* Occasion nudge — warmer gold when an occasion is near. Now clickable:
   tapping it opens a popup with a kid-friendly story about the day. */
.hijri-occasion {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  color: #E9B254;
  margin: 0;
  letter-spacing: 0.01em;
}

/* Button variant — same look as the span, but keyboard- and click-able. */
.hijri-occasion--btn {
  appearance: none;
  background: transparent;
  border: none;
  padding: 4px 8px;
  margin: 2px 0 0;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: rgba(233, 178, 84, 0.40);
  text-underline-offset: 4px;
  border-radius: 4px;
  transition: color 120ms ease, background 120ms ease, text-decoration-color 120ms ease;
}

.hijri-occasion--btn:hover {
  color: #F2C572;
  background: rgba(233, 178, 84, 0.08);
  text-decoration-color: rgba(233, 178, 84, 0.75);
}

.hijri-occasion--btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(233, 178, 84, 0.55);
}

/* ----- Occasion popup (reuses .confirm-overlay backdrop) ----- */

.occasion-card {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 16px;
  max-width: 600px;
  width: 100%;
  max-height: 86vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.40);
}

.occasion-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 24px 16px;
  border-bottom: 1px solid var(--rule);
  background: #FFFEFA;
}

.occasion-header-text { flex: 1; min-width: 0; }

.occasion-title {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: 24px;
  color: var(--ink);
  margin: 0;
  line-height: 1.25;
}

.occasion-subtitle {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  color: var(--label);
  letter-spacing: 0.02em;
  margin: 6px 0 0;
}

.occasion-close {
  appearance: none;
  background: transparent;
  border: none;
  font-size: 24px;
  line-height: 1;
  color: var(--ink-soft);
  cursor: pointer;
  padding: 4px 10px;
  border-radius: 6px;
  transition: color 120ms ease, background 120ms ease;
  flex-shrink: 0;
}
.occasion-close:hover { color: var(--ink); background: var(--bg); }
.occasion-close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(30, 95, 90, 0.40);
}

.occasion-body {
  flex: 1;
  overflow-y: auto;
  padding: 22px 28px 26px;
  scrollbar-width: thin;
  scrollbar-color: rgba(106, 87, 74, 0.30) transparent;
}

.occasion-body::-webkit-scrollbar { width: 6px; }
.occasion-body::-webkit-scrollbar-track { background: transparent; }
.occasion-body::-webkit-scrollbar-thumb { background: rgba(106, 87, 74, 0.30); border-radius: 4px; }

.occasion-body p {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink);
  margin: 0 0 16px;
  max-width: 56ch;
}

.occasion-body p:last-child { margin-bottom: 0; }

/* Footer area inside the occasion popup — holds the "Add to my to-do list"
   button below the story paragraphs. */
.occasion-footer {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
}

/* ============================================================
   "Add to my to-do list" buttons
   ============================================================
   Used in three places (dua response, activity screen, Hijri
   occasion popup). Warm gold pill with an icon + text. The text
   wraps because some prompts (try_it / teach_it) are full
   sentences and can be longer than the button width. */

.add-todo-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  appearance: none;
  background: #FBF5E6;
  border: 1px dashed var(--gold-soft);
  border-radius: 12px;
  padding: 12px 16px;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease, transform 120ms ease, box-shadow 160ms ease;
}

.add-todo-btn:hover {
  background: #F4E6C0;
  border-color: var(--gold);
  border-style: solid;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(176, 138, 62, 0.18);
}

.add-todo-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(176, 138, 62, 0.35);
}

.add-todo-btn-icon {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--gold-soft) 0%, var(--gold) 100%);
  color: #FFFEFA;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  line-height: 1;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.30) inset;
}

.add-todo-btn-text {
  flex: 1;
  min-width: 0;
}

/* Once the item is already on the kid's to-do list, the button switches
   to a solid filled state that reflects status. Still clickable in the
   sense that tapping it takes them to journal.html, but visually it
   reads as "already handled". */
.add-todo-btn--added {
  border-style: solid;
  cursor: pointer;
  transform: none;
}
.add-todo-btn--added:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(176, 138, 62, 0.18);
}

.add-todo-btn--added .add-todo-btn-icon {
  background: linear-gradient(135deg, #1E5F5A 0%, #174945 100%);
}

/* Pending — sits on the kid's list, waiting for them to do it. */
.add-todo-btn--added-pending {
  background: #F4E6C0;
  border-color: var(--gold);
  color: var(--ink);
}

/* Marked done — under parent review. Teal accent to signal it's moved
   past the kid's plate. */
.add-todo-btn--added-done {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.add-todo-btn--added-done .add-todo-btn-icon {
  background: linear-gradient(135deg, var(--accent) 0%, #2A8A82 100%);
}

/* Approved — parent has approved, points earned on Rewards page. */
.add-todo-btn--added-approved {
  background: linear-gradient(135deg, #FFF1C4 0%, #FCD9A1 100%);
  border-color: var(--gold);
  color: #8E5A1F;
}
.add-todo-btn--added-approved .add-todo-btn-icon {
  background: linear-gradient(135deg, var(--gold) 0%, #8E5A1F 100%);
}

/* Group used on the activity screen — wraps the two try_it/teach_it
   buttons under a small eyebrow label. */
.add-todo-group {
  margin: 18px 0 4px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.add-todo-eyebrow {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  color: var(--label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0 0 2px;
}

/* ============================================================
   Toast notifications
   ============================================================
   Single-toast UX (new replaces old). Bottom-right by default,
   centered at the bottom on narrow screens. */

.kc-toast {
  position: fixed;
  right: 20px;
  bottom: 24px;
  z-index: 200;
  display: inline-flex;
  align-items: center;
  gap: 14px;
  background: #2A2017;
  color: #FAF3E4;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 15px;
  line-height: 1.4;
  padding: 12px 18px;
  border-radius: 999px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.30), 0 2px 0 rgba(255, 255, 255, 0.05) inset;
  max-width: calc(100vw - 40px);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 200ms ease, transform 200ms ease;
}

.kc-toast--visible {
  opacity: 1;
  transform: translateY(0);
}

.kc-toast-msg {
  font-weight: 500;
}

.kc-toast-action {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  color: #E9B254;
  text-decoration: underline;
  text-decoration-color: rgba(233, 178, 84, 0.45);
  text-underline-offset: 3px;
  white-space: nowrap;
  transition: color 120ms ease;
}
.kc-toast-action:hover { color: #F2C572; }

@media (max-width: 600px) {
  .kc-toast {
    left: 16px;
    right: 16px;
    bottom: 16px;
    justify-content: space-between;
  }
}

/* Very narrow viewports (iPhone SE and below) — tighten further. */
@media (max-width: 380px) {
  .id-chip { padding: 3px 5px 3px 3px; gap: 6px; max-width: calc(100vw - 32px); }
  .id-chip-avatar { width: 28px; height: 28px; font-size: 12px; }
  .id-chip-label { font-size: 8px; }
  .id-chip-text strong { font-size: 12px; }
  .id-chip-switch { padding: 3px 8px; font-size: 10px; }
}

/* ----- Closing state ----- */

.closing {
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.closing .message {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 24px;
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 16px;
  max-width: 24ch;
  line-height: 1.4;
}

.closing .submessage {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 16px;
  color: var(--ink-soft);
  margin: 0 0 36px;
}

.closing .return {
  appearance: none;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 11px 22px;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 15px;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
  min-height: 44px;
}

.closing .return:hover {
  border-color: var(--accent);
  background: #FFFEFA;
}

/* ==========================================================
   Mobile drawer chrome (defaults: hidden on desktop)
   ----------------------------------------------------------
   Hamburger button and backdrop only exist visually on mobile.
   The desktop layout (two-column grid) doesn't show them at all.
   ========================================================== */

/* ==========================================================
   Sidebar toggle (hamburger) + backdrop — global rules
   ----------------------------------------------------------
   The hamburger lives at top-left, fixed to the viewport, on
   every screen size. On mobile it opens the drawer; on desktop
   it toggles the sidebar column (when closed, body gets the
   .kc-sidebar-closed class, the sidebar hides, and the grid
   collapses to a single column). One control, one mental model.

   The backdrop is mobile-only — on desktop the sidebar is a
   grid column, not an overlay, so there's nothing to dim.
   ========================================================== */
.sidebar-toggle {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  position: fixed;
  top: 16px;
  left: 16px;
  z-index: 70;
  width: 44px;
  height: 44px;
  appearance: none;
  background: #FFFEFA;
  border: 1px solid var(--rule);
  border-radius: 999px;
  cursor: pointer;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.5) inset,
    0 2px 8px rgba(42, 32, 23, 0.08);
  transition: border-color 160ms ease, transform 160ms ease, opacity 160ms ease;
}
.sidebar-toggle:hover { border-color: var(--gold-soft); }
.sidebar-toggle-line {
  width: 18px;
  height: 2px;
  background: var(--ink);
  border-radius: 1px;
  transition: transform 220ms ease, opacity 220ms ease;
}
.sidebar-toggle.is-open .sidebar-toggle-line:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.sidebar-toggle.is-open .sidebar-toggle-line:nth-child(2) {
  opacity: 0;
}
.sidebar-toggle.is-open .sidebar-toggle-line:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* When the sidebar is open on desktop, the toggle sits over the
   sidebar's painted top-left. That's fine — the cream pill is the
   "close this" control, the painting is its backdrop. */

/* Desktop: when the kid hides the sidebar, the grid column animates
   down to 0 and the sidebar slides off-screen rather than snapping
   away via display:none — the previous implementation was abrupt
   and made the content jump. Mobile uses the .is-open class on the
   sidebar for its drawer behaviour and ignores .kc-sidebar-closed. */
@media (min-width: 861px) {
  body.kc-sidebar-closed .app {
    grid-template-columns: 0 minmax(0, 1fr);
  }
  /* No more `display: none` here — keep the sidebar in the layout
     so the transform transition has somewhere to run, then mask it
     off-screen and disable its hit-testing once gone. visibility
     transitions after the transform so the slide-out is visible
     but focus / screen readers leave it alone afterwards. */
  body.kc-sidebar-closed .sidebar {
    transform: translateX(-100%);
    visibility: hidden;
    pointer-events: none;
    transition:
      transform 560ms cubic-bezier(.2, .7, .2, 1),
      visibility 0s linear 560ms;
  }
  /* And the matching transition for the OPEN state, so re-opening
     the sidebar slides it back in at the same pace. Without this
     the open path has no transition declared at all and snaps. */
  .sidebar {
    transition:
      transform 560ms cubic-bezier(.2, .7, .2, 1),
      visibility 0s linear 0s;
  }

  /* When the sidebar is hidden, let the content grow a bit so the
     page reclaims the freed space. The transition is owned by the
     base rule below. */
  body.kc-sidebar-closed .content > main {
    max-width: 1100px !important;
  }
}

/* Single source of truth for wrapper layout on every main page.
   Centred via margin: auto, capped at 860px so the kid's content
   never extends into the top-right id-chip on a standard MacBook
   (1440px) viewport (1440 - 380 sidebar - 16 chip-right - 160 chip
   - 24 gap ≈ 860). When the sidebar is hidden, body.kc-sidebar-
   closed bumps the cap to 1100px so the page reclaims the freed
   space. !important locks the values against any per-page rule
   we may have missed in inline <style> blocks. */
.content > main {
  max-width: 860px !important;
  margin: 0 auto !important;
  padding: 48px 32px 96px 32px !important;
  /* Width-consistency fix (June 2026): .content is a flex column, and
     a flex item with cross-axis auto margins does NOT stretch — it
     shrinks to fit its widest child. Pages with wide grids (activities,
     journey) happened to hit the 860px cap anyway, but the books
     landing's widest child is the hero's 56ch subtitle, so that whole
     page rendered ~570px wide and visibly narrower than its siblings.
     width: 100% restores a deterministic width: every page fills the
     column up to the same 860px cap, centered by the auto margins. */
  width: 100% !important;
  box-sizing: border-box;
  transition:
    max-width 560ms cubic-bezier(.2, .7, .2, 1),
    padding   560ms cubic-bezier(.2, .7, .2, 1);
}

/* Page fade-in — every page boot lifts in gently rather than
   appearing all at once. Applies to both the four main pages
   (<main class="*-page">) and the chat stage (.stage), so the kid
   sees the same "settle in" motion regardless of which page they
   land on. `both` keeps the from-state until the animation runs,
   which avoids a brief flash before the keyframe starts. */
@keyframes kc-page-fade-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.content > main,
.content > .stage {
  animation: kc-page-fade-in 520ms cubic-bezier(.2, .7, .2, 1) both;
}
/* Respect users who've asked the OS to reduce motion. */
@media (prefers-reduced-motion: reduce) {
  .content > main,
  .content > .stage {
    animation: none;
  }
  .app,
  .sidebar,
  .content > main {
    transition: none !important;
  }
}

/* ============================================================
   Shared page hero card
   ------------------------------------------------------------
   All four reader pages — journal, activities, rewards,
   make-a-book — open with the same card so they share one
   "this is the cover of this section" register: an eyebrow
   tag, a title, an italic sub, sitting on a soft gradient
   over cream with a faint gold starburst tucked into the
   top-right corner. Page-specific content (journal's stat
   grid, or any future enrichment) can sit inside this card
   without changing the surface. Journal previously owned this
   design as `.journal-hero`; lifting it here makes it the
   shared register and kills the drift risk of four near-
   identical copies. */
.page-hero {
  position: relative;
  background:
    linear-gradient(135deg, rgba(30, 95, 90, 0.06) 0%, rgba(176, 138, 62, 0.10) 100%),
    #FFFDF6;
  border: 1px solid var(--rule);
  border-radius: 20px;
  padding: 28px 28px 26px;
  margin-bottom: 28px;
  box-shadow: var(--shadow);
  overflow: hidden;
}
.page-hero::before {
  content: '';
  position: absolute;
  right: -60px; top: -60px;
  width: 220px; height: 220px;
  background: radial-gradient(circle, rgba(212, 179, 106, 0.18) 0%, rgba(212, 179, 106, 0) 70%);
  pointer-events: none;
}
.page-hero > * { position: relative; }   /* sit above the starburst */
.page-hero-eyebrow {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--label);
  margin: 0 0 8px;
}
.page-hero-title {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 600;
  font-size: clamp(28px, 4.5vw, 38px);
  color: var(--ink);
  margin: 0 0 6px;
  line-height: 1.15;
}
.page-hero-sub {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 15px;
  color: var(--ink-soft);
  margin: 0;
  max-width: 56ch;
  line-height: 1.55;
}
.page-hero-sub strong {
  font-style: normal;
  font-weight: 500;
  color: var(--ink);
}

.sidebar-backdrop { display: none; }

/* Brand block — the wordmark + tagline are wrapped in a single
   <a href="app.html"> so the whole brand reads as one home tap.
   Strip the link's default colour + underline so it inherits the
   sidebar typography. */
.sidebar .brand-link {
  display: block;
  text-decoration: none;
  color: inherit;
  border-radius: 8px;
  transition: opacity 160ms ease, transform 160ms ease;
}
.sidebar .brand-link:hover { opacity: 0.92; }
.sidebar .brand-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(233, 178, 84, 0.45);
}

/* Active section highlight. The matching nav link gets a faint
   gold-tinted background and a vertical accent rule on the left
   so the kid always knows which page they're on. Visible in both
   themes because the tint sits over whatever the sidebar bg is. */
.side-section-header.is-current {
  background: rgba(233, 178, 84, 0.10);
  color: #F8EFD8;
  border-radius: 6px;
  padding-left: 10px;
  position: relative;
}
.side-section-header.is-current::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 18%;
  bottom: 18%;
  width: 2px;
  background: var(--gold);
  border-radius: 2px;
}

/* ==========================================================
   Responsive — collapse to single column under 860px
   ========================================================== */

@media (max-width: 860px) {
  /* App page mobile — the chat fills the screen by default. The
     sidebar slides in from the left as a drawer when the kid taps
     the hamburger at top-left. The Hijri footer rides inside the
     drawer (previously it was display:none on mobile, which made it
     unreachable on phone). */
  .app { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: min(85vw, 320px);
    height: 100vh;
    height: 100dvh;
    z-index: 60;
    transform: translateX(-100%);
    transition: transform 280ms cubic-bezier(.2, .7, .2, 1);
    border-right: 1px solid rgba(176, 138, 62, 0.22);
    border-bottom: none;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .sidebar.is-open {
    transform: translateX(0);
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.45);
  }

  .sidebar-top { padding: 24px 20px 14px; }
  .sidebar-bottom {
    /* Drawer is taller than the desktop sidebar slice, so let
       Your Stories expand naturally inside the scrollable drawer
       instead of capping at 120px. */
    max-height: none;
    flex: 1 1 auto;
    padding: 14px 20px;
    overflow: visible;
  }
  .sidebar-footer {
    display: block;
    padding: 14px 20px max(22px, env(safe-area-inset-bottom));
    border-top: 1px solid rgba(176, 138, 62, 0.18);
  }
  .ambience { display: none; }

  /* Hamburger toggle styles are now global (see top of file). Only
     the backdrop is mobile-only — the desktop sidebar is a grid
     column, not an overlay, so there's nothing to dim. */
  .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(7, 9, 15, 0.50);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    opacity: 0;
    pointer-events: none;
    z-index: 50;
    transition: opacity 220ms ease;
  }
  .sidebar-backdrop.is-open {
    opacity: 1;
    pointer-events: auto;
  }

  .stage { padding: 72px 28px 56px; }

  /* Defensive: clip any internal overflow at the content edge so a
     long suggestion text or a wide stage child never pushes the
     chip / Ask button past the viewport. */
  .content { overflow-x: hidden; max-width: 100vw; }
  .stage   { overflow-x: hidden; max-width: 100%; }
  .ask-form { width: 100%; max-width: 100%; }

  /* Anchor the chip to the viewport, not to .content's right edge.
     Previously the chip used position:absolute relative to .content;
     if anything inside .content (a stage child, a stray pixel of
     content overflow) made .content wider than the viewport, the
     chip's "right: 16px" sat 16px from .content's right edge — past
     the screen — and the "switch" button got clipped. position:fixed
     ties the chip directly to the viewport, so it's robust regardless
     of what happens in the document flow. */
  .id-chip {
    position: fixed;
    top: 16px;
    right: 16px;
    max-width: calc(100vw - 32px);
  }

  /* Entry page mobile: content sits at the top of the viewport, with
     the painted lantern + sky behind it. The desktop variant uses
     vertical centering inside a 100dvh column (form on the right side
     of the painting); on a narrow phone vertical centering pushes the
     heading too far down and wastes the most valuable real estate.
     Switch align-items to flex-start, then keep the top padding
     proportional to viewport so it sits just under the status bar /
     URL chrome on iOS Safari. Bottom padding wraps the safe-area
     inset so the form never sits under the iOS home indicator. */
  .entry {
    padding: max(20px, env(safe-area-inset-top)) 24px max(32px, env(safe-area-inset-bottom));
    justify-content: center;
    align-items: flex-start;
  }
  .entry-card {
    max-width: 100%;
    text-align: center;
  }
  .entry .skip { align-self: center; }
  .entry .greeting { font-size: 36px; margin-top: 6vh; }
  .entry .intro { font-size: 16px; margin-bottom: 20px; }
  .entry .subline { font-size: 18px; margin-bottom: 28px; }
  .entry .intro,
  .entry .subline,
  .entry .name-form,
  /* home.html's role picker tile column + parent/kid passcode entry
     pad. Both are block-level max-width: 400px elements that would
     otherwise sit hard-left within the centred .entry-card on
     mobile, putting the tiles on a different vertical axis from the
     centred heading. The mobile centring fix originally only
     targeted the .name-form / .intro / .subline trio because home
     was newer and hadn't been audited; pulling .role-buttons and
     .code-form into the same auto-margin treatment shares the axis
     across all entry-page mobile compositions. login.html's
     .auth-form has its own per-page rule that does the same thing,
     so this stays a complete fix.

     .sources-note + .account-row (May 2026): same family of bug.
     The sources line under the role tiles has max-width: 38ch
     (≈350px) and the account-row wraps a single text button. Both
     sat hard-left within the centred card while everything else
     above them was auto-centred, producing the symptom in the
     reported screenshot — heading centred, tiles centred, but the
     sources note pinned to the viewport's left padding. Adding
     them to the auto-margin set restores a single vertical axis
     for the whole picker stack. Account-row is also auto-centred
     so the "Sign out of this account" link stays under the tile
     column rather than dropping to the viewport edge. */
  .entry .role-buttons,
  .entry .code-form,
  .entry .sources-note,
  .entry .account-row { margin-left: auto; margin-right: auto; }
  /* On mobile, deepen the bottom of the scene so the form is readable. */
  .scene-overlay {
    background:
      linear-gradient(
        to bottom,
        rgba(14, 16, 21, 0)    50%,
        rgba(14, 16, 21, 0.55) 80%,
        rgba(14, 16, 21, 0.85) 100%
      );
  }

  /* --- Painted scene: ensure full coverage on portrait phones ---
     .entry-body.is-login .scene up top sets background-size: 130%
     to make the lantern feel large and focal on desktop. With a
     single-value background-size the height is implicit and on tall
     narrow portrait viewports the image can stop short of the
     bottom edge, leaving the .entry-body's #07090F base showing
     through as a "black bar at the bottom" — visible in full-page
     screenshots and on long phones where the form doesn't fill the
     viewport. Forcing `cover` at the mobile breakpoint guarantees
     the painting reaches all four edges. The same background-position
     keeps the lantern roughly where the desktop variant places it,
     so the visual feel doesn't jump when you cross the breakpoint.
     Scoped to .is-login because .is-home (home.html) uses a wider
     100% crop already and doesn't have the same gap. */
  .entry-body.is-login .scene {
    background-size: cover;
    background-position: 35% 55%;
  }

  /* --- Login mobile: vertically centre the form group ---
     The shared .entry mobile rule above sets align-items: flex-start
     so the heading sits just under the URL/status bar on the role
     picker (home.html) — that page is taller (kid tiles + parent
     tile + sources note) and benefits from anchoring high. Login is
     much shorter (heading + intro + email + password + button + one
     toggle link), so flex-start leaves a large empty area below the
     form and the whole group feels cramped against the top edge.
     Switch login's mobile layout back to centre alignment so the
     form sits with equal breathing room above and below, scoped to
     .is-login only so home.html's tall layout is unaffected.
     Also drop the .greeting's 6vh top margin — that was sized for
     flex-start; with centre alignment it pushes the heading off-axis. */
  .entry-body.is-login .entry {
    align-items: center;
  }
  .entry-body.is-login .entry .greeting {
    margin-top: 0;
  }
}

/* ==========================================================
   Entry pages: extend the mobile-style centred layout up to
   1100px wide. The 860px breakpoint above is shared with the
   chat app's sidebar collapse, which has to stay tight; but
   the entry layout's "form on the right, lantern on the left"
   composition only works once the viewport is wide enough for
   the painted lantern to comfortably sit beside a 460px form
   column. Between ~860px and ~1100px (typical portrait tablet
   widths) the desktop layout's `justify-content: flex-end`
   pushes the form so close to the lantern that they collide,
   producing the "content gets misaligned" symptom on iPads
   and similar devices.

   This block re-applies just the .entry / .entry-card centring
   rules at those widths, WITHOUT touching the .sidebar / .stage /
   .id-chip rules from the 860px block (those legitimately stay
   capped at 860px). The body of this block is a strict subset
   of the .entry-only rules from the 860px block above; if either
   set evolves, mirror the change in both places.
   ========================================================== */
@media (min-width: 861px) and (max-width: 1100px) {
  .entry {
    padding: max(20px, env(safe-area-inset-top)) 24px max(32px, env(safe-area-inset-bottom));
    justify-content: center;
    align-items: flex-start;
  }
  .entry-card {
    max-width: 100%;
    text-align: center;
  }
  .entry .skip { align-self: center; }
  .entry .greeting { font-size: 36px; margin-top: 6vh; }
  .entry .intro { font-size: 16px; margin-bottom: 20px; }
  .entry .subline { font-size: 18px; margin-bottom: 28px; }
  .entry .intro,
  .entry .subline,
  .entry .name-form { margin-left: auto; margin-right: auto; }
  /* Same deeper bottom-wash overlay the 860px block uses so the
     form area reads cleanly over the painted scene. */
  .entry-body.is-login .scene-overlay,
  .entry-body.is-home .scene-overlay {
    background:
      linear-gradient(
        to bottom,
        rgba(14, 16, 21, 0)    50%,
        rgba(14, 16, 21, 0.55) 80%,
        rgba(14, 16, 21, 0.85) 100%
      );
  }
  /* Same scene-coverage guarantee as the 860px block — the
     desktop-only 130% background-size leaves bottom gaps at
     portrait tablet aspect ratios too. */
  .entry-body.is-login .scene {
    background-size: cover;
    background-position: 35% 55%;
  }

  /* --- Entry pages tablet (861-1100): keep the desktop right-side
     layout for BOTH login AND home. The .entry / .entry-card block
     above centres content to avoid the lantern-vs-form collision at
     tablet widths. Originally we kept that centring for .is-home (on
     the theory that the role picker's taller stack read better
     centred), but the user reported the same misalignment symptom on
     home.html that we'd already fixed on login.html: the heading
     'Assalāmu ʿalaykum.' sits visually centred while the role-picker
     tiles sit hard-left, putting the two columns on different vertical
     axes. The fix is identical: re-apply the desktop right-anchored
     composition so heading + tiles share one column on the right and
     the painted lantern occupies the left.
     We re-apply the desktop .entry / .entry-card rules verbatim. */
  .entry-body.is-login .entry,
  .entry-body.is-home  .entry {
    /* Mirrors the desktop rule from the .entry block far above. */
    padding: 40px clamp(32px, 6vw, 80px) 40px 0;
    justify-content: flex-end;
    align-items: center;
  }
  .entry-body.is-login .entry-card,
  .entry-body.is-home  .entry-card {
    /* Restore the 460px column the desktop layout uses so the form /
       role picker doesn't stretch full-width again on tablet.
       text-align stays left-aligned for the heading + tile labels. */
    max-width: 460px;
    text-align: left;
  }
  /* The greeting + intro + form share the desktop typography on
     tablet so the "this looks like the computer screen" mental
     model holds. Re-state the values from .entry .greeting /
     .entry .intro at the top of this file so this block's earlier
     mobile-style overrides don't bleed in. */
  .entry-body.is-login .entry .greeting,
  .entry-body.is-home  .entry .greeting {
    font-size: clamp(40px, 4.4vw, 56px);
    margin-top: 0;
  }
  .entry-body.is-login .entry .intro,
  .entry-body.is-home  .entry .intro {
    font-size: 17px;
    margin-bottom: 24px;
  }
  /* And undo the auto-centred form margins so the form / role-picker
     tiles sit flush left within the card again, matching desktop.
     .role-buttons + .code-form are the home-specific surfaces that
     hold the tile column; without zeroed margins they inherit the
     mobile auto-centring and the lantern-vs-tiles collision returns
     in disguise. .sources-note + .account-row likewise: at tablet+
     the card is left-anchored (text-align:left at line ~2635), so
     letting the mobile auto-centring leak through here would shove
     these elements toward an axis that no longer matches the rest
     of the picker stack. */
  .entry-body.is-login .entry .intro,
  .entry-body.is-login .entry .subline,
  .entry-body.is-login .entry .name-form,
  .entry-body.is-home  .entry .intro,
  .entry-body.is-home  .entry .subline,
  .entry-body.is-home  .entry .name-form,
  .entry-body.is-home  .entry .role-buttons,
  .entry-body.is-home  .entry .code-form,
  .entry-body.is-home  .entry .sources-note,
  .entry-body.is-home  .entry .account-row {
    margin-left: 0;
    margin-right: 0;
  }
}

/* ==========================================================
   Utility
   ========================================================== */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================
   Pause ambient animations when the tab is hidden
   ========================================================== */

.kc-paused .scene {
  animation-play-state: paused;
}

/* ==========================================================
   Reduced motion
   ========================================================== */

@media (prefers-reduced-motion: reduce) {
  .scene {
    animation: none !important;
  }
  .stage-inner > * {
    animation: none !important;
  }
  *, *::before, *::after {
    transition-duration: 0ms !important;
  }
}

/* ==========================================================
   Dark mode
   ----------------------------------------------------------
   Tweens often use phones in bed — the bright parchment is harsh.
   This swaps the warm-ivory base tokens for a deep-walnut surface
   and forces dark surfaces on every card across the app.

   Notes on the cascade:
   - Many card backgrounds are hardcoded as hex literals in the
     inline <style> blocks of journal.html, activities.html,
     rewards.html, parents.html. Inline page styles ship AFTER
     this stylesheet in the cascade, so they would win on
     specificity tie. To override without touching every page's
     inline styles, the surface rules below use !important. This
     is the limited, principled use of !important — reserved for
     user-preference overrides (color-scheme).

   - The entry pages (home.html — the gated role picker —
     and login.html) are painted night-sky scenes with their own
     --night-* token scope. They are INTENTIONALLY UNTOUCHED here:
     the global :root token swap below changes --bg / --ink etc.,
     but the entry forms reference --night-*
     tokens which we deliberately do not redefine. Result: the
     entry page looks the same in both light and dark mode.
   ========================================================== */

/* ==========================================================
   30-minute "take a breath" reminder modal
   ----------------------------------------------------------
   A polite, name-personalized nudge that fires every 30 minutes
   of active app use. Same warm tone as the rest of the app —
   no countdown timer in the UI, no nag pattern. One message,
   one button to dismiss. See kc_timer.js for the trigger logic.
   ========================================================== */

.kc-reminder-overlay {
  position: fixed;
  inset: 0;
  z-index: 500;          /* above kc-toast, peek/occasion overlays */
  background: rgba(7, 9, 15, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}
.kc-reminder-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}
/* Same defensive override as .confirm-overlay / .custom-page-overlay:
   author `display: flex` ties UA `[hidden] { display: none }` on
   specificity, so a future caller toggling overlay.hidden = true
   would otherwise leave a transparent click-trap on the page. */
.kc-reminder-overlay[hidden] { display: none; }

.kc-reminder-card {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 16px;
  padding: 32px 32px 24px;
  max-width: 460px;
  width: 100%;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
  transform: translateY(8px) scale(0.985);
  transition: transform 240ms cubic-bezier(.2,.7,.2,1);
  text-align: left;
}
.kc-reminder-overlay.is-open .kc-reminder-card {
  transform: translateY(0) scale(1);
}

.kc-reminder-eyebrow {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--label);
  margin: 0 0 10px;
}

.kc-reminder-heading {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 500;
  font-size: 22px;
  color: var(--ink);
  margin: 0 0 12px;
  line-height: 1.3;
}

.kc-reminder-body {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 16px;
  color: var(--ink);
  margin: 0 0 22px;
  line-height: 1.55;
}

.kc-reminder-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  flex-wrap: wrap;
}

.kc-reminder-todo,
.kc-reminder-ok {
  appearance: none;
  border-radius: 999px;
  padding: 9px 18px;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 14px;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}

.kc-reminder-todo {
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
  font-style: italic;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.kc-reminder-todo:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.kc-reminder-ok {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #FFFEFA;
  font-weight: 500;
}
.kc-reminder-ok:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

/* ==========================================================
   Sync error banner — surfaced by kc_sync.js when a Supabase
   mirror fails. Sits at the bottom of the viewport, quiet and
   uncoloured-by-alarm (the kid's data is safe on this device;
   the banner just communicates that the cloud copy is behind).
   The "Retry now" button triggers KCSync.kidState.flush().
   ========================================================== */
.kc-sync-error-banner {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 600;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px;
  background: #FBF5E6;
  border: 1px solid var(--gold-soft);
  border-radius: 999px;
  box-shadow: 0 6px 24px rgba(42, 32, 23, 0.16);
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 14px;
  color: var(--ink);
  max-width: calc(100vw - 32px);
}
.kc-sync-error-text { font-style: italic; }
.kc-sync-error-retry {
  appearance: none;
  background: var(--accent);
  color: #FFFEFA;
  border: none;
  border-radius: 999px;
  padding: 6px 14px;
  font-family: 'Lexend', sans-serif;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.kc-sync-error-retry:hover { background: var(--accent-hover); }

/* Dark-mode override for the sync error banner. The light-mode
   cream background reads as a glowing rectangle against the dark
   walnut surface; flip to a walnut card with the cream ink so the
   banner sits inside the page rather than shouting at it. The
   retry button keeps its accent fill — that's the brand colour
   for "go ahead, click me" across both modes. */
@media (prefers-color-scheme: dark) {
  .kc-sync-error-banner {
    background: #2C231A;
    border-color: #3F352A;
    color: var(--ink);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
  }
  .kc-sync-error-text { color: var(--ink-soft); }
}

@media (max-width: 540px) {
  .kc-reminder-card { padding: 26px 22px 20px; }
  .kc-reminder-heading { font-size: 20px; }
  .kc-reminder-actions { justify-content: stretch; }
  .kc-reminder-todo, .kc-reminder-ok { flex: 1; text-align: center; justify-content: center; }
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Previously --bg was #14100C (near-pure-black walnut). That read
       as a "void" next to the sidebar's painted lantern scene and was
       hard on the eyes for long reading. Lifted to a softer dark
       walnut (#211A14) — still parchment-by-night in voice, but the
       surface has light enough that the cream text isn't shouting
       against a black hole. Cards step up clearly from this base. */
    --bg:           #211A14;
    --bg-soft:      #2A2118;
    --bg-soft-deep: #312719;
    --ink:          #F5ECD3;   /* warm cream — slightly creamier */
    --ink-soft:     #DCC9A5;   /* lifted for stronger body contrast */
    --rule:         #3F352A;
    --accent:       #65B7AE;
    --accent-hover: #7DCEC5;
    --accent-soft:  #1F3B38;
    --gold:         #E4C57A;
    --gold-soft:    #B89556;
    --label:        #E4C57A;
    --shadow:       0 1px 0 rgba(0, 0, 0, 0.30), 0 8px 24px rgba(0, 0, 0, 0.40);
    --shadow-soft:  0 1px 0 rgba(0, 0, 0, 0.25), 0 4px 14px rgba(0, 0, 0, 0.30);
    --focus-ring:   0 0 0 3px rgba(101, 183, 174, 0.32);
  }

  /* ---------- Card surfaces (override inline hex literals) ----------
     One walnut tone for primary cards. Note: .entry-card is a name
     collision — the entry pages (home.html, login.html) use the same
     class for their form card and it must stay transparent over the
     night-sky painting. We scope .entry-card to non-entry pages with
     body:not(.entry-body). */
  /* .response itself is INTENTIONALLY excluded — in light mode it has
     no background, border, or padding; it just sits on the parchment
     page. Adding a surface to it would create a card that doesn't
     exist in light mode (visible as a "boxed-in" refusal screen). The
     nested .arabic / .arabic-card surfaces inside .response do get
     overridden because they ARE meant to be cards. */
  body:not(.entry-body) .entry-card,
  .response .arabic, .response .arabic-card,
  .todo-card, .new-entry-card, .review-pending-card,
  .stat-tile, .activity-card,
  .kid-card, .review-card, .occasion-card, .peek-card, .peek-item,
  .confirm-card, .ask-box, .ask-input,
  .add-kid-form,
  .commit-card, .checkin-card, .approved-card, .progress-card,
  .badge-card, .tier-card, .privacy-box, .sources-box,
  .parents-section, .id-chip, .kc-toast {
    background: #2C231A !important;
    color: var(--ink);
    border-color: #3F352A !important;
  }

  /* General form inputs — covers .ask-form input/textarea AND any
     standalone <input>/<textarea> in parents.html (add-kid form),
     activities, etc. Excludes inputs already styled via more specific
     rules (e.g. confirm modal buttons aren't form inputs). */
  body:not(.entry-body) input[type="text"],
  body:not(.entry-body) input[type="password"],
  body:not(.entry-body) input[type="number"],
  body:not(.entry-body) input[type="email"],
  body:not(.entry-body) input[type="tel"],
  body:not(.entry-body) input:not([type]),
  body:not(.entry-body) textarea {
    background: #251E17 !important;
    color: var(--ink) !important;
    border-color: #3F352A !important;
  }

  /* Activity-card "Already here" / "Coming soon" pill tags. */
  .activity-tag {
    background: #34291E !important;
    color: var(--gold) !important;
  }
  .activity-card.coming-soon .activity-tag {
    background: rgba(101, 183, 174, 0.14) !important;
    color: var(--accent) !important;
  }

  /* Confirm modal Cancel button — had a hard cream bg + dim text, made
     it look disabled. Flip to walnut with full-strength cream text. */
  .confirm-cancel {
    background: #34291E !important;
    color: var(--ink) !important;
    border-color: #5A4631 !important;
  }
  .confirm-cancel:hover {
    background: #3F3326 !important;
    border-color: var(--ink-soft) !important;
  }

  /* Sources panel at the bottom of a story (Sahih Muslim / Qur'an refs).
     Was a strong cream panel — totally washed out the cream-on-cream
     reference text. Flip to walnut with the gold left-rule preserved. */
  .sources-body {
    background: #2C231A !important;
    border-color: #3F352A !important;
    border-left-color: var(--gold-soft) !important;
  }
  .sources-body .ref { color: var(--ink) !important; }

  /* Activity reflection textarea — white in light mode means kid-typed
     text was unreadable cream-on-white-ish. Walnut bg + cream text. */
  .activity-textarea {
    background: #251E17 !important;
    color: var(--ink) !important;
    border-color: #3F352A !important;
  }
  .activity-textarea:focus {
    border-color: var(--accent) !important;
    box-shadow: 0 0 0 3px rgba(101, 183, 174, 0.18) !important;
  }
  .activity-textarea::placeholder {
    color: rgba(220, 201, 165, 0.55) !important;
  }

  /* "Add to my to-do list" buttons (dua / activity / occasion screens).
     Default state was cream-on-dashed-gold with cream text — invisible
     in dark mode. Walnut + dashed gold border preserves the "draft"
     feel, full-strength cream text restores readability. */
  .add-todo-btn {
    background: #2C231A !important;
    border-color: var(--gold-soft) !important;
    color: var(--ink) !important;
  }
  .add-todo-btn:hover {
    background: #34291E !important;
    border-color: var(--gold) !important;
  }
  .add-todo-btn--added-pending {
    background: rgba(228, 197, 122, 0.12) !important;
    border-color: var(--gold) !important;
    color: var(--ink) !important;
  }
  .add-todo-btn--added-approved {
    background:
      linear-gradient(135deg, #4A3320 0%, #34281C 100%) !important;
    border-color: var(--gold) !important;
    color: var(--gold) !important;
  }

  /* Check-in screen "Last time you wrote" card */
  .checkin-commitment {
    background: #2C231A !important;
    border-color: #3F352A !important;
    border-left-color: var(--gold-soft) !important;
  }

  /* Closing screen "return" button hover — was hard cream flash */
  .closing .return:hover {
    background: rgba(228, 197, 122, 0.10) !important;
    color: var(--ink) !important;
  }

  /* Elevated / featured surfaces — one step warmer/lighter than the
     base card colour so the hierarchy survives. */
  .journal-hero {
    background:
      linear-gradient(135deg, rgba(101, 183, 174, 0.10) 0%, rgba(228, 197, 122, 0.14) 100%),
      #34291E !important;
    border-color: #3F352A !important;
  }

  /* Rewards page level banner — deep amber, raised. */
  .score-banner {
    background:
      linear-gradient(135deg, #4A3320 0%, #34281C 100%) !important;
    color: var(--ink) !important;
    border-color: #5A3F26 !important;
  }
  .score-banner .score-label,
  .score-banner .score-value,
  .score-banner .score-detail { color: var(--ink) !important; }

  /* Activities "coming soon" cards — quieter, dashed, slightly recessed
     from the base bg so they read as "muted, not finished yet". */
  .activity-card.coming-soon {
    background: #251E17 !important;
    border-color: #3F352A !important;
    border-style: dashed !important;
  }
  .activity-card.coming-soon h3 { color: var(--accent) !important; }

  /* Stat tile colored icon backplates */
  .stat-tile.tile-streak .stat-icon { background: #34281C !important; color: var(--gold) !important; }
  .stat-tile.tile-todos  .stat-icon { background: #1F3B38 !important; color: var(--accent) !important; }
  .stat-tile.tile-notes  .stat-icon { background: #3A2A1E !important; color: #E0A07A !important; }

  /* Rejected to-do card — slightly warmer than the base card for the
     "try again" affordance. */
  .todo-card[data-rejected="true"] {
    background: #34281C !important;
    border-color: rgba(228, 165, 107, 0.45) !important;
  }

  /* Tab strip + tab states */
  .tabs {
    background: #1F1813 !important;
    border-color: #3F352A !important;
  }
  .tab { color: var(--ink-soft) !important; }
  .tab:hover {
    background: rgba(228, 197, 122, 0.08) !important;
    color: var(--ink) !important;
  }
  .tab[aria-selected="true"] {
    background: #34291E !important;
    color: var(--ink) !important;
    border-color: #5A4631 !important;
  }
  .tab[aria-selected="true"] .tab-count {
    background: var(--accent) !important;
    color: #211A14 !important;
  }

  /* Lined-paper textarea in the notebook composer */
  .new-entry-textarea {
    background:
      repeating-linear-gradient(
        to bottom,
        transparent 0px,
        transparent 27px,
        rgba(228, 197, 122, 0.10) 27px,
        rgba(228, 197, 122, 0.10) 28px
      ),
      #251E17 !important;
    color: var(--ink) !important;
    border-color: #3F352A !important;
  }

  /* Chips and small surface accents */
  .mood-chip, .todo-source-chip, .review-source-chip,
  .stat-tile .stat-icon, .source-chip {
    background: #34291E !important;
    color: var(--ink-soft);
    border-color: #3F352A !important;
  }
  .mood-chip.is-selected {
    background: #1F3B38 !important;
    color: var(--accent) !important;
    border-color: var(--accent) !important;
  }

  /* Rewards table */
  .rewards-table, .rewards-table tr, .rewards-table td, .rewards-table th {
    background: #2C231A !important;
    color: var(--ink);
    border-color: #3F352A !important;
  }
  .rewards-table thead, .rewards-table thead th {
    background: #34291E !important;
    color: var(--label);
  }
  .progress-fill, .progress-bar > div {
    background: var(--accent) !important;
  }

  /* Empty states (dashed boxes) */
  .j-empty, .todos-empty, .review-pending-empty, .entries-empty,
  .panel-note {
    background: rgba(44, 35, 26, 0.55) !important;
    border-color: #3F352A !important;
    color: var(--ink-soft);
  }

  /* Buttons that ride dark surfaces */
  .new-entry-save, .ask-submit, .next-link.primary, .commit-btn {
    color: #211A14;
  }

  /* Hamburger toggle — cream pill on light, walnut pill on dark. */
  .sidebar-toggle {
    background: #2C231A !important;
    border-color: #3F352A !important;
  }
  .sidebar-toggle-line {
    background: var(--ink) !important;
  }

  /* Active section highlight — gold tint reads fine in both modes,
     but in night mode bump the tint up a touch so it doesn't melt
     into the walnut bg. */
  .side-section-header.is-current {
    background: rgba(228, 197, 122, 0.14) !important;
  }

  /* Shared page-hero card — the day-mode gradient over cream is
     replaced with a dim teal-and-gold wash over walnut. The
     starburst stays (it's gold-tinted rgba and reads fine over
     dark) but bump its base color so it still glints. */
  .page-hero {
    background:
      linear-gradient(135deg, rgba(101, 183, 174, 0.07) 0%, rgba(228, 197, 122, 0.09) 100%),
      #2C231A !important;
    border-color: #3F352A !important;
  }
  .page-hero::before {
    background: radial-gradient(circle, rgba(228, 197, 122, 0.16) 0%, rgba(228, 197, 122, 0) 70%);
  }
  .todo-del, .entry-del, .history-entry-del, .kid-remove-btn {
    color: var(--ink-soft);
  }

  /* Sidebar (app.html). The .ambience layer (painted lantern scene)
     sits behind .sidebar > * — don't paint over it; leave the sidebar
     bg transparent so the painting shows through, and just adjust the
     border-rule between sidebar and reading stage. */
  .sidebar {
    background: transparent !important;
    border-color: #3F352A !important;
  }
  .history-entry {
    background: transparent !important;
    border-color: #3F352A !important;
  }
  .history-entry:hover {
    background: rgba(228, 197, 122, 0.05) !important;
  }

  /* Occasion + peek modal heads */
  .occasion-header, .peek-header {
    background: #34291E !important;
    color: var(--ink) !important;
    border-bottom-color: #3F352A !important;
  }
  .occasion-header h2, .occasion-header .occasion-sub,
  .peek-title, .peek-sub {
    color: var(--ink) !important;
  }
  .occasion-body, .peek-body {
    background: #2C231A !important;
    color: var(--ink);
  }
  .occasion-overlay, .peek-overlay {
    background: rgba(0, 0, 0, 0.55) !important;
  }
  .occasion-close, .peek-close {
    color: var(--ink-soft) !important;
  }
  .occasion-close:hover, .peek-close:hover {
    color: var(--ink) !important;
    background: rgba(228, 197, 122, 0.10) !important;
  }

  /* (Lantern/crescent watermark override removed — the watermark
     itself was retired from app.js.) */

  /* Notebook entry top-ribbon stays accent-colored — fine as is. */

  /* id-chip avatar (gold-on-cream → gold-on-walnut) */
  .id-chip-avatar { color: #211A14 !important; }

  /* Input/textarea text + placeholder readability */
  textarea, input[type="text"], input[type="password"], input[type="number"] {
    color: var(--ink);
  }
  ::placeholder { color: rgba(215, 196, 154, 0.55); }
  :-ms-input-placeholder { color: rgba(215, 196, 154, 0.55); }

  /* Journal hero text shouldn't be cream-on-cream — re-anchor on walnut. */
  .journal-hero .hero-title,
  .journal-hero .stat-num { color: var(--ink) !important; }
  .journal-hero .hero-eyebrow { color: var(--gold) !important; }
  .journal-hero .hero-sub,
  .journal-hero .stat-label { color: var(--ink-soft) !important; }

  /* ---- Night-mode polish (round 2) ----
     Things that were still rendering cream-on-walnut or low contrast
     after the first dark-mode pass. Tightening each one here keeps
     the patches grouped and easy to revisit. */

  /* Activities page state badges (Long-running / Due / Streak / Cold / New)
     — base CSS gives them a hard cream fill that read as a flashlight
     against the dark cards. Flip to walnut chips with their accent
     color preserved. */
  .state-badge {
    background: #34291E !important;
    color: var(--label) !important;
  }
  .state-badge.tone-due {
    background: rgba(228, 197, 122, 0.18) !important;
    color: var(--gold) !important;
  }
  .state-badge.tone-streak {
    background: var(--accent-soft) !important;
    color: var(--accent) !important;
  }
  .state-badge.tone-cold {
    background: #2C231A !important;
    color: var(--ink-soft) !important;
  }
  .state-badge.tone-new {
    background: rgba(101, 183, 174, 0.14) !important;
    color: var(--accent) !important;
  }

  /* "Pick up here" pin — base CSS has cream-on-gold which is
     ~3:1 contrast. Dark walnut text on the gold pill reads far
     better, both visually and accessibly. */
  .lead-pin {
    color: #211A14 !important;
    background: var(--gold) !important;
  }

  /* Activities Today rail items — bright cream surfaces glow against
     the dark page. Walnut walnut walnut. */
  .today-item {
    background: #2C231A !important;
    border-color: #3F352A !important;
    color: var(--ink) !important;
  }
  .today-item .ti-action { color: var(--ink) !important; }
  .today-item .ti-source { color: var(--gold) !important; }

  /* The lead activity card had a warmer cream override that beat the
     generic .activity-card walnut fill in light mode and was being
     overridden in dark mode — re-anchor it on a slightly warmer
     walnut so the lead card still feels lifted. */
  .activity-card.is-lead {
    background: #34281C !important;
    border-left-color: var(--gold) !important;
  }
  .activity-card.is-lead:hover {
    border-left-color: var(--accent) !important;
  }

  /* Parents page — section dividers and add-kid form draft border
     were both walnut-on-walnut, hard to spot. Lift the section h2
     rule slightly and keep the add-kid form's dashed border gold
     so it still reads as a "drafty" affordance at night.

     Important: the broad background override above gives
     .parents-section a walnut "card" surface in dark mode, but in
     light mode the section is a flat block with no padding. That
     mismatch was leaving the h2 and body copy jammed against the
     card's edges (gold underline running edge-to-edge, body text
     starting at x=0). Adding padding + a soft radius here completes
     the card so the content breathes inside it. */
  .parents-section {
    padding: 22px 26px 24px !important;
    border-radius: 14px !important;
  }
  .parents-section h2 {
    border-bottom-color: var(--gold-soft) !important;
  }
  .add-kid-form {
    background: #2C231A !important;
    border-color: var(--gold-soft) !important;
  }

  /* Rewards page "How to earn more" — new card-tile points grid.
     Tiles use #FFFEFA in light mode; walnut at night. The gold
     points number stays gold so the eye still lands on it. */
  .how-to-tile {
    background: #2C231A !important;
    border-color: #3F352A !important;
  }
  .how-to-tile .tile-name { color: var(--ink-soft) !important; }
  .how-to-tile .tile-pts { color: var(--gold) !important; }
  .how-to-grid-label { color: var(--gold) !important; }
  .step-text strong { color: var(--accent) !important; }

  /* 30-minute reminder modal — dark walnut card on a dimmed page. */
  .kc-reminder-card {
    background: #2C231A !important;
    border-color: #3F352A !important;
  }
}

/* ==========================================================
   v2 4d (June 2026) — small shared design-system additions.
   ADDITIVE ONLY: new tokens + utilities; nothing above this
   line changed. The warm parchment/lantern palette stays the
   foundation; these formalise motion + radii so new UI moves
   the same way everywhere.
   ========================================================== */

:root {
  /* Motion tokens — one easing, three speeds. */
  --kc-ease-out:  cubic-bezier(.2, .7, .2, 1);
  --kc-dur-quick: 160ms;   /* hovers, presses */
  --kc-dur-soft:  360ms;   /* card entrances */
  --kc-dur-slow:  600ms;   /* scroll reveals */
  /* Radii + spacing steps used by new components. */
  --kc-radius-card: 14px;
  --kc-radius-pill: 999px;
  --kc-space-1: 6px;
  --kc-space-2: 12px;
  --kc-space-3: 20px;
  --kc-space-4: 32px;
}

/* ---- Scroll reveal (progressive enhancement) -------------
   Elements are NOT hidden by default; the marketing landing's
   tiny IntersectionObserver script adds .kc-reveal at boot and
   .kc-reveal-in when the element scrolls into view. No JS (or
   reduced motion) = everything simply visible. */
.kc-reveal {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity   var(--kc-dur-slow) var(--kc-ease-out),
    transform var(--kc-dur-slow) var(--kc-ease-out);
}
.kc-reveal-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .kc-reveal, .kc-reveal-in { opacity: 1; transform: none; transition: none; }
}

/* ---- Entry pages (login.html / home.html) entrance -------
   The card and role buttons rise gently once on load. Scoped
   to no-preference so reduced-motion users get a still page. */
@media (prefers-reduced-motion: no-preference) {
  .entry-card { animation: kc-entry-rise 560ms var(--kc-ease-out) both; }
  .entry-card .role-btn { opacity: 0; animation: kc-entry-rise 480ms var(--kc-ease-out) forwards; }
  .entry-card .role-btn:nth-child(1) { animation-delay: 140ms; }
  .entry-card .role-btn:nth-child(2) { animation-delay: 220ms; }
  .entry-card .role-btn:nth-child(3) { animation-delay: 300ms; }
  .entry-card .role-btn:nth-child(4) { animation-delay: 380ms; }
  .entry-card .role-btn:nth-child(5) { animation-delay: 460ms; }
  .entry-card .role-btn:nth-child(n+6) { animation-delay: 540ms; }
}
@keyframes kc-entry-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---- Calm press feedback on primary actions --------------- */
.primary-btn:active,
.auth-primary:active,
.btn-primary:active,
.filter-chip:active,
.card-start:active {
  transform: translateY(0) scale(0.98);
}
@media (prefers-reduced-motion: reduce) {
  .primary-btn:active, .auth-primary:active, .btn-primary:active,
  .filter-chip:active, .card-start:active { transform: none; }
}

/* ---- Brand lockup ("KidsCompass · at Rihlah") ---------------- */
.site-nav-brand .brand-at,
.wordmark .brand-at {
  font-size: 0.6em;
  font-style: italic;
  font-weight: 400;
  opacity: 0.75;
  letter-spacing: 0.03em;
}

/* ---- Illustrated empty states ------------------------------
   Tiny inline-SVG art above the existing empty copy in the
   sidebar Stories panel and the chat journal panel. The art is
   injected by JS (kc_sidebar.js / app.js); these rules only
   size and tint it, so pages that never inject it are
   untouched. */
.kc-empty-art {
  display: block;
  width: 44px;
  height: 52px;
  margin: 2px 0 6px;
  color: var(--gold-soft);
  opacity: 0.8;
}
.sidebar .kc-empty-art { color: rgba(233, 178, 84, 0.65); }
@media (prefers-reduced-motion: no-preference) {
  .kc-empty-art .flame { animation: kc-flame 3.2s ease-in-out infinite; transform-origin: center; }
}
@keyframes kc-flame {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 0.85; }
}

/* ==========================================================
   Engagement pass (June 2026) — chat response polish.
   Rec 1.5 / 4.1 / 4.2 / 4.4 from ENGAGEMENT_RECOMMENDATIONS.md.
   ========================================================== */

/* Pulsing lantern dot beside the rotating "thinking" line. */
.loading-lantern {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 999px;
  background: var(--gold);
  margin-right: 10px;
  vertical-align: baseline;
}
@media (prefers-reduced-motion: no-preference) {
  .loading-lantern { animation: kc-lantern-pulse 1.6s ease-in-out infinite; }
}
@keyframes kc-lantern-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.85); }
  50%      { opacity: 0.95; transform: scale(1.0); }
}

/* Staggered story reveal — direct children arrive in sequence so the
   response reads as being TOLD, not served. Instant when reduced. */
@media (prefers-reduced-motion: no-preference) {
  .response--reveal > * {
    opacity: 0;
    transform: translateY(8px);
    animation: kc-rise-in 420ms var(--kc-ease-out) forwards;
  }
  .response--reveal > *:nth-child(1) { animation-delay: 0ms; }
  .response--reveal > *:nth-child(2) { animation-delay: 220ms; }
  .response--reveal > *:nth-child(3) { animation-delay: 440ms; }
  .response--reveal > *:nth-child(4) { animation-delay: 660ms; }
  .response--reveal > *:nth-child(5) { animation-delay: 880ms; }
  .response--reveal > *:nth-child(6) { animation-delay: 1060ms; }
  .response--reveal > *:nth-child(n+7) { animation-delay: 1200ms; }
}
@keyframes kc-rise-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Follow-up chips — the model's two context questions, surfaced. */
.followup-chips {
  margin: 26px 0 4px;
}
.followup-eyebrow {
  font-family: 'Source Serif 4', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  letter-spacing: 0.05em;
  color: var(--label);
  margin: 0 0 8px;
}
.followup-chip {
  appearance: none;
  display: block;
  width: 100%;
  text-align: left;
  background: #FFFEFA;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--gold-soft);
  border-radius: 10px;
  padding: 10px 14px;
  margin: 0 0 8px;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 15.5px;
  color: var(--ink);
  line-height: 1.45;
  cursor: pointer;
  transition: border-left-color var(--kc-dur-quick) ease,
              transform var(--kc-dur-quick) ease,
              box-shadow var(--kc-dur-quick) ease;
}
.followup-chip:hover {
  border-left-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: var(--shadow-soft);
}
@media (prefers-reduced-motion: reduce) {
  .followup-chip { transition: none; }
  .followup-chip:hover { transform: none; }
}
@media (prefers-color-scheme: dark) {
  .followup-chip { background: #2C231A; border-color: #3F352A; border-left-color: #B89556; }
}

/* "Put this story in a book" — quiet anchor in the next-link register. */
.story-to-book {
  display: inline-block;
  text-decoration: underline;
  text-underline-offset: 4px;
  margin-left: 14px;
}

/* Rec 3.2 (June 2026): "save first" nudge — a brief gold pulse on the
   Save-draft button so the toast's instruction points somewhere. */
@media (prefers-reduced-motion: no-preference) {
  .kc-pulse { animation: kc-save-pulse 1.4s ease-in-out 2; }
}
@keyframes kc-save-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(176, 138, 62, 0); }
  50%      { box-shadow: 0 0 0 5px rgba(176, 138, 62, 0.35); }
}

/* Rec 4.2 (June 2026): "your story came along" hint on the books list
   when arriving from the chat handoff link. */
.kc-fromchat-hint {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  background: var(--accent-soft);
  border: 1px solid rgba(30, 95, 90, 0.18);
  border-radius: 12px;
  padding: 12px 14px;
  margin: 0 0 16px;
}
.kc-fromchat-hint p {
  flex: 1;
  margin: 0;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--accent);
}
.kc-fromchat-hint button {
  appearance: none;
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
@media (prefers-color-scheme: dark) {
  .kc-fromchat-hint {
    background: rgba(30, 95, 90, 0.18);
    border-color: rgba(116, 181, 173, 0.25);
  }
  .kc-fromchat-hint p, .kc-fromchat-hint button { color: #9FD0C9; }
}

/* Citation-trust note. Shown beneath a story when the scripture references
   were not checked against our verified corpus (prophet route / Path-A
   answers). Quiet and reassuring, gold hairline like the other "aside"
   elements — not an error state. */
.scholar-note {
  margin: 14px 0 0;
  padding: 12px 14px;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-soft);
  background: var(--accent-soft);
  border-left: 3px solid var(--gold);
  border-radius: 8px;
}
