/* Baloo Bhaijaan 2 and Baloo Da 2 (SIL Open Font License, see fonts/OFL.txt),
   bundled so it works offline. */
@font-face {
  font-family: "Baloo Bhaijaan 2";
  src: url("fonts/BalooBhaijaan2.woff2") format("woff2");
  font-weight: 400 800;
  font-display: block;
}

/* The same font for interface text, with its vertical space balanced around
   the letters, so text sits truly centred in rows, buttons and the ayah marker.
   (Baloo normally reserves extra room below for Arabic, which pushes text up.) */
@font-face {
  font-family: "Baloo UI";
  src: url("fonts/BalooBhaijaan2.woff2") format("woff2");
  font-weight: 400 800;
  font-display: block;
  ascent-override: 95%;
  descent-override: 35%;
  line-gap-override: 0%;
}

/* Bengali letters come from Baloo Da 2, the same design's Bengali sibling.
   Only downloaded when Bengali text is on screen (unicode-range). */
@font-face {
  font-family: "Baloo Bengali";
  src: url("fonts/BalooDa2-Bengali.woff2") format("woff2");
  font-weight: 400 800;
  font-display: block;
  unicode-range: U+0964-0965, U+0980-09FF, U+25CC;
}

/* Hausa's hooked letters (ɓ ɗ ƙ), which Baloo doesn't have, from the rounded
   M PLUS Rounded 1c (OFL, see fonts/OFL-MPLUSRounded1c.txt): just those six. */
@font-face { font-family: "Hausa Letters"; src: url("fonts/MPLUSRounded1c-HausaLetters-Regular.woff2") format("woff2"); font-weight: 400; font-display: block; unicode-range: U+0181, U+018A, U+0198-0199, U+0253, U+0257; }
@font-face { font-family: "Hausa Letters"; src: url("fonts/MPLUSRounded1c-HausaLetters-Medium.woff2") format("woff2"); font-weight: 500; font-display: block; unicode-range: U+0181, U+018A, U+0198-0199, U+0253, U+0257; }
@font-face { font-family: "Hausa Letters"; src: url("fonts/MPLUSRounded1c-HausaLetters-Bold.woff2") format("woff2"); font-weight: 600 800; font-display: block; unicode-range: U+0181, U+018A, U+0198-0199, U+0253, U+0257; }

/* Devanagari (Hindi) and Tamil from Baloo 2 and Baloo Thambi 2, the same
   design's siblings (OFL, fonts/OFL.txt). Only downloaded when shown. */
@font-face {
  font-family: "Baloo Devanagari";
  src: url("fonts/Baloo2-Devanagari.woff2") format("woff2");
  font-weight: 400 800;
  font-display: block;
  unicode-range: U+0900-097F, U+1CD0-1CF9, U+A8E0-A8FF, U+25CC;
}
@font-face {
  font-family: "Baloo Tamil";
  src: url("fonts/BalooThambi2-Tamil.woff2") format("woff2");
  font-weight: 400 800;
  font-display: block;
  unicode-range: U+0B80-0BFF;
}

/* Cyrillic (Russian, Uzbek) from Nunito (OFL, see fonts/OFL-Nunito.txt), a
   soft rounded sans close to Baloo. Only Cyrillic letters, only when shown. */
@font-face {
  font-family: "Nunito Cyrillic";
  src: url("fonts/Nunito-Cyrillic.woff2") format("woff2");
  font-weight: 400 800;
  font-display: block;
  unicode-range: U+0400-052F, U+2116;
}

/* Pashto and Kurdish (Sorani) letters aren't in Baloo, and Arabic-script words
   can't mix fonts without breaking the joins, so text in those languages uses
   Vazirmatn (OFL, see fonts/OFL-Vazirmatn.txt) throughout. The Arabic of the
   adhkar itself stays in Baloo. */
@font-face {
  font-family: "Vazirmatn";
  src: url("fonts/Vazirmatn-Arabic.woff2") format("woff2");
  font-weight: 400 800;
  font-display: block;
}

:root {
  /* 1 for left-to-right languages, -1 for right-to-left: mirrors the slides. */
  --dir: 1;
  --bg: #e6efe6;
  --ink: #3d3a36;
  --muted: #69645e; /* darkest page tint still gives 4.5:1 (WCAG AA) */
  --accent: #8fb39a;
  --soft: rgba(255, 255, 255, 0.55);
  --sheet: #fbf9f6;
  --track: rgba(0, 0, 0, 0.06);
  --scale: 1;
  /* Motion: every animation uses these, so the same kind of movement always
     has the same speed and feel. */
  --t-hover: 0.12s;  /* hover and press feedback */
  --t-quick: 0.16s;  /* quick swaps: digits ticking, fade-outs, tooltips */
  --t-icon: 0.25s;   /* icons and check marks changing */
  --t-move: 0.3s;    /* layout: lines appearing, sizes changing, rows opening */
  --t-sheet: 0.32s;  /* panels and their backdrop */
  --t-pop: 0.4s;     /* small celebrations: dots, ring and bar bouncing */
  --ease-settle: cubic-bezier(0.22, 1, 0.36, 1);   /* moves quickly, settles softly */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* a little overshoot */
  --ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);    /* panels sliding */
  --hover: rgba(0, 0, 0, 0.07);
  --soft-hover: rgba(255, 255, 255, 0.92);
  /* Inside panels: neutral, independent of the page's pastel tint. */
  --fill: rgba(0, 0, 0, 0.05);
  --fill-hover: rgba(0, 0, 0, 0.085);
  --raised: #ffffff;
  --font: "Baloo UI", "Baloo Bengali", "Baloo Devanagari", "Baloo Tamil", "Hausa Letters", "Nunito Cyrillic", "Baloo Bhaijaan 2", ui-rounded, -apple-system, system-ui, "PingFang SC", "Hiragino Sans", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
  --arabic: "Baloo Bhaijaan 2", "Geeza Pro", "Noto Sans Arabic", sans-serif;
}

/* Dark colours: used when Appearance is Dark, or Auto and the device is dark. */
:root[data-theme="dark"] {
    --bg: #1f2622;
    --ink: #ece7df;
    --muted: #a39c92;
    --accent: #9cc3a7;
    --soft: rgba(255, 255, 255, 0.08);
    --sheet: #2a2b2e;
    --track: rgba(255, 255, 255, 0.08);
    --hover: rgba(255, 255, 255, 0.1);
    --soft-hover: rgba(255, 255, 255, 0.18);
    --fill: rgba(255, 255, 255, 0.07);
    --fill-hover: rgba(255, 255, 255, 0.11);
    --raised: rgba(255, 255, 255, 0.16);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
      --bg: #1f2622;
      --ink: #ece7df;
      --muted: #a39c92;
      --accent: #9cc3a7;
      --soft: rgba(255, 255, 255, 0.08);
      --sheet: #2a2b2e;
      --track: rgba(255, 255, 255, 0.08);
      --hover: rgba(255, 255, 255, 0.1);
      --soft-hover: rgba(255, 255, 255, 0.18);
      --fill: rgba(255, 255, 255, 0.07);
      --fill-hover: rgba(255, 255, 255, 0.11);
      --raised: rgba(255, 255, 255, 0.16);
  }
}

* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

html, body { height: 100%; }
/* Paint the page colour from the very first frame (and behind notches/overscroll). */
html { background: var(--bg); }
[dir="rtl"] { --dir: -1; }
/* The page itself never scrolls or rubber-bands. While a panel is open the
   background is fully locked: scrolling inside the panel never passes through
   to the page behind it. */
html, body { overscroll-behavior: none; }
/* Laptops: the trackpad's two-finger swipe still goes back and forward between
   pages (browsers treat it as sideways overscroll). Only touch screens need it
   blocked, where swiping moves between phrases (js/main.js). */
@media (hover: hover) and (pointer: fine) { html, body { overscroll-behavior-x: auto; } }
html.locked, html.locked body { overflow: hidden; }
.sheet, #list-items { overscroll-behavior: contain; touch-action: pan-y; }
#scrim { touch-action: none; }
/* While loading, colours apply instantly, so resuming mid-session doesn't fade
   from the first dhikr's colour to the current one. */
body.loading, body.loading > :not(#loader), body.loading > :not(#loader) * { transition: none !important; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  display: flex;
  flex-direction: column;
  padding: max(1.25rem, env(safe-area-inset-top)) 1.5rem max(1.25rem, env(safe-area-inset-bottom));
  transition: background 0.6s ease;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
}

header, footer, main {
  width: 100%;
  max-width: 45rem;
  margin: 0 auto;
}

/* Only show a focus ring when navigating with Tab, in the app's own colour. */
button:focus { outline: none; }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

/* Progress */
.bar {
  position: relative;
  display: flex;
  margin: -6px 0;
}
/* Each chunk has a taller invisible hit area around the thin visible track. */
.segment {
  transition: flex-grow var(--t-move) var(--ease-settle), min-width var(--t-move) var(--ease-settle),
    margin var(--t-move) var(--ease-settle), opacity var(--t-quick) ease;
  flex-basis: 0;
  min-width: 3px;
  margin-inline-end: 2px;
  padding: 6px 0;
  cursor: default;
}
.segment:last-of-type { margin-inline-end: 0; }
/* Switched-off adhkar: the chunk shrinks away and its gap closes. */
.segment.gone { min-width: 0; margin-inline-end: 0; opacity: 0; pointer-events: none; }
.track {
  height: 5px;
  background: var(--track);
  border-radius: 999px;
  overflow: hidden;
  transition: height var(--t-hover) ease, margin var(--t-hover) ease;
}
.fill {
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: 999px;
  transition: width var(--t-quick) linear; /* linear so a sweep across several chunks keeps one speed */
}
/* A skipped dhikr's "passed over" layer: faint green behind the solid fill (what
   was recited), so a skipped chunk shows both. Current: lifted a little, so your
   place stands out among the others. (js/bar.js renderBar) */
.pass {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 0;
  background: color-mix(in srgb, var(--accent) 32%, transparent);
  border-radius: 999px;
  transition: width var(--t-quick) linear;
}
.track { position: relative; }
.fill { position: relative; }
.segment.current .track { height: 7px; margin: -1px 0; }
/* A finished chunk swells and settles (height, not scale, so the ends stay round). */
.track.pop { animation: track-pop var(--t-pop) var(--ease-spring); }
@keyframes track-pop {
  40% { height: 10px; margin: -2.5px 0; }
}
#tip {
  position: absolute;
  top: 1.375rem;
  left: 0;
  transform: translate(-50%, -4px);
  padding: 0.3125rem 0.625rem;
  border-radius: 999px;
  background: var(--sheet);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
  font-size: 0.75rem;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-hover) ease, transform var(--t-hover) ease;
  z-index: 1;
}
#tip.show { opacity: 1; transform: translate(-50%, 0); }

/* On a laptop: hovering a chunk lifts it and shows its name. */
@media (hover: hover) {
  .segment { cursor: pointer; }
  /* Grow the real height (not a scale) so the rounded ends stay round. */
  .segment:hover .track { height: 9px; margin: -2px 0; }
}
/* Scrubbing (js/bar.js): a comfortable touch area around the thin bar, reaching up
   into the space above it and out to the screen's edges (not down onto the
   buttons). Sliding along it lifts the chunk under your finger, like hovering. */
.bar { touch-action: none; }
.bar::before { content: ""; position: absolute; top: -1rem; bottom: -2px; left: -1.5rem; right: -1.5rem; }
.segment.scrubbed .track { height: 9px; margin: -2px 0; }
/* On touch screens there's no hovering: the chunks only respond to a slide (the
   bar handles it), and the name shows a little lower, clear of your fingertip. */
@media (hover: none) {
  .segment { pointer-events: none; }
  #tip { top: 2.5rem; }
}
.meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

.round {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--soft);
  display: grid;
  place-items: center;
}

/* Heading */
.heading { text-align: center; margin-top: 0.75rem; }
/* Wider screens: the dua name moves up into the top row, centred between the
   menu and settings buttons (the heading overlaps that row, but lets clicks
   through to the buttons). */
#title { font-size: 1.125rem; font-weight: 600; padding: 2px 0.5rem; }
@media (min-width: 37.5em) {
  .heading { margin-top: -2.375rem; pointer-events: none; }
  #title { pointer-events: auto; } /* only the name is clickable; the lines below it let clicks through */
  /* Name, virtue and dots as one tight stack: the name level with the buttons,
     the rest directly beneath it. */
  #title {
    max-width: calc(100% - 17.5rem);
    padding-top: 0.5625rem;
    padding-bottom: 0;
    line-height: 1.3;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  #virtue { margin-top: 1px; }
  #rep { margin-top: 0.375rem; }
}
#rep {
  min-height: 2.125rem;
  margin-top: 0.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  color: var(--muted);
}
.dots {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  max-width: 260px;
}
.dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1.5px solid var(--muted);
  opacity: 0.6;
}
.dots.small { gap: 5px; }
.dots.small .dot { width: 5px; height: 5px; border-width: 1px; }
.dot.on  { background: var(--accent); border-color: var(--accent); opacity: 1; }
.dot.now {
  border-color: var(--accent);
  opacity: 1;
  animation: pulse 1.6s ease-in-out var(--phase, 0ms) infinite;
}
.dot.just { animation: bounce var(--t-pop) var(--ease-spring); }
.dot.now.just {
  animation: bounce var(--t-pop) var(--ease-spring), pulse 1.6s ease-in-out var(--phase, 0ms) infinite;
}
@keyframes bounce {
  0%   { transform: scale(0.6); }
  50%  { transform: scale(1.6); }
  100% { transform: scale(1); }
}
/* Rows changing over: each old dot pops and shrinks to nothing, and the new
   dot grows in, one after another along the row; right to left when going back.
   Two paces:
   - Moving to another dhikr (the old rows drawn over the new page, js/progress.js
     farewell): quick, keeping time with the page's own 0.25s fade. The whole row
     ripples within 60ms, however many dots it has, and everything has settled by
     about 0.3s.
   - Within a dhikr (a recitation or a ten finished, .dots-swap): unhurried, each
     new dot waiting until its old one is mostly gone. */
.dots { --stagger: calc(60ms / var(--n)); --lead: 0ms; --dur: 0.24s; }
.rep-ghost .dots { --dur: 0.18s; }
#rep.after-farewell .dots { --lead: 0.05s; }
.dots-swap .dots { --stagger: 30ms; --dur: 0.3s; }
.dots-swap .dots.grow { --lead: 0.2s; --dur: var(--t-pop); }
.dots.out .dot { animation: vanish var(--dur) ease-in forwards; animation-delay: calc(var(--i) * var(--stagger)); }
.dots.out.rev .dot { animation-delay: calc((var(--n) - 1 - var(--i)) * var(--stagger)); }
@keyframes vanish {
  30%  { transform: scale(1.4); opacity: 1; }
  100% { transform: scale(0); opacity: 0; }
}
/* (The pulse of the current dot takes over once it has grown in.) */
.dots.grow .dot {
  animation: grow var(--dur) var(--ease-spring) backwards;
  animation-delay: calc(var(--lead) + var(--i) * var(--stagger));
}
.dots.grow.rev .dot { animation-delay: calc(var(--lead) + (var(--n) - 1 - var(--i)) * var(--stagger)); }
/* The selected dot pops as it grows in (up to about 1.5×, like a tapped dot's
   bounce), so your place stands out among the arriving dots. */
.dots.grow .dot.now {
  animation: pulse 1.6s ease-in-out var(--phase, 0ms) infinite, grow-pop calc(var(--dur) + 0.12s) ease-out backwards;
  animation-delay: var(--phase, 0ms), calc(var(--lead) + var(--i) * var(--stagger));
}
.dots.grow.rev .dot.now { animation-delay: var(--phase, 0ms), calc(var(--lead) + (var(--n) - 1 - var(--i)) * var(--stagger)); }
@keyframes grow { from { transform: scale(0); opacity: 0; } }
@keyframes grow-pop { 0% { transform: scale(0); opacity: 0; } 55% { transform: scale(1.5); opacity: 1; } 100% { transform: scale(1); } }
/* The counter does the same as a whole, at the quick pace: the finished one (its
   ring filling as it goes) pops and shrinks away as the next dhikr's grows in. */
.counter { --lead: 0ms; }
.counter.out { animation: counter-out 0.18s ease-in forwards; }
@keyframes counter-out {
  30%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(0); opacity: 0; }
}
.counter.grow { animation: grow 0.24s var(--ease-spring) var(--lead) backwards; }
#rep.after-farewell .counter.grow { --lead: 0.05s; }
/* Old and new rows share one place. */
.dots-swap { display: grid; justify-items: center; }
.dots-swap > .dots { grid-area: 1 / 1; }
/* A finished dhikr's dots (js/progress.js farewell), over the next dhikr's. */
.rep-ghost {
  position: fixed;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  pointer-events: none;
}
/* Switching between dots and counter. */
#rep { transition: opacity var(--t-quick) ease, transform var(--t-quick) ease, height var(--t-move) var(--ease-settle); }
#rep.swap-out { opacity: 0; transform: scale(0.92); }
#rep.swap-in { animation: rep-in var(--t-move) var(--ease-settle); }
@keyframes rep-in { from { opacity: 0; transform: scale(0.92); } }

/* Count mode: a phrase ring, then "34 / 100" with digits that tick over. */
.counter {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* Numbers read left to right in every script, also on right-to-left pages. While
   the width glides (a digit added or removed), the units digit stays put and the
   new one is revealed beside it. */
.counter .count-num {
  color: var(--ink);
  font-weight: 600;
  display: inline-flex;
  direction: ltr;
  unicode-bidi: isolate;
  justify-content: flex-end;
  overflow-x: clip;
  transition: width var(--t-move) var(--ease-settle);
}
.digit { display: inline-block; }
.digit.tick.up   { animation: tick-up var(--t-quick) ease-out; }
.digit.tick.down { animation: tick-down var(--t-quick) ease-out; }
@keyframes tick-up   { from { opacity: 0; transform: translateY(4px); } }
@keyframes tick-down { from { opacity: 0; transform: translateY(-4px); } }

/* The phrase ring: a small donut that fills as you go through the phrases. */
.ring { width: 18px; height: 18px; transform: rotate(-90deg); }
.ring circle { fill: none; stroke-width: 3; }
.ring-track { stroke: var(--track); }
.ring-fill { stroke: var(--accent); stroke-linecap: round; }
/* The arc just grows and shrinks; the ring only pops when the circle completes. */
.ring.pop  { animation: ring-pop var(--t-pop) var(--ease-spring); }
@keyframes ring-pop  { 40% { transform: rotate(-90deg) scale(1.4); } }

@keyframes pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.3); opacity: 0.75; }
}

/* Content, centred on the page */
/* Centre on the whole screen, not just the space under the (tall) header:
   add space below equal to how much taller the top area is than the bottom one.
   --header-h is measured in js/main.js. Top area = 20px padding + header;
   bottom area = 64px reserved for the source line. */
#card, #done {
  padding-bottom: max(0px, calc(var(--header-h, 0px) + 1.25rem - 4rem));
  /* No transition: --header-h is measured every frame while the header changes
     size, so the phrase stays centred in step with it instead of trailing. */
}
main {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 0;
}

#ar {
  font-family: var(--arabic);
  font-size: calc(clamp(1.875rem, 7vw, 3.25rem) * var(--scale));
  line-height: 2;
  padding-top: 0.15em;
  overflow: visible; /* never clip tall marks (hamza, stacked harakat) above the letters */
}
/* Only the collapsible lines need clipping, for their show/hide animation. */
#tr, #en, #virtue { overflow: hidden; }
#tr { font-size: calc(0.9375rem * var(--scale)); color: var(--muted); line-height: 1.5; margin-top: 1.25rem; }
#en { font-size: calc(clamp(1rem, 2.4vw, 1.1875rem) * var(--scale)); line-height: 1.5; max-width: 34em; margin-top: 1.125rem; }

/* End-of-ayah marker: a scalloped medallion with the ayah number, as in the mushaf. */
.ayah {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 3.3em;
  height: 3.3em;
  margin-inline-start: 0.15em;
  font-size: 0.4em;
  font-family: var(--font);
  line-height: 1;
  vertical-align: middle;
  color: var(--ink);
}
.ayah::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2040%2040%27%20fill%3D%27none%27%20stroke%3D%27black%27%3E%3Cpath%20d%3D%27M20.00%204.50%20A4.21%204.21%200%200%201%2027.75%206.58%20A4.21%204.21%200%200%201%2033.42%2012.25%20A4.21%204.21%200%200%201%2035.50%2020.00%20A4.21%204.21%200%200%201%2033.42%2027.75%20A4.21%204.21%200%200%201%2027.75%2033.42%20A4.21%204.21%200%200%201%2020.00%2035.50%20A4.21%204.21%200%200%201%2012.25%2033.42%20A4.21%204.21%200%200%201%206.58%2027.75%20A4.21%204.21%200%200%201%204.50%2020.00%20A4.21%204.21%200%200%201%206.58%2012.25%20A4.21%204.21%200%200%201%2012.25%206.58%20A4.21%204.21%200%200%201%2020.00%204.50%20Z%27%20stroke-width%3D%271.4%27%20stroke-linejoin%3D%27round%27/%3E%3Ccircle%20cx%3D%2720%27%20cy%3D%2720%27%20r%3D%2711.5%27%20stroke-width%3D%271%27/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2040%2040%27%20fill%3D%27none%27%20stroke%3D%27black%27%3E%3Cpath%20d%3D%27M20.00%204.50%20A4.21%204.21%200%200%201%2027.75%206.58%20A4.21%204.21%200%200%201%2033.42%2012.25%20A4.21%204.21%200%200%201%2035.50%2020.00%20A4.21%204.21%200%200%201%2033.42%2027.75%20A4.21%204.21%200%200%201%2027.75%2033.42%20A4.21%204.21%200%200%201%2020.00%2035.50%20A4.21%204.21%200%200%201%2012.25%2033.42%20A4.21%204.21%200%200%201%206.58%2027.75%20A4.21%204.21%200%200%201%204.50%2020.00%20A4.21%204.21%200%200%201%206.58%2012.25%20A4.21%204.21%200%200%201%2012.25%206.58%20A4.21%204.21%200%200%201%2020.00%204.50%20Z%27%20stroke-width%3D%271.4%27%20stroke-linejoin%3D%27round%27/%3E%3Ccircle%20cx%3D%2720%27%20cy%3D%2720%27%20r%3D%2711.5%27%20stroke-width%3D%271%27/%3E%3C/svg%3E") center / contain no-repeat;
}

/* What the dhikr is about, in plain words: a quiet line right under its name. */
#sub {
  max-width: 90%;
  margin: -1px auto 0;
  font-size: 0.6875rem;
  line-height: 1.3;
  color: var(--muted);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* The virtue: a one-line italic subtitle under the dhikr's name. */
#virtue {
  max-width: 90%;
  margin: 2px auto 0;
  font-size: 0.8125rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--muted);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Smooth changes from settings: text size, and showing/hiding lines. */
#ar, #tr, #en, #virtue, #sub {
  transition: font-size var(--t-move) var(--ease-settle), height var(--t-move) var(--ease-settle), margin var(--t-move) var(--ease-settle), opacity var(--t-move) var(--ease-settle);
}
#tr.collapsed, #en.collapsed, #virtue.collapsed, #sub.collapsed { margin-top: 0; opacity: 0; }

.fade      { animation: fade-fwd 0.25s ease; }
.fade.back { animation-name: fade-back; }
@keyframes fade-fwd {
  from { opacity: 0.2; transform: translateX(calc(16px * var(--dir))); }
  to   { opacity: 1; transform: none; }
}
@keyframes fade-back {
  from { opacity: 0.2; transform: translateX(calc(-16px * var(--dir))); }
  to   { opacity: 1; transform: none; }
}

/* Done */
/* Turning to another dhikr (js/nav.js turnPage): the name, phrase and source sweep
   out to the side, quickly, then the next dhikr sweeps in from the other side and
   settles (about a third of a second in all), a bigger move than a phrase's small
   slide. The dots stay put and change over in place. Mirrored going back and in
   right-to-left languages. */
body.sweep-out #card, body.sweep-out .heading > :not(#rep), body.sweep-out footer,
body.sweep-out-back #card, body.sweep-out-back .heading > :not(#rep), body.sweep-out-back footer {
  transition: opacity 0.11s ease-in, transform 0.11s cubic-bezier(0.55, 0, 0.75, 0.3);
  opacity: 0;
  transform: translateX(calc(-44px * var(--dir))) scale(0.98);
}
body.sweep-out-back #card, body.sweep-out-back .heading > :not(#rep), body.sweep-out-back footer { transform: translateX(calc(44px * var(--dir))) scale(0.98); }
.sweep      { animation: sweep-in 0.22s var(--ease-settle) both; }
.sweep.back { animation-name: sweep-in-back; }
@keyframes sweep-in      { from { opacity: 0; transform: translateX(calc(44px * var(--dir))) scale(0.98); } }
@keyframes sweep-in-back { from { opacity: 0; transform: translateX(calc(-44px * var(--dir))) scale(0.98); } }
/* The page comes back by sweeping in, not by fading: while it does (body.turned),
   the slower fades that reveal the page after loading, and a line being shown,
   stay out of the way. A running fade outranks an animation, so otherwise it held
   the new dhikr's text dim until it caught up (very visible on iPhone). */
body.turned #card, body.turned footer { transition: none; }
body.turned #sub, body.turned #virtue { transition-property: font-size, height, margin; }
/* As a finished dhikr leaves, its dots are all filled. */
#rep.complete .dot { background: var(--accent); border-color: var(--accent); opacity: 1; animation: none; }
/* The whoosh: the last phrase, dua name and source lift away together. */
body.whoosh #card, body.whoosh .heading, body.whoosh footer {
  transition: opacity 0.28s ease, transform 0.28s cubic-bezier(0.55, 0, 0.75, 0.3);
  opacity: 0;
  transform: translateY(-36px) scale(0.97);
}
/* The exhale: al-ḥamdu lillāh grows in, a soft glow expands once behind it,
   then the rest fades in one after another. */
.done-mark { position: relative; display: grid; place-items: center; }
.breath {
  position: absolute;
  width: 140px;
  height: 140px;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 18%, transparent), transparent 70%);
  opacity: 0;
  pointer-events: none;
}
#done.arrive .breath { animation: breath-out 1.1s cubic-bezier(0.22, 1, 0.36, 1) 0.05s; }
#done.arrive .done-ar { animation: exhale-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both; }
#done.arrive #done-text { animation: soft-in 0.45s ease 0.25s both; }
#done.arrive #done-time { animation: soft-in 0.45s ease 0.35s both; }
#done.arrive #again     { animation: soft-in 0.45s ease 0.5s both; }
@keyframes breath-out {
  0%   { opacity: 0;   transform: scale(0.5); }
  25%  { opacity: 1; }
  100% { opacity: 0;   transform: scale(2.2); }
}
/* Little stars that burst outward along short curved paths, then vanish. */
/* The stars burst out on a wide oval around al-ḥamdu lillāh (sized from its own
   font size), so they land around the words rather than on them. */
.sparks { position: absolute; inset: 50% auto auto 50%; width: 0; height: 0; pointer-events: none; font-size: 3.25rem; --rx: 2.35em; --ry: 1.2em; }
.spark {
  position: absolute;
  left: -7px;
  top: -7px;
  width: 14px;
  height: 14px;
  opacity: 0;
  color: color-mix(in srgb, var(--accent) 45%, #eab550);
}
.spark svg { display: block; width: 100%; height: 100%; fill: currentColor; }
#done.arrive .spark { animation: spark 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.1s; }
@keyframes spark {
  0%   { opacity: 0; transform: translate(calc(cos(var(--a)) * var(--rx) * 0.7), calc(sin(var(--a)) * var(--ry) * 0.7)) scale(0); }
  30%  { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(cos(var(--a)) * var(--rx) * var(--d)), calc(sin(var(--a)) * var(--ry) * var(--d))) scale(var(--s)); }
}
}
@keyframes exhale-in {
  from { opacity: 0; transform: scale(0.82); }
}
@keyframes soft-in {
  from { opacity: 0; transform: translateY(6px); }
}

#done { gap: 0.875rem; }
.done-ar { font-family: var(--arabic); font-size: 3.25rem; }
#done-time { font-size: 0.8125rem; color: var(--muted); }
.pill {
  margin-top: 0.75rem;
  padding: 0.625rem 1.5rem;
  background: var(--soft);
  border-radius: 999px;
}

/* Footer: pinned to the bottom and taken out of the layout, so when the source
   line wraps onto more lines it grows upward into the empty space
   instead of pushing the phrase up. The page keeps a fixed reserve for it. */
footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: max(1.25rem, env(safe-area-inset-bottom));
  padding: 0 1.5rem;
}
body { padding-bottom: calc(max(1.25rem, env(safe-area-inset-bottom)) + 2.75rem); }
/* The phrase doesn't fit on the screen: the source line follows it instead of
   floating over it, and the page scrolls (see fitFooter in js/render.js). */
body.tall { padding-bottom: max(1.25rem, env(safe-area-inset-bottom)); }
body.tall footer { position: static; padding: 0; margin-top: 1.5rem; }
body.tall #card { padding-bottom: 0; }
#grade {
  display: block;
  margin: 0 auto 0.5rem;
  max-width: 34em;
  text-align: center;
  font-size: 0.75rem;
  color: var(--muted);
  line-height: 1.4;
}


/* Sheets */
#scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.25);
  opacity: 0;
  transition: opacity var(--t-sheet) var(--ease-sheet);
}
#scrim.open { opacity: 1; }
/* A very slight blur behind open menus. */
#scrim {
  -webkit-backdrop-filter: blur(1.8px);
  backdrop-filter: blur(1.8px);
}
.sheet {
  position: fixed;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  width: 100%;
  max-width: 30rem;
  max-height: 75vh;
  overflow-y: auto;
  background: var(--sheet);
  border-radius: 22px 22px 0 0;
  padding: 1.375rem 1.375rem max(1.375rem, env(safe-area-inset-bottom));
  transform: translate(-50%, 100%);
  transition: transform var(--t-sheet) var(--ease-sheet);
}
.sheet.open { transform: translate(-50%, 0); }
/* Moving between Settings and its pages (js/sheets.js swapSheet): the page being
   left provides the panel behind; the arriving one is see-through until done, and
   always on top (going back, Settings comes first in the page, so it would
   otherwise be hidden under the page being left). */
.sheet.instant { transition: none; }
.sheet.swapping { background: transparent; z-index: 1; }
/* Sheets still scroll, but without a visible scrollbar. */
/* Small chevron at the top of each panel: tap to close. */
.sheet-close {
  display: block;
  width: 44px;
  height: 22px;
  margin: -12px auto 6px;
  color: var(--muted);
  border-radius: 999px;
  flex: none;
}
#list .sheet-close, #settings .sheet-close, #about .sheet-close, #langs .sheet-close { margin-top: 4px; }

/* Settings, About and Language scroll inside the panel like the menu, with the
   same soft fade at the top and bottom edges. The side padding keeps row
   highlights that reach past the text from being clipped. */
#settings, #about, #langs { overflow: hidden; display: flex; flex-direction: column; padding-top: 0.375rem; padding-bottom: max(0.375rem, env(safe-area-inset-bottom)); }
.sheet-scroll {
  min-height: 0;
  overflow-y: auto;
  margin: 0 -0.75rem;
  padding: 1rem 0.75rem;
  scrollbar-width: none;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-mask-image: linear-gradient(transparent, #000 28px, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(transparent, #000 28px, #000 calc(100% - 28px), transparent);
}
.sheet-scroll::-webkit-scrollbar { display: none; }

/* Menu tools (top-right): edit, or reset + done while editing. The icons swap
   with a quick fade and scale. */
.list-tools { position: absolute; top: 0.75rem; inset-inline-end: 1rem; z-index: 2; display: flex; gap: 0.375rem; }
.tool {
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--fill);
  color: var(--ink);
  transition: opacity var(--t-quick) ease, transform var(--t-icon) var(--ease-spring), background var(--t-hover) ease;
}
#list-edit { position: absolute; inset-inline-end: 0; top: 0; }
#list:not(.editing) #list-done,
#list.editing #list-edit { opacity: 0; transform: scale(0.6); pointer-events: none; }
/* Reset only takes up room while editing and once something is switched off;
   it grows in from nothing, so the "28/30" beside it slides aside to make space. */
#list-reset { overflow: hidden; transition: opacity var(--t-quick) ease, transform var(--t-icon) var(--ease-spring), width var(--t-move) var(--ease-settle), margin var(--t-move) var(--ease-settle), background var(--t-hover) ease; }
#list:not(.can-reset) #list-reset { width: 0; margin-inline-end: -0.375rem; opacity: 0; transform: scale(0.6); pointer-events: none; }

/* The check mark on each row, only while editing: a filled circle with a tick
   when included, an empty ring when not. The tick draws itself in. */
.check {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  margin-inline-start: 12px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: inset 0 0 0 1.5px var(--accent);
  transition: background var(--t-quick) ease, box-shadow var(--t-quick) ease, width var(--t-move) var(--ease-settle),
    margin var(--t-move) var(--ease-settle), opacity var(--t-quick) ease, transform var(--t-icon) var(--ease-spring);
}
/* Outside edit mode the check column shrinks away, and slides open on edit. */
#list:not(.editing) .check { width: 0; margin-inline-start: 0; opacity: 0; transform: scale(0.4); }
.check svg { width: 16px; height: 16px; fill: none; stroke: #fff; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.check path { stroke-dasharray: 16; stroke-dashoffset: 0; transition: stroke-dashoffset var(--t-icon) ease 0.05s; }
#list-items li.off .check { background: transparent; box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--muted) 45%, transparent); }
#list-items li.off .check path { stroke-dashoffset: 16; transition-delay: 0s; }
#list-items .check { align-self: center; } /* the row lines up text on its first line; the check sits in the middle */
#list-items li button:active .check { transform: scale(0.88); }
#list-items .num, #list-items .name, #list-items .count { transition: opacity var(--t-quick) ease; }
#list-items li.off .num, #list-items li.off .name, #list-items li.off .count { opacity: 0.38; }
#list-items li.shake { animation: shake 0.32s ease; }
@keyframes shake { 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } }
.sheet { scrollbar-width: none; }
.sheet::-webkit-scrollbar { display: none; }

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.625rem 0;
  font-size: 0.9375rem;
}
/* Each setting's label has a small line icon before it (it sits on the
   reading-start side, so it moves to the right in right-to-left languages). */
.row .label { display: inline-flex; align-items: center; gap: 0.6875rem; min-width: 0; }
.row-icon { flex: none; color: var(--muted); }
.seg {
  display: flex;
  background: var(--fill);
  border-radius: 999px;
  padding: 3px;
}
.seg button {
  /* Fixed height, so scripts with taller lines (e.g. Bengali) keep rows even. */
  height: 1.875rem;
  padding: 0 0.75rem;
  border-radius: 999px;
  font-size: 0.8125rem;
  color: var(--muted);
}
.seg button.on { background: var(--raised); color: var(--ink); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); }
/* The chosen option's white pill slides to the new choice when you tap (quickly:
   --t-quick). It's one pill behind the buttons, placed by js/sheets.js placePills;
   until it's placed, the chosen button draws its own. */
.seg { position: relative; isolation: isolate; }
.seg::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  width: var(--pill-w, 0);
  height: var(--pill-h, 0);
  transform: translate(var(--pill-x, 0), var(--pill-y, 0));
  border-radius: 999px;
  background: var(--raised);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  opacity: 0;
  transition: transform var(--t-quick) var(--ease-settle), width var(--t-quick) var(--ease-settle), height var(--t-quick) var(--ease-settle);
}
.seg.placed::before { opacity: 1; }
.seg.placed button.on { background: transparent; box-shadow: none; }
.seg.still::before { transition: none; }
#restart { width: 100%; margin-top: 1rem; background: var(--fill); }
/* Pill buttons with an icon: icon and label centred side by side. */
.pill { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; }
/* Icon options (eye / crossed eye, and A A A for text size): fixed square-ish buttons. */
.seg.icons button {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 1.875rem;
  padding: 0;
}
.seg.icons .aa { font-weight: 600; line-height: 1; }

.menu {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  height: 2.25rem;
  padding: 0 0.875rem 0 0.75rem;
  border-radius: 999px;
  background: var(--soft);
  color: var(--ink);
  font-size: 0.8125rem;
}

/* Menu rows (Uber-style): no divider lines, a rounded highlight on hover/press,
   inset slightly from the panel edges. Text lines up with the section headings. */
#list-items { list-style: none; margin: 0 -0.625rem; }

/* The menu scrolls inside the panel, and its text fades out softly at the top
   and bottom edges instead of being cut off. */
#list { overflow: hidden; display: flex; flex-direction: column; padding-top: 0.375rem; padding-bottom: max(0.375rem, env(safe-area-inset-bottom)); }
#list-items {
  min-height: 0;
  overflow-y: auto;
  padding: 1rem 0;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(transparent, #000 28px, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(transparent, #000 28px, #000 calc(100% - 28px), transparent);
}
#list-items::-webkit-scrollbar { display: none; }
/* Rows collapse/expand smoothly (grid row 1fr <-> 0fr). */
#list-items li {
  display: grid;
  grid-template-rows: 1fr;
  margin: 2px 0;
  transition: grid-template-rows var(--t-move) var(--ease-settle), opacity var(--t-move) var(--ease-settle), margin var(--t-move) var(--ease-settle);
}
#list-items li > .collapse { min-height: 0; overflow: hidden; }
#list-items li.gone { grid-template-rows: 0fr; opacity: 0; margin: 0; }
#list-items li.section { margin: 0; }
#list-items li.section span { display: block; padding: 1.375rem 0.625rem 0.375rem; }
#list-items li.section {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
#list-items li.section:first-child span { padding-top: 0; }
#list-items li button {
  display: flex;
  justify-content: space-between;
  align-items: baseline; /* number and count line up with the name, not the subtitle */
  width: 100%;
  padding: 0.625rem 0.625rem;
  text-align: start;
  font-size: 0.9375rem;
  border-radius: 10px;
  transition: background var(--t-hover) ease;
}
#list-items li button:active { background: var(--hover); }
/* Numbers right-aligned in a fixed column, so every name starts on the same line. */
#list-items .num {
  flex: none;
  width: 2em;
  margin-inline-end: 0.6em;
  text-align: end;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
#list-items .name { flex: 1; min-width: 0; }
#list-items .name .title, #list-items .name .sub { display: block; }
#list-items .name .sub:empty { display: none; }
#list-items .name .sub { margin-top: -1px; font-size: 0.6875rem; line-height: 1.25; font-weight: 400; color: var(--muted); }
#list-items .count { color: var(--muted); font-size: 0.8125rem; }
#list-items li.current button { font-weight: 600; background: color-mix(in srgb, var(--accent) 16%, transparent); }
#list-items li.done button { color: var(--muted); }
/* Skipped (passed without reciting): a small faint ring at the end of the row. */
#list-items li.skipped button::after { content: ""; flex: none; align-self: center; width: 0.4375rem; height: 0.4375rem; margin-inline-start: 0.5rem; border-radius: 50%; border: 1.5px solid color-mix(in srgb, var(--accent) 75%, transparent); }

/* Loading: hide the page until the font is ready, so text never swaps fonts
   while you're reading. A small sun–moon shows if it takes more than a moment. */
body.loading > :not(#loader) { visibility: hidden; }
/* Without JavaScript the app can't run: show the link to the full-text page instead. */
body.loading > noscript { visibility: visible; }
.noscript { display: block; margin: 2rem auto; text-align: center; font-weight: 600; color: var(--ink); }
.noscript-about { max-width: 30rem; margin: 3rem auto 0; padding: 0 1.5rem; text-align: center; color: var(--ink); line-height: 1.5; }
header, main, footer { transition: opacity 0.35s ease 0.12s; }
body.loading header, body.loading main, body.loading footer { opacity: 0; }

/* Between the app and the full-text pages, the two looks cross-fade where
   browsers can (with the loader showing on both sides; see leaveTo in js/sheets.js). */
@media (prefers-reduced-motion: no-preference) { @view-transition { navigation: auto; } }
#loader {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-hover) ease;
}
body.loading #loader { opacity: 1; transition-delay: 0.15s; }
/* Changing language: the page fades out, the loader shows briefly, and the
   page fades back in with the new language (see chooseLanguage). */
/* Everything except the loader fades out, including a panel that is still
   sliding away, the dimmed backdrop and the hints. */
body.switching > :not(#loader) { opacity: 0 !important; transition: opacity 0.16s ease !important; }
body.switching #loader { opacity: 1; transition: opacity 0.15s ease 0.05s; }

/* Sun–moon orb (flat, Kurzgesagt-inspired). Every 4s it turns from sun to
   moon and back: rays spin and pull in, a shadow sweeps across into a
   crescent, the glow shifts warm to cool, stars twinkle, companions orbit. */
#loader { --cycle: 4s; }
#loader svg * { transform-box: view-box; }
#loader .float { transform-origin: 80px 80px; animation: float 3s ease-in-out infinite; }
#loader .orbit { transform-origin: 80px 80px; animation: spin 6s linear infinite; }
#loader .rays  { transform-origin: 80px 80px; animation: rays var(--cycle) cubic-bezier(0.65, 0, 0.35, 1) infinite; }
#loader .sun   { animation: sun var(--cycle) ease-in-out infinite; }
#loader .moon  { animation: moon var(--cycle) ease-in-out infinite; }
#loader .shade { animation: shade var(--cycle) cubic-bezier(0.65, 0, 0.35, 1) infinite; }
#loader .warm  { animation: sun var(--cycle) ease-in-out infinite; }
#loader .cool  { animation: moon var(--cycle) ease-in-out infinite; }
#loader .stars { animation: moon var(--cycle) ease-in-out infinite; }
#loader .star  { transform-box: fill-box; transform-origin: center; animation: twinkle 1.4s ease-in-out infinite; }

@keyframes float   { 0%, 100% { transform: translateY(-3px); } 50% { transform: translateY(3px); } }
@keyframes spin    { to { transform: rotate(360deg); } }
@keyframes rays {
  0%   { transform: rotate(0deg)   scale(1);   opacity: 1; }
  40%  { transform: rotate(90deg)  scale(1);   opacity: 1; }
  52%  { transform: rotate(140deg) scale(0.4); opacity: 0; }
  88%  { transform: rotate(140deg) scale(0.4); opacity: 0; }
  100% { transform: rotate(180deg) scale(1);   opacity: 1; }
}
@keyframes sun  { 0%, 40% { opacity: 1; } 52%, 88% { opacity: 0; } 100% { opacity: 1; } }
@keyframes moon { 0%, 40% { opacity: 0; } 52%, 88% { opacity: 1; } 100% { opacity: 0; } }
@keyframes shade {
  0%, 42%  { transform: translateX(56px); }
  60%, 86% { transform: translateX(17px); }
  100%     { transform: translateX(56px); }
}
@keyframes twinkle { 0%, 100% { transform: scale(1); } 50% { transform: scale(0.5); } }

/* Laptop only: real buttons darken slightly on hover (lighten in dark mode);
   the dua name and source line just fade slightly. */
@media (hover: hover) {
  /* On the pastel page, buttons brighten towards solid white (clear on every tint).
     Inside the panels (plain off-white), buttons darken slightly instead. */
  .round, .menu, #again { transition: background var(--t-hover) ease; }
  .round:hover, .menu:hover, #again:hover { background: var(--soft-hover); }
  #restart, .seg button { transition: background var(--t-hover) ease, color var(--t-hover) ease; }
  #restart:hover { background: var(--fill-hover); }
  .seg button:not(.on):hover { color: var(--ink); background: var(--fill); }
  #title { transition: opacity var(--t-hover) ease; }
  #title:hover { opacity: 0.65; }
  #list-items li button:hover { background: var(--hover); }
  .tool:hover { background: var(--fill-hover); }
  .sheet-close { transition: background var(--t-hover) ease; }
  .sheet-close:hover { background: var(--hover); }
  #list-items li.current button:hover { background: color-mix(in srgb, var(--accent) 24%, transparent); }
}

/* Visible only to screen readers. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Reduce Motion (set in the phone's or computer's accessibility settings):
   every animation and transition becomes an instant change. Everything still
   works the same, it just doesn't move. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
}

/* Links in the source line: quiet, with a soft dotted underline. */
#grade a, #credits a {
  color: inherit;
  transition: color var(--t-hover) ease, text-decoration-color var(--t-hover) ease;
  text-decoration: underline dotted;
  text-decoration-color: color-mix(in srgb, var(--muted) 60%, transparent);
  text-underline-offset: 3px;
}
@media (hover: hover) {
  #grade a:hover, #credits a:hover { color: var(--ink); text-decoration-style: solid; }
}

/* "About & sources": a quiet row under Restart, and its panel. */
.about-link {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.25rem;
  width: 100%;
  margin-top: 0.625rem;
  padding: 0.5rem;
  font-size: 0.8125rem;
  color: var(--muted);
  border-radius: 999px;
  transition: color var(--t-hover) ease;
}
@media (hover: hover) { .about-link:hover { color: var(--ink); } }
/* Language and About & Sources: the way back and the page's name sit in the top
   bar beside the handle, like the athkar menu's title, and stay there while the
   page scrolls. Long names step down a little in size to fit (fitTitle). */
.about-head { position: absolute; top: 0.75rem; height: 2rem; inset-inline-start: 1rem; inset-inline-end: calc(50% + 1.625rem); display: flex; align-items: center; gap: 0.4375rem; z-index: 2; }
.about-head .sheet-back { flex: none; }
/* Settings, with no way back, shows its icon there instead (the sliders of its button). */
.about-head .head-icon { flex: none; margin-inline: 0.125rem 0.0625rem; color: var(--ink); }
.about-title { margin: 0; font-size: 1rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.about-title.wrap, #list-title.wrap { font-size: 0.8125rem; line-height: 1.15; white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.about-title.wrap3, #list-title.wrap3 { -webkit-line-clamp: 3; line-clamp: 3; }
/* Each entry: its icon, then the title; the text lines up under the title. */
#credits dt { display: flex; align-items: center; gap: 0.625rem; font-size: 0.8125rem; font-weight: 600; margin-top: 0.875rem; }
#credits .credit-icon { flex: none; width: 1.125rem; height: 1.125rem; color: var(--muted); }
/* The link to the full-text page, under the credits. */
/* "Read All Adhkar as Text": centred under the list, the same quiet link as
   "About & Sources" in Settings (a page icon before it, an arrow after), brightening
   on hover at the same pace. */
.read-text {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  width: fit-content;
  margin: 1.25rem auto 0;
  padding: 0.5rem;
  font-size: 0.8125rem;
  color: var(--muted);
  text-decoration: none;
  transition: color var(--t-hover) ease;
}
.read-text .credit-icon { flex: none; width: 1.125rem; height: 1.125rem; }
.read-text .go { flex: none; margin-inline-start: -0.125rem; }
[dir="rtl"] .read-text .go { transform: scaleX(-1); }
@media (hover: hover) { .read-text:hover { color: var(--ink); } }
#credits dd { font-size: 0.8125rem; line-height: 1.5; color: var(--muted); margin-top: 3px; padding-inline-start: 1.75rem; }

/* The quick morning/evening switch: the sun and moon swap with a small turn. */
.meta-right { display: flex; gap: 0.5rem; }
#mode-toggle { position: relative; color: var(--ink); }
#mode-toggle svg { position: absolute; transition: opacity var(--t-icon) ease, transform var(--t-icon) var(--ease-spring); }
#mode-toggle .sun-icon { color: #e3a33a; }
#mode-toggle .moon-icon { color: #8f86c9; }
#mode-toggle[data-mode="morning"] .moon-icon,
#mode-toggle[data-mode="evening"] .sun-icon { opacity: 0; transform: rotate(-60deg) scale(0.5); }
@media (hover: hover) { #mode-toggle:hover { background: var(--soft-hover); } }

/* The small hover label for icon buttons (laptop only). */
#hint {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 10;
  transform: translate(-50%, 2px);
  padding: 0.3125rem 0.625rem;
  border-radius: 999px;
  background: var(--sheet);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  font-size: 0.75rem;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-hover) ease, transform var(--t-hover) ease;
}
#hint.show { opacity: 1; transform: translate(-50%, 0); }
@media (hover: none) { #hint { display: none; } }

/* Language row and list. */
.lang-link { display: flex; align-items: center; gap: 0.25rem; color: var(--muted); font-size: 0.875rem; padding: 0.375rem 2px; transition: color var(--t-hover) ease; }
/* Arrows point the reading direction: forward ones left, back ones right, in RTL. */
[dir="rtl"] .lang-link svg, [dir="rtl"] .about-link svg, [dir="rtl"] .sheet-back svg { transform: scaleX(-1); }
@media (hover: hover) { .lang-link:hover { color: var(--ink); } }
#lang-items { list-style: none; margin: 0 -0.625rem; }
#lang-items li button {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  margin: 2px 0;
  padding: 0.75rem 0.625rem;
  font-size: 1rem;
  border-radius: 10px;
  text-align: start;
  transition: background var(--t-hover) ease;
}
#lang-items li.current button { font-weight: 600; background: color-mix(in srgb, var(--accent) 16%, transparent); }
#lang-items li:not(.current) .check { opacity: 0; }
#lang-items .names { display: flex; align-items: baseline; gap: 0.625rem; }
#lang-items .alt { font-size: 0.875rem; font-weight: 400; color: var(--muted); }
@media (hover: hover) { #lang-items li button:hover { background: var(--hover); } }

/* Pashto and Kurdish: the whole interface and translation in Vazirmatn (see above),
   and those languages' names in the language list. */
:root:lang(ps), :root:lang(ckb) { --font: "Vazirmatn", "Baloo UI", ui-rounded, -apple-system, system-ui, sans-serif; }
#lang-items .name:lang(ps), #lang-items .name:lang(ckb) { font-family: "Vazirmatn", var(--font); }

/* Menu header, on the top row level with the tools: a small sun or moon (as on
   the loading screen) and the set's name, kept clear of the close chevron. */
.list-head { position: absolute; top: 0.75rem; height: 2rem; inset-inline-start: 1.375rem; inset-inline-end: calc(50% + 1.625rem); display: flex; align-items: center; gap: 0.4375rem; z-index: 2; pointer-events: none; }
.list-orb { flex: none; }
#list[data-mode="morning"] .orb-moon, #list[data-mode="evening"] .orb-sun { display: none; }
#list-title { margin: 0; font-size: 1rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* "28/30" beside the tools, only when some adhkar are hidden (full wording for screen readers / hover). */
#list-shown { display: inline-flex; align-items: center; gap: 0.25rem; padding-inline-end: 0.25rem; font-size: 0.78125rem; color: var(--muted); align-self: center; }
#list-shown[hidden] { display: none; }

/* All the toggles in Settings share one width: the widest one's (measured in
   sizeToggles, since it depends on the language). Options split it evenly, and
   a long label wraps rather than squeezing its toggle. */
#settings .seg.sized { flex: none; }
#settings .row .label { flex: 1 1 auto; margin-inline-end: 0.375rem; }
#settings .seg.sized button { flex: 1 1 0; width: auto; min-width: 0; padding: 0 0.5rem; white-space: nowrap; }
/* Stacked rows (see sizeToggles): label above, toggle full width below. Options
   split the width evenly; a label too long even for that wraps inside its option. */
#settings.stacked .row:has(> .seg) { flex-direction: column; align-items: stretch; gap: 0.5rem; }
#settings.stacked .row:has(> .seg) .label { margin-inline-end: 0; }
#settings.stacked .seg { width: 100%; }
#settings.stacked .seg button { flex: 1 1 0; width: auto; min-width: 0; height: auto; min-height: 1.875rem; padding: 0.25rem 0.5rem; line-height: 1.2; white-space: normal; overflow-wrap: anywhere; }

/* The hidden-count indicator ticks in like the counter digits when it appears. */
#list-shown.tick.down { animation: tick-down var(--t-quick) ease-out; }


/* Chinese and Japanese use the device's own font (a matching rounded CJK font
   would be several megabytes); the right regional glyphs follow the page language. */
/* Hindi: the Devanagari font first, so its full stop (।, shared with Bengali)
   doesn't fetch the Bengali font too. */
:root:lang(hi) { --font: "Baloo UI", "Baloo Devanagari", "Baloo Bengali", "Baloo Tamil", "Hausa Letters", "Nunito Cyrillic", "Baloo Bhaijaan 2", ui-rounded, -apple-system, system-ui, "PingFang SC", "Hiragino Sans", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif; }
:root:lang(ja) { --font: "Baloo UI", ui-rounded, -apple-system, system-ui, "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans CJK JP", "Yu Gothic", sans-serif; }
:root:lang(zh) { --font: "Baloo UI", ui-rounded, -apple-system, system-ui, "PingFang SC", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif; }
#lang-items .name:lang(ja) { font-family: "Hiragino Sans", "Noto Sans CJK JP", "Yu Gothic", sans-serif; }
#lang-items .name:lang(zh) { font-family: "PingFang SC", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif; }

/* Moved out of the page's markup so the content security policy needs no inline styles. */
.aa-s { font-size: 0.75rem; } .aa-m { font-size: 0.9375rem; } .aa-l { font-size: 1.1875rem; } .aa-n { font-size: 0.8125rem; }
#loader .stars > g:nth-child(1) .star { animation-delay: 0s; }
#loader .stars > g:nth-child(2) .star { animation-delay: 0.5s; }
#loader .stars > g:nth-child(3) .star { animation-delay: 1s; }
#loader .stars > g:nth-child(4) .star { animation-delay: 0.3s; }
.spark:nth-child(1) { --a: -80deg; --d: 1.0; --s: 1; }
.spark:nth-child(2) { --a: -25deg; --d: 1.1; --s: 0.7; }
.spark:nth-child(3) { --a: 30deg; --d: 0.95; --s: 0.9; }
.spark:nth-child(4) { --a: 85deg; --d: 1.08; --s: 0.6; }
.spark:nth-child(5) { --a: 140deg; --d: 0.97; --s: 0.8; }
.spark:nth-child(6) { --a: 195deg; --d: 1.12; --s: 1; }
.spark:nth-child(7) { --a: 250deg; --d: 0.93; --s: 0.7; }
