:root{
  /* ===== بامداد — پالت هماهنگ با سایت هوم (سیاه/کرم، بدون رنگ لهجه) =====
     جایگزین پالت قبلیِ «کاغذ/طلایی». اسم متغیرها عمداً همون قبلی نگه داشته
     شده (--paper/--ink/--gold/...) که بقیهٔ کد دست‌نخورده بمونه؛ فقط
     MAPPING رنگی عوض شده:
       --paper/--paper-soft/--card → سیاه + لایه‌های خیلی ظریفِ روش‌تر
       --ink/--ink-soft/--ink-faint → کرم (سه سطح، مثل --cream سایت هوم)
       --line → خط موییِ کرم‌رنگِ کم‌رنگ (مثل --hair)
       --gold/--gold-soft → دیگه طلایی نیستن؛ کرم/سفید (بدون رنگ لهجه)
       --ember/--sage → تنها دو رنگ کاربردیِ باقی‌مونده (خطا/قرمز، موفقیت/سبز)،
         کم‌رنگ‌تر و هماهنگ با تم تیره
       --dusk → دیگه آبی نیست؛ خاکستریِ خنثی (برای دستهٔ «کاری» و گرادیان‌های تزئینی)
     ===== */
  /* به‌روزرسانی: --paper/--ink/--ink-soft/--ink-faint/--line دیگه رنگ رو
     هارد-کد نمی‌کنن، بلکه از shared-tokens.css (همون فایلی که shared.css
     سایت هم ازش می‌خونه) می‌گیرنش — یعنی الان یه منبع واحد برای این
     مقدارها هست. بقیهٔ متغیرها (gold/ember/sage/dusk/paper-soft/card) چون
     معادلی در shared-tokens.css ندارن (رنگ‌های مخصوص خود پلنرن)، دست‌نخورده
     و هارد-کد باقی موندن. */
  --paper:var(--ink-base);
  --paper-soft:rgba(242,242,240,.045);
  --ink:var(--cream);
  --ink-soft:var(--cream-soft);
  --ink-faint:var(--cream-faint);
  --line:var(--hair);
  --gold:#f2f2f0;
  --gold-soft:rgba(242,242,240,.20);
  --ember:#d97a72;
  --sage:#8fae86;
  --dusk:#5c5c5c;
  --card:rgba(242,242,240,.045);
  --radius: 14px;
  --radius-sm: 9px;
  --font-body: 'Vazirmatn', 'IRANSans', Tahoma, 'Segoe UI', system-ui, sans-serif;
  --sky-top:#0a0a0a;
  --sky-bottom:#0a0a0a;
  --halo:var(--gold);
  --glass-border: rgba(242,242,240,.10);
  --glass-border-strong: rgba(242,242,240,.28);
  /* Focal point for the hero photo in .horizon-wrap (cover-cropped). "center
     top" keeps the top of the frame — where a standing figure's head usually
     is — visible instead of being cut by vertical centering. Nudge this once
     the real photo is in (e.g. "80% top" to favor the right side, or
     "center 30%" to shift down a bit) rather than editing the rule itself. */
  --hero-focus: center top;
  --fs-micro: 12px;    /* pass 12: was 11 */
  --fs-caption: 13.5px; /* was 12.5 */
  --fs-body: 15px;      /* was 14 */
  --fs-body-lg: 16px;
  --fs-h2: 19px;
  --fs-h1: 24px;
  --fs-display: 32px;
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px;
  --space-5:20px; --space-6:24px; --space-8:32px; --space-10:40px;
  /* ===== Shadow system (step 5) — two depth tiers, everything else in the
     sheet should reference one of these instead of a hand-rolled box-shadow.
     shadow-card: resting elevation for in-flow cards/panels/buttons.
     shadow-float: for anything fixed/absolute above the page — modals,
     dropdowns, FAB-style floating controls. Real per-edge exceptions (a
     bottom-anchored bar's shadow needs to point up, not down; .glass needs
     its own diffuse glow to read as frosted) are called out with a comment
     at the declaration instead of forcing them into these two shapes. ===== */
  --shadow-card: 0 1px 2px rgba(0,0,0,.25), 0 1px 3px rgba(0,0,0,.3);
  --shadow-float: 0 10px 30px -6px rgba(0,0,0,.55);
  /* بامو (دستیار) — تنها جای اپ که پالت تیره‌ی مستقلِ خودش (سبزآبی/teal) رو
     داره، جدا از پالت سیاه/کرمِ بقیه‌ی صفحات. قبلاً این گرادیان و این رنگ
     تیل تو ۱۲+ جای مختلف به‌صورت هارد-کد تکرار شده بودن (همون چیزی که تو
     HANDOFF به‌عنوان «گرادیان‌های پس‌زمینه‌ی کارت‌ها» مونده بود)؛ الان یه
     منبع واحدن. مقادیرِ محاسبه‌شده عیناً همونیه که قبلاً بود — فقط منبعش
     یکی شده، هیچ تغییر بصری‌ای در کار نیست. مستقل از data-mode چون تمِ بامو
     تو حالت روز/شب فرق نمی‌کنه. */
  --bamo-teal-rgb: 47,230,214;
  --bamo-bg-gradient: radial-gradient(120% 140% at 30% 20%, #123a3a 0%, #051417 55%, #01050a 100%);
}
/* حالت «تیره» دیگه عمداً هیچ فرقی با پیش‌فرض نداره: طبق تصمیم هماهنگ‌سازی با
   سایت هوم، هر دو حالت روشن/تیره روی همون پالت سیاه/کرم قرار گرفتن. سوییچ
   خودکار/روشن/تیرهٔ تنظیمات همچنان کار می‌کنه (منطقش دست نخورده)، فقط دیگه
   چیزی برای تغییر بصری نداره — همون‌طور که خودِ سایت هوم هم فقط یک تم ثابت داره. */
:root[data-mode="night"]{
  --paper:var(--ink-base);
  --paper-soft:rgba(242,242,240,.045);
  --ink:var(--cream);
  --ink-soft:var(--cream-soft);
  --line:var(--hair);
  --card:rgba(242,242,240,.045);
  --shadow-card: 0 1px 2px rgba(0,0,0,.25), 0 1px 3px rgba(0,0,0,.3);
  --shadow-float: 0 10px 30px -6px rgba(0,0,0,.55);
  --glass-border: rgba(242,242,240,.10);
  --glass-border-strong: rgba(242,242,240,.28);
  --gold:#f2f2f0;
  --ember:#d97a72;
  --sage:#8fae86;
  --sky-top:#0a0a0a;
  --sky-bottom:#0a0a0a;
}
*,*::before,*::after{box-sizing:border-box;}
html,body{height:100%;}
body{
  margin:0;
  font-family:var(--font-body);
  background:var(--paper);
  background-attachment:fixed;
  color:var(--ink);
  transition:background .5s ease, color .5s ease;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y:none;
  position:relative;
}
:root[data-mode="night"] body{
  background:var(--paper);
  background-attachment:fixed;
}
h1,h2,h3,h4{
  margin:0;
  font-weight:800;
  letter-spacing:-.02em;
}
p{margin:0;}
button{font-family:inherit;}
input,textarea,select{font-family:inherit;}
::selection{background:var(--gold-soft);}
.num{font-variant-numeric:tabular-nums;letter-spacing:.02em;direction:ltr;unicode-bidi:isolate;}
a{color:inherit;text-decoration:none;}
button{cursor:pointer;border:none;background:none;color:inherit;}
::-webkit-scrollbar{width:8px;height:8px;}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px;}

/* ===== App shell ===== */
#app{
  min-height:100vh;
  min-height:100dvh;
  display:flex;
  flex-direction:column;
  max-width:1180px;
  margin:0 auto;
  position:relative;
  z-index:1;
}
/* subtle paper-grain texture — attached to #app (not fixed to viewport), so it's painted
   once as part of normal layout instead of a separately-composited layer that mobile
   browsers have to repaint on every scroll frame (that fixed-layer cost was the main
   source of the "app feels laggy on phone" issue) */
#app::before{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:0;opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode:multiply;
}
/* faint night sky — a handful of static stars that fade in only in night mode */
#app::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:0;opacity:0;transition:opacity 1.2s ease;
  background-image:
    radial-gradient(1px 1px at 8% 18%, rgba(255,255,255,.55), transparent),
    radial-gradient(1px 1px at 78% 12%, rgba(255,255,255,.4), transparent),
    radial-gradient(1.5px 1.5px at 58% 68%, rgba(255,255,255,.35), transparent),
    radial-gradient(1px 1px at 28% 78%, rgba(255,255,255,.4), transparent),
    radial-gradient(1px 1px at 88% 58%, rgba(255,255,255,.3), transparent),
    radial-gradient(1.5px 1.5px at 42% 38%, rgba(255,255,255,.3), transparent),
    radial-gradient(1px 1px at 15% 52%, rgba(255,255,255,.35), transparent),
    radial-gradient(1px 1px at 68% 88%, rgba(255,255,255,.3), transparent);
}
:root[data-mode="night"] #app::before{ mix-blend-mode:overlay; opacity:.05; }
:root[data-mode="night"] #app::after{ opacity:1; }
.shell-body{
  display:flex;
  flex:1;
  min-height:0;
  position:relative;
  z-index:1;
}
.main-view{
  flex:1;
  min-width:0;
  padding:var(--space-5) var(--space-4) 96px;
  position:relative;
}
@media (min-width:900px){
  .main-view{padding:var(--space-8) var(--space-8) var(--space-10);}
  .shell-body{flex-direction:row-reverse;}
}
.page{display:none;}
.page.active{display:block;animation:fadein .32s cubic-bezier(.16,1,.3,1);}
.page.leaving{
  display:block;position:absolute;inset:0;
  animation:pagefadeout .22s cubic-bezier(.4,0,1,1) forwards;
  pointer-events:none;
}
@keyframes fadein{from{opacity:0;transform:translateY(8px) scale(.99);}to{opacity:1;transform:translateY(0) scale(1);}}
@keyframes pagefadeout{from{opacity:1;transform:translateY(0) scale(1);}to{opacity:0;transform:translateY(-8px) scale(.99);}}

/* ===== Top bar ===== */
.topbar{
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:var(--space-4) var(--space-4) 0;
}
.eyebrow{
  font-size:var(--fs-caption);
  color:var(--ink-soft);
  display:flex;
  gap:8px;
  align-items:center;
}
.icon-btn{
  width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:var(--card);box-shadow:var(--shadow-card);
  color:var(--ink);
}
.icon-btn svg{width:19px;height:19px;}

/* ===== Bottom nav (mobile) ===== */
.bottom-nav{
  position:fixed;bottom:0;left:0;right:0;
  max-width:1180px;margin:0 auto;
  display:flex;
  padding:6px 4px calc(6px + env(safe-area-inset-bottom));
  z-index:40;
  /* was var(--card) — a translucent WHITE tint (4.5% opacity), meant for a
     card floating over content. Against the black page it read as almost
     nothing, so the bar had no visible surface and whatever scrolled
     underneath showed straight through and mixed with its own labels.
     This mirrors shared.css's nav.top-nav.scrolled instead: a semi-opaque
     BLACK + blur, which is what actually reads as a solid frosted bar on a
     black page. */
  background:rgba(10,10,10,.94);
  -webkit-backdrop-filter:blur(18px);
  backdrop-filter:blur(18px);
  -webkit-backdrop-filter:blur(18px);
  border-top:1px solid var(--line);
  /* exception: anchored to the bottom edge, so the shadow has to rise
     upward into the content above it — --shadow-float casts downward and
     would land on the wrong side of the bar. */
  box-shadow:0 -8px 24px -20px rgba(0,0,0,.4);
}
.nav-btn{
  flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:var(--space-2) var(--space-1);border-radius:10px;color:var(--ink-soft);font-size:var(--fs-caption);
  position:relative;transition:color .25s ease;
}
/* Nav icons: plain inline line-art SVGs (currentColor), recoloring for
   --ink-soft normally and --gold when .active automatically, in both
   day and night mode, with no separate icon files to manage. */
.nav-icon{position:relative;z-index:1;display:inline-block;transition:transform .25s cubic-bezier(.34,1.56,.64,1);}
.nav-icon-svg{width:22px;height:22px;display:inline-flex;color:currentColor;}
.nav-icon-svg svg{width:100%;height:100%;display:block;}
.nav-btn span{position:relative;z-index:1;}
/* the pill/circle behind the active nav icon was removed — it read as a
   stray green/yellow blob rather than an intentional highlight, and the
   color change + breathing icon animation already mark the active tab
   clearly on their own. */
.nav-btn.active{color:var(--gold);}
/* .nav-btn.active::before rule removed along with .nav-btn::before above */
@keyframes navIconBreathe{
  0%,100%{transform:translateY(-1px) scale(1);}
  50%{transform:translateY(-1px) scale(1.08);}
}
.nav-btn.active .nav-icon{animation:navIconBreathe 3.2s ease-in-out infinite;}
@media (prefers-reduced-motion: reduce){
  .nav-btn.active .nav-icon{animation:none;}
}
@media (max-width:370px){
  .nav-btn{font-size:var(--fs-micro);padding:var(--space-2) 0;}
  .nav-icon-svg{width:19px;height:19px;}
}
@media (min-width:900px){
  .bottom-nav{display:none;}
}
/* "بیشتر" — a real bottom sheet, App Store-style: slides up from the
   bottom edge over a dim overlay, has a drag handle, and can be dragged
   back down (or tapped outside / handle-dragged) to dismiss — instead of
   the small popover row this used to be. */
.more-sheet-overlay{
  position:fixed;inset:0;background:rgba(20,16,14,0);z-index:65;
  display:none;transition:background .25s ease;
}
.more-sheet-overlay.open{display:block;background:rgba(20,16,14,.45);}
.more-sheet{
  position:fixed;left:0;right:0;bottom:0;z-index:66;
  max-width:1180px;margin:0 auto;
  /* same swap as .bottom-nav: semi-opaque black instead of the near-invisible
     translucent-white --card, so the sheet actually reads as a solid surface. */
  background:rgba(10,10,10,.86);border-radius:22px 22px 0 0;
  backdrop-filter:blur(22px);
  -webkit-backdrop-filter:blur(22px);
  /* exception: bottom sheet rising from the bottom edge needs its shadow
     pointing up, same reasoning as .bottom-nav's exception above. */
  box-shadow:0 -12px 32px -12px rgba(0,0,0,.4);
  padding:8px 10px calc(14px + env(safe-area-inset-bottom));
  transform:translateY(100%);
  transition:transform .32s cubic-bezier(.32,.9,.36,1);
  touch-action:none;
}
.more-sheet.open{transform:translateY(0);}
.more-sheet.dragging{transition:none;}
.more-sheet-handle{
  width:36px;height:4px;border-radius:3px;background:var(--line);
  margin:var(--space-1) auto var(--space-4);
}
.more-sheet-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:6px;
}
.more-sheet-item{
  display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:var(--space-4) var(--space-1);border-radius:16px;color:var(--ink);font-size:var(--fs-caption);font-weight:600;
}
.more-sheet-item:active{background:var(--paper-soft);}
.more-sheet-item.active{color:var(--gold);}
.more-sheet-item-icon{
  width:44px;height:44px;border-radius:14px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  background:var(--paper-soft);color:var(--ink-soft);
}
.more-sheet-item.active .more-sheet-item-icon{background:var(--gold-soft);color:var(--gold);}
.more-sheet-item-icon svg{width:21px;height:21px;}
@media (min-width:900px){
  .more-sheet-overlay,.more-sheet{display:none !important;}
}

/* ===== Sidebar (desktop) ===== */
.sidebar{
  display:none;
}
@media (min-width:900px){
  .sidebar{
    display:flex;flex-direction:column;
    width:220px;flex-shrink:0;
    padding:var(--space-8) var(--space-5);
    gap:6px;
    border-inline-end:1px solid var(--glass-border);
    background:var(--card);box-shadow:var(--shadow-card);
    /* stays in place while .main-view scrolls, and scrolls internally on its
       own if the nav list is ever taller than the viewport (short/16:9
       laptop screens) instead of disappearing off-screen with the page */
    position:sticky;top:0;
    height:100vh;height:100dvh;
    overflow-y:auto;
  }
  .sidebar .brand{
    font-size:var(--fs-h1);font-weight:800;margin-bottom:var(--space-6);
    display:flex;align-items:center;justify-content:center;gap:10px;
  }
  /* two logo files, day/night tone — same asset-swap convention as the lock
     screen (assets/logo-dark.png on light paper, assets/logo-light.png on the
     dark night theme). Only one is shown at a time, picked by data-mode. */
  .brand-logo{height:42px;width:auto;display:block;}
  .brand-logo-night{display:none;}
  :root[data-mode="night"] .brand-logo-day{display:none;}
  :root[data-mode="night"] .brand-logo-night{display:block;}
  .sidebar .nav-btn{
    flex-direction:row;justify-content:flex-start;
    padding:var(--space-3) var(--space-3);font-size:var(--fs-body-lg);gap:10px;
  }
  .sidebar .nav-btn svg,.sidebar .nav-btn .nav-icon-svg{width:19px;height:19px;}
}

/* ===== Cards ===== */
.card{
  background:var(--card);
  border-radius:var(--radius);
  border:1px solid var(--glass-border);
  box-shadow:var(--shadow-card), inset 0 1px 0 rgba(255,255,255,.04);
  padding:var(--space-5);
  margin-bottom:var(--space-3); /* keeps consecutive cards apart when nothing (like a
    .section-title) sits between them — e.g. settings' profile/account cards used to
    touch edge-to-edge with zero gap. A following .section-title already carries its
    own top margin, and adjoining sibling margins collapse to the larger of the two,
    so this never doubles up the spacing where a title is already providing it. */
}
.section-title{
  font-size:var(--fs-body);font-weight:800;margin:var(--space-6) 0 var(--space-3);
  display:flex;align-items:center;justify-content:space-between;
  color:var(--ink);
}
.section-title .hint{font-size:var(--fs-micro);color:var(--ink-soft);font-weight:500;}
/* Section-title icon badges — opt-in via .sti-wrap/.sti, used only where the
   markup adds them (currently Settings). Wrapped as a single flex child so
   .section-title's existing space-between layout (title vs. .hint) is
   unaffected everywhere else it's used across the app. */
.sti-wrap{display:inline-flex;align-items:center;gap:8px;}
.sti{
  width:22px;height:22px;border-radius:50%;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--card);border:1px solid var(--line);
}
.sti svg{width:12px;height:12px;color:var(--ink-soft);}

/* ===== Sunrise arc (signature element) =====
   Photo hero. Two files, day/night tone — same asset-swap convention as
   .brand-logo / .goal-card::before (data-mode on <html> picks the layer).
   Drop the real photos in as:
     assets/dashboard-hero-day.jpg
     assets/dashboard-hero-night.jpg
   The dark linear-gradient on top is the readability layer: darkest on the
   text side (right, since layout is RTL), fading to transparent on the
   figure side (left) so the person in the photo stays clean. If the actual
   photo has its subject on the opposite side, either swap this gradient's
   direction to "to right" or mirror the image itself with
   transform:scaleX(-1) on .horizon-wrap (don't edit the asset file) —
   whichever the real photo needs. background-position is a placeholder
   (left center / right center) and MUST be checked against the real photo's
   aspect ratio so the figure isn't cropped oddly. */
.horizon-wrap{
  position:relative;
  border-radius:20px;
  padding:var(--space-4) var(--space-5);
  min-height:190px;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:14px;
  background:
    linear-gradient(to left, rgba(20,16,14,.6) 0%, rgba(20,16,14,.32) 45%, rgba(20,16,14,0) 72%),
    url('assets/dashboard-hero-day.jpg') var(--hero-focus, center top) / cover no-repeat;
  overflow:hidden;
  border:1px solid var(--glass-border-strong);
  box-shadow:var(--shadow-card), inset 0 1px 0 rgba(255,255,255,.10);
}
:root[data-mode="night"] .horizon-wrap{
  background:
    linear-gradient(to left, rgba(5,4,9,.66) 0%, rgba(5,4,9,.36) 45%, rgba(5,4,9,0) 72%),
    url('assets/dashboard-hero-night.jpg') var(--hero-focus, center top) / cover no-repeat;
}
/* WebP variants of the two rules above — [data-webp="1"] is set synchronously at
   the top of <body> (see inline script right after </head>), so these are already
   correct on first paint, not swapped in a frame later. Falls back to the plain
   .jpg rules above on any browser that doesn't support WebP. */
:root[data-webp="1"] .horizon-wrap{
  background:
    linear-gradient(to left, rgba(20,16,14,.6) 0%, rgba(20,16,14,.32) 45%, rgba(20,16,14,0) 72%),
    url('assets/dashboard-hero-day.webp') var(--hero-focus, center top) / cover no-repeat;
}
:root[data-mode="night"][data-webp="1"] .horizon-wrap{
  background:
    linear-gradient(to left, rgba(5,4,9,.66) 0%, rgba(5,4,9,.36) 45%, rgba(5,4,9,0) 72%),
    url('assets/dashboard-hero-night.webp') var(--hero-focus, center top) / cover no-repeat;
}
@media (max-width:899px){
  .horizon-wrap{min-height:160px;}
}
/* compact variant of .horizon-wrap for page headers that don't need the
   greeting/arc layout — just a period-aware photo behind a title+pills */
.horizon-wrap.page-header-photo{
  min-height:0;padding:var(--space-4) var(--space-4) var(--space-3);align-items:stretch;
}
.horizon-wrap.page-header-photo .pill{
  background:rgba(255,255,255,.14);color:#fff;border:1px solid rgba(255,255,255,.22);
}
.horizon-wrap.page-header-photo .pill.active{
  background:var(--gold);color:var(--paper);border-color:var(--gold);
}
/* period-aware halo — a soft glow whose color drifts with the time of day
   (set via --halo, updated in JS by applyPeriod()); this is the "signature"
   piece of the lock-screen identity carried into the dashboard */
.horizon-wrap::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(58% 60% at 84% -6%, var(--halo) 0%, transparent 68%);
  opacity:.4;
  transition:background 1.2s ease, opacity 1.2s ease;
}
:root[data-mode="night"] .horizon-wrap::before{opacity:.5;}

/* compact row layout: text block (eyebrow+greeting+sub+meta) on one side,
   the shrunk sunrise arc on the other. Both children need z-index:1 to sit
   above the ::before halo layer. */
.horizon-wrap .horizon-text{position:relative;z-index:1;min-width:0;color:#fff;}
.horizon-wrap .eyebrow{color:rgba(255,255,255,.78);}
.horizon-wrap .greeting{font-size:var(--fs-h2);font-weight:800;margin-top:var(--space-1);color:#fff;}
.horizon-wrap .greeting-sub{font-size:var(--fs-caption);color:rgba(255,255,255,.82);margin-top:var(--space-1);}
.horizon-wrap .horizon-meta{display:flex;align-items:center;gap:8px;margin-top:var(--space-2);}

.momentum-badge{
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--fs-micro);font-weight:700;color:var(--ink-soft);
  background:var(--card);padding:var(--space-1) var(--space-3);border-radius:20px;
}
/* reflection button becomes a small round icon-btn (icon only, no label text —
   see the JS in renderDashboard() that now sets innerHTML without the trailing
   text), matching the .icon-btn used on the calendar page but sized down and
   given a translucent fill so it reads against a busy photo instead of paper. */
.reflection-entry-btn{
  display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
  width:32px;height:32px;border-radius:50%;
  color:#fff;background:rgba(255,255,255,.16);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
}
.reflection-entry-btn svg{width:16px;height:16px;}
.reflection-entry-btn.done{color:var(--sage);}

.growth-card{text-align:center;position:relative;overflow:hidden;}
/* "growth" gets its own backdrop (a flat/gradient illustrated tree, not a period-tied
   color — this card is about accomplishment, not time of day). Drop the two files below
   into an "assets" folder next to this file, using exactly these names — same convention
   as the LOGIN_PERIODS background set further down. The radial-gradient sage wash stays
   underneath as a fallback tint so the card still reads fine if an image is missing. */
.growth-card::before{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:0;
  background:
    url('assets/growth-tree-day.jpg') center/cover no-repeat,
    radial-gradient(65% 75% at 50% 108%, var(--sage) 0%, transparent 66%);
  opacity:.16;
}
:root[data-mode="night"] .growth-card::before{
  background:
    url('assets/growth-tree-night.jpg') center/cover no-repeat,
    radial-gradient(65% 75% at 50% 108%, var(--sage) 0%, transparent 66%);
}
:root[data-webp="1"] .growth-card::before{
  background:
    url('assets/growth-tree-day.webp') center/cover no-repeat,
    radial-gradient(65% 75% at 50% 108%, var(--sage) 0%, transparent 66%);
}
:root[data-mode="night"][data-webp="1"] .growth-card::before{
  background:
    url('assets/growth-tree-night.webp') center/cover no-repeat,
    radial-gradient(65% 75% at 50% 108%, var(--sage) 0%, transparent 66%);
}
.growth-tree-wrap,.growth-caption{position:relative;z-index:1;}
.growth-tree-wrap{display:flex;justify-content:center;align-items:flex-end;height:88px;}
.growth-tree-wrap img.growth-tree-photo{
  height:100%;width:auto;max-width:100%;object-fit:contain;border-radius:10px;
  animation:growthPop .5s cubic-bezier(.34,1.56,.64,1);
}
@keyframes growthPop{0%{transform:scale(.7);opacity:0;}100%{transform:scale(1);opacity:1;}}
.growth-caption{font-size:var(--fs-micro);color:var(--ink-soft);margin-top:var(--space-2);}

/* "X days to goal" card — sits between the welcome header and the quote card, only
   when a personal goal is set (see DB.settings.goal). Uses the real photo assets:
     assets/goal-mountain-day.jpg
     assets/goal-mountain-night.jpg
   The card is much wider than it is tall, so `cover` crops the tall middle of the
   photo away; anchoring to the bottom keeps the warm foreground/mountain-base band
   visible instead of just empty sky. */
.goal-card{
  position:relative;overflow:hidden;text-align:center;
  padding:var(--space-6) var(--space-6);margin:var(--space-4) 0;
  color:#fff;
  border-radius:var(--radius);
  border:1px solid var(--glass-border-strong);
  box-shadow:var(--shadow-card), inset 0 1px 0 rgba(255,255,255,.10);
}
.goal-card::before{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:0;
  background-image:
    linear-gradient(180deg, rgba(20,16,14,.25) 0%, rgba(16,13,11,.62) 100%),
    url('assets/goal-mountain-day.jpg');
  background-repeat:no-repeat, no-repeat;
  background-position:center, center bottom;
  background-size:100% 100%, cover;
}
:root[data-mode="night"] .goal-card::before{
  background-image:
    linear-gradient(180deg, rgba(8,6,12,.3) 0%, rgba(5,4,9,.66) 100%),
    url('assets/goal-mountain-night.jpg');
  background-repeat:no-repeat, no-repeat;
  background-position:center, center bottom;
  background-size:100% 100%, cover;
}
:root[data-webp="1"] .goal-card::before{
  background-image:
    linear-gradient(180deg, rgba(20,16,14,.25) 0%, rgba(16,13,11,.62) 100%),
    url('assets/goal-mountain-day.webp');
  background-repeat:no-repeat, no-repeat;
  background-position:center, center bottom;
  background-size:100% 100%, cover;
}
:root[data-mode="night"][data-webp="1"] .goal-card::before{
  background-image:
    linear-gradient(180deg, rgba(8,6,12,.3) 0%, rgba(5,4,9,.66) 100%),
    url('assets/goal-mountain-night.webp');
  background-repeat:no-repeat, no-repeat;
  background-position:center, center bottom;
  background-size:100% 100%, cover;
}
.goal-card-inner{position:relative;z-index:1;}
.goal-card .goal-days{font-size:var(--fs-display);font-weight:800;}
.goal-card .goal-title{font-size:var(--fs-caption);font-weight:600;opacity:.85;margin-top:var(--space-1);}

.time-capsule-card{
  margin-top:var(--space-3);border-radius:var(--radius);padding:var(--space-6);
  border:1px solid var(--glass-border-strong);
  box-shadow:var(--shadow-card), inset 0 1px 0 rgba(255,255,255,.10);
  background:linear-gradient(135deg, var(--dusk) 0%, #2a2a2a 100%);color:var(--ink);
  text-align:center;
}
.time-capsule-card .tc-month{font-size:var(--fs-caption);opacity:.75;font-weight:700;letter-spacing:.03em;}
.time-capsule-card .tc-headline{font-size:var(--fs-body-lg);font-weight:800;margin-top:var(--space-2);line-height:1.7;}
.time-capsule-card .tc-stats{display:flex;justify-content:center;gap:18px;margin-top:var(--space-3);}
.time-capsule-card .tc-stat-num{font-size:var(--fs-h2);font-weight:800;}
.time-capsule-card .tc-stat-label{font-size:var(--fs-micro);opacity:.7;margin-top:var(--space-1);}
.arc-box{position:relative;display:flex;justify-content:center;margin:0;}
.arc-box svg{width:100%;max-width:380px;height:auto;}
.arc-pct{
  position:absolute;bottom:6px;left:0;right:0;
  text-align:center;font-size:var(--fs-display);font-weight:800;color:var(--ink);
}
.arc-pct span{font-size:var(--fs-caption);font-weight:600;color:var(--ink-soft);display:block;margin-top:var(--space-1);}
.arc-box.celebrate #arcFill{
  animation: arcGlowPulse 1.8s ease;
}
.arc-box.celebrate #arcSun{
  animation: arcSunPulse 1.8s ease;
}
@keyframes arcGlowPulse{
  0%{ filter:none; }
  30%{ filter:drop-shadow(0 0 10px var(--halo, var(--gold))); }
  100%{ filter:none; }
}
@keyframes arcSunPulse{
  0%{ r:9; }
  30%{ r:13; fill:var(--gold); }
  100%{ r:9; }
}
/* compact version sitting inside .horizon-wrap: shrunk from max-width:380px
   down to ~80px per the brief, positioned beside the text block instead of
   stacked under it. Only the number is legible at this size, so the
   "پیشرفت امروز" label is hidden here (still used at full size anywhere
   else .arc-box/.arc-pct might appear later). Ring stroke colors
   (var(--line)/var(--halo)/var(--ink) on the sun dot) were left as-is —
   worth a contrast check once the real photo is in place. */
.horizon-wrap .arc-box{z-index:1;flex-shrink:0;width:80px;}
.horizon-wrap .arc-box svg{max-width:80px;}
.horizon-wrap .arc-pct{bottom:auto;top:50%;transform:translateY(-50%);}
.horizon-wrap .arc-pct #arcPctNum{font-size:var(--fs-body-lg);font-weight:800;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.4);}
.horizon-wrap .arc-pct #arcPctLabel{display:none;}

.quote-attribution{display:flex;align-items:center;gap:8px;margin-top:var(--space-3);position:relative;z-index:1;}
.quote-avatar{
  width:32px;height:32px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
}
.quote-avatar img{width:100%;height:100%;object-fit:cover;display:block;}
.quote-author{font-size:var(--fs-micro);font-weight:700;color:var(--ink-soft);}

/* The base .quote-card rule below had lost its selector at some point (its
   declarations — including the border-radius that rounds the card's
   corners — were sitting orphaned outside any rule and so never applied).
   Restoring the selector here fixes the corners and the card's background/
   shadow/accent-bar in one go. */
.quote-card{
  position:relative;background:var(--card);border-radius:var(--radius);
  padding:var(--space-4) var(--space-5);margin:var(--space-4) 0;box-shadow:var(--shadow-card);
  border-inline-start:3px solid var(--gold);
  overflow:hidden;
}
/* period-aware wash — same --halo the welcome header uses, much fainter here
   since this card is mostly text */
.quote-card::before{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:0;
  background:radial-gradient(75% 110% at 100% 0%, var(--halo) 0%, transparent 62%);
  opacity:.13;
  transition:background 1.2s ease;
}
.quote-card .quote-mark,.quote-card .quote-text{position:relative;z-index:1;}
.quote-card .quote-mark{width:20px;height:20px;display:block;margin-bottom:var(--space-2);}
.quote-text{
  font-size:var(--fs-body);font-weight:600;line-height:1.9;color:var(--ink);
  transition:opacity .35s ease;
}

/* ===== Mini timeline (dashboard) ===== */
.mt-row{display:flex;align-items:center;gap:10px;padding:var(--space-2) var(--space-2);border-radius:10px;}
.mt-row.now{background:rgba(242,242,240,.13);}
:root[data-mode="night"] .mt-row.now{background:rgba(242,242,240,.14);}
.mt-row .mt-time{width:44px;font-size:var(--fs-caption);color:var(--ink-soft);}
.mt-row.now .mt-time{color:var(--gold);font-weight:700;}
.mt-now-badge{
  font-size:var(--fs-micro);font-weight:700;color:var(--gold);
  background:rgba(242,242,240,.16);border-radius:20px;padding:var(--space-1) var(--space-2);margin-inline-start:6px;
}
.mt-play-btn{
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
  width:26px;height:26px;border-radius:50%;border:1.5px solid var(--line);
  color:var(--ink-soft);background:transparent;
}
.mt-row.now .mt-play-btn{border-color:var(--gold);color:var(--gold);}
.mt-play-btn svg{width:11px;height:11px;}

/* ===== Task list ===== */
.task-row{
  display:flex;align-items:flex-start;gap:10px;
  padding:var(--space-3) var(--space-1);border-bottom:1px solid var(--line);
  position:relative;
  touch-action:pan-y;
}
.task-row.pinned{background:linear-gradient(90deg, var(--gold-soft) 0%, transparent 12%);}
.task-row:last-child{border-bottom:none;}
.task-side-btn{
  width:34px;height:34px;flex-shrink:0;margin-top:0;color:var(--ink-soft);
  display:flex;align-items:center;justify-content:center;opacity:.65;transition:opacity .2s,color .2s,transform .2s cubic-bezier(.34,1.56,.64,1);
}
.task-side-btn svg{width:22px;height:22px;}
.task-side-btn[data-action="pin"] svg{stroke-width:1.5;}
.task-side-btn:hover{opacity:1;}
.task-row.pinned .task-side-btn[data-action="pin"]{
  color:var(--gold);opacity:1;transform:scale(1.12);
  filter:drop-shadow(0 0 4px rgba(242,242,240,.5));
}
.task-check{
  width:22px;height:22px;border-radius:50%;
  border:2px solid var(--line);flex-shrink:0;margin-top:var(--space-1);
  display:flex;align-items:center;justify-content:center;
  transition:background .2s,border-color .2s,transform .3s cubic-bezier(.34,1.56,.64,1);
}
.task-check svg{width:12px;height:12px;opacity:0;transition:opacity .15s;}
.task-check svg path{stroke-dasharray:20;stroke-dashoffset:20;transition:stroke-dashoffset .25s ease .05s;}
.task-row.done .task-check{background:var(--sage);border-color:var(--sage);}
.task-row.done .task-check svg{opacity:1;stroke:#fff;}
.task-row.done .task-check svg path{stroke-dashoffset:0;}
.task-row.just-done .task-check{animation:taskCheckPop .4s cubic-bezier(.34,1.56,.64,1);}
@keyframes taskCheckPop{0%{transform:scale(1);}45%{transform:scale(1.28);}100%{transform:scale(1);}}
.task-row.just-done{animation:taskRowFlash .7s ease;}
@keyframes taskRowFlash{0%{background:rgba(124,143,110,0);}25%{background:rgba(124,143,110,.14);}100%{background:rgba(124,143,110,0);}}
.task-row.done .task-title{text-decoration:line-through;color:var(--ink-soft);transition:color .3s;}
.task-main{flex:1;min-width:0;}
.task-title{font-size:var(--fs-body);font-weight:600;}
/* exception: this icon sits inline before title text that can wrap onto
   multiple lines, not a single-line row — flex+gap would misalign it against
   wrapped lines, so it keeps a manual margin+vertical-align instead of the
   .icon-with-text pattern below. */
.task-meta{display:flex;gap:6px;margin-top:var(--space-1);flex-wrap:wrap;}
/* step 6: icon+text rows use gap instead of manual margin-left, so spacing
   never drifts if the font or icon changes. */
.icon-with-text{display:inline-flex;align-items:center;gap:var(--space-2);}
.icon{display:inline-block;vertical-align:middle;}
.chip{
  display:inline-flex;align-items:center;gap:var(--space-2);
  font-size:var(--fs-micro);padding:var(--space-1) var(--space-2);border-radius:20px;
  background:var(--paper-soft);color:var(--ink-soft);font-weight:600;
}
.chip.overdue{background:var(--ember);color:#fff;}
.chip.tag-chip{background:transparent;border:1px solid var(--line);color:var(--ink-soft);}
.dot{width:8px;height:8px;border-radius:50%;display:inline-block;}
/* urgent priority: a colored side-bar instead of a text chip, so it reads
   at a glance without adding to the chip clutter */
.task-row.urgent{border-inline-start:3px solid var(--ember);padding-inline-start:9px;margin-inline-start:-13px;}
/* category icon with dot fallback baked in: the dot is always rendered
   underneath, the icon just visually replaces it once/if it loads —
   so a 404 on the icon file never leaves an empty gap */
/* secondary meta (repeat/subtasks/tags) collapsed by default */
.task-expand-btn{
  font-size:var(--fs-caption);font-weight:800;color:var(--ink-soft);background:var(--paper-soft);
  width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  line-height:1;padding:0;
}
.task-meta-extra{margin-top:var(--space-1);}
.task-swipe-bg{
  position:absolute;inset:0;border-radius:10px;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 var(--space-4);font-size:var(--fs-caption);font-weight:700;color:#fff;
  opacity:0;pointer-events:none;
}

/* ===== Buttons ===== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  padding:var(--space-3) var(--space-5);border-radius:12px;font-weight:700;font-size:var(--fs-body);
  background:var(--ink);color:var(--paper);
}
.btn.gold{background:var(--gold);color:var(--paper);}
.btn.ghost{background:var(--paper-soft);color:var(--ink);}
.btn.sm{padding:var(--space-2) var(--space-3);font-size:var(--fs-caption);border-radius:9px;}
.btn.block{width:100%;}
.btn.danger{background:var(--ember);color:#fff;}
.btn-icon{width:16px;height:16px;flex-shrink:0;}
.btn-icon-img{width:18px;height:18px;object-fit:contain;}

/* ===== FAB ===== */
.fab{
  position:fixed;bottom:78px;left:18px;
  width:56px;height:56px;border-radius:50%;
  background:var(--gold);color:var(--paper);
  display:flex;align-items:center;justify-content:center;
  /* exception: this is a colored gold glow tied to the CTA's brand color,
     not a neutral elevation shadow, so it stays custom instead of
     --shadow-float. */
  box-shadow:0 10px 24px -8px rgba(242,242,240,.7);
  z-index:41;
}
.fab svg{width:24px;height:24px;}
@media (min-width:900px){.fab{bottom:32px;left:32px;}}

.search-fab{
  position:fixed;top:calc(14px + env(safe-area-inset-top));left:16px;z-index:50;
  width:38px;height:38px;border-radius:50%;background:var(--card);box-shadow:var(--shadow-float);
  display:flex;align-items:center;justify-content:center;color:var(--ink-soft);
}
.search-fab svg{width:18px;height:18px;}
@media (min-width:900px){.search-fab{left:auto;right:24px;top:24px;}}

.search-screen{
  position:fixed;inset:0;z-index:95;background:var(--paper);display:none;flex-direction:column;
}
.search-screen.open{display:flex;}
.search-header{
  display:flex;align-items:center;gap:10px;
  padding:calc(14px + env(safe-area-inset-top)) 16px 14px;border-bottom:1px solid var(--line);
}
.search-header input{flex:1;border:none;background:transparent;font-size:var(--fs-body-lg);color:var(--ink);outline:none;}
.search-icon{width:18px;height:18px;color:var(--ink-soft);flex-shrink:0;}
.search-results{flex:1;overflow-y:auto;padding:var(--space-2) var(--space-4);}
.search-result-group{margin-top:var(--space-4);}
.search-result-group h4{font-size:var(--fs-caption);color:var(--ink-soft);margin-bottom:var(--space-2);}
.search-result-item{padding:var(--space-3) var(--space-1);border-bottom:1px solid var(--line);cursor:pointer;}
.search-result-item .srt-title{font-size:var(--fs-caption);font-weight:600;}
.search-result-item .srt-sub{font-size:var(--fs-micro);color:var(--ink-soft);margin-top:var(--space-1);}

/* ===== Modal ===== */
.modal-overlay{
  position:fixed;inset:0;background:rgba(20,15,25,.45);
  display:none;align-items:flex-end;justify-content:center;z-index:60;
  backdrop-filter: blur(2px);
}
.modal-overlay.open{display:flex;}
.modal{
  background:var(--card);width:100%;max-width:480px;
  border-radius:20px 20px 0 0;padding:20px 18px calc(20px + env(safe-area-inset-bottom));
  max-height:88vh;max-height:88dvh;overflow-y:auto;
  animation:slideup .25s var(--ease);
}
@media (min-width:900px){
  .modal-overlay{align-items:center;}
  .modal{border-radius:18px;}
}
@keyframes slideup{from{transform:translateY(30px);opacity:0;}to{transform:translateY(0);opacity:1;}}
@media (prefers-reduced-motion: reduce){
  .modal{animation:none;}
}
.modal h3{font-size:var(--fs-h2);margin-bottom:var(--space-4);}
.field{margin-bottom:var(--space-3);}
.subtask-item{display:flex;align-items:center;gap:8px;padding:var(--space-2) 0;}
.subtask-item input[type="checkbox"]{width:auto;flex-shrink:0;}
.subtask-item span{flex:1;font-size:var(--fs-caption);}
.subtask-item span.done{text-decoration:line-through;color:var(--ink-soft);}
.subtask-item button{color:var(--ink-soft);flex-shrink:0;padding:var(--space-1) var(--space-2);}
.subtask-item button svg{width:14px;height:14px;}
.field label{font-size:var(--fs-caption);color:var(--ink-soft);font-weight:700;display:block;margin-bottom:var(--space-2);}
.field input[type="text"],.field input[type="date"],.field input[type="time"],.field input[type="number"],.field textarea,.field select{
  width:100%;padding:var(--space-3) var(--space-3);border-radius:10px;border:1.5px solid var(--line);
  background:var(--paper-soft);color:var(--ink);font-size:var(--fs-body);
}
.field textarea{resize:vertical;min-height:70px;}
/* the reflection screen sits on the shared dark .onboarding-screen backdrop
   (not a light paper page like every other .field user), so its inputs get
   a glass treatment instead of the default light paper-soft fill — this is
   the one .field context where something actually sits behind them to blur */
#reflectionScreen .field label{color:rgba(255,255,255,.65);}
#reflectionScreen .field textarea{
  background:rgba(255,255,255,.10);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border:1.5px solid rgba(255,255,255,.22);
  color:#fff;
}
#reflectionScreen .field textarea::placeholder{color:rgba(255,255,255,.4);}
#reflectionScreen .field textarea:focus{
  outline:none;border-color:var(--gold);background:rgba(255,255,255,.16);
}

/* ===== Jalali (Shamsi) date picker — replaces native <input type="date">, which is
   always Gregorian regardless of locale. The native input is kept in the DOM as the
   hidden source of truth (same YYYY-MM-DD dateKey format everything else expects);
   this button just shows/edits it in Jalali via a small calendar popover. ===== */
.jalali-date-btn{
  width:100%;padding:var(--space-3) var(--space-3);border-radius:10px;border:1.5px solid var(--line);
  background:var(--paper-soft);color:var(--ink);font-size:var(--fs-body);
  display:flex;align-items:center;justify-content:space-between;gap:8px;
}
.jalali-date-btn .jdb-placeholder{color:var(--ink-soft);}
.jalali-date-btn svg{width:16px;height:16px;color:var(--ink-soft);flex-shrink:0;}
.jalali-picker-modal{max-width:320px;}
.jalali-picker-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-2);}
.jalali-picker-head .icon-btn{width:32px;height:32px;}
.jalali-picker-head .icon-btn svg{width:15px;height:15px;}
.jalali-picker-title{font-size:var(--fs-body);font-weight:800;}
.jalali-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;font-size:var(--fs-micro);color:var(--ink-soft);margin-bottom:var(--space-1);}
.jalali-picker-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;}
.jp-cell{
  aspect-ratio:1/1;display:flex;align-items:center;justify-content:center;
  border-radius:50%;font-size:var(--fs-micro);color:var(--ink);
  max-height:32px;
}
.jp-cell.empty{visibility:hidden;}
.jp-cell.today{color:var(--ink-soft);font-weight:800;}
.jp-cell.selected{background:var(--gold);color:var(--paper);font-weight:800;}
.pill-group{display:flex;gap:8px;flex-wrap:wrap;}
.pill{
  padding:var(--space-2) var(--space-3);border-radius:20px;font-size:var(--fs-caption);font-weight:700;
  background:var(--paper-soft);color:var(--ink-soft);border:1.5px solid transparent;
}
.pill.active{background:var(--ink);color:var(--paper);}
.mood-pill,.mood-pill-editor,.energy-pill-editor{padding:var(--space-2);width:36px;height:36px;display:flex;align-items:center;justify-content:center;}
.mood-pill svg,.mood-pill-editor svg,.energy-pill-editor svg{width:19px;height:19px;}
.modal-actions{display:flex;gap:10px;margin-top:var(--space-4);}
.modal-actions .btn{flex:1;}
.recap-canvas-wrap{width:100%;border-radius:16px;overflow:hidden;box-shadow:var(--shadow-card);}
.recap-canvas-wrap canvas{width:100%;height:auto;display:block;}

/* ===== Toast ===== */
.toast{
  position:fixed;bottom:150px;left:50%;transform:translateX(-50%) translateY(20px);
  background:var(--ink);color:var(--paper);padding:var(--space-3) var(--space-5);border-radius:30px;
  font-size:var(--fs-caption);font-weight:600;opacity:0;pointer-events:none;transition:.3s;z-index:80;
  white-space:nowrap;
  display:flex;align-items:center;gap:8px;
}
.toast svg{width:16px;height:16px;flex-shrink:0;}
/* error variant — same pill, ember tint instead of plain ink, so a failure
   reads differently from a confirmation at a glance, not just by wording */
.toast.error{background:var(--ember);}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0);}
@media (min-width:900px){.toast{bottom:30px;}}

.undo-toast{
  position:fixed;bottom:150px;left:50%;transform:translateX(-50%) translateY(20px);
  background:var(--ink);color:var(--paper);padding:var(--space-3) var(--space-2) var(--space-3) var(--space-5);border-radius:30px;
  font-size:var(--fs-caption);font-weight:600;opacity:0;pointer-events:none;transition:.3s;z-index:81;
  white-space:nowrap;display:flex;align-items:center;gap:10px;
}
.undo-toast.show{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto;}
.undo-toast button{
  background:var(--gold);color:var(--paper);padding:var(--space-2) var(--space-4);border-radius:20px;font-size:var(--fs-caption);font-weight:800;
}
@media (min-width:900px){.undo-toast{bottom:30px;}}

/* ===== Lock screen ===== */
#lock-screen{
  position:fixed;inset:0;background:var(--paper);z-index:100;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:26px;
  padding-top:calc(16vh + env(safe-area-inset-top));
  /* CHANGE: there was no bottom padding at all, so on shorter screens the last
     item in the column (the forgot-pin link) could end up pressed right against
     the very bottom edge with no breathing room. This guarantees a comfortable
     minimum gap below it regardless of device/safe-area. */
  padding-bottom:calc(28px + env(safe-area-inset-bottom));
  overflow:hidden;
  opacity:1;transition:opacity .2s ease;
}
/* two stacked layers so the background photo can crossfade instead of jump-cutting
   when the time-of-day bucket changes while the screen is open */
.lock-bg-layer{
  position:absolute;inset:0;z-index:0;
  background-size:cover;background-position:center;background-repeat:no-repeat;
  opacity:0;transform:scale(1.06);
  /* CHANGE 2: slight saturation/contrast lift so the (intentionally soft/pastel)
     source photos read a bit richer without leaving realistic/photographic territory */
  filter:saturate(1.15) contrast(1.05);
  transition:opacity .4s ease, transform .2s ease-out, filter .25s ease;
}
.lock-bg-layer.visible{opacity:1;}
/* flat, cheap fallback color so a missing/unloaded image never leaves a blank screen */
#lock-screen{background-color:var(--paper);}
/* CHANGE 1: no longer a flat full-screen tint (that was muddying the desktop photo's
   own built-in flat/cream text-safe zone on the left). Now a direction-aware gradient:
   dark only at the very top edge (behind the date) and bottom edge (behind the pin pad),
   fully transparent through the middle where the photo should read clean.
   applyLoginOverlay() below builds this gradient string per time-of-day period. */
.lock-overlay{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  transition:background .4s ease;
}
/* extra darken+blur layer that fades in only while the user is actively entering a PIN,
   to pull focus toward the pad — cheap opacity fade, no layout cost.
   Slightly reduced from .35 -> .3 since the new edge gradient above already adds some
   darkening at the bottom where the pad sits, so the two shouldn't stack too heavily. */
.lock-overlay-typing{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:rgba(6,4,10,.3);
  opacity:0;transition:opacity .25s ease;
}
#lock-screen.typing .lock-overlay-typing{opacity:1;}
#lock-screen.typing .lock-bg-layer{filter:blur(2px) saturate(1.15) contrast(1.05);}
/* everything that sits visually on top of the photo — but NOT the background
   layers/overlay themselves, which need to keep their own absolute positioning.
   .lock-recovery covers both #lockRecovery (forgot-pin question) and
   #lockSecSetup (first-time security-question setup) — neither had this, so
   the .typing dim/blur layer (z-index:1) was painting OVER their text instead
   of behind it, which is why the dim looked "missing" there and text could
   wash out against a bright wallpaper (e.g. the morning photo). */
.lock-date, .lock-center, #pinDots, #pinError, #pinPad, .lock-recovery{
  position:relative;z-index:2;
}

/* top-left day / date */
.lock-date{
  position:absolute;top:calc(30px + env(safe-area-inset-top));right:30px;
  text-align:center;color:#fff;
  opacity:0;transform:translateY(-12px);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1);
}
/* CHANGE 1 (redesigned per CHANGE 10 feedback, same rationale as .lock-center::before
   below): softer/larger/lower-opacity than the first pass so it never reads as a shape. */
.lock-date::before{
  content:'';
  position:absolute;inset:-32px -55px;
  background:radial-gradient(closest-side,
    rgba(8,6,14,.28) 0%,
    rgba(8,6,14,.14) 45%,
    rgba(8,6,14,0) 100%);
  filter:blur(24px);
  z-index:-1;
  pointer-events:none;
}
.lock-date.show{opacity:1;transform:translateY(0);}
.lock-date .lock-day{font-size:var(--fs-body);font-weight:700;letter-spacing:.02em;text-shadow:0 1px 4px rgba(0,0,0,.5);}
.lock-date .lock-daynum{font-size:var(--fs-caption);font-weight:500;opacity:.9;margin-top:var(--space-1);letter-spacing:.01em;text-shadow:0 1px 4px rgba(0,0,0,.5);}
/* tiny day-progress indicator: a dot sliding along a thin track to show where in
   the 24h day the current moment sits — decorative, no functional weight */
.lock-progress{position:relative;width:74px;height:2px;background:rgba(255,255,255,.25);border-radius:2px;margin:var(--space-2) auto 0 auto;}
.lock-progress-dot{position:absolute;top:50%;width:6px;height:6px;border-radius:50%;background:var(--gold);transform:translate(50%,-50%);transition:left .4s ease;}

/* centered logo + time-text + person-of-the-day block
   Layout intent: logo sits near the top (~1/5 of screen height), the short
   time-of-day line right under it (~3/10), then a visual gap, then the
   quote-of-the-day + portrait block roughly centered. Built with flexible
   gaps/margins instead of hard vh percentages, since fixed percentages break
   across the very different aspect ratios phones/laptops actually use — this
   gets the same proportions while staying safe on tall/short screens alike. */
.lock-center{
  display:flex;flex-direction:column;align-items:center;gap:4px;margin-bottom:var(--space-2);
  position:relative;
}
/* CHANGE 1 (redesigned per CHANGE 10 feedback): the first version of this halo used a
   tight radius + fairly opaque center, which read as a distinct dark "blob" shape behind
   the logo on real photos instead of just quietly helping contrast. This version is much
   larger relative to the block, multi-stop (peaks low and fades in several gentle steps
   instead of one sharp falloff), and heavily blurred — the goal is that it's never
   perceptible as a shape at all, just a faint, diffuse dimming. */
.lock-center::before{
  content:'';
  position:absolute;
  left:50%;top:50%;transform:translate(-50%,-50%);
  width:calc(100% + 340px);height:calc(100% + 300px);
  background:radial-gradient(closest-side,
    rgba(8,6,14,.32) 0%,
    rgba(8,6,14,.18) 40%,
    rgba(8,6,14,.08) 65%,
    rgba(8,6,14,0) 100%);
  filter:blur(46px);
  z-index:-1;
  pointer-events:none;
}
.lock-logo{
  display:flex;align-items:center;justify-content:center;gap:10px;
  color:#fff;font-size:26px;font-weight:800;
  opacity:0;transform:translateY(12px);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1), font-size .3s cubic-bezier(.16,1,.3,1);
}
.lock-logo-mark{width:1em;height:1em;flex-shrink:0;}
/* brand touch: a slow, subtle gold glow around the logo itself (drop-shadow
   follows the icon+text shapes, unlike a box/radial glow which would just
   be a rectangle or circle behind it). Kept slow and low-contrast so it
   reads as ambient warmth, not a flashing effect. */
.lock-logo.show{animation:lockLogoGlow 4s ease-in-out infinite;}
@keyframes lockLogoGlow{
  0%,100%{filter:drop-shadow(0 0 10px rgba(242,242,240,.25)) drop-shadow(0 0 22px rgba(242,242,240,.12));}
  50%{filter:drop-shadow(0 0 16px rgba(242,242,240,.4)) drop-shadow(0 0 32px rgba(242,242,240,.2));}
}
.lock-logo.show{opacity:1;transform:translateY(0);}
/* Windows / laptop only (matches the app's own 900px desktop breakpoint):
   push the logo + quote + PIN pad to the left side and size the logo up.
   Android / phones (below 900px) are untouched and stay centered. */
@media (min-width:900px){
  #lock-screen{ align-items:flex-start; padding-left:9%; padding-right:9%; }
  .lock-logo{ font-size:44px; }
}
/* CHANGE 10: with no pin pad below it, the logo+quote block is the screen's only real
   content, so it gets noticeably more visual weight than the "with PIN" sizes above. */
#lock-screen.no-pin .lock-logo{ font-size:44px; }
@media (min-width:900px){
  #lock-screen.no-pin .lock-logo{ font-size:60px; }
}
/* short time-of-day line, right under the logo (was .lock-quote) — kept small
   and tight to the logo on purpose so it doesn't compete for attention with
   the person/quote block below it */
.lock-time-text{
  font-size:var(--fs-caption);font-weight:600;color:#fff;text-align:center;max-width:260px;
  letter-spacing:.01em;line-height:1.5;
  text-shadow:0 1px 4px rgba(0,0,0,.5);
  opacity:0;transform:translateY(10px);
  margin-top:calc(var(--space-3) * -1);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1), font-size .3s cubic-bezier(.16,1,.3,1);
}
.lock-time-text.show{opacity:1;transform:translateY(0);}
#lock-screen.no-pin .lock-time-text{ font-size:var(--fs-caption); max-width:300px; }
@media (min-width:900px){
  .lock-time-text{ font-size:var(--fs-caption); }
  #lock-screen.no-pin .lock-time-text{ font-size:var(--fs-body); }
}

/* daily real-person quote card — sits between the time-text and the pin pad.
   .glass (defined earlier) supplies the background/border/blur/shadow; this
   block only adds its own layout (padding, radius, sizing, reveal transition). */
.lock-person{
  display:flex;flex-direction:column;align-items:center;
  padding:var(--space-5) var(--space-5);border-radius:20px;margin-top:var(--space-4);max-width:300px;
  opacity:0;transform:translateY(14px);
  transition:opacity .35s cubic-bezier(.16,1,.3,1), transform .35s cubic-bezier(.16,1,.3,1);
}
.lock-person.show{opacity:1;transform:translateY(0);}
.lock-person-photo-wrap{
  width:64px;height:64px;border-radius:50%;padding:var(--space-1);
  background:var(--gold);
}
.lock-person-photo{
  width:100%;height:100%;border-radius:50%;object-fit:cover;display:block;
  border:2px solid rgba(255,255,255,.25);
}
.lock-person-quote{
  margin-top:var(--space-3);font-size:var(--fs-body);font-weight:600;color:#fff;text-align:center;
  line-height:1.6;text-shadow:0 1px 4px rgba(0,0,0,.4);
}
.lock-person-name{
  margin-top:var(--space-2);font-size:var(--fs-caption);font-weight:600;color:rgba(255,255,255,.75);
}

/* CHANGE 4 + 10: "tap anywhere to continue" affordance, shown only when no PIN is set up
   (the screen isn't a real lock in that case). Same fade+translate language and easing as
   the rest of the lock screen. Sized up per CHANGE 10 feedback — the first pass read as a
   tiny corner icon; this reads as a real, deliberate call-to-action instead. Still no heavy
   effects: just a bigger label + arrow and the same gentle bounce as before. */
.lock-tap-hint{
  display:flex;flex-direction:column;align-items:center;gap:10px;
  margin-top:var(--space-8);
  color:rgba(255,255,255,.72);
  font-size:var(--fs-body-lg);font-weight:600;letter-spacing:.01em;
  text-shadow:0 1px 4px rgba(0,0,0,.5);
  opacity:0;transform:translateY(12px);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1);
}
@media (min-width:900px){
  .lock-tap-hint{ font-size:var(--fs-h2); margin-top:var(--space-10); }
}
.lock-tap-hint.show{
  opacity:1;transform:translateY(0);
  animation:lockTapPulse 2.6s ease-in-out .5s infinite;
}
.lock-tap-hint svg{width:28px;height:28px;animation:lockTapArrow 1.8s cubic-bezier(.16,1,.3,1) infinite;}
@media (min-width:900px){
  .lock-tap-hint svg{width:32px;height:32px;}
}
@keyframes lockTapPulse{0%,100%{opacity:.6;}50%{opacity:1;}}
@keyframes lockTapArrow{0%,100%{transform:translateY(0);}50%{transform:translateY(4px);}}
/* CHANGE 6: respect OS-level "reduce motion" — turn off the staged reveal fades, the
   continuous tap-hint bounce, and the wrong-PIN shake. Background crossfade between
   time-of-day photos is left alone since it's a one-off state change, not decorative
   motion. Parallax is disabled in JS (applyLoginParallax), not here. */
@media (prefers-reduced-motion: reduce){
  .lock-date, .lock-center, .lock-logo, .lock-time-text, .lock-tap-hint,
  .lock-forgot-pin, .lock-recovery,
  .pin-dots, .pin-pad{
    transition:none !important;
  }
  .lock-tap-hint.show{ animation:none !important; }
  .lock-tap-hint svg{ animation:none !important; }
  .lock-logo.show{
    animation:none !important;
    filter:drop-shadow(0 0 14px rgba(242,242,240,.3)) drop-shadow(0 0 26px rgba(242,242,240,.16));
  }
  .pin-dots.shake{ animation:none !important; }
  .pin-dots span{ transition:none !important; }
  .pin-dots span.filled::after{ animation:none !important; opacity:0 !important; }
  .arc-box.celebrate #arcFill{ animation:none !important; }
  .arc-box.celebrate #arcSun{ animation:none !important; }
  .page.active{ animation:none !important; }
  .page.leaving{ animation:none !important; opacity:0 !important; }
}

#lock-screen .brand{font-size:var(--fs-h1);font-weight:800;display:flex;align-items:center;justify-content:center;gap:10px;color:#fff;}
/* single unified glass panel behind the whole entry cluster (dots, error,
   pad, forgot-pin link) — replaces the earlier approach of three separate
   frosted capsules, so the cluster reads as one deliberate card instead of
   a few floating pills. */
.pin-cluster{
  display:flex;flex-direction:column;align-items:center;
  gap:16px;
  padding:var(--space-6) var(--space-6);border-radius:28px;
  background:rgba(20,16,26,.34);
  border:1px solid rgba(255,255,255,.14);
  backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);
  box-shadow:var(--shadow-float);
}
.pin-dots{
  display:flex;align-items:center;gap:16px;
  opacity:0;transform:translateY(12px);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1);
}
.pin-dots.show{opacity:1;transform:translateY(0);}
.pin-dots span{
  position:relative;width:13px;height:13px;border-radius:50%;
  border:1.5px solid rgba(255,255,255,.55);background:rgba(255,255,255,.06);
  transition:background .3s ease, border-color .3s ease, transform .3s cubic-bezier(.34,1.56,.64,1);
}
/* soft gold glow that blooms out and fades each time a digit lands, instead of the
   dot just hard-cutting from empty to filled */
.pin-dots span::after{
  content:'';position:absolute;inset:-8px;border-radius:50%;
  background:radial-gradient(circle, var(--gold), transparent 70%);
  opacity:0;transform:scale(.5);pointer-events:none;
}
.pin-dots span.filled{background:var(--gold);border-color:var(--gold);transform:scale(1.15);}
.pin-dots span.filled::after{animation:pinPulse .6s ease forwards;}
@keyframes pinPulse{0%{opacity:.9;transform:scale(.55);}100%{opacity:0;transform:scale(1.9);}}
/* short, light shake to signal a wrong PIN — a few pixels of horizontal motion, nothing heavier */
@keyframes pinShake{
  10%,90%{transform:translateX(-1px);}
  20%,80%{transform:translateX(2px);}
  30%,50%,70%{transform:translateX(-4px);}
  40%,60%{transform:translateX(4px);}
}
.pin-dots.shake{animation:pinShake .35s ease;}
.pin-pad{
  display:grid;grid-template-columns:repeat(3,64px);gap:18px;
  opacity:0;transform:translateY(12px);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1);
}
.pin-pad.show{opacity:1;transform:translateY(0);}
/* dimmed + inert while a failed-attempt lockout is counting down */
.pin-pad.locked{opacity:.35;pointer-events:none;}
.pin-key{
  width:64px;height:64px;border-radius:50%;
  background:rgba(255,255,255,.10);
  border:1px solid rgba(255,255,255,.16);
  /* exception: momentary rim-light + soft drop, not the panel's own
     elevation — kept custom rather than either shadow token. */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10), 0 2px 8px -4px rgba(0,0,0,.4);
  color:#fff;font-size:var(--fs-h1);font-weight:700;display:flex;align-items:center;justify-content:center;
  transition:transform .08s ease, background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
/* press feedback now leans into the app's own gold identity instead of a neutral
   white flash, so the pad itself feels like بامداد rather than a generic keypad.
   exception: the box-shadow below is a momentary press glow (inset highlight +
   outward gold bloom), not an elevation shadow, so it isn't one of the two
   shadow tokens. */
.pin-key:active{
  transform:scale(.92);
  background:rgba(242,242,240,.22);
  border-color:rgba(242,242,240,.55);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18), 0 0 16px rgba(242,242,240,.35);
}
.pin-error{color:var(--ember);font-size:var(--fs-caption);min-height:20px;line-height:1.5;text-shadow:0 1px 4px rgba(0,0,0,.5);}

/* ===== Forgot-PIN / security-question recovery + first-time PIN+question setup =====
   Small text link under the pad; tapping it swaps the pin-dots/pin-pad out for a
   text-answer form (recovery), and a correct answer swaps that for the same
   pin-pad again (this time collecting a brand-new PIN). The very first time a PIN
   is ever turned on, the same pad is reused once more to collect a mandatory
   security question + answer before the PIN actually takes effect. */
.lock-pin-label{
  font-size:var(--fs-body);font-weight:700;color:#fff;text-align:center;
  text-shadow:0 1px 4px rgba(0,0,0,.5);
  min-height:18px;
}
.lock-pin-label:empty{min-height:0;}
.lock-forgot-pin{
  font-size:var(--fs-caption);font-weight:600;color:rgba(255,255,255,.9);
  text-align:center;text-decoration:underline;cursor:pointer;
  text-shadow:0 1px 4px rgba(0,0,0,.5);
  /* separated from the keypad above it with its own top divider + extra
     margin, so within the shared panel it still reads as a distinct,
     lower-emphasis exit from the pad rather than a 13th key. */
  margin-top:var(--space-2);padding-top:var(--space-4);
  border-top:1px solid rgba(255,255,255,.14);
  width:100%;
  opacity:0;transform:translateY(8px);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1);
}
.lock-forgot-pin.show{opacity:1;transform:translateY(0);}
.lock-recovery{
  display:flex;flex-direction:column;align-items:stretch;gap:10px;
  width:min(300px, 84vw);
  opacity:0;transform:translateY(10px);
  transition:opacity .3s cubic-bezier(.16,1,.3,1), transform .3s cubic-bezier(.16,1,.3,1);
}
.lock-recovery.show{opacity:1;transform:translateY(0);}
.lock-recovery-question{
  font-size:var(--fs-body-lg);font-weight:600;color:#fff;text-align:center;line-height:1.6;
  text-shadow:0 1px 4px rgba(0,0,0,.5);
}
.lock-recovery-input{
  width:100%;padding:var(--space-3) var(--space-4);border-radius:12px;border:1px solid rgba(255,255,255,.25);
  background:rgba(255,255,255,.1);color:#fff;font-size:var(--fs-body-lg);font-family:inherit;text-align:center;
  outline:none;transition:border-color .2s ease, background .2s ease;
}
select.lock-recovery-input{cursor:pointer;text-align:center;text-align-last:center;}
select.lock-recovery-input option{color:var(--paper);}
.lock-recovery-input::placeholder{color:rgba(255,255,255,.45);}
.lock-recovery-input:focus{border-color:var(--gold);background:rgba(255,255,255,.16);}
.lock-recovery-input:disabled{opacity:.5;}
.lock-recovery-error{color:var(--ember);font-size:var(--fs-caption);min-height:16px;text-shadow:0 1px 4px rgba(0,0,0,.5);text-align:center;}
.lock-recovery-submit{
  width:100%;padding:var(--space-3);border-radius:12px;background:var(--gold);color:var(--paper);
  font-size:var(--fs-body-lg);font-weight:700;transition:transform .08s ease, opacity .2s ease;
}
.lock-recovery-submit:active{transform:scale(.97);}
.lock-recovery-submit:disabled{opacity:.4;pointer-events:none;}
.lock-recovery-cancel{
  margin-top:var(--space-1);font-size:var(--fs-caption);color:rgba(255,255,255,.6);
  text-align:center;text-decoration:underline;cursor:pointer;
  text-shadow:0 1px 4px rgba(0,0,0,.5);
}

/* ===== Habits ===== */
.habit-row{display:flex;align-items:center;gap:12px;padding:var(--space-3) var(--space-1);border-bottom:1px solid var(--line);}
.habit-row:last-child{border-bottom:none;}
.streak-badge{
  display:flex;align-items:center;gap:4px;font-size:var(--fs-caption);font-weight:700;color:var(--ink-soft);
  background:var(--paper-soft);padding:var(--space-1) var(--space-3);border-radius:20px;
}
.habit-days{display:flex;gap:3px;margin-top:var(--space-2);flex-wrap:wrap;max-width:210px;}
.habit-weekly-goal{display:flex;align-items:center;gap:4px;font-size:var(--fs-micro);color:var(--ink-soft);margin-top:var(--space-1);}
.inline-glyph{width:13px;height:13px;flex-shrink:0;}
.hday{width:11px;height:11px;border-radius:3px;background:var(--paper-soft);}
.hday.on{background:var(--sage);}
.habit-row.just-done{animation:taskRowFlash .7s ease;}
.streak-badge.flame-pop{animation:flamePop .5s cubic-bezier(.34,1.56,.64,1);}
@keyframes flamePop{0%{transform:scale(1);}50%{transform:scale(1.35) rotate(-6deg);}100%{transform:scale(1);}}

/* ===== Empty state ===== */
.empty{
  text-align:center;padding:var(--space-10) var(--space-3);color:var(--ink-soft);
}
.empty svg{width:44px;height:44px;margin-bottom:var(--space-3);opacity:.5;}
.empty p{font-size:var(--fs-caption);line-height:1.7;}

/* ===== Timeline (day view) ===== */
.timeline{position:relative;display:flex;}
.tl-hourlabels{width:52px;flex-shrink:0;position:relative;}
.tl-hour{
  position:absolute;right:2px;left:0;top:0;transform:translateY(-6px);
  font-size:var(--fs-micro);color:var(--ink-soft);text-align:left;
  transition:font-size .2s,font-weight .2s,color .2s;
}
.tl-hour.has-tasks{font-size:var(--fs-caption);font-weight:800;color:var(--ink);}
.tl-canvas{flex:1;position:relative;border-right:1px solid var(--line);}
.tl-gridline{position:absolute;left:0;right:0;border-top:1px solid var(--line);}
.tl-block{
  position:absolute;border-radius:8px;box-sizing:border-box;cursor:pointer;
  padding:var(--space-1) var(--space-2);font-size:var(--fs-micro);font-weight:700;color:#fff;overflow:hidden;
  line-height:1.3;white-space:nowrap;text-overflow:ellipsis;
}
.tl-empty{padding:var(--space-6) var(--space-2);text-align:center;color:var(--ink-soft);font-size:var(--fs-caption);}

/* ===== Week view ===== */
.week-view{display:flex;gap:6px;overflow-x:auto;padding-bottom:var(--space-2);}
.week-col{flex:1;min-width:118px;background:var(--card);border-radius:12px;border:1px solid var(--glass-border);box-shadow:var(--shadow-card);padding:var(--space-3) var(--space-2);}
.week-col-head{font-size:var(--fs-micro);font-weight:700;color:var(--ink-soft);display:flex;flex-direction:column;align-items:center;gap:2px;margin-bottom:var(--space-2);padding-bottom:var(--space-2);border-bottom:1px solid var(--line);}
.week-col-head .num{font-size:var(--fs-body-lg);color:var(--ink);}
.week-col.is-today .week-col-head .num{
  display:inline-flex;align-items:center;justify-content:center;
  width:24px;height:24px;border-radius:50%;
  border:2px solid var(--ink-soft);
  margin-right:var(--space-1);
}
.week-col-body{display:flex;flex-direction:column;gap:5px;min-height:40px;}
.week-task-chip{
  font-size:var(--fs-micro);padding:var(--space-1) var(--space-2);border-radius:6px;background:var(--paper-soft);
  border-inline-start:3px solid var(--gold);cursor:pointer;line-height:1.5;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.week-task-chip.done{opacity:.5;text-decoration:line-through;}
.week-empty{font-size:var(--fs-micro);color:var(--ink-soft);text-align:center;padding:var(--space-2) 0;opacity:.5;}

/* ===== Activity heatmap ===== */
.heatmap-grid{display:grid;grid-template-rows:repeat(7,1fr);grid-auto-flow:column;gap:3px;overflow-x:auto;padding-bottom:var(--space-1);}
.heat-cell{width:11px;height:11px;border-radius:3px;background:var(--paper-soft);flex-shrink:0;}
.heat-cell.lvl1{background:var(--gold-soft);}
.heat-cell.lvl2{background:var(--gold);opacity:.6;}
.heat-cell.lvl3{background:var(--gold);opacity:.85;}
.heat-cell.lvl4{background:var(--gold);}
.heatmap-legend{display:flex;align-items:center;gap:4px;margin-top:var(--space-2);font-size:var(--fs-micro);color:var(--ink-soft);}
.heatmap-legend .heat-cell{width:10px;height:10px;}
.achv-badge{font-size:var(--fs-h1);width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--paper-soft);opacity:.4;flex-shrink:0;color:var(--ink-soft);}
.achv-badge svg{width:18px;height:18px;}
.achv-badge.earned{opacity:1;background:rgba(143,174,134,.16);color:var(--sage);}

/* ===== Journal ===== */
.journal-entry{padding:var(--space-3) 0;border-bottom:1px solid var(--line);position:relative;}
.journal-prompt-chip{
  display:flex;align-items:center;gap:6px;width:100%;text-align:right;font-size:var(--fs-caption);color:var(--ink-soft);
  background:var(--paper-soft);border:1px dashed var(--line);border-radius:8px;
  padding:var(--space-2) var(--space-3);margin-bottom:var(--space-2);line-height:1.7;
}
.journal-prompt-chip .inline-glyph{flex-shrink:0;}
.journal-prompt-chip:hover{color:var(--gold);border-color:var(--gold);}
.journal-delete-btn{position:absolute;left:0;top:12px;color:var(--ink-soft);opacity:.4;width:26px;height:26px;display:flex;align-items:center;justify-content:center;transition:opacity .2s;}
.journal-delete-btn svg{width:15px;height:15px;}
.journal-delete-btn:hover{opacity:1;color:var(--ember);}
.journal-entry:last-child{border-bottom:none;}
.journal-date{font-size:var(--fs-micro);color:var(--ink-soft);font-weight:700;display:flex;align-items:center;gap:6px;}
.mood-inline{display:inline-flex;color:var(--ink-soft);}
.mood-inline svg{width:15px;height:15px;}
.mood-strip-glyph{display:flex;justify-content:center;color:var(--ink-soft);}
.mood-strip-glyph svg{width:17px;height:17px;}
.mood-strip-dot{width:4px;height:4px;border-radius:50%;background:var(--line);display:inline-block;}
.mood-strip-energy{display:flex;justify-content:center;height:14px;margin-top:2px;color:var(--ink-soft);}
.mood-strip-energy svg{width:12px;height:12px;}
.journal-text{font-size:var(--fs-caption);margin-top:var(--space-1);line-height:1.9;}
.journal-reflection{margin-top:var(--space-2);padding-top:var(--space-2);border-top:1px dashed var(--line);font-size:var(--fs-caption);color:var(--ink-soft);display:flex;flex-direction:column;gap:4px;line-height:1.7;}
.ref-line{display:flex;align-items:flex-start;gap:6px;}

/* ===== Stats ===== */
.stat-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;}
.stat-card{background:var(--card);border-radius:var(--radius-sm);padding:var(--space-4);border:1px solid var(--glass-border);box-shadow:var(--shadow-card);}
.stat-num{font-size:var(--fs-h1);font-weight:800;}
.stat-label{font-size:var(--fs-micro);color:var(--ink-soft);margin-top:var(--space-1);}
.stat-icon{width:22px;height:22px;color:var(--ink-soft);margin-bottom:var(--space-1);display:block;}

/* ===== Settings ===== */
.profile-avatar, .profile-avatar-placeholder{
  width:72px;height:72px;border-radius:50%;object-fit:cover;
  margin:0 auto;display:flex;align-items:center;justify-content:center;
  background:var(--paper-soft);color:var(--ink-soft);font-size:26px;font-weight:800;
}
/* ===== Gallery ===== */
.gallery-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3);}
.gallery-item{
  border-radius:var(--radius);overflow:hidden;aspect-ratio:3/4;position:relative;
  background:var(--paper-soft);box-shadow:var(--shadow-card);
}
.gallery-item img{width:100%;height:100%;object-fit:cover;display:block;}
.gallery-item .gallery-item-label{
  position:absolute;inset-inline:0;bottom:0;padding:var(--space-2) var(--space-3);
  background:linear-gradient(0deg, rgba(0,0,0,.55), transparent);
  color:#fff;font-size:var(--fs-caption);font-weight:700;
}
.gallery-preview-modal{max-width:420px;}
/* narrower than the default 480px modal, and an explicit max-height/overflow
   on top of .modal's own (88vh) since 17 grid items would otherwise push
   the picker past a comfortable height on shorter screens */
.gallery-picker-modal{max-width:420px;max-height:80vh;overflow-y:auto;}
.gallery-preview-modal img{width:100%;border-radius:var(--radius);display:block;object-fit:cover;max-height:60vh;}
.gallery-preview-modal .modal-actions .btn{flex:1;text-align:center;}
.setting-row{
  display:flex;align-items:center;justify-content:space-between;
  padding:var(--space-3) var(--space-1);border-bottom:1px solid var(--line);
}
.setting-row:last-child{border-bottom:none;}
.setting-row .label{font-size:var(--fs-body);font-weight:600;}
.setting-row .desc{font-size:var(--fs-micro);color:var(--ink-soft);margin-top:var(--space-1);}
.switch{width:44px;height:26px;border-radius:20px;background:var(--line);position:relative;transition:.2s;flex-shrink:0;}
.switch::after{content:'';position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;background:#fff;transition:.2s;}
.switch.on{background:var(--gold);}
.switch.on::after{transform:translateX(-18px);}

.cat-color-swatch{
  width:26px;height:26px;border-radius:50%;background:var(--sw);
  border:2px solid transparent;transition:transform .2s;
}
.cat-color-swatch.active{border-color:var(--ink);transform:scale(1.08);}

/* ===== Bamo persona presets + live preview (settings page) ===== */
.bamo-preview-box{
  display:flex;flex-direction:column;align-items:center;gap:var(--space-2);
  padding:var(--space-4) var(--space-2);margin-bottom:var(--space-4);
  border-radius:var(--radius);
  background:var(--bamo-bg-gradient);
  border:2px solid rgba(var(--bamo-teal-rgb),.32);
  box-shadow:0 14px 30px -12px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.10);
}
.bamo-preview-eyes{width:132px;height:auto;display:block;overflow:visible;}
.bamo-preview-line{font-size:var(--fs-caption);color:rgba(242,242,240,.78);text-align:center;min-height:1.4em;}
.bamo-persona-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:var(--space-3);}
.bamo-persona-card-btn{
  text-align:start;padding:var(--space-3);border-radius:var(--radius-sm);
  background:var(--paper-soft);border:1.5px solid transparent;transition:.15s;
}
.bamo-persona-card-btn.active{background:var(--gold-soft);border-color:var(--ink);}
.bamo-persona-name{font-size:var(--fs-caption);font-weight:700;}
.bamo-persona-desc{font-size:var(--fs-micro);color:var(--ink-soft);margin-top:2px;}
.bamo-persona-custom-badge{
  display:inline-block;font-size:var(--fs-micro);color:var(--ink-soft);
  background:var(--paper-soft);border-radius:20px;padding:2px 10px;margin-inline-start:8px;
}
.bamo-manual-toggle{margin-bottom:var(--space-3);}

.cat-row-delete{color:var(--ink-soft);opacity:.5;width:26px;height:26px;display:flex;align-items:center;justify-content:center;transition:opacity .2s;}
.cat-row-delete:hover{opacity:1;color:var(--ember);}
.cat-row-delete svg{width:15px;height:15px;}

/* Pomodoro */
.pomo-ring-wrap{display:flex;justify-content:center;margin:var(--space-2) 0;}
.pomo-time{font-size:var(--fs-display);font-weight:800;text-align:center;line-height:1.2;}
.pomo-modes{display:flex;gap:8px;justify-content:center;margin-top:var(--space-3);}
@media (max-width:370px){ .pomo-time{font-size:var(--fs-display);} }

/* ===== Focus page — soft gold halo behind the card, buttons compacted into
   a glass icon-badge row instead of 3 stacked ghost bars. Reuses the shared
   .glass surface (and its existing night-mode override) rather than a new
   background, so it stays visually consistent and needs no extra dark-mode
   rule here. */
.focus-card{position:relative;overflow:hidden;}
.focus-card::before, .focus-card::after{
  content:'';position:absolute;width:220px;height:220px;border-radius:50%;
  background:radial-gradient(circle, rgba(242,242,240,.35) 0%, rgba(242,242,240,0) 70%);
  pointer-events:none;
}
.focus-card::before{top:-70px;right:-70px;}
.focus-card::after{bottom:-80px;left:-60px;width:200px;height:200px;background:radial-gradient(circle, rgba(242,242,240,.22) 0%, rgba(242,242,240,0) 70%);}
.focus-card > *{position:relative;z-index:1;}
.focus-action-row{display:flex;gap:8px;margin-top:var(--space-4);}
.focus-action{
  flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:var(--space-4) var(--space-1) var(--space-3);border-radius:16px;
  transition:transform .15s ease;
  border:1px solid var(--glass-border);
  background:var(--card);box-shadow:var(--shadow-card);
}
.focus-action:active{transform:scale(.97);}
.focus-action-icon{
  width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(242,242,240,.16);border:1px solid rgba(242,242,240,.35);
}
.focus-action-svg{width:18px;height:18px;color:var(--gold);}
.focus-action-label{font-size:var(--fs-micro);font-weight:600;color:var(--ink);line-height:1.4;}

/* ===== Dashboard quick-link cards (دفتر/عادت‌ها/تمرکز) — same technique as
   .growth-card just above: a soft colored wash behind a .glass surface, so
   the glass actually has something to blur even without a photo backdrop.
   Reuses the .focus-action-icon/-svg badge built for the focus page. */
.dash-link-card{position:relative;overflow:hidden;}
.dash-link-card::before{
  content:'';position:absolute;top:-50px;left:50%;transform:translateX(-50%);
  width:180px;height:180px;border-radius:50%;pointer-events:none;
}
.dash-link-card.tone-dusk::before{background:radial-gradient(circle, rgba(242,242,240,.28) 0%, rgba(56,71,104,0) 70%);}
.dash-link-card.tone-sage::before{background:radial-gradient(circle, rgba(242,242,240,.28) 0%, rgba(124,143,110,0) 70%);}
.dash-link-card.tone-gold::before{background:radial-gradient(circle, rgba(242,242,240,.32) 0%, rgba(242,242,240,0) 70%);}
.dash-link-card > *{position:relative;z-index:1;}
.dash-link-btn{
  display:flex;align-items:center;justify-content:center;gap:10px;
  width:100%;padding:var(--space-3) var(--space-4);border-radius:14px;
  font-weight:700;font-size:var(--fs-caption);color:var(--ink);
  background:rgba(255,255,255,.55);border:1px solid rgba(255,255,255,.6);
  transition:transform .15s ease, background .15s ease;
}
:root[data-mode="night"] .dash-link-btn{
  background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.14);color:#fff;
}
.dash-link-btn:active{transform:scale(.97);background:rgba(255,255,255,.75);}
:root[data-mode="night"] .dash-link-btn:active{background:rgba(255,255,255,.16);}
.dash-link-btn .focus-action-icon{width:30px;height:30px;flex-shrink:0;}
.dash-link-btn .focus-action-svg{width:15px;height:15px;}

/* ===== Dedicated Chronometer screen ===== */
.chrono-screen{
  position:fixed;inset:0;background:var(--paper);z-index:90;
  display:none;flex-direction:column;align-items:center;justify-content:center;gap:34px;
}
.chrono-screen.open{display:flex;}
.chrono-ring-wrap{position:relative;display:flex;align-items:center;justify-content:center;}
.chrono-ring-wrap svg{width:min(78vw,320px);height:min(78vw,320px);transition:filter .3s;}
#chronoRingFill{transition:stroke-dashoffset 1s linear;}
.chrono-screen.running .chrono-ring-wrap svg{filter:drop-shadow(0 0 18px rgba(242,242,240,.55));}
.chrono-time{
  position:absolute;font-size:var(--fs-display);font-weight:800;color:var(--ink);
  font-variant-numeric:tabular-nums;letter-spacing:.02em;
}
.chrono-controls{display:flex;gap:14px;}
.chrono-controls .btn{min-width:120px;padding:var(--space-3) var(--space-5);font-size:var(--fs-body-lg);}

/* ===== Minimal Countdown Timer screen — Time First, Everything Else Second ===== */
.timer-screen{
  position:fixed;inset:0;z-index:90;background:var(--paper);color:var(--ink);
  display:none;flex-direction:column;justify-content:space-between;
  transition:background .3s ease, color .3s ease;
}
.timer-screen.open{display:flex;}

.mt-controls-top{
  display:flex;align-items:center;gap:6px;padding:var(--space-4);
  transition:opacity .35s ease;
}
.mt-icon-btn{
  width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:transparent;color:inherit;opacity:.55;transition:opacity .2s,background .2s;
}
.mt-icon-btn:hover{opacity:1;background:rgba(128,128,128,.12);}
.mt-icon-btn svg{width:19px;height:19px;}

.mt-center{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;}
.mt-focus-label{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-caption);font-weight:700;color:var(--ink-soft);opacity:.85;max-width:280px;text-align:center;}
.mt-time{display:flex;flex-direction:row;direction:ltr;align-items:baseline;gap:2px;user-select:none;}
.mt-seg{
  width:2.6ch;text-align:center;background:transparent;border:none;color:inherit;
  font-family:inherit;font-weight:800;font-size:min(17vw,140px);line-height:1;
  font-variant-numeric:tabular-nums;letter-spacing:-.01em;direction:ltr;
  -moz-appearance:textfield;caret-color:var(--gold);overflow:visible;
}
.mt-seg::-webkit-outer-spin-button,.mt-seg::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.mt-seg:focus{outline:none;}
.mt-seg[readonly]{caret-color:transparent;}
.mt-colon{font-size:min(12vw,96px);font-weight:800;opacity:.35;line-height:1;transform:translateY(-2px);}
/* Bold tabular digits at 20vw were wider than the 2.05ch input box could hold,
   so the last digit of each segment got clipped on phones. Slightly smaller
   vw-based sizing + a wider box (2.6ch) keeps every digit fully visible. */
@media (max-width:370px){
  .mt-seg{font-size:min(15vw,80px);width:2.7ch;}
  .mt-colon{font-size:min(10vw,60px);}
}

.mt-controls-bottom{
  display:flex;flex-direction:column;align-items:center;gap:14px;padding:0 var(--space-4) var(--space-6);
  transition:opacity .35s ease;
}
.mt-presets{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:420px;}
.mt-presets button{
  padding:var(--space-2) var(--space-4);border-radius:20px;font-size:var(--fs-caption);font-weight:700;
  background:rgba(128,128,128,.12);color:inherit;opacity:.75;
}
.mt-presets button:hover{opacity:1;}
.mt-row{display:flex;align-items:center;gap:16px;flex-wrap:wrap;justify-content:center;}
.mt-bg-picker{display:flex;gap:8px;}
.mt-bg-picker button{
  width:26px;height:26px;border-radius:50%;padding:0;position:relative;
  border:2px solid rgba(128,128,128,.35);
}
.mt-bg-picker button[data-bg="standard"] span{background:linear-gradient(135deg,var(--paper) 50%,var(--ink) 50%);}
.mt-bg-picker button[data-bg="white"] span{background:#ffffff;}
.mt-bg-picker button[data-bg="black"] span{background:#0a0a0a;}
.mt-bg-picker button span{position:absolute;inset:2px;border-radius:50%;display:block;}
.mt-bg-picker button.active{border-color:var(--gold);}
.mt-actions{display:flex;gap:10px;}
.mt-btn{
  padding:var(--space-3) var(--space-6);border-radius:24px;font-size:var(--fs-caption);font-weight:700;
  background:rgba(128,128,128,.12);color:inherit;
}
.mt-btn.primary{background:var(--gold);color:var(--paper);}

/* controls fade away while running & idle-mouse; focus mode hides them entirely */
.timer-screen.controls-hidden .mt-controls-top,
.timer-screen.controls-hidden .mt-controls-bottom{opacity:0;pointer-events:none;}
.timer-screen.focus .mt-controls-top,
.timer-screen.focus .mt-controls-bottom{display:none;}

/* the one exit affordance that survives focus mode — always reachable, never auto-hidden */
.mt-focus-exit{
  display:none;position:absolute;z-index:5;
  top:calc(var(--space-4) + env(safe-area-inset-top));
  inset-inline-start:var(--space-4);
}
.timer-screen.focus .mt-focus-exit{display:flex;}

.exercise-item{
  display:flex;align-items:center;gap:12px;padding:var(--space-4) var(--space-1);border-bottom:1px solid var(--line);
}
.exercise-item .ex-check{
  width:24px;height:24px;border-radius:50%;border:2px solid var(--line);flex-shrink:0;
  display:flex;align-items:center;justify-content:center;transition:.2s;
}
.exercise-item.done .ex-check{background:var(--sage);border-color:var(--sage);}
.exercise-item .ex-check svg{width:13px;height:13px;opacity:0;stroke:#fff;stroke-width:3;}
.exercise-item.done .ex-check svg{opacity:1;}
.exercise-item .ex-main{flex:1;}
.exercise-item .ex-title{font-size:var(--fs-body);font-weight:700;}
.exercise-item.done .ex-title{text-decoration:line-through;color:var(--ink-soft);}
.exercise-item .ex-sub{font-size:var(--fs-micro);color:var(--ink-soft);margin-top:var(--space-1);}
.exercise-item .ex-start{
  padding:var(--space-2) var(--space-3);border-radius:16px;background:var(--paper-soft);color:var(--ink);
  font-size:var(--fs-micro);font-weight:700;flex-shrink:0;
}

/* ===== Onboarding — narrative "day with بامداد" story. Reuses the exact same
   4 period photos already shipped for the lock screen (assets/login-<period>-
   9x16.jpg / 16x9.jpg via resolveLoginBgFile) and the same glass-pill /
   gradient-readability language as .horizon-wrap.page-header-photo — no new
   imagery needed. The 4 slides are walked in a FIXED morning->noon->sunset->
   night order as a story (unlike the lock screen, which is period-aware and
   only shows the real current time of day). */
.onboarding-screen{
  position:fixed;inset:0;z-index:150;background:var(--paper);
  display:none;flex-direction:column;overflow:hidden;
}
.onboarding-screen.open{display:flex;}
.ob-slides{position:relative;flex:1;width:100%;}
.ob-slide{
  position:absolute;inset:0;
  background-size:cover;background-position:center;background-repeat:no-repeat;
  opacity:0;pointer-events:none;transition:opacity .5s ease;
  display:flex;flex-direction:column;justify-content:flex-end;
}
.ob-slide.active{opacity:1;pointer-events:auto;}
.ob-slide::before{
  content:'';position:absolute;inset:0;
  background:linear-gradient(to top, rgba(10,8,14,.88) 0%, rgba(10,8,14,.5) 38%, rgba(10,8,14,.05) 68%);
}
.ob-slide-content{position:relative;z-index:1;padding:0 var(--space-6) 200px;text-align:center;color:#fff;}
.ob-slide-eyebrow{font-size:var(--fs-caption);font-weight:700;color:var(--gold);letter-spacing:.06em;margin-bottom:var(--space-2);}
.ob-slide h3{font-size:var(--fs-h1);font-weight:800;margin-bottom:var(--space-3);text-shadow:0 2px 10px rgba(0,0,0,.3);}
.ob-slide p{font-size:var(--fs-body);line-height:1.9;color:rgba(255,255,255,.88);max-width:320px;margin:0 auto;}
.ob-skip-wrap{position:absolute;top:calc(16px + env(safe-area-inset-top));left:16px;z-index:3;}
.ob-skip-wrap button{
  font-size:var(--fs-caption);font-weight:600;color:#fff;padding:var(--space-2) var(--space-4);border-radius:20px;
  background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.22);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}
.ob-bottom{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:0 24px calc(24px + env(safe-area-inset-bottom));}
.ob-dots{display:flex;justify-content:center;gap:7px;margin-bottom:var(--space-4);}
.ob-dots span{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.35);transition:.2s;}
.ob-dots span.active{background:var(--gold);width:20px;border-radius:5px;}

@media (min-width:900px){
  .grid-2{display:grid;grid-template-columns:1.3fr 1fr;gap:20px;align-items:start;}
}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
/* ===== Glassmorphism system (design v2) — layered on top of the existing
   color variables, not replacing them. RULE (tightened): .glass is reserved
   for elements that sit directly on top of an actual photo — the dashboard
   hero (.horizon-wrap), the lock screen's background photo layer, and any
   card whose own ::before is a full-strength photo (e.g. .goal-card's
   mountain shot). Everything else — including cards that only carry a
   faint/low-opacity decorative tint (.growth-card, .quote-card), structural
   chrome (.sidebar, .bottom-nav), and cards on the plain paper backdrop
   below a page's hero — is a flat card: background:var(--card) + box-shadow:
   var(--shadow-card), inherited from the base .card rule (or added explicitly
   where an element isn't a .card). Because .glass/.glass-btn are declared
   last in this stylesheet, adding the class alongside an existing card class
   (e.g. class="card goal-card glass") overrides that class's flat
   background/border without touching its other rules (padding, layout,
   ::before photo backdrops, etc). ===== */
.glass{
  background: rgba(255,255,255,.14);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border: 1.5px solid rgba(255,255,255,.42);
  /* exception: needs its own diffuse, deep-purple-tinted shadow plus an
     inset rim light to read as frosted glass on a photo — neither
     --shadow-card (too faint) nor --shadow-float (wrong color, no rim
     light) reproduces that. */
  box-shadow: 0 8px 32px -12px rgba(20,16,30,.45), inset 0 1px 0 rgba(255,255,255,.15);
}
:root[data-mode="night"] .glass{
  background: rgba(30,24,45,.35);
  border: 1.5px solid rgba(255,255,255,.24);
}
.glass-btn{
  background: rgba(255,255,255,.10);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,.18);
  transition: background .2s ease, transform .15s ease;
}
.glass-btn:active{ transform: scale(.97); background: rgba(255,255,255,.18); }
/* ===================================================================
   BAMO — living companion widget (visual layer only; behavior/reactions
   are wired up in the two script blocks placed after the app's main
   script, near the end of the document. Fixed corner bubble, always visible,
   deliberately its own small dark "porthole" rather than a themed
   .glass card — Bamo reads as a distinct living creature, not another
   UI panel, and this way it doesn't need separate day/night styling.
   Every class/id below is bamo-prefixed to stay clear of the rest of
   the app's CSS. =================================================== */
.bamo-widget{
  position:fixed;
  left:0;right:0;margin:0 auto;               /* box-model centering, keeps `transform` free */
  /* brought down further still (was 56px, before that 74px) — the goal is
     for it to sit docked into the bottom-nav's reserved slot at roughly the
     same level as the other nav icons, not hover above the bar as a
     separate floating blob over page content. */
  bottom:calc(26px + env(safe-area-inset-bottom));
  width:80px;height:80px;
  z-index:50;
  border-radius:26px;
  background:var(--bamo-bg-gradient);
  border:2px solid rgba(var(--bamo-teal-rgb),.32);
  box-shadow:0 14px 30px -12px rgba(0,0,0,.6), 0 0 0 6px rgba(1,5,10,.85), inset 0 1px 0 rgba(255,255,255,.10);
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  -webkit-touch-callout:none;
  user-select:none;
  touch-action:manipulation;
  transition:transform .25s cubic-bezier(.34,1.56,.64,1);
}
.bamo-widget:active{ transform:scale(.92); }
.bamo-widget svg{ width:100%;height:100%;display:block;overflow:visible; }
@media (max-width:370px){
  .bamo-widget{ width:68px;height:68px; bottom:calc(22px + env(safe-area-inset-bottom)); }
}
@media (min-width:900px){
  /* Desktop uses the sidebar, not the bottom-nav — no bar to sit on top of,
     so Bamo goes back to a plain corner bubble. */
  .bamo-widget{
    left:14px;right:auto;margin:0;
    top:calc(env(safe-area-inset-top) + 14px);bottom:auto;
    width:88px;height:64px;border-radius:22px;
  }
}
.bamo-widget.bamo-breathing{
  animation:bamoBreathe var(--bamo-breathe-dur,6.8s) cubic-bezier(.45,0,.55,1) infinite;
  transform-origin:center;
}
@keyframes bamoBreathe{
  0%,100%{transform:scale(1)}
  50%{transform:scale(1.02)}
}
@media (prefers-reduced-motion: reduce){
  .bamo-widget.bamo-breathing{ animation:none; }
}
.bamo-halo{ filter:blur(16px); }
.bamo-eye-shape{ fill:url(#bamoEyeGrad); }
.bamo-glint{ fill:#fff; }
.bamo-lid{ fill:#01050a; }

/* ===== BAMO full-screen chat ===== */
.bamo-chat-overlay{
  position:fixed;inset:0;z-index:90;              /* stays below #lock-screen's z-index:100 on purpose */
  display:none;flex-direction:column;
  background:
    radial-gradient(120% 60% at 50% 0%, rgba(var(--bamo-teal-rgb),.10) 0%, transparent 60%),
    linear-gradient(180deg, #02070a 0%, #01050a 55%, #000 100%);
  opacity:0;transition:opacity .28s ease;
}
.bamo-chat-overlay.open{ display:flex;opacity:1; }
.bamo-chat-topbar{
  display:flex;align-items:center;justify-content:flex-end;gap:8px;
  padding:calc(env(safe-area-inset-top) + 12px) 14px 6px;
}
.bamo-chat-close{
  width:38px;height:38px;border-radius:50%;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);
  color:#d8fff9;display:flex;align-items:center;justify-content:center;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.bamo-chat-close svg{width:18px;height:18px;}
.bamo-chat-eyes-slot{
  flex:0 0 auto;height:20vh;min-height:120px;max-height:200px;
  display:flex;align-items:center;justify-content:center;
  padding:4px 0 10px;
}
.bamo-chat-eyes-slot svg{ width:min(320px,58vw);height:auto;overflow:visible; }
.bamo-chat-messages{
  flex:1;min-height:0;overflow-y:auto;
  padding:6px 16px 10px;display:flex;flex-direction:column;gap:10px;
}
.bamo-msg{
  max-width:78%;padding:10px 14px;border-radius:16px;font-size:14px;line-height:1.7;
  word-wrap:break-word;white-space:pre-wrap;
}
.bamo-msg.bamo{
  align-self:flex-start;
  background:rgba(var(--bamo-teal-rgb),.14);border:1px solid rgba(var(--bamo-teal-rgb),.22);color:#e9fffc;
  border-bottom-left-radius:4px;
}
.bamo-msg.user{
  align-self:flex-end;
  background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.14);color:#fff;
  border-bottom-right-radius:4px;
}
.bamo-guest-lock-link{
  display:inline-block;
  margin-inline-start:6px;
  margin-top:6px;
  padding:5px 14px;
  border:1px solid rgba(var(--bamo-teal-rgb),.4);
  border-radius:999px;
  color:#e9fffc;
  font-weight:500;
  text-decoration:none;
  white-space:nowrap;
}
.bamo-guest-lock-link:hover{ background:rgba(var(--bamo-teal-rgb),.14); }
/* Quick-reply chips shown right after the first greeting — a scrollable
   row of ready-made sentences so a first-time visitor sees, at a glance,
   the kind of thing Bamo actually understands (app-specific commands),
   instead of guessing and treating it like a general chatbot. They vanish
   the moment any message — tapped or typed — is sent, so they never
   compete with the ongoing conversation afterwards. */
.bamo-chat-suggestions{
  flex:0 0 auto;display:flex;gap:8px;overflow-x:auto;
  padding:2px 14px 12px;
}
.bamo-chat-suggestions.hidden{ display:none; }
.bamo-chat-suggestions::-webkit-scrollbar{ display:none; }
.bamo-suggestion-chip{
  flex:0 0 auto;white-space:nowrap;
  padding:8px 14px;border-radius:999px;
  border:1px solid rgba(var(--bamo-teal-rgb),.35);
  background:rgba(var(--bamo-teal-rgb),.10);
  color:#e9fffc;font-size:12.5px;font-family:inherit;
  cursor:pointer;transition:background .2s ease;
}
.bamo-suggestion-chip:hover, .bamo-suggestion-chip:active{ background:rgba(var(--bamo-teal-rgb),.22); }

/* Action chips attached to a specific bamo message (e.g. "برو به تمرکز")
   that navigate the person straight to a page of the app instead of just
   talking about it. Visually a bit more solid than the quick-reply
   suggestion chips above (filled, not outlined) so the two read as
   different affordances: one sends a message, the other takes you
   somewhere. Sits directly under its own message, not in the shared
   suggestions row, and never disappears once shown. */
.bamo-msg-actions{
  display:flex;flex-wrap:wrap;gap:8px;
  margin:6px 0 4px;
}
.bamo-action-chip{
  padding:8px 14px;border-radius:999px;border:none;
  background:rgba(var(--bamo-teal-rgb),.85);color:#062b28;
  font-size:12.5px;font-family:inherit;font-weight:600;
  cursor:pointer;transition:background .2s ease, transform .1s ease;
}
.bamo-action-chip:hover{ background:rgba(var(--bamo-teal-rgb),1); }
.bamo-action-chip:active{ transform:scale(.97); }
.bamo-chat-inputbar{
  flex:0 0 auto;display:flex;gap:8px;align-items:center;
  padding:10px 14px calc(12px + env(safe-area-inset-bottom));
  border-top:1px solid rgba(255,255,255,.08);
}
.bamo-chat-input{
  flex:1;border-radius:20px;border:1px solid rgba(255,255,255,.16);
  background:rgba(255,255,255,.06);color:#fff;padding:11px 16px;font-size:14px;
  font-family:inherit;outline:none;
}
.bamo-chat-input::placeholder{ color:rgba(255,255,255,.4); }
.bamo-chat-send{
  width:42px;height:42px;border-radius:50%;flex:0 0 auto;
  background:linear-gradient(135deg,#8FFFF3,#2FE6D6);
  border:none;color:#01201d;display:flex;align-items:center;justify-content:center;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.bamo-chat-send svg{width:18px;height:18px;}
.bamo-chat-send:disabled{ opacity:.4; }

/* ===== BAMO full-screen "just the eyes" mode (long-press the widget) ===== */
.bamo-focus-overlay{
  position:fixed;inset:0;z-index:90;
  display:none;align-items:center;justify-content:center;
  background:
    radial-gradient(120% 60% at 50% 40%, rgba(var(--bamo-teal-rgb),.10) 0%, transparent 60%),
    linear-gradient(180deg, #02070a 0%, #01050a 55%, #000 100%);
  opacity:0;transition:opacity .3s ease;
  cursor:pointer;
}
.bamo-focus-overlay.open{ display:flex;opacity:1; }
.bamo-focus-close{
  position:fixed;top:calc(env(safe-area-inset-top) + 14px);left:14px;
  width:38px;height:38px;border-radius:50%;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);
  color:#d8fff9;display:flex;align-items:center;justify-content:center;
  cursor:pointer;-webkit-tap-highlight-color:transparent;z-index:91;
}
.bamo-focus-close svg{width:18px;height:18px;}
.bamo-focus-eyes-slot{ width:min(520px,86vw);pointer-events:none; }
.bamo-focus-eyes-slot svg{ width:100%;height:auto;overflow:visible; }

/* Hidden developer panel — Alt+D (not a bare "d", so it never fires while
   typing in a task/journal field). Not part of the character itself. */
.bamo-debug{
  position:fixed;top:calc(env(safe-area-inset-top) + 84px);left:14px;
  display:none;gap:6px;flex-wrap:wrap;max-width:220px;z-index:50;
}
.bamo-debug button{
  border:1px solid rgba(120,220,205,.25);background:rgba(4,16,18,.85);color:#d8fff9;
  border-radius:10px;padding:5px 8px;font-size:11px;cursor:pointer;
}
body.bamo-debug-on .bamo-debug{display:flex}

/* Empty flex slot in .bottom-nav where the calendar button used to be —
   reserves the layout width so the row still has 5 equal slots and BAMO
   (fixed-positioned, centered on the viewport) lands exactly on top of it. */
.nav-btn-spacer{ pointer-events:none; animation:none; }
/* UX pass: 6 real tabs + Bamo's slot. The center slot is a bit wider so Bamo
   (80px) never covers the neighbouring icons; tabs may shrink below their label. */
.bottom-nav .nav-btn{min-width:0;padding-inline:0;}
.bottom-nav .nav-btn > span:last-child{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.bottom-nav .nav-btn-spacer{flex:1.45;}
@media (max-width:370px){ .bottom-nav .nav-btn-spacer{flex:1.7;} }
/* The "+" button only helps where something can be added. */
body[data-page="settings"] .fab,
body[data-page="stats"] .fab,
body[data-page="focus"] .fab{display:none;}
/* Keep the last card clear of the bar, Bamo and the "+" button. */
@media (max-width:899px){
  .main-view{padding-bottom:calc(150px + env(safe-area-inset-bottom));}
}
/* "+" sits just above the bar on the far side, smaller, so it covers less content. */
@media (max-width:899px){
  .fab{width:52px;height:52px;bottom:calc(84px + env(safe-area-inset-bottom));}
}


/* ===== added (accessibility pass 1) =====
   - visible keyboard focus for buttons/links/switches (the app had none)
   - inputs are 16px on touch screens so iOS doesn't auto-zoom on focus
     (needed now that pinch-zoom is no longer blocked in the viewport meta) */
button:focus-visible,a:focus-visible,[role="switch"]:focus-visible,.switch:focus-visible,[tabindex]:not([tabindex="-1"]):focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
#journalEditorText:focus-visible{border-color:var(--ink-soft) !important;}
.bamo-chat-input:focus-visible{border-color:rgba(255,255,255,.5);}
@media (pointer:coarse){
  input:not(.mt-seg):not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]),textarea,select{font-size:16px !important;}
}

/* ===== added (pass 3): touch targets — invisible hit-area extension to ~44px, visuals unchanged ===== */
.task-check,.mt-play-btn,.task-side-btn,.mood-pill,.mood-pill-editor,.energy-pill-editor,.icon-btn,.cat-row-delete{position:relative;}
.task-check::before,.mt-play-btn::before,.task-side-btn::before,.mood-pill::before,.mood-pill-editor::before,.energy-pill-editor::before,.icon-btn::before,.cat-row-delete::before,.journal-delete-btn::before,.switch::before{content:'';position:absolute;}
.task-check::before{inset:-11px;}
.mt-play-btn::before,.cat-row-delete::before,.journal-delete-btn::before{inset:-9px;}
.task-side-btn::before{inset:-5px 0;}
.mood-pill::before,.mood-pill-editor::before,.energy-pill-editor::before{inset:-4px 0;}
.icon-btn::before{inset:-3px;}
.switch::before{inset:-9px -4px;}

/* ===== صفحهٔ تمرکز: حلقهٔ پیشرفت + آمار امروز + ۷ روز اخیر =====
   فقط از توکن‌ها (--gold/--card/--glass-border/...) استفاده می‌کنه. ===== */
.focus-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-3);margin-top:var(--space-3)}
@media (min-width:820px){
  .focus-layout{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:var(--space-4);align-items:start}
}
.focus-main{text-align:center;padding:var(--space-6) var(--space-5);margin-bottom:0;
  background:radial-gradient(120% 90% at 50% 0%, var(--gold-soft), transparent 62%), var(--card)}
.focus-main::before,.focus-main::after{display:none}
.focus-side{display:grid;gap:var(--space-3)}
.focus-side .card{margin-bottom:0}
.focus-mode{font-size:var(--fs-caption);font-weight:600;color:var(--ink-soft)}
.focus-ring-wrap{position:relative;width:min(72vw,280px);aspect-ratio:1;margin:var(--space-4) auto;display:grid;place-items:center}
.focus-ring{position:absolute;inset:0;width:100%;height:100%;transform:rotate(-90deg)}
.focus-ring circle{fill:none;stroke-width:3.2;stroke-linecap:round}
.focus-ring-track{stroke:var(--glass-border)}
.focus-ring-prog{stroke:var(--gold);transition:stroke-dashoffset .9s linear, stroke .3s ease}
.focus-ring-prog.is-break{stroke:var(--sage)}
.focus-ring-wrap .pomo-time{position:relative;font-size:clamp(40px,11vw,56px)}
.focus-presets{display:flex;gap:var(--space-2);justify-content:center;flex-wrap:wrap;margin-bottom:var(--space-4)}
.focus-preset{min-height:40px;padding:0 var(--space-4);border-radius:999px;border:1px solid var(--glass-border);
  background:transparent;color:var(--ink-soft);font:inherit;font-size:var(--fs-caption);cursor:pointer;transition:border-color .15s ease,color .15s ease,background .15s ease}
.focus-preset:hover:not(:disabled){border-color:var(--glass-border-strong);color:var(--ink)}
.focus-preset[aria-pressed="true"]{background:var(--gold-soft);border-color:var(--gold);color:var(--gold)}
.focus-preset:disabled{opacity:.45;cursor:default}
.focus-preset:focus-visible,.focus-btnrow .btn:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.focus-btnrow{display:flex;gap:var(--space-2);max-width:380px;margin:0 auto}
.focus-btnrow .btn{flex:1;min-height:48px}
.focus-btnrow #pomoStartMini{flex:2}
.focus-btnrow #pomoResetMini{background:transparent;border:1px solid var(--glass-border);color:var(--ink)}
.focus-btnrow #pomoResetMini:hover:not(:disabled){border-color:var(--glass-border-strong)}
.focus-btnrow .btn:disabled{opacity:.45;cursor:default}
.focus-h{font-size:var(--fs-body);font-weight:700;margin:0 0 var(--space-3);color:var(--ink)}
.focus-stats{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)}
.focus-stat{text-align:center;padding:var(--space-3) var(--space-2);border-radius:var(--radius-sm);background:var(--paper-soft)}
.focus-stat-num{font-size:var(--fs-display);font-weight:800;line-height:1.2;color:var(--gold)}
.focus-stat-label{font-size:var(--fs-caption);color:var(--ink-soft);margin-top:2px}
.focus-bars{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:var(--space-2);height:150px}
.focus-bar-col{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:0}
.focus-bar-val{font-size:var(--fs-micro);color:var(--ink-soft);min-height:16px;line-height:16px}
.focus-bar-track{flex:1;width:100%;display:flex;align-items:flex-end;justify-content:center}
.focus-bar{width:60%;max-width:28px;border-radius:6px 6px 3px 3px;background:var(--gold-soft);transition:height .4s ease}
.is-today .focus-bar{background:var(--gold)}
.focus-bar-label{font-size:var(--fs-micro);color:var(--ink-faint)}
.focus-empty{margin:0;padding:var(--space-4) 0;text-align:center;font-size:var(--fs-caption);color:var(--ink-soft)}
.focus-empty[hidden],.focus-bars[hidden]{display:none}
.focus-tools-h{margin:var(--space-6) 0 0}
#page-focus .focus-action-row{margin-top:var(--space-3)}
#page-focus .focus-action-icon{background:var(--gold-soft);border-color:var(--glass-border-strong)}
@media (prefers-reduced-motion:reduce){.focus-ring-prog,.focus-bar{transition:none}}
