/* =========================================================================
   COMPONENTS
   Layout chrome, cards, reader typography, player, drawer, overlays.
   ========================================================================= */

/* Reserve room for the fixed player and the mobile tab bar so the last ayah
   is never trapped underneath them. Both are toggled from JS. */
body {
  padding-bottom: env(safe-area-inset-bottom);
}
body.has-player {
  --player-offset: var(--player-h);
}
body:not(.has-player) {
  --player-offset: 0px;
}

/* ---------------------------------------------------------------- *
 * Skip link
 * ---------------------------------------------------------------- */
.skip-link {
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: var(--z-toast);
  padding: var(--space-3) var(--space-5);
  background: var(--accent);
  color: var(--accent-contrast);
  border-radius: var(--radius-md);
  font-weight: var(--weight-semibold);
  transform: translateY(-160%);
  transition: transform var(--dur-base) var(--ease-out);
}
.skip-link:focus {
  transform: translateY(0);
}

/* ---------------------------------------------------------------- *
 * Header
 * ---------------------------------------------------------------- */
.app-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  height: var(--header-h);
  background: var(--surface-veil);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
.app-header.is-stuck {
  border-bottom-color: var(--border-soft);
  box-shadow: var(--shadow-sm);
}
.app-header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  height: 100%;
}
.app-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
}
.brand__mark {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: var(--radius-lg);
  color: var(--accent);
  background: var(--accent-chip);
  border: 1px solid var(--accent-border);
  transition: transform var(--dur-base) var(--ease-out);
}
.brand:hover .brand__mark {
  transform: rotate(22.5deg);
}
.brand:active .brand__mark {
  transform: rotate(22.5deg) scale(0.9);
}
.brand__text {
  display: flex;
  flex-direction: column;
  line-height: 1.12;
}
.brand__text strong {
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
}
.brand__text span {
  font-size: var(--text-2xs);
  color: var(--text-subtle);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.app-nav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-left: var(--space-4);
}
.app-nav__link {
  position: relative;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--text-muted);
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out);
}
.app-nav__link:hover {
  color: var(--text);
  background: var(--surface-hover);
}
.app-nav__link.is-active {
  color: var(--accent);
  background: var(--accent-chip);
  font-weight: var(--weight-semibold);
}
/* After .is-active: the current link already carries --accent-chip, so an
   earlier press rule would be a no-op on the very link most likely tapped. */
.app-nav__link:active {
  color: var(--accent);
  background: var(--accent-soft-hover);
}

/* Every engine tested supports backdrop-filter, but it can be disabled by
   the user or missing on older builds — without a blur behind it a 0.82 veil
   lets content read straight through the sticky chrome. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .app-header,
  .reader-bar,
  .browse__controls,
  .player,
  .mobile-nav {
    background: var(--bg);
  }
}

/* ---------------------------------------------------------------- *
 * Buttons
 * ---------------------------------------------------------------- */
.icon-btn {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  border: 1px solid transparent;
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.icon-btn:hover {
  color: var(--text);
  background: var(--surface-hover);
  border-color: var(--border-soft);
}
/* Press states carry the whole burden of touch feedback now that the UA tap
   highlight is off (see base.css). A transform alone is too quiet on a small
   control, so each one also takes a wash from the theme. */
.icon-btn:active {
  transform: scale(0.94);
  color: var(--text);
  background: var(--surface-hover);
}
.icon-btn--sm {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
}
/* Carries a value instead of a glyph. The width is fixed rather than fitted so
   the row beside it does not shift as the label grows from "1x" to "1.25x",
   and the figures are tabular so the digits do not jitter between steps. */
.icon-btn--text {
  width: 46px;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
}
.icon-btn.is-on {
  color: var(--accent);
  background: var(--accent-chip);
  border-color: var(--accent-border);
}
.icon-btn:disabled {
  opacity: 0.4;
  pointer-events: none;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  border: 1px solid transparent;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn:active {
  transform: translateY(1px);
}
.btn--primary {
  background: var(--accent);
  color: var(--accent-contrast);
  box-shadow: var(--shadow-sm);
}
.btn--primary:hover {
  background: var(--accent-hover);
}
.btn--primary:active {
  background: var(--accent-hover);
  box-shadow: none;
}
.btn--ghost {
  color: var(--text-muted);
  border-color: var(--border);
}
.btn--ghost:hover {
  color: var(--text);
  background: var(--surface-hover);
  border-color: var(--border-strong);
}
.btn--ghost:active {
  color: var(--text);
  background: var(--surface-hover);
  border-color: var(--border-strong);
}
/* For the action in a confirmation the user is being warned about. Carries its
   own colour rather than reusing --primary: the point of the dialog is that
   this button is not the safe one, and it should not look identical to Save. */
.btn--danger {
  background: var(--danger);
  color: var(--danger-contrast);
  box-shadow: var(--shadow-sm);
}
.btn--danger:hover,
.btn--danger:active {
  /* No darker danger token exists, and inventing one per theme for a single
     button is not worth it — dimming reads as pressed against any of them. */
  filter: brightness(0.92);
}
.btn--danger:active {
  box-shadow: none;
}

.btn--block {
  width: 100%;
}
.btn--sm {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  /* Below 560px #playSurahBtn sheds its label and becomes icon-only, which
     left it ~33px — under the 36px floor every other control is held to. The
     reader bar's height comes from the 42px back button, so this costs
     nothing there. */
  min-height: 36px;
}

.play-btn {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--accent-contrast);
  box-shadow: var(--shadow-md);
  transition: transform var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out);
}
.play-btn:hover {
  background: var(--accent-hover);
  transform: scale(1.05);
}
.play-btn:active {
  transform: scale(0.95);
  background: var(--accent-hover);
  box-shadow: var(--shadow-sm);
}

/* Install button — only ever rendered when the app can actually be
   installed, so it never promises something the browser will not do. */
.install-btn {
  gap: var(--space-2);
  white-space: nowrap;
  flex-shrink: 0;
}
@media (max-width: 480px) {
  /* Icon only on narrow phones; the header still has to fit the brand. */
  .install-btn span {
    display: none;
  }
  .install-btn {
    padding-inline: var(--space-3);
  }
}

/* iOS instruction steps */
.modal__panel--sheet {
  width: min(440px, 100%);
}
.steps {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.steps__item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  font-size: var(--text-md);
  line-height: 1.6;
  color: var(--text-muted);
}
.steps__item strong {
  color: var(--text);
  font-weight: var(--weight-semibold);
}
.steps__num {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-full);
  background: var(--accent-chip);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
}
.steps__icon {
  display: inline-grid;
  place-items: center;
  vertical-align: -6px;
  width: 28px;
  height: 28px;
  margin-inline: 2px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
  color: var(--accent);
}

/* ---------------------------------------------------------------- *
 * Hero
 * ---------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  padding-block: var(--space-16) var(--space-12);
  background:
    radial-gradient(120% 90% at 50% -10%, var(--accent-soft) 0%, transparent 62%),
    var(--bg);
  border-bottom: 1px solid var(--border-soft);
}
.hero__content {
  position: relative;
  z-index: 1;
  text-align: center;
  max-width: 640px;
  margin-inline: auto;
}
.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--space-1);
  /* Compensates the trailing letter-space; see .badge. */
  padding-inline: calc(var(--space-3) + var(--tracking-widest)) var(--space-3);
  margin-bottom: var(--space-5);
  border-radius: var(--radius-full);
  background: var(--gold-soft);
  border: 1px solid var(--gold-border);
  color: var(--gold);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
}
.hero__bismillah {
  font-family: var(--font-arabic);
  font-size: clamp(1.9rem, 6vw, 3rem);
  line-height: 2.1;
  color: var(--accent);
  margin-bottom: var(--space-3);
  direction: rtl;
}
.hero h1 {
  font-size: clamp(var(--text-2xl), 5vw, var(--text-3xl));
  margin-bottom: var(--space-3);
}
/* Scoped to the hero copy specifically: `.hero p` also matched the
   continue-reading card's paragraphs, and at (0,1,1) it outranked their own
   (0,1,0) classes — painting dark slate text onto a dark emerald card. */
.hero__content p {
  color: var(--text-muted);
  font-size: var(--text-md);
  line-height: 1.65;
}

/* ---------------------------------------------------------------- *
 * Continue reading
 * ---------------------------------------------------------------- */
.continue-card {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: var(--space-5);
  margin-top: var(--space-8);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-xl);
  background: linear-gradient(135deg, var(--cta-from) 0%, var(--cta-to) 100%);
  color: var(--on-accent);
  box-shadow: var(--shadow-lg);
  text-align: left;
}
.continue-card .pattern-overlay {
  background-color: var(--on-accent);
  opacity: 0.12;
}
.continue-card__body {
  position: relative;
  z-index: 1;
  flex: 1;
  min-width: 0;
}
.continue-card__label {
  color: var(--on-accent-muted);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  margin-bottom: var(--space-1);
}
.continue-card__title {
  color: var(--on-accent);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.continue-card__meta {
  color: var(--on-accent-muted);
  font-size: var(--text-sm);
  margin-top: 2px;
}
.continue-card__actions {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}
.continue-card__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-md);
  /* Solid rather than the glassy translucent fill it used to have: white on
     a 16% white wash over the gradient only reached 4.04:1. A solid pill also
     reads as the primary action it is. */
  background: var(--on-accent);
  color: var(--cta-to);
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
  transition: background-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.continue-card__cta:hover {
  background: var(--gold-100);
  transform: translateY(-1px);
}
.continue-card__cta:active {
  background: var(--gold-100);
  transform: scale(0.97);
}
.continue-card__dismiss {
  color: var(--on-accent-dim);
}
.continue-card__dismiss:hover {
  color: var(--on-accent);
  background: var(--on-accent-soft);
  border-color: transparent;
}
/* Sits on the accent panel, so it presses against --on-accent-* rather than
   the page surface the other icon buttons use. */
.continue-card__dismiss:active {
  color: var(--on-accent);
  background: var(--on-accent-soft);
  border-color: transparent;
}

/* ---------------------------------------------------------------- *
 * Search + tabs
 * ---------------------------------------------------------------- */
.browse {
  padding-block: var(--space-10) var(--space-16);
}
/* Pinned under the header: the surah list is ~15000px on a phone, and the
   controls used to sit below the hero and the continue card, so switching to
   Juz meant scrolling all the way back up to reach the tabs.

   No `display: contents` wrapper is needed here, unlike .reader-bar — this is
   already a direct child of .browse, which spans the whole card list, so the
   sticky containing block is the list rather than the bar's own height.

   padding-block, not just margin-bottom: margin does not travel with a stuck
   element, so cards would slide through the gap under the veil. */
.browse__controls {
  position: sticky;
  top: var(--header-h);
  z-index: var(--z-sticky);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  padding-block: var(--space-3);
  margin-bottom: var(--space-6);
  background: var(--surface-veil);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--border-soft);
}

.search {
  position: relative;
  flex: 1;
  min-width: 260px;
}
.search__icon {
  position: absolute;
  left: var(--space-4);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-faint);
  pointer-events: none;
  display: grid;
}
.search__input {
  width: 100%;
  height: var(--control-h);
  /* Right padding leaves room for the custom clear button. */
  padding-inline: calc(var(--space-4) * 2 + 20px) calc(var(--space-4) + 30px);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: var(--text-base);
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
/* WebKit renders its own clear affordance on type=search, which would sit
   next to ours. Suppress it and keep the one we control. */
.search__input::-webkit-search-cancel-button,
.search__input::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
}
.search__input::placeholder {
  color: var(--text-faint);
  /* Safari renders placeholders lighter than the declared colour. */
  opacity: 1;
}
.search__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
.search__clear {
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
}

.tabs {
  display: inline-flex;
  height: var(--control-h);
  padding: 4px;
  border-radius: var(--radius-lg);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
  gap: 2px;
}
.tabs__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding-inline: var(--space-5);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--text-muted);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.tabs__btn:hover {
  color: var(--text);
}
.tabs__btn.is-active {
  background: var(--surface);
  color: var(--accent);
  font-weight: var(--weight-semibold);
  box-shadow: var(--shadow-xs);
}
/* After .is-active on purpose. The two selectors have identical specificity
   (0,2,0), so source order decides — declared any earlier and pressing the
   tab you are already on would show nothing at all.

   The scale is what makes this legible. A background wash alone is nearly
   invisible here: the track is --bg-subtle and the press tint --surface-hover,
   which are a shade apart in Parchment and barely separable in Midnight. */
.tabs__btn:active {
  color: var(--accent);
  background: var(--surface-hover);
  box-shadow: none;
  transform: scale(0.96);
}

/* ---------------------------------------------------------------- *
 * Surah cards
 * ---------------------------------------------------------------- */
.surah-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-4);
}

.surah-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  text-align: left;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.surah-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-border);
  box-shadow: var(--shadow-md);
}
.surah-card:hover .surah-card__num {
  color: var(--accent);
}
.surah-card:hover .surah-card__num::before {
  border-color: var(--accent-border);
  background: var(--accent-soft);
}
/* A card lifts under a cursor and sinks under a finger: pressing something
   should read as pushing it in, not pulling it up. */
.surah-card:active {
  transform: scale(0.985);
  border-color: var(--accent-border);
  box-shadow: var(--shadow-xs);
}

/* The number sits inside a rhombus, a common motif in Quranic manuscript
   numbering. The rhombus is a rotated *pseudo-element*, not the box itself:
   rotating a 44px box makes its visual bounds 62px, overflowing the layout
   box by ~9px a side and pulling the numeral optically toward the title.
   A 32px square rotated 45° spans 45.3px, so it sits inside a true 46px
   footprint and the spacing either side is exactly what the gap declares. */
.surah-card__num {
  position: relative;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex-shrink: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  transition: color var(--dur-base) var(--ease-out);
}
.surah-card__num::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 32px;
  height: 32px;
  transform: translate(-50%, -50%) rotate(45deg);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  transition: border-color var(--dur-base) var(--ease-out),
              background-color var(--dur-base) var(--ease-out);
}
.surah-card__num > span {
  position: relative; /* above the rhombus */
}

/* These are <span>s inside an <a>, so they need an explicit block display —
   left inline they run together on one line and the ellipsis never applies. */
.surah-card__body {
  display: block;
  flex: 1;
  min-width: 0;
}
.surah-card__title {
  display: block;
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.surah-card__meaning {
  display: block;
  font-size: var(--text-sm);
  color: var(--text-subtle);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.surah-card__tags {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.surah-card__arabic {
  font-family: var(--font-arabic);
  font-size: 1.5rem;
  line-height: 2;
  color: var(--gold);
  flex-shrink: 0;
  direction: rtl;
  padding-left: var(--space-2);
}

/* Letter-spacing appends a trailing space to the last glyph, so centred
   tracked text sits ~half a space left of true centre. The extra leading
   padding cancels it — the amount is bound to the tracking so the two can
   never drift apart. */
.badge {
  --badge-tracking: var(--tracking-wide);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding-block: 2px;
  padding-inline: calc(var(--space-2) + var(--badge-tracking)) var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--badge-tracking);
  line-height: 1.45;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid transparent;
}
.badge--makkah {
  background: var(--gold-soft);
  color: var(--gold);
  border-color: var(--gold-border);
}
.badge--madinah {
  background: var(--accent-chip);
  color: var(--accent);
  border-color: var(--accent-border);
}
.badge--count {
  --badge-tracking: 0em; /* untracked, so it needs no optical compensation */
  background: var(--bg-subtle);
  color: var(--text-subtle);
  border-color: var(--border-soft);
  text-transform: none;
}

/* ---------------------------------------------------------------- *
 * Juz list
 * ---------------------------------------------------------------- */
.juz-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-4);
}
.juz-card {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  text-align: left;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.juz-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-border);
  box-shadow: var(--shadow-md);
}
.juz-card:active {
  transform: scale(0.985);
  border-color: var(--accent-border);
  box-shadow: var(--shadow-xs);
}
.juz-card__num {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  background: var(--accent-chip);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}
.juz-card__label {
  display: block;
  font-weight: var(--weight-semibold);
  font-size: var(--text-md);
}
.juz-card__meta {
  display: block;
  font-size: var(--text-sm);
  color: var(--text-subtle);
}

/* ---------------------------------------------------------------- *
 * Reader — surah header card
 * ---------------------------------------------------------------- */
.reader {
  padding-block: var(--space-6) var(--space-20);
}
.reader__inner {
  max-width: var(--reader-max);
  margin-inline: auto;
}

/* A sticky element can only travel within its parent's box. This wrapper
   exists purely so the bar can be re-rendered independently, and left as a
   normal div it would be exactly the bar's own height — giving it nowhere to
   stick. `display: contents` removes the box while keeping the element (and
   its delegated listeners) in the tree, so the bar sticks within
   `.reader__inner`, which spans the whole surah. */
.reader__bar-slot {
  display: contents;
}

.reader-bar {
  position: sticky;
  top: var(--header-h);
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-block: var(--space-3);
  margin-bottom: var(--space-6);
  background: var(--surface-veil);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--border-soft);
}
.reader-bar__title {
  flex: 1;
  min-width: 0;
}
.reader-bar__title strong {
  display: block;
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Block + ellipsis, not inline: on a 393px phone "The Opener · 7 verses"
   wrapped to a second line and pushed the sticky bar from 56px to 100px. */
.reader-bar__title span {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-subtle);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.reader-bar__tools {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.surah-head {
  position: relative;
  overflow: hidden;
  padding: var(--space-8) var(--space-6);
  margin-bottom: var(--space-8);
  border-radius: var(--radius-2xl);
  text-align: center;
  background:
    radial-gradient(90% 120% at 50% 0%, var(--accent-soft) 0%, transparent 70%),
    var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}
.surah-head__content {
  position: relative;
  z-index: 1;
}
.surah-head__arabic {
  font-family: var(--font-arabic);
  font-size: clamp(2rem, 7vw, 2.9rem);
  line-height: 2;
  color: var(--accent);
  direction: rtl;
}
.surah-head__name {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  margin-top: var(--space-1);
}
.surah-head__meaning {
  color: var(--text-muted);
  font-size: var(--text-base);
  margin-top: 2px;
}
.surah-head__tags {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

/* The juz header carries a number, not a name, so it wants less vertical
   drama than a surah's — and no Bismillah, which belongs to the surahs
   inside it. */
.surah-head--juz .surah-head__arabic {
  font-size: clamp(1.6rem, 5.5vw, 2.2rem);
  line-height: 1.8;
}

/* ---------------------------------------------------------------- *
 * Reader — a surah beginning inside a juz
 * ---------------------------------------------------------------- */

.juz-seg {
  margin: var(--space-8) 0 var(--space-6);
}
.juz-seg:first-child {
  margin-top: 0;
}
.juz-seg__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-xl);
  background:
    linear-gradient(90deg, var(--accent-soft) 0%, transparent 75%),
    var(--surface);
  border: 1px solid var(--border);
}
.juz-seg__num {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-full);
  background: var(--accent-chip);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}
.juz-seg__names {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.juz-seg__name {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: inherit;
  text-decoration: none;
}
.juz-seg__name:hover {
  text-decoration: underline;
}
.juz-seg__meta {
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.juz-seg__arabic {
  font-family: var(--font-arabic);
  font-size: clamp(1.1rem, 4vw, 1.5rem);
  line-height: 2;
  color: var(--accent);
  direction: rtl;
  text-align: right;
}

/* Page mode styles the whole verse list as one right-to-left block of mushaf
   Arabic. This heading is a label *about* the reading, not part of it, so it
   restores the page defaults — inherited `direction: rtl` reverses the flex
   row, and the Arabic face and its user-scalable size land on the Latin surah
   name. Values mirror `body` in base.css; `.juz-seg__arabic` sets its own
   direction and face, so it is unaffected. */
.ayah-list--page .juz-seg {
  direction: ltr;
  text-align: left;
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text);
}

.bismillah {
  margin-top: var(--space-6);
  color: var(--gold);
}
/* Inside a juz the Bismillah follows a heading rather than a full header,
   so it needs its own breathing room and centring. */
.bismillah--inline {
  margin-top: var(--space-5);
  text-align: center;
}
.bismillah__text {
  font-family: var(--font-arabic);
  font-size: clamp(1.5rem, 5.5vw, 2.1rem);
  line-height: 2.2;
  color: var(--text-arabic);
  direction: rtl;
  margin-block: var(--space-2);
}
.ornament {
  width: 100%;
  max-width: 320px;
  height: 26px;
  margin-inline: auto;
  color: var(--gold);
}

/* ---------------------------------------------------------------- *
 * Reader — ayah cards
 * ---------------------------------------------------------------- */
.ayah-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.ayah {
  position: relative;
  /* Skips layout and paint for offscreen verses, so changing the font size
     reflows only what is visible instead of all 286 ayahs of Al-Baqarah.
     The intrinsic size keeps the scrollbar honest while they are skipped. */
  content-visibility: auto;
  contain-intrinsic-size: auto 340px;
  padding: var(--space-6);
  border-radius: var(--radius-xl);
  border: 1px solid transparent;
  scroll-margin-top: calc(var(--header-h) * 2 + var(--space-4));
  transition: background-color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.ayah:hover {
  background: var(--surface);
  border-color: var(--border-soft);
}
.ayah + .ayah {
  border-top: 1px solid var(--border-soft);
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
.ayah:hover + .ayah,
.ayah:hover {
  border-top-color: transparent;
}

/* Currently reciting: a warm wash plus a gold spine on the leading edge. */
.ayah.is-playing {
  background: var(--highlight);
  border-color: transparent;
  box-shadow: inset 3px 0 0 var(--highlight-border);
}
.ayah.is-target {
  animation: ayah-flash 1.8s var(--ease-out);
}
@keyframes ayah-flash {
  0%, 45% { background: var(--accent-soft); }
  100% { background: transparent; }
}

.ayah__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.ayah__key {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 3px var(--space-3);
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
  color: var(--text-subtle);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}
.ayah.is-playing .ayah__key {
  background: var(--gold-soft);
  border-color: var(--gold-border);
  color: var(--gold);
}

/* Action bar: hidden until hover on pointer devices, always shown on touch
   (there is no hover to reveal it). */
.ayah__actions {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.ayah:hover .ayah__actions,
.ayah:focus-within .ayah__actions,
.ayah.is-playing .ayah__actions {
  opacity: 1;
  transform: none;
}
@media (hover: none) {
  .ayah__actions {
    opacity: 1;
    transform: none;
  }
}
.ayah__actions .icon-btn.is-saved {
  color: var(--gold);
}

.ayah__arabic {
  font-family: var(--font-arabic);
  font-size: var(--arabic-size);
  line-height: var(--arabic-leading);
  color: var(--text-arabic);
  direction: rtl;
  text-align: right;
  /* Uthmani script relies on these for correct ligature shaping. */
  font-feature-settings: 'liga' 1, 'calt' 1, 'kern' 1;
  margin-bottom: var(--space-4);
  cursor: pointer;
}
/* Tapping the Arabic recites from that verse — the only way in on a mushaf
   page, where the action bar above is hidden. The UA tap highlight is off
   document-wide (base.css), so the press state is the only feedback a finger
   gets; --highlight is the wash the reciting verse already wears, so the
   press previews what the tap is about to do. No role or tabindex here: a
   role would make a screen reader announce a whole ayah as a button label
   and take the paragraph's lang="ar" with it. */
.ayah__arabic:active {
  background: var(--highlight);
  border-radius: var(--radius-sm);
}
.ayah__marker {
  display: inline-block;
  vertical-align: middle;
  color: var(--gold);
  margin-inline-start: var(--space-2);
}
.ayah-marker {
  display: block;
}

.ayah__transliteration {
  font-size: calc(var(--translation-size) * 0.94);
  line-height: 1.75;
  color: var(--text-subtle);
  font-style: italic;
  margin-bottom: var(--space-3);
  padding-left: var(--space-4);
  border-left: 2px solid var(--border);
}
.ayah__translation {
  font-size: var(--translation-size);
  line-height: var(--translation-leading);
  color: var(--text-muted);
}
.ayah__sajdah {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
  padding: 3px var(--space-3);
  border-radius: var(--radius-full);
  background: var(--gold-soft);
  border: 1px solid var(--gold-border);
  color: var(--gold);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}

/* Page mode: verses read as one flowing block of Arabic, mushaf-style. */
.ayah-list--page .ayah {
  display: inline;
  padding: 0;
  border: none;
  background: none;
  box-shadow: none;
}
.ayah-list--page {
  display: block;
  font-family: var(--font-arabic);
  font-size: var(--arabic-size);
  line-height: var(--arabic-leading);
  color: var(--text-arabic);
  direction: rtl;
  text-align: center;
  padding: var(--space-6);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}
.ayah-list--page .ayah__head,
.ayah-list--page .ayah__translation,
.ayah-list--page .ayah__transliteration,
.ayah-list--page .ayah__sajdah {
  display: none;
}
.ayah-list--page .ayah__arabic {
  display: inline;
  margin: 0;
  font-size: inherit;
  line-height: inherit;
}
.ayah-list--page .ayah.is-playing {
  background: var(--highlight);
  border-radius: var(--radius-sm);
  box-shadow: none;
}
/* Continuous mode draws the verse boundary with `.ayah:hover`; a mushaf page
   has no card edge to hover, so the wash is what shows which verse the
   pointer would recite. Not on touch — there is no hover to lose. */
@media (hover: hover) {
  .ayah-list--page .ayah__arabic:hover {
    background: var(--accent-soft);
    border-radius: var(--radius-sm);
  }
}

.page-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.page-nav__status {
  font-size: var(--text-sm);
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}

/* Surah-to-surah navigation at the end of the reader. */
.reader-foot {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-10);
}
.reader-foot__link {
  flex: 1;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  transition: border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.reader-foot__link:hover {
  border-color: var(--accent-border);
  transform: translateY(-2px);
}
.reader-foot__link:active {
  border-color: var(--accent-border);
  background: var(--surface-hover);
  transform: scale(0.98);
}
.reader-foot__link--next {
  justify-content: flex-end;
  text-align: right;
}
.reader-foot__label {
  display: block;
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-faint);
}
.reader-foot__name {
  display: block;
  font-weight: var(--weight-semibold);
}

/* ---------------------------------------------------------------- *
 * Player
 * ---------------------------------------------------------------- */
.player {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-player);
  height: var(--player-h);
  background: var(--surface-veil);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--border);
  box-shadow: var(--shadow-player);
  padding-bottom: env(safe-area-inset-bottom);
  animation: player-in var(--dur-slow) var(--ease-out);
}
@keyframes player-in {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}
.player__inner {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  height: var(--player-h);
}

/* Thin surah-level progress line pinned to the player's top edge. */
.player__progress-rail {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--border-soft);
}
.player__progress-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent), var(--gold-bright));
  transition: width var(--dur-base) linear;
}

.player__meta {
  min-width: 0;
  flex: 1;
}
.player__verse {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2);
  margin-left: calc(var(--space-2) * -1);
  border-radius: var(--radius-md);
  text-align: left;
  min-width: 0;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.player__verse:hover {
  background: var(--surface-hover);
}
/* A full-width list row: scaling it looks like a glitch, so the press goes a
   shade deeper than hover instead. */
.player__verse:active {
  background: var(--accent-chip);
}
.player__ayah-badge {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  background: var(--accent-chip);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}
.player__labels {
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}
.player__surah {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.player__sub {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  white-space: nowrap;
}

.player__transport {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}
.player__seek {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1.6;
  min-width: 0;
}
.player__time {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  /* Wide enough for "12:34" so the seek bar never shifts as time ticks. */
  width: 38px;
}
.player__time:last-child {
  text-align: right;
}
.player__options {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* ---------------------------------------------------------------- *
 * Form controls
 * ---------------------------------------------------------------- */
.select {
  height: 38px;
  padding-inline: var(--space-3) var(--space-8);
  border-radius: var(--radius-md);
  background-color: var(--surface);
  border: 1px solid var(--border);
  font-size: var(--text-sm);
  color: var(--text);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  background-image: var(--select-arrow);
  background-repeat: no-repeat;
  background-position: right var(--space-2) center;
  background-size: 17px;
  transition: border-color var(--dur-fast) var(--ease-out);
}
.select:hover {
  border-color: var(--border-strong);
}
.select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
.select--reciter {
  max-width: 190px;
}
.select--block {
  width: 100%;
  height: 44px;
  font-size: var(--text-base);
}

.range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 20px;
  background: transparent;
  cursor: pointer;
}
.range::-webkit-slider-runnable-track {
  height: 5px;
  border-radius: var(--radius-full);
  background: var(--border);
}
.range::-moz-range-track {
  height: 5px;
  border-radius: var(--radius-full);
  background: var(--border);
}
.range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  margin-top: -5px;
  border-radius: var(--radius-full);
  background: var(--accent);
  border: 2px solid var(--surface);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-out);
}
.range::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: var(--radius-full);
  background: var(--accent);
  border: 2px solid var(--surface);
  box-shadow: var(--shadow-sm);
}
.range:hover::-webkit-slider-thumb {
  transform: scale(1.18);
}
/* Confirms the thumb was actually grabbed — the one place where the tap
   highlight never helped, since it does not paint pseudo-elements. */
.range:active::-webkit-slider-thumb {
  transform: scale(1.28);
}
.range:active::-moz-range-thumb {
  transform: scale(1.28);
}
.range:focus-visible::-webkit-slider-thumb {
  box-shadow: var(--ring);
}

/* A 15px thumb is fine for a mouse and far too small for a finger; WCAG 2.5.8
   wants 24px minimum and a comfortable touch target is nearer 28px. */
@media (pointer: coarse) {
  .range {
    height: 34px;
  }
  .range::-webkit-slider-runnable-track {
    height: 8px;
  }
  .range::-moz-range-track {
    height: 8px;
  }
  .range::-webkit-slider-thumb {
    width: 28px;
    height: 28px;
    margin-top: -10px;
  }
  .range::-moz-range-thumb {
    width: 28px;
    height: 28px;
  }
}

/* Stepper + slider. The buttons matter more than the slider on a phone:
   dragging a thumb to hit an exact size is fiddly, tapping is not. */
.size-control {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.size-control .range {
  flex: 1;
  min-width: 0;
}
.size-control__btn {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font-weight: var(--weight-bold);
  line-height: 1;
  transition: background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.size-control__btn:hover {
  color: var(--accent);
  border-color: var(--accent-border);
  background: var(--accent-chip);
}
.size-control__btn:active {
  transform: scale(0.93);
  color: var(--accent);
  border-color: var(--accent-border);
  background: var(--accent-chip);
}
.size-control__btn:disabled {
  opacity: 0.38;
  pointer-events: none;
}
.size-control__btn--small {
  font-size: var(--text-sm);
}
.size-control__btn--large {
  font-size: var(--text-lg);
}

/* Switch */
.switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  cursor: pointer;
}
.switch__label {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
}
.switch__hint {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  margin-top: 1px;
}
.switch__track {
  position: relative;
  flex-shrink: 0;
  width: 46px;
  height: 27px;
  border-radius: var(--radius-full);
  background: var(--border);
  transition: background-color var(--dur-base) var(--ease-out);
}
.switch__track::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 21px;
  height: 21px;
  border-radius: var(--radius-full);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-out);
}
.switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.switch input:checked + .switch__track {
  background: var(--accent);
}
.switch input:checked + .switch__track::after {
  transform: translateX(19px);
}
.switch input:focus-visible + .switch__track {
  box-shadow: var(--ring);
}

/* ---------------------------------------------------------------- *
 * Settings drawer
 * ---------------------------------------------------------------- */
.scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  background: var(--scrim);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  animation: fade-in var(--dur-base) var(--ease-out);
}
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-drawer);
  width: min(410px, 100vw);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-xl);
  animation: drawer-in var(--dur-slow) var(--ease-out);
}
@keyframes drawer-in {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}
.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--border-soft);
  flex-shrink: 0;
}
.drawer__head h2 {
  font-size: var(--text-lg);
}
.drawer__body {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2) var(--space-6) var(--space-6);
  overscroll-behavior: contain;
}
.drawer__foot {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--border-soft);
  flex-shrink: 0;
}
/* Two full-width labels do not fit side by side on a 360px drawer at the
   default button padding, so the footer pair runs tighter than .btn does
   elsewhere. Equal basis keeps neither action looking like the primary one
   by width alone — colour does that job. */
.drawer__foot .btn {
  flex: 1 1 0;
  min-width: 0;
  padding-inline: var(--space-3);
  white-space: nowrap;
}

.field {
  padding-block: var(--space-5);
  border-bottom: 1px solid var(--border-soft);
}
.field:last-child {
  border-bottom: none;
}
.field__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.field__label span:first-child {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-subtle);
}
/* Explanatory line under a control. Sits between label and control, or under
   the control as a footnote — hence the margin on both sides. */
.field__hint {
  margin-block: var(--space-2);
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--text-subtle);
}
.field__hint:last-child {
  margin-bottom: 0;
}

/* An inline statement of fact about what is on screen — not an error, and not
   dismissible, so it is quieter than a toast and louder than body text. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--accent-chip);
  color: var(--text-muted);
  font-size: var(--text-sm);
  line-height: 1.55;
}
.notice svg {
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--accent);
}
.notice strong {
  color: var(--text);
  font-weight: var(--weight-semibold);
}

.field__value {
  font-size: var(--text-xs);
  color: var(--accent);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}
.field__preview {
  margin-top: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
  overflow: hidden;
}
.field__preview .prev-arabic {
  font-family: var(--font-arabic);
  font-size: var(--arabic-size);
  line-height: var(--arabic-leading);
  color: var(--text-arabic);
  direction: rtl;
  text-align: right;
}
.field__preview .prev-translation {
  font-size: var(--translation-size);
  line-height: var(--translation-leading);
  color: var(--text-muted);
}

/* Theme picker */
.theme-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
.theme-swatch {
  padding: var(--space-3);
  border-radius: var(--radius-md);
  border: 2px solid var(--border);
  background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.theme-swatch:hover {
  transform: translateY(-2px);
}
.theme-swatch.is-active {
  border-color: var(--accent);
}
/* After .is-active, as with the other toggle groups. */
.theme-swatch:active {
  transform: scale(0.96);
  border-color: var(--accent-border);
}
.theme-swatch__chip {
  height: 42px;
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-2);
  border: 1px solid var(--hairline);
  display: grid;
  place-items: center;
}
/* These three are deliberately literal, not tokens: each chip previews what a
   theme looks like, so it must keep those colours no matter which theme is
   currently active. Tokenising them would make every swatch look identical. */
.theme-swatch__chip--parchment {
  background: linear-gradient(135deg, #FDFBF7 55%, #047857 55%);
  color: #B45309;
}
.theme-swatch__chip--midnight {
  background: linear-gradient(135deg, #0F172A 55%, #34D399 55%);
  color: #FCD34D;
}
.theme-swatch__chip--emerald {
  background: linear-gradient(135deg, #064E3B 55%, #6EE7B7 55%);
  color: #FCD34D;
}
.theme-swatch__name {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-muted);
}
.theme-swatch.is-active .theme-swatch__name {
  color: var(--accent);
}

/* Segmented control */
.segmented {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 2px;
  padding: 4px;
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
}
.segmented__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  /* 8px of padding around a 17px glyph is 33px, under the 36px floor the
     device suite holds every other control to. It went unnoticed because the
     tap-target sweep does not select .segmented__btn. */
  min-height: 36px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-muted);
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.segmented__btn:hover {
  color: var(--text);
}
.segmented__btn.is-active {
  background: var(--surface);
  color: var(--accent);
  font-weight: var(--weight-semibold);
  box-shadow: var(--shadow-xs);
}
/* Same equal-specificity ordering, and the same reason for the scale, as
   .tabs__btn above. */
.segmented__btn:active {
  color: var(--accent);
  background: var(--surface-hover);
  box-shadow: none;
  transform: scale(0.96);
}

/* ---------------------------------------------------------------- *
 * Modal (tafsir)
 * ---------------------------------------------------------------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: var(--scrim);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: fade-in var(--dur-base) var(--ease-out);
}
.modal__panel {
  width: min(720px, 100%);
  max-height: min(82vh, 780px);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  animation: modal-in var(--dur-slow) var(--ease-out);
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(18px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
.modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--border-soft);
  flex-shrink: 0;
}
.modal__head h2 {
  font-size: var(--text-lg);
}
.modal__sub {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  margin-top: 2px;
}
.modal__body {
  overflow-y: auto;
  padding: var(--space-6);
  overscroll-behavior: contain;
}

/* ---- Confirmation dialog ----
   Reuses .modal for the backdrop and .modal__panel for the card, so it inherits
   the blur, the entry animation and the per-theme surface. Only three things
   differ: it sits above the drawer that launched it, it is sized for a question
   rather than a scrolling document, and its own padding replaces the
   head/body split a panel with a close button needs. */
.confirm {
  z-index: var(--z-confirm);
}
.confirm__panel {
  width: min(23rem, 100%);
  padding: var(--space-6);
  /* Small, so the sentence sits with the question it explains rather than
     floating midway to the buttons. The buttons take their own margin below —
     a larger gap here would apply to both pairs, which is the opposite. */
  gap: var(--space-2);
}
.confirm__title {
  font-size: var(--text-lg);
}
.confirm__text {
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--text-muted);
}
.confirm__actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
/* Equal width, as in the drawer footer: the safe answer must not be the harder
   one to hit, which is what a narrow Cancel next to a wide primary produces. */
.confirm__actions .btn {
  flex: 1 1 0;
  min-width: 0;
}

/* Tafsir HTML comes from the API; these style the tags it actually emits. */
.tafsir-content {
  font-family: var(--font-prose);
  font-size: var(--text-md);
  line-height: 1.78;
  color: var(--text-muted);
}
.tafsir-content h1,
.tafsir-content h2,
.tafsir-content h3 {
  color: var(--text);
  font-size: var(--text-md);
  line-height: 1.35;
  margin-block: var(--space-5) var(--space-2);
}
/* The API emits runs of consecutive headings; collapse the gap between them
   so they read as one title block rather than three stranded lines. */
.tafsir-content h1 + h2,
.tafsir-content h2 + h2,
.tafsir-content h2 + h3,
.tafsir-content h3 + h3 {
  margin-top: var(--space-1);
  color: var(--text-muted);
  font-size: var(--text-base);
}
.tafsir-content h1:first-child,
.tafsir-content h2:first-child {
  margin-top: 0;
}
.tafsir-content p {
  margin-bottom: var(--space-4);
}
.tafsir-content .arabic,
.tafsir-content [dir='rtl'] {
  font-family: var(--font-arabic);
  font-size: 1.45rem;
  line-height: 2.1;
  color: var(--text-arabic);
  direction: rtl;
  text-align: right;
  margin-block: var(--space-4);
}
.tafsir-content b,
.tafsir-content strong {
  color: var(--text);
}

.tafsir-verse {
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--gold);
}
.tafsir-verse__arabic {
  font-family: var(--font-arabic);
  font-size: 1.6rem;
  line-height: 2.15;
  color: var(--text-arabic);
  direction: rtl;
  text-align: right;
}
.tafsir-verse__translation {
  font-size: var(--text-base);
  color: var(--text-muted);
  margin-top: var(--space-2);
}

/* ---------------------------------------------------------------- *
 * Toasts
 * ---------------------------------------------------------------- */
.toast-stack {
  position: fixed;
  /* Spans the viewport and centres its children, rather than sitting at
     left:50%: a shrink-to-fit box anchored at the midpoint can only be half
     the screen wide, which is what a wrapping message would be squeezed into. */
  left: 0;
  right: 0;
  bottom: calc(var(--player-offset, 0px) + var(--space-6) + env(safe-area-inset-bottom));
  padding-inline: var(--space-4);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  /* Each pill sizes to its own text. Stretching them to the stack's width
     leaves short messages in a full-width bar with the text off to one side. */
  align-items: center;
  gap: var(--space-2);
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* A long message wraps rather than running off a narrow screen — the pill
     is centred by the stack, so overflow would be cut off on both sides. */
  max-width: min(92vw, 26rem);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--slate-800);
  color: var(--on-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1.45;
  box-shadow: var(--shadow-lg);
  animation: toast-in var(--dur-base) var(--ease-out);
}
[data-theme='parchment'] .toast {
  background: var(--slate-800);
}
[data-theme='midnight'] .toast,
[data-theme='emerald'] .toast {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  color: var(--text);
}
/* Two classes deliberately: the per-theme rules above are `[data-theme] .toast`,
   so a single-class error rule loses to them and errors render in the ordinary
   surface colour under midnight and emerald. */
.toast.toast--error {
  background: var(--danger);
  color: var(--danger-contrast);
  border-color: transparent;
}
.toast.is-leaving {
  animation: toast-out var(--dur-base) var(--ease-in-out) forwards;
}
.toast svg {
  color: var(--emerald-400);
  flex-shrink: 0;
}
.toast--error svg {
  color: var(--danger-contrast);
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(12px) scale(0.96); }
  to { opacity: 1; transform: none; }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(8px) scale(0.96); }
}

/* ---------------------------------------------------------------- *
 * States: loading, empty, error
 * ---------------------------------------------------------------- */
.skeleton {
  border-radius: var(--radius-md);
  background: linear-gradient(
    90deg,
    var(--bg-subtle) 25%,
    var(--surface-hover) 50%,
    var(--bg-subtle) 75%
  );
  background-size: 220% 100%;
  animation: shimmer 1.4s infinite linear;
}
@keyframes shimmer {
  from { background-position: 220% 0; }
  to { background-position: -20% 0; }
}
.skeleton-card {
  height: 84px;
  border-radius: var(--radius-lg);
}
.skeleton-ayah {
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.state {
  text-align: center;
  padding: var(--space-16) var(--space-5);
  max-width: 440px;
  margin-inline: auto;
}
.state__icon {
  display: grid;
  place-items: center;
  width: 66px;
  height: 66px;
  margin: 0 auto var(--space-5);
  border-radius: var(--radius-xl);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
  color: var(--text-faint);
}
.state__title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-2);
}
.state__text {
  color: var(--text-muted);
  margin-bottom: var(--space-5);
  line-height: 1.65;
}

.spinner {
  width: 22px;
  height: 22px;
  border: 2.5px solid var(--border);
  border-top-color: var(--accent);
  border-radius: var(--radius-full);
  animation: spin 0.7s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

.section-title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.section-title h2 {
  font-size: var(--text-lg);
}
.section-title__count {
  font-size: var(--text-sm);
  color: var(--text-subtle);
}

/* ---------------------------------------------------------------- *
 * Bookmarks
 * ---------------------------------------------------------------- */
.bookmark-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.bookmark-card {
  position: relative;
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--gold);
  transition: border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.bookmark-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}
.bookmark-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.bookmark-card__ref {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--accent);
  transition: opacity var(--dur-fast) var(--ease-out);
}
/* A bare text link — nothing to wash or scale without shifting the line, so
   it dims instead. */
.bookmark-card__ref:active {
  opacity: 0.6;
}
.bookmark-card__date {
  font-size: var(--text-xs);
  color: var(--text-faint);
}
.bookmark-card__arabic {
  font-family: var(--font-arabic);
  font-size: 1.6rem;
  line-height: 2.15;
  color: var(--text-arabic);
  direction: rtl;
  text-align: right;
  margin-bottom: var(--space-3);
}
.bookmark-card__translation {
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--text-muted);
}
.bookmark-card__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

/* ---------------------------------------------------------------- *
 * Footer
 * ---------------------------------------------------------------- */
.app-footer {
  padding-block: var(--space-8);
  padding-bottom: calc(var(--space-8) + var(--player-offset, 0px));
  border-top: 1px solid var(--border-soft);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-subtle);
}
.app-footer a {
  color: var(--accent);
  font-weight: var(--weight-medium);
}
.app-footer a:hover {
  text-decoration: underline;
}

/* ---------------------------------------------------------------- *
 * Mobile navigation
 * ---------------------------------------------------------------- */
.mobile-nav {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  /* The bar is anchored below the viewport and given matching extra height and
     bottom padding, so its top edge and content box land exactly where
     `bottom: 0` would put them. The overhang is only there to absorb an
     overscroll bounce on engines without `overscroll-behavior` (iOS < 16):
     the bar lifts, but what appears underneath is more bar, not a gap.
     Fixed elements add no scrollable overflow, so nothing else moves. */
  bottom: calc(var(--nav-overscroll) * -1);
  z-index: var(--z-nav);
  height: calc(
    var(--mobile-nav-h) + env(safe-area-inset-bottom) + var(--nav-overscroll)
  );
  padding-bottom: calc(env(safe-area-inset-bottom) + var(--nav-overscroll));
  background: var(--surface-veil);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--border);
}
.mobile-nav__link {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  color: var(--text-subtle);
  transition: color var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}
.mobile-nav__link.is-active {
  color: var(--accent);
}
/* The tab bar is the most-tapped surface in the app and had no press state at
   all — the UA highlight was doing the whole job. The link fills its column,
   so washing the background would paint a full-height slab over the blurred
   bar; the icon dipping is the lighter read. The dim is what makes the press
   legible on the tab you are already on, where the colour is already accent.
   Declared after .is-active so it is not outranked by source order. */
.mobile-nav__link:active {
  color: var(--accent);
  opacity: 0.62;
}
.mobile-nav__link:active .mobile-nav__icon {
  transform: scale(0.86);
}
.mobile-nav__icon {
  display: grid;
  place-items: center;
  height: 24px;
  transition: transform var(--dur-fast) var(--ease-out);
}

/* ---------------------------------------------------------------- *
 * Responsive
 * ---------------------------------------------------------------- */
@media (max-width: 900px) {
  .player__seek {
    display: none;
  }
  .select--reciter {
    max-width: 130px;
  }
}

@media (max-width: 768px) {
  :root {
    --header-h: 60px;
    --player-h: 68px;
  }

  .app-nav {
    display: none;
  }
  /* Keep the product name on phones; only the smaller subtitle is dropped. */
  .brand__text span {
    display: none;
  }
  .brand__text strong {
    font-size: var(--text-base);
  }

  .mobile-nav {
    display: flex;
  }

  /* Lift fixed chrome above the tab bar and keep content clear of both. */
  .player {
    bottom: calc(var(--mobile-nav-h) + env(safe-area-inset-bottom));
    padding-bottom: 0;
  }
  body:not(.has-player) {
    --player-offset: 0px;
  }
  .app-footer {
    padding-bottom: calc(
      var(--space-8) + var(--mobile-nav-h) + var(--player-offset, 0px) +
      env(safe-area-inset-bottom)
    );
  }
  .toast-stack {
    bottom: calc(
      var(--mobile-nav-h) + var(--player-offset, 0px) + var(--space-4) +
      env(safe-area-inset-bottom)
    );
  }

  .hero {
    padding-block: var(--space-10) var(--space-8);
  }
  .browse {
    padding-block: var(--space-6) var(--space-10);
  }
  .browse__controls {
    gap: var(--space-3);
  }
  .search {
    min-width: 100%;
  }
  .tabs {
    width: 100%;
  }
  .tabs__btn {
    flex: 1;
  }

  .surah-grid,
  .juz-grid {
    grid-template-columns: 1fr;
  }

  .continue-card {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-4);
  }
  .continue-card__actions {
    justify-content: space-between;
  }
  .continue-card__cta {
    flex: 1;
    justify-content: center;
  }

  .ayah {
    padding: var(--space-5) var(--space-2);
  }
  .surah-head {
    padding: var(--space-6) var(--space-4);
  }

  /* On mobile the player collapses to identity + transport, keeping only the
     two controls worth a tap mid-recitation: speed and close. Reciter and
     download stay reachable from the surah page and Settings. */
  .player__inner {
    gap: var(--space-3);
  }
  .player__options .icon-btn:not(#closePlayerBtn):not(#speedBtn) {
    display: none;
  }
  .select--reciter {
    display: none;
  }

  .reader-foot {
    flex-direction: column;
  }
  .modal__panel {
    max-height: 88vh;
  }
  .drawer {
    width: 100vw;
  }
}

/* The reader bar carries back + title + mode toggle + Play. Below ~560px the
   fixed controls squeeze the title until the surah name itself truncates
   ("A…"), so shed chrome progressively rather than the one label that
   identifies the page. Reading mode stays reachable in Settings. */
@media (max-width: 560px) {
  .reader-bar__title span {
    display: none;
  }
  #playSurahBtn span {
    display: none;
  }
  #playSurahBtn {
    padding-inline: var(--space-3);
  }
}

/* Below 400px the two-up group costs the surah name its last ~50px, so it
   collapses to one button: the mode you are *not* in. Tapping it switches,
   which is all the pair ever did — the active half was only ever a state
   readout, and the title is the better use of the pixels. The wrapper sheds
   its chrome with it: a lone button inside a group frame reads as a control
   that failed to render, not as a button. Scoped to .reader-bar; the drawer's
   copy of this control is a settings readout and keeps both halves.

   Sized explicitly rather than given .icon-btn: these buttons are 33px in the
   group (8px padding around a 17px glyph), which is under the suite's 36px
   floor — inheriting the icon-btn class would pull the >=400px pair into the
   measured tap-target set at that size. */
@media (max-width: 400px) {
  .reader-bar .segmented {
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
  }
  .reader-bar .segmented__btn.is-active {
    display: none;
  }
  .reader-bar .segmented__btn {
    width: 38px;
    height: 38px;
    padding: 0;
    border-radius: var(--radius-md);
  }
  .reader-bar .segmented__btn svg {
    width: 19px;
    height: 19px;
  }
}

@media (max-width: 420px) {
  .player__ayah-badge {
    display: none;
  }
  .surah-card {
    padding: var(--space-4);
    gap: var(--space-3);
  }
  .surah-card__arabic {
    font-size: 1.3rem;
  }
}

/* ================================================================== *
 * Prayer times, qibla and the Hijri date
 * ================================================================== */
.times {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

/* ---- Header: the date, and the countdown people actually came for ---- */
.times__head {
  position: relative;
  overflow: hidden;
  padding: var(--space-8) var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-2xl);
  background:
    radial-gradient(125% 150% at 50% -25%, var(--accent-chip) 0%, transparent 60%),
    var(--surface);
  box-shadow: var(--shadow-sm);
  text-align: center;
}
/* Lifts the content clear of the absolutely-positioned pattern overlay. */
.times__head-inner {
  position: relative;
}
.times__gregorian {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-subtle);
}
.times__hijri {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}
.times__hijri svg {
  flex: none;
  color: var(--gold);
}

/* The countdown is the reason most people open this page, so it reads as the
   headline rather than a footnote under the date. */
.times__next {
  display: inline-grid;
  justify-items: center;
  gap: var(--space-1);
  margin-top: var(--space-6);
  padding: var(--space-4) var(--space-8);
  border: 1px solid var(--accent-border);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-xs);
}
.times__next-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-subtle);
}
.times__next-label svg {
  color: var(--accent);
}
.times__next-name {
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--accent);
}
.times__next-in {
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}
/* Empty until the first tick paints; an empty card would look like a bug. */
.times__next:empty {
  display: none;
}

/* ---- The five prayers ---- */
.prayer-list {
  list-style: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
.prayer {
  display: grid;
  grid-template-columns: 3px 1fr auto auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border-soft);
  transition: background-color var(--dur-base) var(--ease-out);
}
.prayer:last-child {
  border-bottom: none;
}
/* The rail carries the current/next state. A lit rail costs no layout shift,
   where a border or a weight change on the row would nudge everything else. */
.prayer__marker {
  width: 3px;
  height: 18px;
  border-radius: var(--radius-full);
  background: transparent;
  transition:
    background-color var(--dur-base) var(--ease-out),
    height var(--dur-base) var(--ease-out);
}
.prayer__label {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
}
.prayer__name {
  font-weight: var(--weight-medium);
}
.prayer__tag {
  font-size: var(--text-2xs);
  font-style: normal;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}
.prayer__arabic {
  font-family: var(--font-arabic);
  font-size: var(--text-lg);
  color: var(--text-faint);
}
.prayer__time {
  min-width: 5.5ch;
  text-align: right;
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold);
  color: var(--text);
}
/* Sunrise is a boundary, not a prayer, so it sits quieter than the five. */
.prayer--boundary .prayer__name,
.prayer--boundary .prayer__time {
  font-weight: var(--weight-normal);
  color: var(--text-subtle);
}

/* The window you are currently inside. */
.prayer.is-current {
  background: var(--accent-chip);
}
.prayer.is-current .prayer__marker {
  height: 28px;
  background: var(--accent);
}
.prayer.is-current .prayer__name {
  color: var(--accent);
  font-weight: var(--weight-semibold);
}
.prayer.is-current .prayer__time {
  color: var(--accent);
}
/* The one being counted down to. */
.prayer.is-next .prayer__marker {
  background: var(--accent-border);
}
.prayer.is-next .prayer__time {
  color: var(--accent);
}

/* ---- Qibla ---- */
.qibla {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-8) var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
/* Scoped to .qibla on purpose. Unscoped, this rule sat later in the file than
   the shared `.section-title` component and silently restyled every heading on
   the home and bookmarks pages too. */
.qibla .section-title {
  align-self: flex-start;
  gap: var(--space-2);
  margin-bottom: 0;
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-subtle);
}
.qibla .section-title svg {
  color: var(--accent);
}

.qibla__dial {
  /* Overwritten inline with the computed bearing; declared here so the dial
     is still coherent if script never runs. */
  --needle: 0deg;
  position: relative;
  width: min(260px, 72vw);
  aspect-ratio: 1;
}
/* The rose — ticks, cardinals and needle together — is what turns, exactly as
   the printed card of a real compass does. At rest --rose is 0deg, so N sits at
   the top and the needle rests at the fixed bearing; live, the rose counters
   the device heading so N keeps pointing at true north. Rotating the needle
   alone would leave N painted at the top of the screen whichever way the phone
   was facing, which reads as a compass but isn't one. */
.qibla__ring {
  --rose: 0deg;
  position: relative;
  width: 100%;
  height: 100%;
  border: 1px solid var(--border);
  border-radius: 50%;
  background:
    radial-gradient(circle closest-side, var(--surface) 62%, transparent 63%),
    radial-gradient(circle closest-side, var(--accent-chip) 0%, transparent 72%),
    var(--bg-subtle);
  transform: rotate(var(--rose, 0deg));
  will-change: transform;
}
/* Only once a heading is arriving — the resting dial should not ease in from
   nowhere on first paint. The JS feeds an unwrapped angle, so 359deg -> 361deg
   animates two degrees forward rather than spinning the long way back. */
.qibla__ring.is-live {
  transition: transform 260ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Tick marks, drawn as conic gradients masked to a ring band — no extra
   elements and no 72 hand-placed spans. */
.qibla__ticks {
  position: absolute;
  inset: 0;
  border-radius: 50%;
}
.qibla__ticks--minor {
  opacity: 0.5;
  background: repeating-conic-gradient(
    from -0.35deg,
    var(--text-faint) 0deg 0.7deg,
    transparent 0.7deg 7.5deg
  );
  -webkit-mask-image: radial-gradient(circle closest-side, transparent 0 89%, #000 90% 96%, transparent 97%);
  mask-image: radial-gradient(circle closest-side, transparent 0 89%, #000 90% 96%, transparent 97%);
}
.qibla__ticks--major {
  opacity: 0.75;
  background: repeating-conic-gradient(
    from -0.7deg,
    var(--text-subtle) 0deg 1.4deg,
    transparent 1.4deg 30deg
  );
  -webkit-mask-image: radial-gradient(circle closest-side, transparent 0 82%, #000 83% 96%, transparent 97%);
  mask-image: radial-gradient(circle closest-side, transparent 0 82%, #000 83% 96%, transparent 97%);
}

.qibla__cardinal {
  position: absolute;
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  color: var(--text-faint);
}
.qibla__cardinal--n { top: 12%; left: 50%; transform: translateX(-50%); color: var(--gold); }
.qibla__cardinal--s { bottom: 12%; left: 50%; transform: translateX(-50%); }
.qibla__cardinal--e { right: 12%; top: 50%; transform: translateY(-50%); }
.qibla__cardinal--w { left: 12%; top: 50%; transform: translateY(-50%); }

/* Pinned at the qibla bearing and left there. It is the rose around it that
   turns, so the needle's angle on screen is bearing minus heading without this
   element having to know the heading at all. */
.qibla__needle {
  position: absolute;
  inset: 0;
  transform: rotate(var(--needle, 0deg));
}
/* The pointing half: a tapered blade rather than a hairline, so the direction
   is readable at a glance on a phone held at arm's length. */
.qibla__needle::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 17%;
  width: 13px;
  height: 33%;
  transform: translateX(-50%);
  background: linear-gradient(to bottom, var(--accent) 0%, var(--accent) 58%, transparent 100%);
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
/* Counterweight, so the needle reads as balanced on its hub. */
.qibla__needle::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 22%;
  width: 9px;
  height: 25%;
  transform: translateX(-50%);
  background: var(--text-faint);
  opacity: 0.3;
  clip-path: polygon(50% 100%, 100% 0, 0 0);
}
.qibla__hub {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 12px;
  height: 12px;
  transform: translate(-50%, -50%);
  border: 2px solid var(--accent);
  border-radius: 50%;
  background: var(--surface);
}
.qibla__kaaba {
  position: absolute;
  left: 50%;
  top: 3%;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--accent);
  color: var(--accent);
  box-shadow: var(--shadow-xs);
}

/* Live tracking: a slow breath on the Kaaba marker, so a still needle reads as
   "following you" rather than "frozen". */
.qibla__dial.is-live .qibla__kaaba {
  animation: qibla-breathe 2.4s var(--ease-in-out) infinite;
}
@keyframes qibla-breathe {
  0%, 100% { transform: translateX(-50%) scale(1); }
  50%      { transform: translateX(-50%) scale(1.09); }
}
.qibla__dial.is-seeking .qibla__needle {
  opacity: 0.45;
}
/* Held too upright to trust. The dial is dimmed rather than frozen, because the
   reading is still arriving — it just should not be read as precise. */
.qibla__dial.is-unsteady .qibla__ring {
  opacity: 0.55;
}
.qibla__dial.is-unsteady .qibla__kaaba {
  animation: none;
}
@media (prefers-reduced-motion: reduce) {
  .qibla__dial.is-live .qibla__kaaba { animation: none; }
  .qibla__ring, .qibla__ring.is-live { transition: none; }
}

.qibla__read {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: var(--space-2) var(--space-3);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.qibla__read strong {
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.qibla__point {
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  background: var(--accent-chip);
  color: var(--accent);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
}
.qibla__dist {
  width: 100%;
  font-size: var(--text-xs);
  color: var(--text-faint);
}
.qibla__status {
  max-width: 44ch;
  text-align: center;
  font-size: var(--text-xs);
  line-height: 1.55;
  color: var(--text-subtle);
}
.qibla__toggle {
  margin-top: calc(var(--space-1) * -1);
}

/* ---- Location ---- */
.times__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  font-size: var(--text-sm);
  color: var(--text-subtle);
}
.times__place {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
.times__place svg {
  flex: none;
  color: var(--accent);
}
.times__place-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.times__place-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: var(--weight-semibold);
  color: var(--text);
}
.times__place-src {
  font-size: var(--text-2xs);
  color: var(--text-faint);
}

/* Phones: the dial and the header card give back their generous padding
   before anything is allowed to scroll sideways. */
@media (max-width: 480px) {
  .times { gap: var(--space-6); }
  .times__head { padding: var(--space-6) var(--space-4); }
  .times__next { padding: var(--space-3) var(--space-5); }
  .qibla { padding: var(--space-6) var(--space-4); }
  .prayer { padding: var(--space-4); gap: var(--space-3); }
}

.manual-loc {
  max-width: 460px;
  margin: var(--space-6) auto 0;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.manual-loc__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}
.manual-loc__field {
  display: block;
  margin-bottom: var(--space-3);
}
.manual-loc__field span {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-subtle);
}
.manual-loc__field input {
  width: 100%;
  height: var(--control-h);
  padding-inline: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg);
  color: var(--text);
}
.manual-loc__field input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ---------------------------------------------------------------- *
 * Touch: hover is not a state a finger can leave
 * ---------------------------------------------------------------- */
/* Safari applies :hover on touch and keeps it applied until something else is
   tapped, so a lift meant for a passing cursor latches on and the card stays
   floating after the finger is gone. The press states above are the real
   feedback on these devices; the hover lift only competes with them. Colour
   and border hovers are left alone — those read as a lingering highlight on
   the row you just touched, which is harmless and even useful. */
@media (hover: none) {
  .surah-card:hover,
  .juz-card:hover,
  .bookmark-card:hover,
  .reader-foot__link:hover,
  .continue-card__cta:hover,
  .theme-swatch:hover,
  .play-btn:hover {
    transform: none;
  }
  .range:hover::-webkit-slider-thumb {
    transform: none;
  }
  .range:active::-webkit-slider-thumb {
    transform: scale(1.28);
  }
}

/* ---------------------------------------------------------------- *
 * Downloaded recitation — storage rows in the settings drawer
 * ---------------------------------------------------------------- */
.store-list:not(:empty) {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-block: var(--space-3);
}

/* The name takes the slack so a long reciter name truncates rather than
   pushing the size and the delete control off the row. */
.store-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
}

.store-row__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: var(--weight-medium);
}

.store-row__meta {
  flex-shrink: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.store-row__del {
  flex-shrink: 0;
  color: var(--text-faint);
}
.store-row__del:hover {
  color: var(--danger, var(--accent));
}

/* Attribution for the time zone boundaries. A licence condition rather than a
   design element, so it is sized to be findable and not to compete. */
.times__credit {
  margin-top: calc(var(--space-3) * -1);
  text-align: center;
  font-size: var(--text-2xs);
  color: var(--text-faint);
}
.times__credit a {
  color: inherit;
  text-decoration: underline;
}
