/* ==========================================================================
   "Kashi" learner layer: glazed eight-point star tiles (khatam) and a faint girih
   lattice on top of the Firouzeh & Ink tokens. Used by the learning path, the
   Today dashboard, the lesson player, the practice hub and the test screens.
   RTL-first logical properties; motion only at data-motion >= 2.
   ========================================================================== */

:root {
  --tile-done: #0b8f86; --tile-done-ledge: #05655e;
  --tile-sun: #ffb627; --tile-sun-ledge: #c98500; --on-sun: #14122b;
  --tile-gold: #e9b949; --tile-gold-ledge: #a87a12;
  /* the girih lattice texture is retired (docs/DESIGN-APPLE.md §1: texture competed with content); the khatam tiles stay */
  --lattice: none; --lattice-light: none;
  --sheet-shadow: 0 -18px 40px -24px rgb(20 18 43 / 0.35);
  /* one skill palette for hub tiles, lesson heroes, test tickets and charts (docs/UI-DESIGN.md §2.11). White text and
     icons on each are >= 4.4:1 */
  --sk-reading: #3a3fcb; --sk-listening: #07756d; --sk-writing: #b4640a; --sk-speaking: #b8336a;
  --sk-vocabulary: #8a4a06; --sk-grammar: #2b2f8f; --sk-pronunciation: #6b4fd8; --sk-function: #0b7a3e;
  /* status tones: fg on bg >= 4.5:1 */
  --warning-fg: #8a5300; --warning-bg: #fff1d6; --info-fg: #1f5fbf; --info-bg: #e7eefb;
  --success-bg: #e4f4ea; --danger-bg: #fce9e7;
  --ice: #9fd3f5; --ice-ledge: #5aa5dc; --on-ice: #0f3d5c;
}
/* controls need a 3:1 boundary: --line, not the decorative --hair (docs/UI-DESIGN.md §4) */
.lcard .opt, .lcard .token, .lcard .stile, .mode, .lcard input[type="text"], .lcard select, .pairbtn, .rate { border-color: var(--line); }
.sheet.hint { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start; border-color: #c98500;
  background: color-mix(in srgb, var(--saffron) 14%, var(--card)); }
.sheet.hint > .ic { inline-size: 20px; block-size: 20px; color: #8a5300; margin-block-start: 4px; }
.sheet.hint strong { color: #8a5300; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .sheet.hint strong, :root:not([data-theme="light"]) .sheet.hint > .ic { color: #ffc84d; }
}
:root[data-theme="dark"] .sheet.hint strong, :root[data-theme="dark"] .sheet.hint > .ic { color: #ffc84d; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --warning-fg: #ffc84d; --warning-bg: #36290b; --info-fg: #8db2ff; --info-bg: #152447;
    --success-bg: #12301f; --danger-bg: #3a1519; --ice: #7cc2ee; --ice-ledge: #2f7fb8; --on-ice: #0f0e22; }
}
:root[data-theme="dark"] { --warning-fg: #ffc84d; --warning-bg: #36290b; --info-fg: #8db2ff; --info-bg: #152447;
  --success-bg: #12301f; --danger-bg: #3a1519; --ice: #7cc2ee; --ice-ledge: #2f7fb8; --on-ice: #0f0e22; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --on-done: #0f0e22; --tile-done: #22b8ad; --tile-done-ledge: #0b6e67; --lattice: var(--lattice-light); --sheet-shadow: 0 -18px 40px -20px rgb(0 0 0 / 0.7); }
}
:root[data-theme="dark"] { --on-done: #0f0e22; --tile-done: #22b8ad; --tile-done-ledge: #0b6e67; --lattice: var(--lattice-light); --sheet-shadow: 0 -18px 40px -20px rgb(0 0 0 / 0.7); }
.nav-login { white-space: nowrap; }
@media (max-width: 420px) { .nav-login .nl-more { display: none; } .nav { gap: 8px; } }
.defs { position: absolute; inline-size: 0; block-size: 0; overflow: hidden; }
.kicker { color: var(--teal); font-weight: 700; font-size: var(--fs-xs); }
/* ---- khatam tile ---------------------------------------------------------------------------------------------- */
.khatam { --tf: var(--card); --tl: var(--hair); --ti: var(--ink-2); --ts: var(--hair);
  position: relative; display: inline-grid; place-items: center; inline-size: 76px; aspect-ratio: 100 / 108; flex: none; }
.khatam svg { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; overflow: visible; }
.khatam .k-ledge { fill: var(--tl); stroke: var(--tl); stroke-width: 7; stroke-linejoin: round; }
.khatam .k-face { fill: var(--tf); stroke: var(--ts); stroke-width: 7; stroke-linejoin: round; transition: transform 140ms var(--ease-std); }
.khatam .k-glaze { fill: none; stroke: rgb(255 255 255 / 0.35); stroke-width: 2; stroke-linejoin: round; }
.khatam .ic { position: relative; inline-size: 30%; block-size: auto; aspect-ratio: 1; color: var(--ti); margin-block-end: 8%; stroke-width: 2.1; transition: transform 140ms var(--ease-std); }
.khatam.done { padding: 0; gap: 0; text-align: initial; --tf: var(--tile-done); --ts: var(--tile-done); --tl: var(--tile-done-ledge); --ti: var(--on-done, #fff); }
.khatam.current { --tf: var(--tile-sun); --ts: var(--tile-sun); --tl: var(--tile-sun-ledge); --ti: var(--on-sun); }
.khatam.placed { --tf: color-mix(in srgb, var(--tile-done) 18%, var(--card)); --ts: color-mix(in srgb, var(--tile-done) 45%, var(--hair));
  --tl: color-mix(in srgb, var(--tile-done) 35%, var(--hair)); --ti: var(--teal); }
.khatam.gold { --tf: var(--tile-gold); --ts: var(--tile-gold); --tl: var(--tile-gold-ledge); --ti: var(--on-sun); }
.khatam.open { --ts: color-mix(in srgb, var(--indigo) 22%, var(--hair)); --tl: color-mix(in srgb, var(--indigo) 30%, var(--hair)); --ti: var(--indigo); }
.khatam.open .k-glaze { stroke: color-mix(in srgb, var(--indigo) 14%, var(--hair)); }
.khatam.locked { --tf: var(--paper-2); --ts: var(--hair); --tl: var(--hair); --ti: var(--ink-2); }
.khatam.locked .k-glaze { stroke: transparent; }
.khatam.sm { inline-size: 56px; }
.khatam.xs { inline-size: 26px; }
.khatam.xs .ic { inline-size: 42%; }
.khatam.medal { inline-size: 92px; }
.khatam.lg { inline-size: 112px; }
/* ---- page head + segmented tabs ------------------------------------------------------------------------------ */
.seg-tabs { display: inline-flex; gap: 2px; padding: 3px; border-radius: 999px; background: var(--paper-2); border: 1px solid var(--hair);
  max-inline-size: 100%; overflow-x: auto; scrollbar-width: none; }
.seg-tabs::-webkit-scrollbar { display: none; }
.seg-tabs a { flex: none; white-space: nowrap; padding: 4px 14px; min-block-size: var(--ctl-sm); display: inline-flex; align-items: center; border-radius: 999px; text-decoration: none;
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); }
@media (hover: hover) and (pointer: fine) { .seg-tabs a:hover { color: var(--ink); } }
.seg-tabs a.on { background: var(--ink); color: var(--paper); }
/* lesson popover: a bottom sheet on every screen size (Popover API; path.js falls back to plain navigation) */
.pop { position: fixed; inset: auto 0 0; margin: 0 auto calc(12px + var(--safe-b)); inline-size: min(100% - 24px, 480px);
  padding: 18px; border: 1px solid var(--hair); border-radius: var(--r-xl); background: var(--card); color: var(--ink); box-shadow: var(--sheet-shadow), var(--shadow); direction: rtl; text-align: start; }
.pop:popover-open { display: grid; gap: 12px; }
html[data-motion="2"] .pop:popover-open, html[data-motion="3"] .pop:popover-open { animation: sheet-in 280ms var(--ease-out); }
.pop::backdrop { background: rgb(15 14 34 / 0.38); }
.pop-head { display: flex; gap: 12px; align-items: flex-start; }
.pop-head h3 { font-size: var(--fs-lg); line-height: 1.5; }
.pop p { color: var(--ink-2); }
.btn-sun { background: var(--tile-sun); color: var(--on-sun); font-weight: 700; }
.btn-sun:active { transform: scale(0.97); }
.continue-card .btn-sun { flex: none; }
@media (max-width: 560px) { .continue-card { flex-wrap: wrap; } .continue-card .btn { inline-size: 100%; } }
@media (forced-colors: active) { .lesson-wrap, .today-hero, .lvl-gate, .now-card, .htile::after { background-image: none; forced-color-adjust: auto; } }
.intro-hero.acc-us, .intro-hero.acc-uk, .intro-hero.acc-au, .intro-hero.acc-nz, .intro-hero.acc-ca, .intro-hero.acc-ie, .intro-hero.acc-sc, .intro-hero.acc-in, .intro-hero.acc-za, .intro-hero.acc-other { color: #fff; }
.media-banner { display: flex; gap: 12px; align-items: center; padding: 12px 14px; margin-block-end: 16px; border-radius: var(--r-lg); text-decoration: none; color: #f4f1fb;
  background: var(--lattice-light), linear-gradient(135deg, #14122b, #8e2756 80%); box-shadow: var(--e2); }
.media-banner b { color: #fff; font-size: var(--fs-md); }
.media-banner .small { color: #e7e3f5; }
.media-banner > .ic { margin-inline-start: auto; flex: none; }
.mb-ic { inline-size: 40px; block-size: 40px; border-radius: var(--r-md); display: grid; place-items: center; flex: none; background: var(--tile-sun); color: var(--on-sun); }
.intro-hero { position: relative; overflow: hidden; display: grid; gap: 10px; padding: clamp(16px, 2.2vw, 24px); border-radius: var(--r-card); color: var(--ink);
  background: var(--surface); box-shadow: var(--e1); }  /* Soft Precision: a light card, a large title */
.intro-hero h1 { font-size: var(--fs-h1); color: var(--ink); font-weight: 800; }
.intro-hero .en { color: var(--ink-2); }
.facts { display: flex; flex-wrap: wrap; gap: 8px; }
.facts div { padding: 10px 12px; border-radius: var(--r-ctl); background: var(--surface-2); display: grid; }
.facts b { font-size: var(--fs-lg); line-height: 1.3; }
.facts span { font-size: var(--fs-xs); color: var(--ink-2); }
/* ---- keyframes + motion tiers --------------------------------------------------------------------------------- */
@keyframes halo { 0%, 100% { transform: scale(0.92); opacity: 0.9; } 50% { transform: scale(1.12); opacity: 0.5; } }
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
@keyframes sheet-in { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes foot-up { from { transform: translateY(100%); } to { transform: none; } }
@keyframes medal-in { 0% { transform: scale(0.4) rotate(-45deg); opacity: 0; } 100% { transform: none; opacity: 1; } }
@media (hover: hover) and (pointer: fine) { html[data-motion="0"] .tile-btn:hover .k-face, html[data-motion="0"] .htile:hover, html[data-motion="0"] .ticket:hover, html[data-motion="0"] .qtile:hover, html[data-motion="0"] .continue-card:hover, html[data-motion="0"] .mode:hover { transform: none; } }
/* ==== additions: icon mirroring, new tile states, Today v2, select->check player, personal hub ================== */

/* direction-aware icons: the sprite is drawn LTR ("right" = forward); .ic-dir mirrors it in RTL, so one logical
   "next" icon is right in both the RTL app and the LTR test player */
.ic-dir:dir(rtl) { transform: scaleX(-1); }
@supports not selector(:dir(rtl)) { [dir="rtl"] .ic-dir { transform: scaleX(-1); } [dir="ltr"] .ic-dir { transform: none; } }
/* ---- tile states: in_progress (arc), review_due (saffron dot), frozen (week dots) ---- */
.khatam.in_progress { --ts: color-mix(in srgb, var(--indigo) 22%, var(--hair)); --tl: color-mix(in srgb, var(--indigo) 30%, var(--hair)); --ti: var(--indigo); }
.khatam .k-arc-track, .khatam .k-arc { fill: none; stroke-width: 5; transform: rotate(-90deg); transform-origin: 50px 50px; }
.khatam .k-arc-track { stroke: color-mix(in srgb, var(--tile-done) 18%, transparent); }
.khatam .k-arc { stroke: var(--tile-done); stroke-linecap: round; stroke-dasharray: calc(max(var(--arc, 0), 6) * 1px) 100px; }
.khatam.review_due { --tf: var(--tile-done); --ts: var(--tile-done); --tl: var(--tile-done-ledge); --ti: var(--on-done, #fff); }
.khatam .k-due { position: absolute; inset-block-start: 8%; inset-inline-start: 8%; inline-size: 12px; block-size: 12px; border-radius: 50%;
  background: var(--tile-sun); border: 2px solid var(--card); box-shadow: 0 0 0 1px var(--tile-sun-ledge); }
.khatam.xs .k-due { inline-size: 8px; block-size: 8px; border-width: 1px; inset-block-start: 0; inset-inline-start: 0; }
.khatam.frozen { --tf: var(--ice); --ts: var(--ice); --tl: var(--ice-ledge); --ti: var(--on-ice); }
.khatam.frozen .ic { stroke: currentColor; }
.pop-note { display: flex; gap: 8px; align-items: center; padding: 6px 10px; border-radius: var(--r-sm); background: var(--paper-2); font-size: var(--fs-sm); color: var(--ink); }
.pop-note.due { background: color-mix(in srgb, var(--saffron) 18%, var(--card)); }
.pop-note .ic { inline-size: 16px; block-size: 16px; flex: none; }
.pop h2 { font-size: var(--fs-lg); }
/* ---- practice hub + test list: personal data ---- */
.resume-bar { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; padding: 12px 14px; margin-block-end: 12px; border-radius: var(--r-lg); font-size: var(--fs-sm);
  background: var(--surface); border: 0; box-shadow: var(--e1); }  /* resumable work: a resting card, the accent button */
.resume-bar .rb-text { display: grid; gap: 2px; flex: 1 1 220px; min-inline-size: 0; }
.resume-bar .rb-text small { color: var(--ink-2); }
.resume-bar .bar { flex: none; inline-size: 100%; block-size: 4px; }
.resume-bar .btn-sun { min-block-size: var(--ctl); }
.chip-rail { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; padding-block: 2px; margin-block-end: 16px; scroll-snap-type: x proximity;
  mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent); padding-inline: 0 24px; }
.chip-rail::-webkit-scrollbar { display: none; }
.chip-rail .pill { flex: none; white-space: nowrap; scroll-snap-align: start; }
.tag.new { background: var(--info-bg); color: var(--info-fg); }
.tag.prog { background: var(--warning-bg); color: var(--warning-fg); }
/* lesson / test hero facts: an even grid instead of a ragged wrap */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); }
.facts div { min-inline-size: 0; }
/* the English subtitle under a Persian title starts on the same (right) edge */
.lh-en, .intro-hero h1 + .en, .intro-hero p.en { text-align: right; }
/* chat: the play button inside a partner bubble is a compact inline control */
.bubble .play-btn { min-block-size: 32px; min-inline-size: 32px; padding-inline: 6px; border-width: 1px; vertical-align: middle; margin-inline-start: 6px; display: inline-flex; }
.bubble .play-btn .ic { inline-size: 16px; block-size: 16px; }
.bubble.partner { box-shadow: 0 1px 2px rgb(20 18 43 / 0.05); }
.coach { border: 1px solid color-mix(in srgb, var(--saffron) 45%, var(--hair)); line-height: 1.9; }
.coach bdi { font-family: var(--f-en, "Atkinson Next", system-ui, sans-serif); }
.composer { padding-block: 10px; }
.composer input { border-radius: 999px; padding-inline: 18px; }
.composer .btn { min-inline-size: 44px; padding-inline: 12px; }
.has-tabbar .composer { inset-block-end: calc(62px + var(--safe-b)); }
@media (min-width: 900px) { .has-tabbar .composer { inset-block-end: 0; } }
/* the 7-day XP bars never grew: a %-height needs a definite grid track */
.weekbars .wb { grid-template-rows: minmax(0, 1fr) auto; align-content: stretch; }
.weekbars .wb i { align-self: end; inline-size: min(22px, 64%); border-radius: 6px 6px 2px 2px;
  background: linear-gradient(to bottom, color-mix(in srgb, var(--indigo) 75%, var(--card)), var(--indigo)); }
.weekbars .wb.today i { background: linear-gradient(to bottom, color-mix(in srgb, var(--tile-done) 70%, var(--card)), var(--tile-done)); }
.weekbars .wb.today small { color: var(--ink); font-weight: 800; }
/* stat strip: a few numbers + one action (vocab decks, notebook) */
.stat-strip { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; justify-content: space-between; padding: 10px; margin-block-end: 16px;
  border-radius: var(--r-lg); background: var(--card); border: 1px solid var(--hair); box-shadow: var(--e1); }
.stat-strip dl { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 0; flex: 1 1 320px; }
.stat-strip dl > div { padding: 8px 10px; border-radius: var(--r-md); background: var(--well); display: grid; gap: 0; min-inline-size: 0; }
.stat-strip dl > div.hot { background: color-mix(in srgb, var(--saffron) 20%, var(--card)); }
.stat-strip dt { font-size: var(--fs-xs); color: var(--ink-2); font-weight: 500; line-height: 1.5; }
.stat-strip dd { margin: 0; font: 700 var(--fs-xl)/1.25 var(--f-display); }
.stat-strip dd small { font-size: var(--fs-xs); font-weight: 500; color: var(--ink-2); }
.stat-strip > .btn { flex: 1 1 auto; max-inline-size: 280px; }
@media (max-width: 559px) { .stat-strip > .btn { max-inline-size: none; inline-size: 100%; } }
/* ==== "small and classy" refinement (docs/UI-DESIGN.md §۷): touch sizes for controls that live in scroll rails or
   segmented groups, where an invisible hit area would be clipped. Mouse users get the compact 34px sizes. ========== */
@media (pointer: coarse) {
  .seg-tabs { padding: 2px; }
  .seg-tabs a, .pill, .rv-filter button, .seg button, .tab, .bl-chips a { min-block-size: 40px; }
  .rv-filter { padding: 2px; }
}
/* ==== Apple-grade component layer (docs/DESIGN-APPLE.md §4–5) ====================================================
   Loaded last of the global sheets (base.html: app, ui, kashi) so it wins over both at equal specificity. One place that turns the existing components into grouped, borderless surfaces: resting cards lose their outline
   and get the soft --e1 lift (dark mode keeps a 0.5px light edge through --e1), nothing lifts on hover, pressing a
   tappable surface scales it down at once (feedback on pointer-down), segmented controls are iOS segments. */
:is(.card, .lrow, .lcardx, .tcard, .passage, .qtile, .htile, .prompt-card, .fbcard, .stat, .notice, .track-meter, .chart, .table-wrap,
  .rv-item, .issue, .auth-card, .next-item, .plan-day, .statchip, .todo a, .now-card, .empty-mini, .toast, .lockbox) {
  border-color: transparent; box-shadow: var(--e1);
}
:is(.card, .lrow, .lcardx, .htile, .qtile, .tcard, .passage, .prompt-card, .fbcard, .notice, .auth-card, .chart, .table-wrap) { border-radius: var(--r-lg); }
.card.link, .lcardx, .lrow, .htile, .qtile, .next-item, .todo a, .continue-card {
  transition: transform var(--dur-2) var(--spring), box-shadow var(--dur-2) var(--ease-std), background-color var(--dur-2) var(--ease-std); }
@media (hover: hover) and (pointer: fine) { .card.link:hover, .lcardx:hover, .lrow:hover, .htile:hover, .qtile:hover, .next-item:hover, .continue-card:hover, .bcard:hover, .note:hover, .stile:hover, .rate:hover, button.opt:hover:not([disabled]), .chip:hover:not(:disabled) { transform: none; } }
@media (hover: hover) and (pointer: fine) {
  .card.link:hover, .lcardx:hover, .lrow:hover, .htile:hover, .qtile:hover, .next-item:hover, .todo a:hover { box-shadow: var(--e2); border-color: transparent; }
}
.card.link:active, .lcardx:active, .lrow:active, .htile:active, .qtile:active, .next-item:active, .todo a:active, .continue-card:active {
  transform: scale(0.98); transition-duration: var(--dur-1); }
/* touch (mobile-native §1, §5, §8): hover belongs to fine pointers only, so every other tappable control answers on
   pointer-down here; controls (never content) don't start a text selection or the callout menu on long-press */
.pill:active, .tab:active, .seg-tabs a:active, .seg button:active, .token:active:not([disabled]), .stile:active, .rate:active,
button.opt:active:not([disabled]), .rv-choice:active:not(:disabled), .sugg:active, .wr-insert:active, .pr-sw:active, .btn-glass:active,
.talk-ic:active, .tpt-bar button:active, .tpt-x:active, .bl-chips a:active, .bl-tags a:active, .bl-pages a:active {
  transform: scale(0.96); transition-duration: var(--dur-1); }
.sp-topic:active, .sp-cue:active, .wr-card:active, .bl-pn a:active, .recent-list a:active, a.st-row:active, .mini-trail:active {
  transform: scale(0.98); transition-duration: var(--dur-1); }
.qopt:active, .choices label:active, .talk-switch:active, .sib-trail a:active, details.more > summary:active {
  background: color-mix(in srgb, var(--ink) 7%, transparent); }
.tabbar a, .tab, .seg-tabs a, .seg button, .pill, .btn, .icon-btn, .tile-btn, .opt, .token, .stile, .rate, .rv-choice, .choices label,
.chips-pick label, .sp-fab, .tpt-bar button {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.htile::after { display: none; }
.htile { padding: 16px; gap: 6px; }
.htile .hic { border-radius: 11px; box-shadow: none; }
.htile .count { background: color-mix(in srgb, var(--h) 12%, transparent); }
.qtile.hot { box-shadow: var(--e1), inset 0 0 0 1.5px color-mix(in srgb, var(--saffron) 70%, transparent); }
.lcardx.done { box-shadow: var(--e1), inset 0 0 0 1.5px color-mix(in srgb, var(--ok) 45%, transparent); }
.todo a { background: var(--card); }
.card h2 { font-size: var(--fs-lg); }
.page { padding-block: 12px 64px; }
.page-head { gap: 8px; margin-block-end: 24px; }
.page-head .kicker { color: var(--ink-2); font-weight: 600; }
.crumbs { font-size: var(--fs-xs); }
/* segmented controls (iOS): a fill track; the selected segment is a raised card, not an inverted pill */
.seg-tabs, .seg { display: inline-flex; gap: 0; padding: 2px; border: 0; border-radius: 10px; background: color-mix(in srgb, var(--ink) 7%, transparent); overflow-x: auto; }
.seg-tabs a, .seg button { border: 0; background: transparent; border-radius: 8px; min-block-size: 32px; padding: 4px 14px; font-weight: 500; font-size: var(--fs-sm); color: var(--ink);
  transition: background-color var(--dur-2) var(--ease-std), box-shadow var(--dur-2) var(--ease-std); }
.seg-tabs a.on, .seg button[aria-pressed="true"], .seg button[aria-selected="true"] { background: var(--card); color: var(--ink); font-weight: 650;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.12), 0 0 0 0.5px rgb(0 0 0 / 0.04); }
:root[data-theme="dark"] :is(.seg-tabs a.on, .seg button[aria-pressed="true"]) { background: #636366; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) :is(.seg-tabs a.on, .seg button[aria-pressed="true"]) { background: #636366; } }
@media (pointer: coarse) { .seg-tabs a, .seg button { min-block-size: 40px; } }
/* filter chips: capsules on a fill; the selected one takes the accent */
.pill { border: 0; background: color-mix(in srgb, var(--ink) 6%, transparent); color: var(--ink); font-weight: 500; transition: background-color var(--dur-2), color var(--dur-2); }
@media (hover: hover) and (pointer: fine) { .pill:hover { background: color-mix(in srgb, var(--ink) 10%, transparent); border-color: transparent; } }
.pill.on { background: var(--indigo); color: var(--on-indigo); border-color: transparent; box-shadow: none; font-weight: 650; }
.tag { font-weight: 500; }
/* inputs: 12px corners, a quiet edge, an accent halo on focus */
:is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="file"], [type="hidden"]), .input, select, textarea) {
  border-radius: 12px; border-color: color-mix(in srgb, var(--line) 55%, transparent); }
input:focus-visible, .input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--indigo); box-shadow: 0 0 0 4px color-mix(in srgb, var(--indigo) 22%, transparent); }
.choices label, .choice { border-radius: 12px; }
.choices label:has(input:checked), .choice:has(input:checked) { background: var(--tint); border-color: var(--indigo); }
/* empty states: no dashed box, just the symbol, a title, one line, one action */
.empty { border: 0; background: transparent; }
.empty > .ic:first-child { box-shadow: none; background: var(--tint); border-radius: 50%; }
.lockbox { border: 0; background: color-mix(in srgb, var(--saffron) 12%, var(--card)); }
/* dialogs: a centred card on desktop, a bottom sheet on phones */
.tp-dialog { border-radius: var(--r-xl); box-shadow: var(--e2); padding: 24px; }
.tp-dialog::backdrop { background: var(--scrim); }
@media (max-width: 599px) {
  .tp-dialog { margin: auto 0 0; inline-size: 100%; max-inline-size: 100%; border-end-start-radius: 0; border-end-end-radius: 0;
    padding-block-end: calc(24px + var(--safe-b)); }
  html:not([data-motion="0"]) .tp-dialog[open] { animation: sheet-rise var(--dur-3) var(--spring); }
}
/* the popover sheets of the learner layer (.pop) get the same treatment */
.pop { box-shadow: var(--e3); }
.pop::backdrop { background: var(--scrim); }
/* toasts */
.toast { border: 0; border-radius: var(--r-md); }
/* auth: a calm card, no glazed band */
.auth-card { border-radius: var(--r-xl); padding: 28px 24px; box-shadow: var(--e2); }
.auth-card::before { display: none; }
.auth-wrap { background: none; }
/* sticky learner bars over content use the material */
.start-bar, .court-head { border: 0; background: var(--mat-card); -webkit-backdrop-filter: var(--mat-blur); backdrop-filter: var(--mat-blur); box-shadow: var(--e2); }
.has-tabbar .start-bar { inset-block-end: calc(var(--tabbar-h) + var(--safe-b) + 12px); }
.court-head { inset-block-start: calc(var(--header-h) + var(--safe-t) + 8px); }
.lfoot { border-block-start: 0; box-shadow: var(--e3); border-start-start-radius: var(--r-xl); border-start-end-radius: var(--r-xl); }
/* tables: hairline rows */
.table th { background: transparent; font-weight: 600; }
.table th, .table td { border-block-end: 0.5px solid var(--sep); }
:is(.ticket, .deckc, .mode, .resume-bar, .stat-strip, .estimate-note) { border-color: transparent; box-shadow: var(--e1); }
.ticket::before { display: none; }
.ticket, .deckc { transition: transform var(--dur-2) var(--spring), box-shadow var(--dur-2) var(--ease-std); }
@media (hover: hover) and (pointer: fine) { .ticket:hover, .deckc:hover, .mode:hover { transform: none; } }
@media (hover: hover) and (pointer: fine) { .ticket:hover, .deckc:hover { box-shadow: var(--e2); border-color: transparent; } }
.ticket:active, .deckc:active { transform: scale(0.98); transition-duration: var(--dur-1); }
.ticket .tk-meta { border-block-start: 0.5px solid var(--sep); }
.deckc.on, .mode:has(input:checked) { box-shadow: var(--e1), inset 0 0 0 1.5px color-mix(in srgb, var(--h, var(--indigo)) 60%, transparent); }
.estimate-note { background: color-mix(in srgb, var(--saffron) 12%, var(--card)); }
/* large titles carry no decorative icon (Apple: the title is the symbol) */
.page-head h1 > .ic:first-child, .path-head h1 > .ic:first-child { display: none; }
/* inside the Android app (html.in-app, set by the boot script from the user agent): no website footer; its pages move
   into the menu sheet (.app-only), which is hidden on the website */
.in-app .site-footer { display: none; }
html:not(.in-app) .app-only { display: none; }
/* Android 15+ draws the page under a transparent status bar. Inside the app keep a strip of page ground behind it, so the
   icons (dark on light pages, light on dark ones: fx.js syncSystemBars) never sit on a dark card scrolling past.
   --safe-area-inset-top is injected by Capacitor (SystemBars insetsHandling "css"). */
.in-app body::before { content: ""; position: fixed; z-index: 2147483000; inset-block-start: 0; inset-inline: 0;
  block-size: var(--safe-area-inset-top, env(safe-area-inset-top, 0px)); background: var(--paper); pointer-events: none; }
.lfoot-msg { min-inline-size: 0; }
.lfoot-msg > div, .lfoot .ans, .lfoot-msg p { min-inline-size: 0; overflow-wrap: anywhere; }
/* programmatic focus targets (the question title after each swap, the done heading) draw no ring; real controls keep
   their :focus-visible ring */
[tabindex="-1"]:focus, [tabindex="-1"]:focus-visible { outline: none; }
/* long English options, tokens and prompts wrap instead of pushing the page sideways */
.opt > span, .token, .stile, .qtext, .prompt-big, .tline, .pool { overflow-wrap: anywhere; min-inline-size: 0; }
/* a two-line button label (e.g. «درس بعدی: …») gets breathing room instead of touching the capsule edge */
.btn { padding-block: 8px; }
.btn-sm { padding-block: 5px; }
/* bottom sheets never grow past the screen */
.pop { max-block-size: calc(100dvh - var(--safe-t) - var(--safe-b) - 24px); overflow-y: auto; overscroll-behavior: contain; }
@media (max-width: 979px) {
  /* reading on a phone: the Passage / Questions switch stays under the top bar while either pane scrolls */
  .tp-tabs { position: sticky; inset-block-start: calc(var(--tp-top-h, 53px) + var(--safe-t)); z-index: 19; display: flex; margin: 0;
    padding: 6px 12px; border-radius: 0; background: var(--mat); -webkit-backdrop-filter: var(--mat-blur); backdrop-filter: var(--mat-blur); }
  .tp-tabs button { flex: 1 1 0; }
  .tp-pane { padding: 16px 16px 32px; }
  .qitem { scroll-margin-block: calc(120px + var(--safe-t)) 90px; }
}
@media (max-width: 899px) {
  .has-tabbar .composer { inset-block-end: calc(var(--tabbar-h) + var(--safe-b)); }
  .has-tabbar .to-current { inset-block-end: calc(var(--tabbar-h) + var(--safe-b) + 12px); }
}
/* htmx loading lines (htmx's own indicator styles are off: htmx-config includeIndicatorStyles=false) */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: inline; }
/* on-screen keyboard (phones): typing hides the tab bar, and the bars that sat above it drop to the keyboard edge.
   In the app the WebView shrinks above the keyboard (and in Chrome with interactive-widget=resizes-content), so
   without this the tab bar rode on top of the keyboard and ate a fifth of what was left of the screen. */
@media (max-width: 899px) and (pointer: coarse) {
  body:has(:is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="button"], [type="submit"], [type="file"], [type="hidden"]), textarea, [contenteditable="true"]):focus) {
    padding-block-end: 0 !important;
  }
  body:has(:is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="button"], [type="submit"], [type="file"], [type="hidden"]), textarea, [contenteditable="true"]):focus) .tabbar { display: none; }
  body:has(:is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="button"], [type="submit"], [type="file"], [type="hidden"]), textarea, [contenteditable="true"]):focus)
    :is(.composer-wrap, .composer) { inset-block-end: 0; }
  body:has(:is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="button"], [type="submit"], [type="file"], [type="hidden"]), textarea, [contenteditable="true"]):focus)
    .start-bar { inset-block-end: 8px; }
}
/* touch screens: keyboard-shortcut badges are noise, and buttons that scripts focus after a swap («ادامه», the suggested
   rating, «نمایش پاسخ») must not look pressed or selected; keyboard users on a fine pointer keep both */
@media (pointer: coarse) {
  .opt kbd, .rate kbd, .tfbtns kbd { display: none; }
  :is(#continue, #check, #reveal, #rv-answer, .rate, .rv-choice, .lfoot .btn):focus-visible { outline: none; }
}
/* the kids door (templates/_kids_entry.html): landing hero + dashboard; a warm, playful row that reads as "for children" */
.kids-entry { display: flex; align-items: center; gap: 12px; inline-size: fit-content; max-inline-size: 100%;
  margin-block-start: 16px; padding: 8px 12px 8px 16px; padding-inline: 8px 16px; border-radius: 999px;
  text-decoration: none; color: var(--ink);
  background: var(--surface); box-shadow: var(--e1);   /* Soft Precision: a resting card; the smiling sun carries the play */
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .kids-entry:hover { box-shadow: var(--e2); } }
.kids-entry:active { transform: scale(0.98); }
.kids-entry .ke-face { inline-size: 44px; block-size: 44px; flex: none; }
.kids-entry .ke-face svg { inline-size: 100%; block-size: 100%; overflow: visible; }
.kids-entry .ke-rays { stroke: var(--tile-sun); stroke-width: 3; stroke-linecap: round; transform-origin: 24px 24px; }
.kids-entry .ke-sun { fill: var(--tile-sun); stroke: var(--tile-sun-ledge); stroke-width: 1.5; }
.kids-entry .ke-eye { fill: #2b1d05; }
.kids-entry .ke-cheek { fill: #ff7aa8; opacity: 0.75; }
.kids-entry .ke-smile { fill: none; stroke: #2b1d05; stroke-width: 2; stroke-linecap: round; }
.kids-entry .ke-text { display: grid; gap: 1px; min-inline-size: 0; }
.kids-entry b { font-size: var(--fs-md); line-height: 1.4; }
.kids-entry small { color: var(--ink-2); font-size: var(--fs-xs); }
.kids-entry > .ic { flex: none; inline-size: 18px; block-size: 18px; opacity: 0.6; }
@keyframes ke-spin { to { transform: rotate(360deg); } }
html:not([data-motion="0"]) .kids-entry .ke-rays { animation: ke-spin 14s linear infinite; }
@media (prefers-reduced-motion: reduce) { .kids-entry .ke-rays { animation: none !important; } }
.page > .kids-entry { inline-size: 100%; border-radius: var(--r-lg); margin-block-start: 0; }

/* ==== «Soft Precision» sitewide layer (design system «الف · نرم و دقیق», founder decision 2026-10-28) ================
   Last of the global sheets, so it settles every shared component at equal specificity: one accent (indigo) for
   actions, turquoise only for progress, saffron only for rewards; capsule buttons, filled quiet chips, iOS segments,
   3:1 field borders, 3px focus rings, 44-48px targets, 240ms cubic-bezier(.22,1,.36,1), press = scale(.97).
   Every rule starts with :where(body:not(.kz, .kzp, .kzl, .tp-page)) (zero specificity): the kids section keeps its own look
   until its own pass. Page sheets that load later (today.css, tools.css, ...) still win where they need to. */

/* focus: a 3px accent ring, 2px off the control */
:where(body:not(.kz, .kzp, .kzl, .tp-page)) :focus-visible { outline-width: var(--ring-w); outline-color: var(--ring); }

/* buttons: capsules, 700, at least 44px; the primary call to action is always the accent, never saffron */
:where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn { font-weight: 700; min-block-size: max(var(--ctl), 44px);
  transition: transform var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out), filter var(--dur-2) var(--ease-out); }
:where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn-sm { min-block-size: var(--ctl-sm); }
:where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn-lg { min-block-size: 52px; }
:where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn:active:not([disabled]) { transform: var(--press); }
:where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn-ghost { background: var(--accent-soft); color: var(--accent-ink); }
@media (hover: hover) and (pointer: fine) {
  :where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn-ghost:hover { background: color-mix(in srgb, var(--accent) 18%, var(--accent-soft)); }
}
:where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn-sun { background: var(--accent); color: var(--on-accent); }
@media (hover: hover) and (pointer: fine) { :where(body:not(.kz, .kzp, .kzl, .tp-page)) .btn-sun:hover { filter: brightness(1.08); } }

/* inputs: 12px corners, a 3:1 edge, 17px text (no zoom on focus), 48px on touch; the accent ring on focus */
:where(body:not(.kz, .kzp, .kzl, .tp-page)) :is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="file"], [type="hidden"], [type="submit"], [type="button"]), .input, select, textarea) {
  border: 1px solid var(--field-bd); border-radius: var(--r-ctl); background-color: var(--surface); font-size: var(--fs-md); }
:where(body:not(.kz, .kzp, .kzl, .tp-page)) :is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="file"], [type="hidden"], [type="submit"], [type="button"]), .input, select) {
  min-block-size: 44px; padding-inline: 14px; }
@media (pointer: coarse) {
  :where(body:not(.kz, .kzp, .kzl, .tp-page)) :is(input:not([type="radio"], [type="checkbox"], [type="range"], [type="file"], [type="hidden"], [type="submit"], [type="button"]), .input, select) { min-block-size: 48px; }
}
:where(body:not(.kz, .kzp, .kzl, .tp-page)) :is(input, .input, select, textarea):focus-visible {
  outline: 2px solid transparent; border-color: var(--accent); box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--accent) 30%, transparent); }
:where(body:not(.kz, .kzp, .kzl, .tp-page)) select:not([multiple]):not(.tp select) { padding-inline: 14px 36px; }
:where(body:not(.kz, .kzp, .kzl, .tp-page)) .field > label, :where(body:not(.kz, .kzp, .kzl, .tp-page)) .field > .label { font-weight: 700; }

/* cards: borderless surfaces with the soft layered shadow (the kashi component layer above sets the shadow) */
:where(body:not(.kz, .kzp, .kzl)) .card { border-radius: var(--r-card); }

/* badges and chips: quiet fills, never loud pills */
:where(body:not(.kz, .kzp, .kzl)) .tag { background: var(--fill-q); color: var(--ink); font-weight: 600; }
:where(body:not(.kz, .kzp, .kzl)) .tag.premium { background: var(--warn-soft); color: var(--warn-ink); }
:where(body:not(.kz, .kzp, .kzl)) .tag.ok { background: var(--ok-soft); color: var(--ok-ink); }
:where(body:not(.kz, .kzp, .kzl)) .tag.bad { background: var(--bad-soft); color: var(--bad-ink); }
:where(body:not(.kz, .kzp, .kzl)) .tag.new { background: var(--accent-soft); color: var(--accent-ink); }
:where(body:not(.kz, .kzp, .kzl)) .tag.prog { background: color-mix(in srgb, var(--teal) 14%, transparent); color: var(--teal-ink); }
:where(body:not(.kz, .kzp, .kzl)) .lvl { background: var(--fill-q); color: var(--ink); border-radius: 6px; font-weight: 800; }
:where(body:not(.kz, .kzp, .kzl)) .pill { background: var(--fill-q); color: var(--ink); font-weight: 600; }
:where(body:not(.kz, .kzp, .kzl)) .pill.on { background: var(--accent-soft); color: var(--accent-ink); font-weight: 700; }
@media (hover: hover) and (pointer: fine) {
  :where(body:not(.kz, .kzp, .kzl)) .pill:not(.on):hover { background: color-mix(in srgb, var(--ink) 11%, transparent); }
}

/* segmented controls: a fill track, 12px segments, the chosen one a raised chip (the filter bar's .fbar-seg already is) */
:where(body:not(.kz, .kzp, .kzl)) :is(.seg-tabs, .seg) { padding: 3px; gap: 2px; border-radius: calc(var(--r-ctl) + 3px); background: var(--fill-q); }
:where(body:not(.kz, .kzp, .kzl)) :is(.seg-tabs a, .seg button) { border-radius: var(--r-ctl); color: var(--ink-2); font-weight: 700; min-block-size: 36px; }
:where(body:not(.kz, .kzp, .kzl)) :is(.seg-tabs a.on, .seg button[aria-pressed="true"], .seg button[aria-selected="true"]) {
  background: var(--seg-on); color: var(--ink); box-shadow: var(--sh-seg); }
@media (pointer: coarse) { :where(body:not(.kz, .kzp, .kzl)) :is(.seg-tabs a, .seg button) { min-block-size: 40px; } }

/* toasts: a dark floating capsule (light in dark mode), the state as a small dot */
:where(body:not(.kz, .kzp, .kzl)) .toast { background: var(--toast-bg); color: var(--toast-ink); border-radius: var(--r-pop); box-shadow: var(--e2);
  font-weight: 600; padding: 12px 18px; }
:where(body:not(.kz, .kzp, .kzl)) .toast::before { background: var(--toast-acc); }
:where(body:not(.kz, .kzp, .kzl)) .toast.success::before { background: var(--toast-ok); }
:where(body:not(.kz, .kzp, .kzl)) .toast.error::before { background: var(--bad); }
:where(body:not(.kz, .kzp, .kzl)) .toast.warning::before { background: var(--saffron); }
:where(body:not(.kz, .kzp, .kzl)) :is(.toast.success, .toast.error, .toast.warning) { background: var(--toast-bg); }

/* empty states: the symbol in a soft accent disc, a title, one line, one action */
:where(body:not(.kz, .kzp, .kzl)) .empty > .ic:first-child { background: var(--accent-soft); color: var(--accent-ink); }
:where(body:not(.kz, .kzp, .kzl)) .empty-mini { background: var(--surface-2); }
:where(body:not(.kz, .kzp, .kzl)) .empty-mini .ic { color: var(--accent-ink); }
:where(body:not(.kz, .kzp, .kzl)) .lockbox { background: var(--warn-soft); color: var(--ink); }

/* progress is turquoise; rewards (streak, XP, gold) saffron */
:where(body:not(.kz, .kzp, .kzl)) .bar { background: var(--fill-q); }
:where(body:not(.kz, .kzp, .kzl)) .bar > i { background: var(--teal-deco); }

/* the khatam tiles stay the path's markers, calmer: the current lesson takes the accent (saffron is for rewards), done
   tiles are turquoise, open ones a quiet outline, locked a fill; the glaze highlight is gone */
:where(body:not(.kz, .kzp, .kzl)) .khatam.current { --tf: var(--accent); --ts: var(--accent); --tl: color-mix(in srgb, var(--accent) 70%, #000); --ti: var(--on-accent); }
:where(body:not(.kz, .kzp, .kzl)) .khatam .k-glaze { stroke: transparent; }
:where(body:not(.kz, .kzp, .kzl)) .khatam.open { --tf: var(--surface); --ts: color-mix(in srgb, var(--accent) 26%, var(--hair)); --tl: transparent; --ti: var(--accent-ink); }
:where(body:not(.kz, .kzp, .kzl)) .khatam.locked { --tf: var(--fill-q); --ts: transparent; --tl: transparent; }

/* grouped lists: 50px rows on phones, 0.5px inset separators */
:where(body:not(.kz, .kzp, .kzl)) .glist .ic { color: var(--accent-ink); }

/* the tab bar: the current tab wears the soft accent */
:where(body:not(.kz, .kzp, .kzl)) .tab-lens { background: var(--accent-soft); box-shadow: none; }
:where(body:not(.kz, .kzp, .kzl)) .tabbar:not(.has-lens) a[aria-current="page"] { background: var(--accent-soft); }
:where(body:not(.kz, .kzp, .kzl)) .tabbar a:is([aria-current="page"], .is-target, [aria-expanded="true"]) { color: var(--accent-ink); }

/* reading text: 17px for prose */
:where(body:not(.kz, .kzp, .kzl)) .prose { font-size: var(--fs-md); }
:where(body:not(.kz, .kzp, .kzl)) .page-head h1 { font-weight: 800; }
:where(body:not(.kz, .kzp, .kzl)) .page-head .kicker { color: var(--accent-ink); }
