/* فونت از خودِ اپ سرو می‌شود؛ Google Fonts از داخلِ ایران کند یا مسدود است. */ @import 'vazirmatn/Vazirmatn-Variable-font-face.css'; @import 'tailwindcss'; /* * پالتِ اپ — همان رنگ‌های طراحیِ اولیه، یک‌جا. * هر رنگ یک کلاسِ Tailwind می‌سازد: bg-coral، text-ink، border-line، … */ @theme { --font-sans: 'Vazirmatn', system-ui, sans-serif; --color-coral: #ED6956; /* رنگِ اصلیِ برند */ --color-steel: #91ADC6; /* نقشه */ --color-teal: #97C0C0; /* درس‌ها */ --color-violet: #9B7BFF; /* دستیار (پی) */ --color-orange: #FF7A3D; /* جدولِ امتیاز (دلتا) */ --color-indigo: #4C5FD5; /* سیگما */ --color-rose: #F3A9B0; /* اسپلش */ --color-gold: #E8A400; --color-mint: #5FBF8F; --color-ink: #1a1a2e; /* متنِ اصلی */ --color-body: #3a3a5c; /* متنِ بدنه */ /* متنِ کم‌رنگ. تا ۲۰۲۶-۱۰-۰۳ ‎#9e9ec0 بود: کنتراست ۲٫۶ روی سفید، زیرِ حدِ ۴٫۵ِ WCAG، و همین رنگ زیرنویسِ ۱۰–۱۲ پیکسلیِ همه‌ی صفحه‌ها و آیکونِ تب‌های غیرفعال است. این یکی روی سفید ۴٫۵ و روی پس‌زمینه‌ی صفحه ۴٫۲ است. */ --color-muted: #727299; --color-faint: #b0b0c8; --color-line: #e9e6f7; /* حاشیه‌ی کارت */ --color-soft: #f0eeff; /* پس‌زمینه‌ی ملایم */ --color-page: #f6f5fb; /* پس‌زمینه‌ی صفحه؛ کمی گرم‌تر از آبیِ قبلی */ } @layer base { html, body, #root { height: 100%; } body { margin: 0; background: #14142a; color: var(--color-ink); font-family: var(--font-sans); -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent; } button { cursor: pointer; font: inherit; /* بی‌تأخیرِ دابل‌تپ و بی‌زوم با دو ضربه روی دکمه‌ها */ touch-action: manipulation; } button:disabled { cursor: not-allowed; } /* کشیدنِ صفحه به پایین در کروم اندروید کلِ اپ را رفرش می‌کرد (pull-to-refresh) و وسطِ آزمون جوابِ جاری را می‌پراند؛ صفحه‌های داخلی خودشان اسکرول دارند. */ html, body { overscroll-behavior: none; } /* حلقه‌ی فوکوس فقط برای صفحه‌کلید (focus-visible)، نه برای لمس. */ :focus-visible { outline: 2px solid var(--color-indigo); outline-offset: 2px; } } /* کاربری که در تنظیماتِ گوشی «کاهشِ حرکت» را زده: انیمیشن‌ها و transitionهای CSS تقریباً آنی می‌شوند. انیمیشن‌های motion را MotionConfig در App خاموش می‌کند. */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } @layer base { input, textarea { font: inherit; } /* متنِ چندخطی (پاراگراف، گام‌های درس، متنِ سوال، حبابِ پی) دو‌طرف‌چین است تا لبه‌ی چپ مرتب باشد. این‌ها در لایه‌ی base‌اند، پس هر جا کلاسِ text-center / text-left داده شده برنده است و تیترها و برچسب‌های کوتاه سرِ جایشان می‌مانند. خطِ آخر طبقِ معمول راست‌چین می‌ماند. text-justify فقط فاصله‌ی بینِ کلمه‌ها را باز می‌کند (کشیده‌نویسی در CSS نیست). */ p, li, .whitespace-pre-line { text-align: justify; text-justify: inter-word; /* از تک‌کلمه‌ی یتیم در خطِ آخر جلوگیری می‌کند */ text-wrap: pretty; } /* پاراگرافِ داخلِ بخشِ وسط‌چین (حالتِ خالی، آنبوردینگ، اسپلش) وسط‌چین می‌ماند؛ بدونِ این، قاعده‌ی بالا ارثِ text-center را می‌شکست. */ .text-center :is(p, li, .whitespace-pre-line) { text-align: center; } .text-left :is(p, li, .whitespace-pre-line) { text-align: left; } } @utility no-scrollbar { scrollbar-width: none; &::-webkit-scrollbar { display: none; } } /* فاصله‌ی امن بالای صفحه در گوشی‌های ناچ‌دار (وقتی اپ به صفحه‌ی اصلی اضافه شده). */ @utility pt-safe { padding-top: max(env(safe-area-inset-top), 0px); } @utility pb-safe { padding-bottom: max(env(safe-area-inset-bottom), 0px); } /* نمادهای شناورِ سربرگ (ui.tsx). فقط transform، پس روی GPU می‌ماند. */ @keyframes glyph-float { 0%, 100% { transform: translateY(0) rotate(-6deg); } 50% { transform: translateY(-7px) rotate(6deg); } } .glyph { animation: glyph-float 6s ease-in-out infinite; will-change: transform; } /* ناحیه‌ی لمسِ بزرگ‌تر بدونِ تغییرِ ظاهر: دکمه‌های کوچکِ سربرگ (۲۸–۳۲ پیکسل) برای انگشت کوچک‌اند. */ .hit { position: relative; } .hit::after { content: ''; position: absolute; inset: -7px -3px; } /* نوارِ اشتراک و نشانِ تدریسینو: فقط transform/opacity تا روی GPU بماند و روانی حفظ شود. */ @keyframes bar-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } } .bar-fill { transform-origin: right; animation: bar-fill 0.9s cubic-bezier(.2,.8,.2,1) both; } @keyframes shine { 0% { transform: translateX(120%); } 60%, 100% { transform: translateX(-220%); } } .shine { animation: shine 3.2s ease-in-out infinite; will-change: transform; } @keyframes spark { 0%, 100% { opacity: .25; transform: scale(.7); } 50% { opacity: 1; transform: scale(1); } } .spark { animation: spark 2.4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; } /* نوارِ انتظارِ میانِ دو صفحه (MainApp → HoldBar). */ @keyframes hold-bar { 0% { transform: translateX(120%); } 100% { transform: translateX(-320%); } } .hold-bar { animation: hold-bar 0.9s cubic-bezier(.4,0,.2,1) infinite; will-change: transform; } /* شعله‌ی زنجیره (StreakFlame): دو لایه با ریتمِ متفاوت، از پایین تکان می‌خورند. */ @keyframes flame-a { 0%, 100% { transform: scale(1, 1) skewX(0deg); } 33% { transform: scale(.97, 1.04) skewX(-2deg); } 66% { transform: scale(1.02, .97) skewX(2deg); } } @keyframes flame-b { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(.94, 1.08); } } .flame-outer { transform-box: fill-box; transform-origin: 50% 100%; animation: flame-a 1.4s ease-in-out infinite; } .flame-inner { transform-box: fill-box; transform-origin: 50% 100%; animation: flame-b .9s ease-in-out infinite; } @keyframes ice-glint { 0%, 70%, 100% { opacity: 0; } 80% { opacity: 1; } } .ice-glint { animation: ice-glint 2.8s ease-in-out infinite; } @keyframes spark-rise { 0% { transform: translateY(0) scale(1); opacity: 0; } 15% { opacity: 1; } 100% { transform: translateY(-180px) scale(.3); opacity: 0; } } .spark-rise { animation: spark-rise 1.8s ease-out infinite; } /* همراه‌های کنارِ مسیرِ جزیره‌ها (IslandPath): فقط transform، تا روی گوشیِ ضعیف هم روی GPU بماند. */ @keyframes buddy-hop { 0%, 55%, 100% { transform: translateY(0) scale(1, 1); } 20% { transform: translateY(-12px) scale(.96, 1.05); } 40% { transform: translateY(0) scale(1.06, .94); } } @keyframes buddy-sway { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } } .buddy-hop { animation: buddy-hop 1.6s ease-in-out infinite; transform-origin: 50% 100%; } .buddy-sway { animation: buddy-sway 3.2s ease-in-out infinite; transform-origin: 50% 100%; }