/*
 * Sämja — global styles + theme variables.
 * Loaded by every template via templates/_theme.html.
 *
 * The CSS variables here are the single source of truth for color. Tailwind
 * config (in _theme.html) exposes them as named utilities so templates can
 * use class names like `bg-page`, `text-muted`, `border-edge` instead of
 * raw `var(...)` expressions. Add or rename a color in BOTH places.
 */

/*
 * SÄMJA — theme tokens, built from the dawn landing page as the single
 * source of truth. Same variable NAMES as the legacy Modus app.css (so
 * templates + Alpine bindings are untouched); values are pure Sämja.
 * NO amber, NO brown anywhere. The legacy three-color bubble system
 * (you / their side / your AI) is re-expressed in the Sämja greens +
 * slate-sage so the desk reads as the same world as the landing.
 */
:root {
  --bg-primary: #F4F1EA;
  --bg-surface: #FBF7EE;
  --bg-private: #EDF1ED;
  --text-primary: #22302B;
  --text-muted:  #5E6B62;
  --accent-primary: #1B4332;
  --accent-light:   #95D5B2;
  --intent-propose: #2D6A4F;
  --intent-counter: #8FA8A0;
  --intent-accept:  #2D6A4F;
  --intent-decline: #9A3B30;
  --border: #E2DDD1;
  --tint-you: rgba(27, 67, 50, 0.07);
  --tint-ai:  rgba(143, 168, 160, 0.12);
  --bubble-user-bg:     var(--accent-primary);
  --bubble-user-text:   #FBF3E4;
  --bubble-user-border: color-mix(in srgb, var(--accent-primary) 30%, transparent);
  --bubble-user-shadow: 0 1px 12px rgba(27, 67, 50, 0.10);
  --bubble-ai-bg:       rgba(255, 255, 255, 0.62);
  --bubble-ai-border:   rgba(27, 67, 50, 0.12);
  --bubble-ai-text:     var(--text-primary);
  --bubble-ai-shadow:   0 1px 10px rgba(27, 67, 50, 0.05);
  --corner-glow: radial-gradient(120% 80% at 100% 0%, rgba(149, 213, 178, 0.18) 0%, rgba(244, 241, 234, 0) 55%);
}
/* Dark/light theme removed — the site is light-only now. (The desk's
   night-sky dark glass is a SEPARATE, sky-driven system: see
   body.desk-shell[data-sky="night"] below — not a user theme.) */
body, body * {
  transition-property: background-color, color, border-color, box-shadow, fill, stroke;
  transition-duration: 200ms; transition-timing-function: ease;
}
body.no-transition, body.no-transition * { transition: none !important; }
html { font-feature-settings: 'cv11', 'ss01'; }
body {
  background-color: var(--bg-primary); color: var(--text-primary);
  font-family: 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 16px; line-height: 1.6; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}
.font-display { font-family: 'Fraunces', Georgia, serif; font-weight: 400; letter-spacing: -0.01em; }
@keyframes pulse-dot { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.4;transform:scale(.85)} }
.dot-pulse { animation: pulse-dot 1.6s ease-in-out infinite; }
@keyframes connected-glow { 0%{box-shadow:0 0 0 0 rgba(45,106,79,.55)} 100%{box-shadow:0 0 0 14px rgba(45,106,79,0)} }
.dot-glow-once { animation: connected-glow 1.4s ease-out 1; }
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(95,107,98,.3); border-radius: 2px; }
::-webkit-scrollbar-thumb:hover { background: rgba(95,107,98,.5); }
.bubble-accent { border-left-width: 3px; border-left-style: solid; }
.bubble-user-radius { border-radius: 18px 18px 4px 18px; }
.bubble-ai-radius   { border-radius: 18px 18px 18px 4px; }
.bubble-user {
  background: var(--bubble-user-bg); border: 1px solid var(--bubble-user-border);
  color: var(--bubble-user-text); box-shadow: var(--bubble-user-shadow);
  -webkit-backdrop-filter: blur(12px) saturate(180%); backdrop-filter: blur(12px) saturate(180%);
}
.bubble-ai {
  background: var(--bubble-ai-bg); border: 1px solid var(--bubble-ai-border);
  color: var(--bubble-ai-text); box-shadow: var(--bubble-ai-shadow);
  -webkit-backdrop-filter: blur(12px) saturate(180%); backdrop-filter: blur(12px) saturate(180%);
}
.bubble-ai.is-draft { border-width: 2px; border-color: color-mix(in srgb, var(--accent-primary) 40%, transparent); }
.your-corner-bg { background-color: var(--bg-private); background-image: var(--corner-glow); }
.glass {
  background-color: color-mix(in srgb, var(--bg-surface) 80%, transparent);
  backdrop-filter: saturate(180%) blur(20px); -webkit-backdrop-filter: saturate(180%) blur(20px);
}
.scroll-fade-mask { mask-image: linear-gradient(to bottom, transparent 0%, black 6%, black 94%, transparent 100%); }
@keyframes thinking-bounce { 0%,60%,100%{transform:translateY(0)} 30%{transform:translateY(-6px)} }
.thinking-dot {
  display:inline-block; width:8px; height:8px; border-radius:50%;
  background-color: var(--accent-primary); animation: thinking-bounce 1.2s ease-in-out infinite;
}
.thinking-dot:nth-child(1){animation-delay:0ms} .thinking-dot:nth-child(2){animation-delay:133ms} .thinking-dot:nth-child(3){animation-delay:266ms}
.prompt-chip {
  background-color: var(--bg-surface); border: 1px solid var(--border); color: var(--text-primary);
  border-radius: 999px; padding: 6px 14px; font-size: 13px; cursor: pointer;
  transition: background-color 150ms ease, transform 150ms ease;
}
.prompt-chip:hover { background-color: var(--bg-primary); transform: translateY(-1px); }

/* OVERRIDE LAYER — stock Tailwind colors hardcoded in desk.html → Sämja, no amber */
.bg-emerald-100 { background-color: rgba(149,213,178,.25) !important; }
.text-emerald-600, .text-emerald-700, .text-emerald-800 { color: var(--intent-accept) !important; }
.dark\:bg-emerald-900\/30 { background-color: rgba(45,106,79,.22) !important; }
.bg-blue-100, .bg-blue-50 { background-color: rgba(143,168,160,.18) !important; }
.text-blue-600, .text-blue-700 { color: var(--text-muted) !important; }
.dark\:bg-blue-900\/30 { background-color: rgba(143,168,160,.16) !important; }
.dark\:text-blue-300 { color: var(--accent-light) !important; }
.bg-amber-100, .bg-amber-50 { background-color: rgba(143,168,160,.20) !important; }
.text-amber-700 { color: #3D5249 !important; }
.dark\:text-amber-300 { color: var(--accent-light) !important; }
.bg-amber-500 { background-color: var(--accent-light) !important; }
.bg-amber-600 { background-color: var(--intent-propose) !important; }
.hover\:bg-amber-700:hover { background-color: var(--accent-primary) !important; }
.bg-rose-50  { background-color: rgba(154,59,48,.08) !important; }
.text-rose-700, .text-rose-900 { color: var(--intent-decline) !important; }
.dark\:text-rose-400 { color: #D78A7E !important; }
.bg-rose-700 { background-color: var(--intent-decline) !important; }
.hover\:bg-rose-800:hover { background-color: #7E2F26 !important; }
.text-indigo-700 { color: var(--accent-primary) !important; }
.text-purple-700 { color: var(--text-muted) !important; }


/* SUPPLEMENT (coding agent, not design agent): three amber utilities in
   desk.html the override layer above didn't enumerate — mapped to the
   same Sämja sage/forest replacements so "no amber anywhere" holds.
   border-amber-500: 3px card edge (desk.html:1179).
   hover:bg-amber-50 + dark:hover:bg-amber-900/20: button hover (desk.html:209). */
.border-amber-500 { border-color: var(--accent-light) !important; }
.hover\:bg-amber-50:hover { background-color: rgba(143,168,160,.20) !important; }
.dark\:hover\:bg-amber-900\/20:hover { background-color: rgba(45,106,79,.22) !important; }

/* ============================================================
   SÄMJA DESIGN-SYSTEM TOKENS + ATMOSPHERE
   (added site-wide so every page can use the named tokens from the
   landing/desk design without redefining them inline)
   ============================================================ */
:root {
  --forest:      #1B4332;
  --forest-2:    #2D6A4F;
  --sage:        #95D5B2;
  --sage-soft:   #B7CBC1;
  --slate-sage:  #8FA8A0;
  --linen:       #F4F1EA;
  --linen-2:     #EDE8DD;
  /* Deeper alternate for the calm-library tonal bands — nudged below
     --linen-2 so the banding registers as deliberate rhythm (TWEAKS §A1)
     without disturbing home/dawn's existing --linen-2 surfaces. */
  --linen-band:  #EAE2D2;
  --linen-hi:    #FBF7EE;
  --ink:         #22302B;
  --muted:       #5E6B62;
  --cream-hi:    #FBF3E4;
  --edge:        #E4DFD3;
}

/* Sky atmosphere stack — fixed layers behind page content.
   Pair with a `.stage` (or any z-index:3 wrapper) for the content. */
/* Negative z so the fixed sky sits ABOVE the body background but BEHIND
   all in-flow content — no per-page content wrapping required. (The
   landing defines its own .sky inline, scoped to its .hero, so these
   global rules don't affect it.) */
.sky      { position: fixed; inset: 0; z-index: -3; }
.sky img  { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; transition: opacity 1.2s ease; }
/* Desk sky starts hidden so the default bg_dawn never flashes the wrong sky
   before the first state poll resolves — __samjaSky reveals it with the
   correct image (sky-flicker fix 3). Desk-only: #sky-img exists only there;
   static/marketing/legal pages embed the correct sky in server-rendered HTML
   (no JS swap), so they never flicker and must NOT start hidden. */
#sky-img { opacity: 0; }
.sky-wash { position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background: linear-gradient(180deg, rgba(20,28,40,0.32) 0%, rgba(20,28,40,0.06) 22%, rgba(244,241,234,0.04) 50%, rgba(31,43,34,0.22) 100%); }
.grain    { position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.stage    { position: relative; z-index: 1; }

/* Pages that opt into the sky backdrop set body.has-sky so their opaque
   body background doesn't hide the fixed sky behind it. */
body.has-sky { background: transparent !important; }

/* DESK-SCOPED stacking fix (DESK_VISUAL_SPEC §4 — "if it renders as a gray
   slab, fix the stacking context, do not switch to a solid fill").
   backdrop-filter does not sample a backdrop painted at NEGATIVE z-index, so
   the desk topbar's glass had no sky to blur and composited gray. Lift the
   desk's sky layers OUT of negative z so the topbar (z-30) and the glass
   panels actually sample them. Scoped to .desk-shell ONLY: every other
   has-sky page (account, legal, join, status, …) relies on the global
   negative-z sky so its in-flow content paints over the sky without needing
   its own z-index — a global change would hide their content. With the desk
   sky now at z:0, the desk's in-flow content must sit above it (main +
   record footer get z:1 in desk.html; header/banner/footers already do). */
body.desk-shell .sky,
body.desk-shell .sky-wash,
body.desk-shell .grain { z-index: 0; }

/* Contained sky HERO band for marketing pages — sky behind the page
   title only; the gradient wash fades to linen at the bottom so the
   normal (opaque) linen content below the fold stays fully readable.
   Unlike .sky (fixed, whole page), .sky-band is absolute within its
   own relative section. */
.sky-band { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.sky-band img { width: 100%; height: 100%; object-fit: cover; object-position: center 32%; }
.sky-band-wash { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(20,28,40,0.34) 0%, rgba(20,28,40,0.10) 28%, rgba(20,28,40,0) 55%, color-mix(in srgb, var(--bg-primary) 70%, transparent) 88%, var(--bg-primary) 100%); }

/* Frosted glass card. Named .glasscard to NOT collide with the legacy
   .glass (used by the desk header / marketing nav). */
.glasscard {
  border: 1px solid rgba(255,255,255,0.30);
  box-shadow: 0 20px 70px rgba(15,23,34,0.40), inset 0 1px 0 rgba(255,255,255,0.40);
  -webkit-backdrop-filter: blur(22px) saturate(1.1); backdrop-filter: blur(22px) saturate(1.1);
  border-radius: 24px;
  background: rgba(244,241,234,0.62);
}
.glasscard.corner { background: rgba(251,247,238,0.78); }
/* Dark glass — required when the sky is bg_night.png. */
[data-sky="night"] .glasscard {
  background: rgba(20,28,40,0.55) !important;
  border-color: rgba(255,255,255,0.14) !important;
}
[data-sky="night"] .glasscard,
[data-sky="night"] .glasscard * { color: var(--cream-hi) !important; }
[data-sky="night"] .glasscard .text-muted,
[data-sky="night"] .glasscard a:not(.btn) { color: rgba(251,243,228,0.78) !important; }

/* Desk night mode. window.__samjaSky sets data-sky="night" on the desk
   shell for terminal / walked-away states. Remap the surface/text/border
   tokens so the desk's .glass header, bg-card panels, and .your-corner-bg
   panels turn into dark glass with cream text (they all resolve to these
   vars). Scoped to .desk-shell so it never touches the shared LIGHT
   marketing/legal nav — those pages also use data-sky="night" but keep
   their light chrome + .glasscard reading card. */
body.desk-shell[data-sky="night"] {
  /* SOLID dark surfaces — opaque so the sky never leaks through the
     panels (the translucent version read as washed-out "light leaking
     through" the Your Corner card). The sky stays a backdrop; panels are
     solid dark glass with cream text. */
  --bg-surface: #1a232c;
  --bg-private: #161e26;
  --text-primary: #FBF3E4;
  --text-muted: rgba(251, 243, 228, 0.72);
  --border: rgba(255, 255, 255, 0.12);
  --tint-you: rgba(149, 213, 178, 0.12);
  --tint-ai: rgba(143, 168, 160, 0.10);
  /* DESK_VISUAL_SPEC §7.1: forest (#1B4332) is invisible on the dark
     onboarding desk. Flip the forest accent to SAGE here so EVERY forest
     accent — thinking dots, in-chat icons, focus rings, text/border accents —
     reads at once (the locked "green adapts shade: forest on light, sage on
     dark" rule, applied to the accent token, not per element). The bright
     Send/Draft CTAs are the one exception: they go to --forest-2 (below), per
     §5, so they stay button-like rather than sage. */
  --accent-primary: var(--sage);
}
/* §5 exception: the bright CTAs (Send / Draft / Send opening) must be
   FOREST-2 on the dark desk, not sage. Covers both Tailwind `bg-accent`
   buttons and the inline-styled composer Send. cream/white text stays legible. */
body.desk-shell[data-sky="night"] .bg-accent,
body.desk-shell[data-sky="night"] .composer-send { background-color: var(--forest-2) !important; }

/* Desk top bar — LIGHT/main desk (Fix 3). Two layers: a diagonal specular
   sheen on top + a near-opaque CREAM BODY (rgba(252,250,245,.86)) under it.
   The cream body backs the dark meta text regardless of whether backdrop-filter
   composites the sky — earlier the legibility depended entirely on the blur, so
   it washed out live when the page composited differently than the isolated
   reference. This version is robust to the blur being dropped (verified with
   backdrop-filter force-disabled). The blur stays as a refinement, not a crutch.
   Dark/night desk overrides this below. */
.desk-topbar {
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  backdrop-filter: blur(18px) saturate(1.3);
  background:
    linear-gradient(105deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.45) 15%, rgba(255,255,255,0) 32%),
    linear-gradient(180deg, rgba(252,250,245,.86) 0%, rgba(250,247,240,.80) 100%);
  border-bottom: 1px solid rgba(255,255,255,.55);
  box-shadow: 0 1px 0 rgba(255,255,255,.8) inset, 0 6px 20px rgba(15,23,34,.08);
}
body.desk-shell[data-sky="night"] .desk-topbar {
  /* On DARK skies (night + pre-dawn/beforesunrise), the frosted bar shows a
     dark sky through it, so dark text would be unreadable. Match the
     marketing/landing cream-on-sky nav instead: a faint dark-tinted frosted
     bar with cream text + cream/sage mark. Atmospheric, not a slab. (§3.3)
     Leave-as-is: override the light cream body + neutralize its white
     sheen/highlight and drop shadow here so none of it leaks onto night. */
  background: color-mix(in srgb, #141c28 34%, transparent);
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow: none;
  --text-primary: var(--cream-hi);
  --text-muted: rgba(251, 243, 228, 0.78);
  --border: rgba(255, 255, 255, 0.16);
}
/* Pre-dawn/night: brand mark dots go cream/sage (the .on-light forest dots
   would vanish on the dark bar). */
body.desk-shell[data-sky="night"] .desk-topbar .samja-mark .dot.l { background: var(--cream-hi); }
body.desk-shell[data-sky="night"] .desk-topbar .samja-mark .dot.r { background: var(--sage); }
/* The status/meta text in the topbar uses semantic Tailwind greens/ambers
   (connection status, "Verified", key fingerprints) that are too dark on the
   night backing. Lift them to legible light variants so they read on dark
   (TWEAKS §C — same dark-context legibility fix as the title/links). */
body.desk-shell[data-sky="night"] .desk-topbar .text-emerald-700,
body.desk-shell[data-sky="night"] .desk-topbar .text-emerald-800,
body.desk-shell[data-sky="night"] .desk-topbar .hover\:text-emerald-800:hover { color: #6ee7b7; }
body.desk-shell[data-sky="night"] .desk-topbar .text-amber-700 { color: #fcd34d; }
body.desk-shell[data-sky="night"] .desk-topbar .text-indigo-700 { color: #a5b4fc; }
body.desk-shell[data-sky="night"] .desk-topbar .text-purple-700 { color: #d8b4fe; }

/* Desk footer sits on solid light --linen on EVERY sky. Under night the
   global token remap turns --text-* cream — which would vanish on linen — so
   re-localize the footer subtree back to dark ink/muted + light hairline. */
body.desk-shell[data-sky="night"] .desk-footer {
  --text-primary: #22302B;
  --text-muted: #5E6B62;
  --border: #E4DFD3;
}
/* "Only you and your AI see this" privacy pill — its inline forest text/tint
   is unreadable on the dark onboarding (pre-dawn) glass. On dark skies flip it
   to cream-on-sage so it reads (TWEAKS §I2). !important beats the inline style;
   only fires under data-sky="night" (post-I4 that's onboarding/terminal), so
   the light live-desk pill keeps its forest treatment. */
body.desk-shell[data-sky="night"] .corner-privacy-pill {
  color: var(--cream-hi) !important;
  background: rgba(149, 213, 178, 0.16) !important;
  border-color: rgba(149, 213, 178, 0.40) !important;
}

/* DESK PANELS — enclosed-card treatment (DESK_VISUAL_SPEC §2). Privacy is
   signalled by DEPTH/enclosure, never hue. Shared = open/floating (lighter,
   flatter — the exposed shared space); Your Corner = sealed/enclosed (denser,
   deeper shadow + inset ring — a contained vault). */
.desk-panel-public {
  background: rgba(251, 247, 238, 0.66);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 20px;
  box-shadow: 0 8px 26px rgba(15, 23, 34, 0.10);
}
.desk-panel-private {
  background: rgba(238, 234, 224, 0.92);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 20px;
  box-shadow: 0 20px 55px rgba(15, 23, 34, 0.26), inset 0 0 0 1.5px rgba(27, 67, 50, 0.10);
}
/* Dark (onboarding / pre-dawn): only Your Corner exists — dark glass + sage
   inset ring. */
body.desk-shell[data-sky="night"] .desk-panel-private {
  background: rgba(20, 28, 40, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.40), inset 0 0 0 1.5px rgba(149, 213, 178, 0.10);
}

/* Two-dot Sämja brand mark (shared nav/footer/desk). */
.samja-mark { position: relative; width: 26px; height: 26px; flex: none; display: inline-block; }
.samja-mark .dot { position: absolute; top: 50%; margin-top: -4px; width: 8px; height: 8px; border-radius: 50%; }
.samja-mark .dot.l { left: 3px; background: var(--cream-hi); }
.samja-mark .dot.r { right: 3px; background: var(--sage); animation: samja-pulse 4s ease-in-out infinite; }
/* On light/linen surfaces use forest dots (no pulse). */
.samja-mark.on-light .dot.l { background: var(--forest); }
.samja-mark.on-light .dot.r { background: var(--forest-2); animation: none; }
@keyframes samja-pulse { 0%,100%{transform:scale(1);opacity:1} 50%{transform:scale(1.15);opacity:.7} }

/* Turn pill — SINGLE shared token block used by BOTH the desk header
   (now a light .desk-topbar) and the home cards (light glass), so they
   never drift (home handoff §2.8). Forest text on sage; pulse animates
   background + border only (text stays static — P3-A). */
.turnpill { display:inline-flex; align-items:center; gap:8px; padding:7px 14px; border-radius:100px; font-size:13px; font-weight:600; border:1px solid transparent; }
.turnpill .d { width:7px; height:7px; border-radius:50%; flex:none; }
.turnpill.you { background:rgba(149,213,178,0.5); border-color:rgba(45,106,79,0.25); color:var(--forest); animation:turnPulse 3.2s ease-in-out 1s infinite; }
.turnpill.you .d { background:var(--forest-2); animation:dotPulse 3.2s ease-in-out 1s infinite; }
.turnpill.wait { background:rgba(143,168,160,0.22); color:var(--muted); border-color:rgba(143,168,160,0.3); }
.turnpill.wait .d { background:var(--slate-sage); }
.turnpill.done { background:rgba(149,213,178,0.4); color:var(--forest); border-color:transparent; }
.turnpill.done .d { display:none; }
.turnpill.done::before { content:"\2713"; font-size:12px; margin-right:-2px; }
@keyframes turnPulse { 0%,100%{background:rgba(149,213,178,0.5);border-color:rgba(45,106,79,0.25)} 50%{background:var(--sage);border-color:var(--sage)} }
@keyframes dotPulse  { 0%,100%{background:var(--forest-2)} 50%{background:var(--forest)} }

/* Reduced-motion: kill all atmosphere/brand animation; state still
   readable via color + label (turn pill) and static dots (mark). */
@media (prefers-reduced-motion: reduce) {
  .turnpill.you, .turnpill.you .d,
  .samja-mark .dot.r,
  .sky img { animation: none !important; transition: none !important; }
}

/* Async-button spinner. Track uses currentColor so it reads on BOTH
   solid (white text) and outlined (forest text) buttons; the bright
   arc is full currentColor. inline-flex friendly. */
.btn-spinner {
  display: inline-block;
  width: 14px; height: 14px;
  border: 2px solid color-mix(in srgb, currentColor 28%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: btn-spin 0.7s linear infinite;
  vertical-align: middle;
  margin-right: 7px;
  flex-shrink: 0;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn-spinner { animation: none; opacity: 0.6; }
}

/* ============================================================
   MARKETING LAYOUT — fixed sky + left cream title, then either
   fade-to-clean (thinking pages) or glass panels (feeling pages).
   Pages set body.has-sky + {% include "_sky.html" %} (fixed sky).
   ============================================================ */
/* Left cream title, high under the floating header (home rhythm). */
.mkt-head { max-width: 920px; margin: 0 auto; padding: clamp(74px,8vh,94px) clamp(20px,4vw,40px) clamp(16px,2.4vh,24px); position: relative; z-index: 1; }
.mkt-head h1 { font-family: 'Fraunces', Georgia, serif; font-weight: 300; font-size: clamp(34px,5vw,56px); line-height: 1.04; letter-spacing: -0.02em; color: var(--cream-hi); text-shadow: 0 2px 30px rgba(20,28,40,.55), 0 1px 3px rgba(20,28,40,.5); max-width: 20ch; }
.mkt-head p { margin-top: 14px; font-size: clamp(16px,1.9vw,20px); line-height: 1.5; color: rgba(251,243,228,0.95); text-shadow: 0 1px 12px rgba(20,28,40,.5); max-width: 46ch; }

/* Fade-to-clean body: dissolves the fixed sky into linen, then carries
   "thinking" content (cards, prose) on a clean linen surface. */
.mkt-body { position: relative; z-index: 1; background: var(--linen); }
.mkt-body::before { content: ""; position: absolute; left: 0; right: 0; top: -130px; height: 130px; background: linear-gradient(180deg, transparent 0%, var(--linen) 100%); pointer-events: none; }
.mkt-inner { max-width: 920px; margin: 0 auto; padding: clamp(10px,2vh,24px) clamp(20px,4vw,40px) clamp(44px,8vh,84px); }

/* Glass marketing stack: panels float on the fixed sky all the way down
   (feeling pages — About). */
.mkt-stack { max-width: 920px; margin: 0 auto; padding: 0 clamp(20px,4vw,40px) clamp(44px,8vh,84px); display: flex; flex-direction: column; gap: clamp(16px,3vh,26px); position: relative; z-index: 1; }
.mkt-panel { background: rgba(251,247,238,0.70); -webkit-backdrop-filter: blur(24px) saturate(1.2); backdrop-filter: blur(24px) saturate(1.2); border: 1px solid rgba(255,255,255,.45); border-radius: 22px; box-shadow: 0 20px 60px rgba(15,23,34,.26), inset 0 1px 0 rgba(255,255,255,.5); padding: clamp(26px,4vw,44px); }

/* ============================================================
   CALM LIBRARY — INFO PAGES (How it works · Pricing · FAQ · About)
   (TWEAKS §A — supersedes the fade/glass info-page direction.)
   A dawn sky BAND behind the header + title only, dissolving into
   linen; then a body of full-bleed alternating tonal bands on a
   single left axis (~780px reading column). No glass-on-sky here —
   the sky stays reserved for feeling/doing surfaces. The shared
   cream-on-sky header (_nav, position:absolute) floats over the band.
   ============================================================ */
.lib-band { position: relative; overflow: hidden; background: var(--ink); }
.lib-sky { position: absolute; inset: 0; z-index: 0; }
.lib-sky img { width: 100%; height: 100%; object-fit: cover; object-position: center 22%; }
.lib-wash { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(20,28,40,.28) 0%, rgba(20,28,40,.04) 40%, rgba(244,241,234,.4) 82%, var(--linen) 100%); }
/* Big top padding clears the floating (absolute) header; the title gets
   its cream-on-sky moment, then the wash melts the band into linen. */
.lib-head { position: relative; z-index: 2; max-width: 780px; margin: 0 auto;
  padding: clamp(96px,15vh,150px) clamp(20px,5vw,48px) clamp(46px,9vh,90px); }
.lib-head h1 { font-family: 'Fraunces',Georgia,serif; font-weight: 300; font-size: clamp(36px,5.2vw,58px); line-height: 1.03; letter-spacing: -.02em; color: var(--cream-hi); text-shadow: 0 2px 30px rgba(20,28,40,.5); }
.lib-head p { margin-top: 14px; font-size: clamp(16px,1.9vw,20px); line-height: 1.5; color: rgba(251,243,228,.95); text-shadow: 0 1px 12px rgba(20,28,40,.5); max-width: 46ch; }

/* Full-bleed alternating tonal bands (landing rhythm), hairline between. */
.band-sec { width: 100%; border-bottom: 1px solid var(--border); }
.band-sec.tone-a { background: var(--linen); }
.band-sec.tone-b { background: var(--linen-band); }
.band-inner { max-width: 780px; margin: 0 auto; padding: clamp(40px,7vh,82px) clamp(20px,5vw,48px); }
.band-inner .eyebrow { font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--forest-2); font-weight: 600; margin-bottom: 14px; }
.band-inner h2 { font-family: 'Fraunces',Georgia,serif; font-weight: 300; font-size: clamp(24px,3.4vw,34px); line-height: 1.12; letter-spacing: -.01em; color: var(--forest); margin-bottom: 22px; }
.band-inner .lead { font-size: 16px; color: var(--muted); line-height: 1.65; max-width: 60ch; }
/* Three-column sub-grid (e.g. the core-mechanic columns). */
.lib-three { display: grid; grid-template-columns: repeat(3,1fr); gap: 26px; }
.lib-three h3 { font-family: 'Fraunces',Georgia,serif; font-weight: 500; font-size: 17px; color: var(--ink); margin-bottom: 7px; }
.lib-three p { font-size: 13.5px; color: var(--muted); line-height: 1.6; }
@media (max-width: 720px) { .lib-three { grid-template-columns: 1fr; gap: 18px; } }

/* ============================================================
   CANCEL / LEAVE CONVERSATION (CANCEL_LEAVE_SPEC §2). Shared by the
   home dashboard cards and the desk. Calm ghost button at rest;
   reveals its destructive nature (terracotta) only on hover. The
   confirm dialog puts the destructive action on the RIGHT, escape left.
   ============================================================ */
.btn-cancel-ghost {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-weight: 500;
  font-size: 13px;
  padding: 7px 14px;
  border-radius: 9px;
  cursor: pointer;
  font-family: 'Hanken Grotesk', sans-serif;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.btn-cancel-ghost:hover { border-color: var(--terracotta, #9A3B30); color: var(--terracotta, #9A3B30); }
/* Quiet underlined text-link variant (desk waiting panel / Your Corner). */
.link-cancel-quiet {
  background: none; border: none; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 13px; color: var(--muted);
  text-decoration: underline; text-underline-offset: 3px; transition: color 0.2s ease;
}
.link-cancel-quiet:hover { color: var(--terracotta, #9A3B30); }

.cancel-dialog-backdrop {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(20,28,40,0.45);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.cancel-dialog {
  background: var(--linen);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: 0 24px 60px rgba(15,23,34,0.22);
  padding: 28px;
  max-width: 400px;
  width: 100%;
}
.cancel-dialog-title { font-family: 'Fraunces', serif; font-size: 22px; font-weight: 500; color: var(--ink); margin-bottom: 10px; }
.cancel-dialog-body { font-size: 14.5px; color: var(--muted); line-height: 1.6; margin-bottom: 24px; }
.cancel-dialog-actions { display: flex; gap: 10px; justify-content: flex-end; }
.btn-dialog-escape {
  background: none; border: 1px solid var(--border); color: var(--muted);
  padding: 10px 18px; border-radius: 9px; font-family: 'Hanken Grotesk', sans-serif;
  font-size: 14px; cursor: pointer;
}
.btn-dialog-escape:hover { color: var(--ink); }
.btn-dialog-confirm {
  background: var(--terracotta, #9A3B30); color: #fff; font-weight: 600;
  padding: 10px 18px; border-radius: 11px; border: none;
  font-family: 'Hanken Grotesk', sans-serif; font-size: 14px; cursor: pointer;
}
.btn-dialog-confirm:hover { background: #7E2F26; }
.btn-dialog-confirm:disabled { opacity: 0.6; cursor: default; }

/* Draft editing textarea — always a clean ink-on-light writing surface,
   regardless of the active sky / dark-glass mode (Desk UX §2.4). */
.draft-edit-surface { background: var(--cream-hi) !important; color: var(--ink) !important; }

/* ============================================================
   LEAVE / CANCEL CONVERSATION (supersedes the earlier cancel button).
   Lives in the desk header meta row after the Verified badge (Fix 5):
   a legible text link in the meta color behind a thin left divider —
   NOT a pill. Hover → terracotta. 3-screen leave dialog below.
   ============================================================ */
/* Home dashboard-card cancel/leave — still a quiet ghost pill (NOT relocated;
   Fix 5 only moves the DESK header control). Kept for templates/home.html. */
.btn-leave-ghost {
  background: rgba(255,255,255,0.4);
  border: 1px solid var(--border);
  color: var(--muted);
  font-weight: 500; font-size: 13px;
  padding: 7px 16px; border-radius: 100px;
  cursor: pointer; font-family: 'Hanken Grotesk', sans-serif;
  transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
  text-decoration: none;
}
.btn-leave-ghost:hover { border-color: #c0573f; color: #c0573f; background: rgba(192,87,63,0.06); }

.desk-meta-leave {
  border: none;
  border-left: 1px solid rgba(94,107,98,0.2);
  padding: 0 0 0 9px;
  background: none;
  color: var(--muted);
  font-weight: 500; font-size: 12px;
  cursor: pointer; font-family: 'Hanken Grotesk', sans-serif;
  transition: color 0.15s ease;
  text-decoration: none;
}
.desk-meta-leave:hover { color: #c0573f; }
/* Dark/night desk — cream-tinted divider + muted cream text. */
body.desk-shell[data-sky="night"] .desk-meta-leave {
  border-left-color: rgba(251,243,228,0.2);
  color: rgba(251,243,228,0.55);
}
body.desk-shell[data-sky="night"] .desk-meta-leave:hover { color: #c0573f; }

.leave-dialog {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(20,28,40,0.45);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.leave-dialog-inner {
  background: var(--linen); border: 1px solid var(--border); border-radius: 18px;
  box-shadow: 0 24px 60px rgba(15,23,34,0.22); padding: 28px; max-width: 420px; width: 100%;
}
.btn-dialog-warn {
  background: var(--forest); color: var(--cream-hi);
  padding: 10px 18px; border-radius: 9px; border: none;
  font-family: 'Hanken Grotesk', sans-serif; font-size: 14px; font-weight: 600; cursor: pointer;
}
.btn-dialog-warn:hover { background: var(--forest-2); }

/* ============================================================
   .appcard — shared app-page card surface (home / account /
   agreement-reached record). Values lifted VERBATIM from home.html .card
   (Fix 1). Additive: does NOT touch the desk's .glasscard / .glass.
   ============================================================ */
.appcard {
  background: rgba(251,247,238,0.62);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  backdrop-filter: blur(14px) saturate(1.1);
  border: 1px solid rgba(255,255,255,0.42);
  border-radius: 15px;
}

/* .apppanel — shared dark-glass content panel (home's .field values, Fix 1).
   Wraps app-page content (account; home uses .field inline). Cream cards
   (.appcard) sit inside it. Additive; no collision with .glasscard/.glass. */
.apppanel {
  background: rgba(251,247,238,0.22);
  -webkit-backdrop-filter: blur(16px) saturate(1.1); backdrop-filter: blur(16px) saturate(1.1);
  border: 1px solid rgba(255,255,255,0.3);
  border-radius: 28px;
  box-shadow: 0 24px 70px rgba(15,23,34,0.24), inset 0 1px 0 rgba(255,255,255,0.4);
}
