/* =====================================================================
   Amaly — Muslim Life & Social Platform
   style.css   [FSD Tampilan-b, NFR-USE-001, NFR-USE-005]

   Palette derived from the Amaly logo:
     deep    #0f5c46   primary brand green
     mid     #1c7a58
     leaf    #2fae6d   accent
     teal    #1f8f8a   secondary accent (leaf gradient)
     gold    #f5c451   crescent
   ===================================================================== */

/*
 * hidden means hidden.
 *
 * The attribute works through `[hidden] { display: none }` in the
 * browser's own stylesheet, which any author `display` rule outranks. So
 * every element in this application that shipped hidden and was also
 * given a display — .a-tenmin, .a-hint, .a-btn, .a-flash — was visible
 * the whole time, whatever its markup said and whatever its script did.
 *
 * The ten-minute countdown was how this surfaced: ten full blocks under
 * a prayer two hours away, meaning the opposite of what blocks mean. The
 * script had been setting box.hidden correctly all along and none of it
 * reached the screen.
 *
 * !important is right here and almost nowhere else. This is not winning
 * an argument about appearance; it is making one attribute mean one
 * thing everywhere, so that no rule added later can quietly reveal
 * something a script is holding back.
 */
[hidden] { display: none !important; }

:root {
  --deep:      #0f5c46;
  --deep-800:  #0b4635;
  --mid:       #1c7a58;
  --leaf:      #2fae6d;
  --teal:      #1f8f8a;
  --gold:      #f5c451;

  --ink:       #16261f;
  --ink-2:     #3d5149;
  --muted:     #6b7c76;
  --line:      #dbe6e1;
  --line-2:    #eaf1ee;
  /*
   * --accent-600 and --accent-700 were used in 36 places and defined in
   * none. A CSS variable that resolves to nothing is not a missing colour:
   * the whole declaration becomes invalid, and the property falls back to
   * its initial value. For `stroke` that initial value is `none`, which is
   * why the dhikr ring's progress arc was drawn, positioned and animated
   * correctly and could not be seen at all.
   *
   * The same silence had been affecting focus outlines and the progress
   * ring on the dashboard since those were written.
   */
  --accent-600: #0f5c46;
  --accent-700: #0b4635;
  --bg:        #f4f7f6;
  --panel:     #ffffff;
  --tint:      #eef5f2;

  --ok:        #197a4d;
  --ok-bg:     #e6f5ec;
  --warn:      #9a6a06;
  --warn-bg:   #fdf3dd;
  --bad:       #a32b2b;
  --bad-bg:    #fbeaea;
  --info:      #1b5e8a;
  --info-bg:   #e7f1f8;

  --radius:    12px;
  --radius-sm: 8px;
  --shadow:    0 1px 2px rgba(16,48,38,.06), 0 6px 20px rgba(16,48,38,.06);
  --top-h:     58px;
  --side-w:    264px;
  --font:      -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono:      ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  /*
   * Type that grows with the screen.
   *
   * This was a flat 15px everywhere, which is right in the hand and
   * small on a desk: the same text a phone shows across 360px a monitor
   * was showing across 1500px, at the same size, so a desktop reader got
   * a longer line AND a smaller-feeling one. Reading gets harder in both
   * directions at once.
   *
   * clamp() with a vw term rather than breakpoints, so there is no width
   * at which the page jumps a step. 15px on a phone, about 16.5 on a
   * laptop, 18 on a large monitor, and never beyond — past that, longer
   * lines are the problem and bigger letters make them worse.
   *
   * Most text in this application inherits from here. What does not —
   * hints, badges, small labels — is deliberately fixed and stays where
   * it is; those are meant to sit below the reading size, not to grow
   * with it.
   */
  font-size: clamp(15px, 14.2px + 0.22vw, 18px);
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
}

a { color: var(--deep); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Accessibility ---------------------------------------------------- */
.a-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.a-skip {
  position: absolute; left: -999px; top: 0; z-index: 100;
  background: var(--deep); color: #fff; padding: 10px 16px;
}
.a-skip:focus { left: 8px; top: 8px; }

:focus-visible { outline: 3px solid var(--leaf); outline-offset: 2px; }

/* Top bar  [FSD FR-UI-004] ----------------------------------------- */
.a-top {
  position: fixed; inset: 0 0 auto 0; height: var(--top-h); z-index: 40;
  display: flex; align-items: center; gap: 12px; padding: 0 14px;
  background: linear-gradient(100deg, var(--deep-800) 0%, var(--deep) 45%, var(--mid) 100%);
  color: #fff;
  box-shadow: 0 1px 0 rgba(0,0,0,.12);
}
.a-top__brand { display: flex; align-items: center; gap: 9px; color: #fff; }
.a-top__brand:hover { text-decoration: none; }
.a-top__mark { display: block; width: 32px; height: 32px; object-fit: contain; }
.a-top__name { font-weight: 700; font-size: 18px; letter-spacing: .2px; }
.a-top__site { flex: 1 1 auto; min-width: 0; }
.a-top__sitename {
  display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; opacity: .9; font-size: 14px;
}
.a-top__right { display: flex; align-items: center; gap: 10px; }
.a-top__user {
  font-size: 14px; opacity: .95; max-width: 160px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.a-top__frozen { margin-right: 4px; }
.a-top__icon { position: relative; color: #fff; font-size: 18px; line-height: 1; padding: 6px; }
.a-dot {
  position: absolute; top: -2px; right: -4px; min-width: 17px; height: 17px;
  border-radius: 9px; background: var(--gold); color: #4a3606;
  font-size: 11px; font-weight: 700; line-height: 17px; text-align: center; padding: 0 4px;
}
.a-select--top {
  background: rgba(255,255,255,.12); color: #fff; border: 1px solid rgba(255,255,255,.28);
  padding: 5px 8px; border-radius: var(--radius-sm); font-size: 13px;
}
.a-select--top option { color: var(--ink); }
.a-inline { display: inline-block; margin: 0; }

.a-top__burger {
  display: none; flex-direction: column; justify-content: center; gap: 4px;
  width: 38px; height: 38px; background: transparent; border: 0; cursor: pointer; padding: 0 8px;
}
.a-top__burger span { display: block; height: 2px; background: #fff; border-radius: 2px; }

/* Shell + sidebar  [FSD FR-UI-002/003] ----------------------------- */
.a-shell { display: flex; padding-top: var(--top-h); min-height: 100vh; }

.a-side {
  position: fixed; top: var(--top-h); bottom: 0; left: 0; width: var(--side-w);
  display: flex; flex-direction: column;
  background: var(--panel); border-right: 1px solid var(--line); z-index: 30;
}
.a-side__dash {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 12px 6px; padding: 11px 14px;
  border-radius: var(--radius-sm); font-weight: 650; color: var(--deep);
  background: var(--tint); border: 1px solid var(--line-2);
}
.a-side__dash:hover { background: #e4efe9; text-decoration: none; }
.a-side__dash.is-active { background: var(--deep); color: #fff; border-color: var(--deep); }
.a-side__dashicon { font-size: 15px; }

.a-side__scroll { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding: 4px 8px 12px; }

.a-group { margin-bottom: 2px; }
.a-group__head {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  background: transparent; border: 0; cursor: pointer;
  padding: 9px 10px; border-radius: var(--radius-sm);
  font: inherit; font-size: 12px; font-weight: 700; letter-spacing: .6px;
  text-transform: uppercase; color: var(--muted); text-align: left;
}
.a-group__head:hover { background: var(--line-2); color: var(--ink-2); }
.a-group__chev { transition: transform .16s ease; font-size: 11px; }
.a-group.is-open .a-group__chev { transform: rotate(90deg); }
.a-group__items { list-style: none; margin: 0; padding: 0; display: none; }
.a-group.is-open .a-group__items { display: block; }

.a-item {
  display: block; padding: 8px 12px 8px 22px; margin: 1px 0;
  border-radius: var(--radius-sm); color: var(--ink-2); font-size: 14px;
  border-left: 3px solid transparent;
}
.a-item:hover { background: var(--line-2); text-decoration: none; color: var(--ink); }
.a-item.is-active {
  background: var(--tint); color: var(--deep); font-weight: 650;
  border-left-color: var(--leaf);
}

.a-side__credit { border-top: 1px solid var(--line); padding: 10px 14px; font-size: 12px; color: var(--muted); }
.a-side__credit summary { cursor: pointer; font-weight: 650; color: var(--ink-2); }
.a-credit { list-style: none; margin: 8px 0 0; padding: 0; }
.a-credit li { display: flex; flex-direction: column; margin-bottom: 6px; }
.a-credit li span { color: var(--muted); }
.a-credit__launch, .a-credit__ver { margin: 6px 0 0; }

/* Main ------------------------------------------------------------- */
.a-main { flex: 1 1 auto; margin-left: var(--side-w); padding: 20px 22px 56px; min-width: 0; }

.a-page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin: 0 0 16px;
}
/* Headings scale with the body text they sit above, or the hierarchy
   flattens as the page grows: 22px over 18px body is nearly no
   difference, and a heading that does not look like one stops doing its
   job of letting somebody skim. */
.a-page-head h1 { margin: 0; font-size: clamp(22px, 17.4px + 0.5vw, 30px);
  letter-spacing: -.2px; color: var(--deep-800); }
.a-page-head p { margin: 4px 0 0; color: var(--muted); font-size: 14px; max-width: 68ch; }

.a-card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  /* Padding follows too. A card whose text has grown but whose margins
     have not looks cramped, and on a wide screen there is room to spare. */
  padding: clamp(14px, 12.4px + 0.42vw, 26px); margin-bottom: 16px;
}
.a-card--narrow { max-width: 440px; }
.a-card__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.a-card__head h2 { margin: 0; font-size: clamp(16px, 15px + 0.28vw, 21px); color: var(--deep-800); }
.a-card__note { margin: 0 0 12px; color: var(--muted); font-size: 13px; }

.a-grid { display: grid; gap: 14px; }
.a-grid--stats { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.a-grid--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

.a-stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; }
.a-stat__label { font-size: 12px; text-transform: uppercase; letter-spacing: .6px; color: var(--muted); }
.a-stat__value { font-size: 27px; font-weight: 700; color: var(--deep); line-height: 1.2; margin-top: 4px; }
.a-stat--alert .a-stat__value { color: var(--bad); }

/* Forms ------------------------------------------------------------ */
.a-field { margin-bottom: 14px; }
.a-field > label { display: block; font-size: 13px; font-weight: 650; color: var(--ink-2); margin-bottom: 5px; }
.a-hint { display: block; font-size: 12px; color: var(--muted); margin-top: 4px; }

.a-input, .a-select, .a-textarea {
  width: 100%; padding: 10px 12px; font: inherit; font-size: 14px;
  color: var(--ink); background: #fff;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.a-input:focus, .a-select:focus, .a-textarea:focus { border-color: var(--leaf); }
.a-textarea { min-height: 130px; resize: vertical; }
.a-input[readonly], .a-input:disabled { background: var(--line-2); color: var(--muted); }
.a-row { display: flex; gap: 12px; flex-wrap: wrap; }
.a-row > * { flex: 1 1 200px; }

.a-check { display: flex; align-items: flex-start; gap: 8px; font-size: 14px; margin-bottom: 8px; }
.a-check input { width: 18px; height: 18px; margin-top: 2px; flex: 0 0 auto; }

.a-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 16px; }

.a-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 44px; padding: 10px 18px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: #fff; color: var(--ink);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.a-btn:hover { background: var(--line-2); text-decoration: none; }
.a-btn--primary { background: var(--deep); border-color: var(--deep); color: #fff; }
.a-btn--primary:hover { background: var(--deep-800); }
.a-btn--accent { background: var(--leaf); border-color: var(--leaf); color: #06301f; }
.a-btn--danger { background: var(--bad); border-color: var(--bad); color: #fff; }
.a-btn--danger:hover { background: #8b2222; }
.a-btn--ghost { background: transparent; }
.a-btn--sm { min-height: 34px; padding: 6px 12px; font-size: 13px; }
.a-btn--exit { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.3); color: #fff; min-height: 34px; padding: 6px 14px; }
.a-btn--exit:hover { background: rgba(255,255,255,.24); }
.a-btn--block { width: 100%; }
.a-btn:disabled { opacity: .5; cursor: not-allowed; }

/* Tables ----------------------------------------------------------- */
.a-tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.a-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.a-table th, .a-table td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--line-2); vertical-align: top; }
.a-table thead th {
  background: var(--tint); color: var(--deep-800); font-size: 12px;
  text-transform: uppercase; letter-spacing: .5px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 1;
}
.a-table tbody tr:hover { background: #fafcfb; }
.a-table--matrix th, .a-table--matrix td { padding: 7px 9px; }
.a-table--matrix td.a-cell-check { text-align: center; }
.a-table--matrix td.a-cell-check input { width: 18px; height: 18px; }
.a-num { font-variant-numeric: tabular-nums; }
.a-mono { font-family: var(--mono); font-size: 12px; color: var(--ink-2); word-break: break-all; }

.a-empty { padding: 28px 16px; text-align: center; color: var(--muted); }

/* Badges, flashes -------------------------------------------------- */
.a-badge {
  display: inline-block; padding: 2px 9px; border-radius: 20px;
  font-size: 12px; font-weight: 650; line-height: 1.7;
}
.a-badge--ok    { background: var(--ok-bg);   color: var(--ok); }
.a-badge--warn  { background: var(--warn-bg); color: var(--warn); }
.a-badge--bad   { background: var(--bad-bg);  color: var(--bad); }
.a-badge--info  { background: var(--info-bg); color: var(--info); }
.a-badge--muted { background: var(--line-2);  color: var(--muted); }

.a-flash {
  padding: 11px 14px; border-radius: var(--radius-sm); margin-bottom: 14px;
  font-size: 14px; border: 1px solid transparent;
}
.a-flash--ok   { background: var(--ok-bg);   color: var(--ok);   border-color: #c6e6d3; }
.a-flash--warn { background: var(--warn-bg); color: var(--warn); border-color: #f0dfae; }
.a-flash--bad  { background: var(--bad-bg);  color: var(--bad);  border-color: #f0c9c9; }
.a-flash--info { background: var(--info-bg); color: var(--info); border-color: #c5dcec; }

.a-note {
  border-left: 4px solid var(--leaf); background: var(--tint);
  padding: 12px 14px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 13.5px; color: var(--ink-2); margin: 14px 0;
}
.a-note--danger { border-left-color: var(--bad); background: var(--bad-bg); color: #6e2020; }
.a-note strong { color: var(--deep-800); }
.a-note--danger strong { color: #6e2020; }

/* Filters / pagination --------------------------------------------- */
.a-filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; margin-bottom: 14px; }
.a-filters .a-field { margin-bottom: 0; min-width: 150px; }

.a-pager { display: flex; gap: 6px; align-items: center; justify-content: space-between; margin-top: 14px; flex-wrap: wrap; }
.a-pager__info { color: var(--muted); font-size: 13px; }
.a-pager__links { display: flex; gap: 6px; }

/* Auth screens ----------------------------------------------------- */
.a-centered { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 24px 16px; }
.a-auth { width: 100%; max-width: 430px; }
.a-auth__brand { text-align: center; margin-bottom: 18px; }
.a-logo--auth { width: 190px; height: auto; display: inline-block; }
.a-auth__foot { text-align: center; color: var(--muted); font-size: 12.5px; margin-top: 16px; }
.a-auth h1 { margin: 0 0 4px; font-size: 20px; color: var(--deep-800); }
.a-auth__sub { margin: 0 0 18px; color: var(--muted); font-size: 14px; }
.a-auth__links { margin-top: 16px; display: flex; justify-content: space-between; font-size: 13.5px; flex-wrap: wrap; gap: 8px; }

.a-or { display: flex; align-items: center; gap: 12px; margin: 18px 0; color: var(--muted); font-size: 12px; }
.a-or::before, .a-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* Google Identity Services renders a fixed-width element, so the wrapper
   centres it rather than the button centring itself. */
.a-gsi { display: flex; justify-content: center; margin: 4px 0 10px; }
.a-gsi > div { margin: 0 auto; }
.a-hint--centred { text-align: center; }

.a-error-code { font-size: 42px; margin: 8px 0 0; color: var(--deep); }
.a-error-msg { color: var(--ink-2); }

/* ==================================================================
   The feed
   ------------------------------------------------------------------
   Amaly has no follower count, no like tally and no share button, so
   the visual rhythm a social card usually borrows from engagement
   numbers is simply not available. What locates a post here instead is
   PROVENANCE: who wrote it and which circle it belongs to. So that is
   what the card is built around — an avatar, a name, and a coloured
   spine keyed to the circle type, readable at a glance from across the
   room. Everything else stays quiet.
   ================================================================== */

.a-post {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 16px 18px 12px;
  margin: 0 0 14px;
  position: relative;
  overflow: hidden;
  transition: box-shadow .18s ease, border-color .18s ease;
}
.a-post:hover { box-shadow: 0 6px 22px rgba(11,70,53,.07); border-color: var(--line-2); }

/* The spine: the circle a post came from, as colour. */
.a-post::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--seal, var(--line));
}
.a-post--family  { --seal: #0f5c46; }
.a-post--friend  { --seal: #1f8f8a; }
.a-post--halaqah { --seal: #b98900; }
.a-post--mosque  { --seal: #4a6fa5; }
.a-post--office  { --seal: #7a8a85; }

.a-post__head { display: flex; align-items: center; gap: 11px; margin-bottom: 10px; }
.a-post__who  { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.a-post__name {
  font-weight: 650; font-size: 15px; color: var(--deep-800);
  letter-spacing: -.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Inline rather than flex: as a flex row this stretched the full width
   of the card and threw the circle's colour dot out to the right edge
   whenever the line wrapped. */
.a-post__meta { font-size: 12.5px; color: var(--muted); display: block; }
.a-post__meta > * { display: inline; vertical-align: baseline; }
/* Named for its context, not its shape: .a-dot was already taken by the
   notification badge in the top bar, which is absolutely positioned — so a
   separator borrowing the name was flung to the corner of every card. */
.a-post__sep { margin: 0 5px; opacity: .45; }

/* Avatar: initials on a hue derived from the name, so a person is the
   same colour every time. Kept inside the brand's green-teal range. */
.a-av {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 650; letter-spacing: .02em;
  color: #17453a; background: #dcece5; border: 1px solid #c6ded5;
  user-select: none;
}
/* Six tints rather than a continuous hue: a class can be applied under
   style-src 'self', and six is enough to tell two people apart. */
.a-av--0 { color:#17453a; background:#dcece5; border-color:#c6ded5; }
.a-av--1 { color:#14514a; background:#d8ebe8; border-color:#bfdcd8; }
.a-av--2 { color:#1c4f2f; background:#dcecdd; border-color:#c4ddc6; }
.a-av--3 { color:#40461a; background:#e8ebd6; border-color:#d5dabc; }
.a-av--4 { color:#4a3a12; background:#efe7d3; border-color:#ded2b6; }
.a-av--5 { color:#1d3f52; background:#dbe8ef; border-color:#c2d7e2; }

.a-seal { font-weight: 550; color: var(--deep-700, #0d5340); white-space: nowrap; }
.a-seal::before {
  content: ""; display: inline-block; width: 6px; height: 6px;
  border-radius: 50%; margin-right: 5px; vertical-align: 1px;
  background: var(--seal, var(--line));
}

.a-post__kind {
  display: inline-block; margin: 0 0 8px; padding: 2px 9px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--deep-700, #0d5340); background: var(--tint); border-radius: 999px;
}
.a-post__body {
  font-size: 15.5px; line-height: 1.62; color: #1d2b26;
  overflow-wrap: anywhere; margin-bottom: 2px;
}

/* Action row: one real action, and it is not a like. */
.a-post__bar {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line-2);
}
.a-act {
  appearance: none; background: none; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 11px; border-radius: 10px;
  font: inherit; font-size: 13.5px; font-weight: 550; color: var(--muted);
  transition: background .15s ease, color .15s ease;
}
.a-act:hover  { background: var(--tint); color: var(--deep-800); }
.a-act:focus-visible { outline: 2px solid var(--accent-600); outline-offset: 2px; }
.a-act__mark {
  width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid currentColor; position: relative; flex: 0 0 auto;
}
.a-act.is-on { color: var(--accent-700, #14776f); }
.a-act.is-on .a-act__mark { background: currentColor; border-color: currentColor; }
.a-act.is-on .a-act__mark::after {
  content: ""; position: absolute; inset: 3px 4px 4px 3px;
  border-left: 1.5px solid #fff; border-bottom: 1.5px solid #fff;
  transform: rotate(-45deg);
}

/* Composer */
.a-compose__top { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; }
.a-compose__prompt { color: var(--muted); font-size: 15px; }
.a-compose .a-textarea { min-height: 84px; }

/* Comments */
.a-comments__more { margin: 0 0 8px; font-size: 13px; color: var(--muted); font-weight: 550; }
.a-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; margin-right: 6px;
  border-radius: 999px; background: var(--deep-800); color: #fff;
  font-size: 11.5px; font-weight: 650;
}

@media (max-width: 640px) {
  /* Media goes edge to edge on a phone; the frame around a photo is
     wasted space on a 5-inch screen. */
  .a-post { border-radius: 0; border-left: 0; border-right: 0; margin-left: -14px; margin-right: -14px; padding: 14px 14px 10px; }
  .a-post::before { width: 4px; }
  .a-gal { margin-left: -14px; margin-right: -14px; }
  .a-gal__item:first-child { padding-left: 14px; }
  .a-gal__item:last-child  { padding-right: 14px; }
  .a-post__body { font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  .a-post, .a-act { transition: none; }
}

/* Composer, closed by default ------------------------------------- */
.a-compose > summary { list-style: none; cursor: pointer; }
.a-compose > summary::-webkit-details-marker { display: none; }
.a-compose__top {
  display: flex; align-items: center; gap: 11px;
  padding: 4px 2px; border-radius: 999px;
}
.a-compose__prompt { color: var(--muted); font-size: 15px; flex: 1 1 auto; }
.a-compose__plus {
  width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--tint); color: var(--deep-800); font-size: 19px; line-height: 1;
  transition: transform .18s ease, background .18s ease;
}
.a-compose > summary:hover .a-compose__plus { background: var(--line-2); }
.a-compose[open] > summary { margin-bottom: 12px; border-bottom: 1px solid var(--line-2); padding-bottom: 12px; }
.a-compose[open] .a-compose__plus { transform: rotate(45deg); }

/* Background posts ------------------------------------------------- */
/* A fixed palette, each with its own foreground: contrast is decided
   once here rather than by each person at the moment they post. */
.a-bgpost {
  margin: 10px 0 2px; padding: 34px 26px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  min-height: 190px; text-align: center; text-wrap: balance;
}
.a-bgpost .a-fmt { max-width: 32ch; }
.a-bgpost .a-fmt p { margin: 0 0 .35em; }
.a-bgpost .a-fmt > :last-child { margin-bottom: 0; }
.a-bgpost--xl .a-fmt { font-size: 27px; line-height: 1.36; font-weight: 600; letter-spacing: -.015em; }
.a-bgpost--lg .a-fmt { font-size: 21px; line-height: 1.45; font-weight: 550; }
.a-bgpost--md .a-fmt { font-size: 17px; line-height: 1.55; }
.a-bgpost blockquote { border-left-color: currentColor; opacity: .92; }

.a-bgpick { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.a-bgpick__opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.a-bgpick__sw {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 10px; cursor: pointer;
  font-size: 15px; font-weight: 650; border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08);
}
.a-bgpick__sw--none {
  background: #fff; color: var(--muted);
  background-image: linear-gradient(45deg, transparent 45%, var(--line) 45%, var(--line) 55%, transparent 55%);
}
.a-bgpick__opt input:checked + .a-bgpick__sw { border-color: var(--deep-800); }
.a-bgpick__opt input:focus-visible + .a-bgpick__sw { outline: 2px solid var(--accent-600); outline-offset: 2px; }


/* Palette classes. The set is fixed, so it belongs in the stylesheet:
   the Content-Security-Policy is style-src 'self', which blocks inline
   style attributes — correctly, since that is also how injected CSS
   would arrive. */
.a-bg--sage { background: linear-gradient(150deg,#0f5c46 0%,#14776f 100%); color: #f4fbf8; }
.a-bg--sage blockquote { border-left-color: rgba(255,255,255,.34); }
.a-bg--dawn { background: linear-gradient(150deg,#1f8f8a 0%,#7cc4a8 100%); color: #06302a; }
.a-bg--dawn blockquote { border-left-color: rgba(6,48,42,.28); }
.a-bg--sand { background: linear-gradient(150deg,#f3e6c8 0%,#e3cfa1 100%); color: #4a3a12; }
.a-bg--sand blockquote { border-left-color: rgba(74,58,18,.26); }
.a-bg--night { background: linear-gradient(150deg,#0b2b34 0%,#123b46 100%); color: #e8f4f2; }
.a-bg--night blockquote { border-left-color: rgba(232,244,242,.3); }
.a-bg--gold { background: linear-gradient(150deg,#8a6300 0%,#b98900 100%); color: #fff8e6; }
.a-bg--gold blockquote { border-left-color: rgba(255,248,230,.32); }
.a-bg--paper { background: linear-gradient(150deg,#f7f9f8 0%,#e6efeb 100%); color: #123b31; }
.a-bg--paper blockquote { border-left-color: rgba(18,59,49,.22); }

/* Small utilities, because style-src 'self' drops inline attributes. */
.a-field--sm { max-width: 210px; }
.a-actions--tight { margin: 4px 0 0; }
.a-mt8 { margin-top: 8px; }

/* Type presets ----------------------------------------------------- */
/* Font and size as designed pairings. The member picks a voice; the
   pairing decides the millimetres. */
.a-type--plain   { font-family: inherit; }
.a-type--display {
  font-size: 1.32em; line-height: 1.3; font-weight: 640; letter-spacing: -.018em;
}
.a-type--serif {
  font-family: Georgia, "Iowan Old Style", "Palatino Linotype", serif;
  font-size: 1.07em; line-height: 1.62;
}
.a-type--note { font-size: .95em; line-height: 1.78; }
.a-bgpost.a-type--display .a-fmt { font-weight: 660; }

/* Composer workspace ---------------------------------------------- */
.a-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  padding: 6px; margin-bottom: 8px;
  background: var(--tint); border-radius: 10px;
}
.a-tool {
  appearance: none; border: 0; background: none; cursor: pointer;
  min-width: 32px; height: 32px; padding: 0 8px; border-radius: 7px;
  font: inherit; font-size: 14px; color: var(--deep-800);
  display: inline-flex; align-items: center; justify-content: center;
}
.a-tool:hover { background: #fff; }
.a-tool:focus-visible { outline: 2px solid var(--accent-600); outline-offset: 1px; }
.a-tool--wide { font-size: 12.5px; font-weight: 600; padding: 0 12px; }
.a-toolbar__sep { width: 1px; height: 20px; background: var(--line); margin: 0 3px; }

.a-workspace { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.a-workspace__write, .a-workspace__preview { min-width: 0; }
.a-preview {
  border: 1px dashed var(--line); border-radius: 12px; padding: 10px;
  background: repeating-linear-gradient(45deg, #fbfdfc 0 10px, #f6faf8 10px 20px);
}
/* The white default must not beat the palette class, which sits earlier
   in the file at the same specificity — that painted the preview white on
   white the moment a background was chosen. */
.a-preview__canvas { border-radius: 10px; min-height: 120px; padding: 12px 14px; }
.a-preview__canvas:not(.a-bgpost) { background: #fff; }
.a-preview__canvas.a-bgpost { padding: 26px 20px; min-height: 150px; }
.a-preview__empty { color: var(--muted); font-style: italic; }

.a-preset { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.a-preset__opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.a-preset__chip {
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 7px 13px; border-radius: 10px; cursor: pointer;
  border: 2px solid var(--line); background: #fff; min-width: 74px;
}
.a-preset__a { font-size: 17px; line-height: 1.1; color: var(--deep-800); }
.a-preset__l { font-size: 11px; color: var(--muted); letter-spacing: .01em; }
.a-preset__opt input:checked + .a-preset__chip { border-color: var(--deep-800); background: var(--tint); }
.a-preset__opt input:focus-visible + .a-preset__chip { outline: 2px solid var(--accent-600); outline-offset: 2px; }

@media (max-width: 780px) {
  /* The preview goes underneath rather than beside: two 180px columns are
     worse than one readable one. */
  .a-workspace { grid-template-columns: 1fr; }
}

/* Text over video -------------------------------------------------- */
/* A scrim behind the words, and never across the middle of the frame
   where the play control sits. */
.a-vover {
  position: absolute; left: 0; right: 0; padding: 16px 18px;
  pointer-events: none; text-align: center;
}
/* Clear of the native control bar. Sitting at bottom:0 put the caption
   directly on top of play, mute and fullscreen — legible, and unusable. */
.a-vover--bottom {
  bottom: 0; padding-bottom: 56px;
  background: linear-gradient(to top, rgba(6,20,16,.82) 46%, transparent);
}
.a-vover--top    { top: 0;    background: linear-gradient(to bottom, rgba(6,20,16,.78), transparent); }
.a-vover--middle { top: 14%;  background: none; }
.a-vover__t {
  color: #fff; font-size: 19px; font-weight: 600; line-height: 1.35;
  letter-spacing: -.01em; text-wrap: balance;
  text-shadow: 0 1px 3px rgba(0,0,0,.62), 0 0 18px rgba(0,0,0,.35);
}
.a-vover--middle .a-vover__t { font-size: 23px; }

@media (max-width: 560px) {
  .a-bgpost { min-height: 160px; padding: 26px 18px; }
  .a-bgpost--xl .a-fmt { font-size: 22px; }
  .a-bgpost--lg .a-fmt { font-size: 18px; }
  .a-vover__t { font-size: 16px; }
  .a-vover--bottom { padding-bottom: 48px; }
  .a-vover--middle .a-vover__t { font-size: 19px; }
}

/* Feed gallery ----------------------------------------------------- */
/* A swipeable strip with no JavaScript: scroll-snap does the work, which
   means it behaves like a native carousel on a phone and degrades to a
   plain scrollable row everywhere else. */
.a-gal {
  display: flex; gap: 8px; margin: 10px 0 0;
  overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch; scrollbar-width: thin;
  border-radius: var(--radius-sm);
}
.a-gal__item {
  flex: 0 0 100%; scroll-snap-align: center; margin: 0;
  position: relative; min-width: 0;
}
.a-gal--multi .a-gal__item { flex-basis: 86%; }
/*
 * The photograph keeps its own proportions.
 *
 * It used to be cropped into a fixed 4:5 frame — a steady rhythm down the
 * feed, but it cut the top and bottom off anything landscape and the
 * sides off anything tall. A photograph of the Haram taken wide came out
 * as a slice of the middle, and the member who took it had no way to know
 * what everyone else was seeing. Whatever a consistent column is worth,
 * it is not worth showing people something other than the picture they
 * posted.
 *
 * `height: auto` with the width and height attributes already on the tag
 * means the browser reserves the right shape before the file arrives, so
 * nothing jumps as the feed loads. The cap is on height, not shape: a very
 * tall photo is contained rather than allowed to fill the screen.
 */
.a-gal__media {
  display: block; width: 100%; height: auto;
  max-height: 78vh; object-fit: contain;
  background: var(--line-2);
  border: 1px solid var(--line); border-radius: 12px;
}
.a-gal__item video.a-gal__media { background: #0b1512; }
.a-gal__dur {
  position: absolute; right: 8px; bottom: 8px;
  background: rgba(0,0,0,.66); color: #fff;
  font-size: 12px; padding: 2px 7px; border-radius: 10px;
}
.a-gal__count { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
.a-comment--reply {
  margin-left: 22px; border-left: 2px solid var(--line);
  background: transparent;
}
.a-replylink { cursor: pointer; user-select: none; }

/* Dashboard: what is open now ------------------------------------- */
/* Deliberately a short list of single actions, not a score. */
.a-open__list { list-style: none; margin: 0; padding: 0; }
.a-open__item {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 10px 12px; margin-bottom: 6px;
  background: var(--tint); border-radius: var(--radius-sm);
  border-left: 3px solid var(--line);
}
.a-open__item--salah   { border-left-color: var(--deep-700); }
.a-open__item--fasting { border-left-color: var(--accent-600); }
.a-open__item--huquq   { border-left-color: var(--gold-600, #b98900); }
.a-open__link { flex: 1 1 200px; text-decoration: none; color: inherit; min-width: 0; }
.a-open__link:hover .a-open__label { text-decoration: underline; }
.a-open__label { display: block; font-weight: 600; color: var(--deep-800); }
.a-open__detail { display: block; font-size: 12px; color: var(--muted); }
.a-open__actions { display: flex; gap: 6px; flex-wrap: wrap; }

@media (max-width: 560px) {
  .a-gal--multi .a-gal__item { flex-basis: 92%; }
  /* flex-basis follows the main axis: once this becomes a column, the
     200px basis on the link is a 200px HEIGHT, which is where the tall
     empty box came from. Reset it rather than restating the shorthand. */
  .a-open__item { flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px; }
  .a-open__link { flex: 0 0 auto; }
  .a-open__actions { justify-content: stretch; }
  .a-open__actions .a-btn { flex: 1 1 auto; }
}

/* Formatted text -------------------------------------------------- */
/* Structural marks only, rendered in the site's own type. */
.a-fmt > :first-child { margin-top: 0; }
.a-fmt > :last-child  { margin-bottom: 0; }
.a-fmt p  { margin: 0 0 .6em; }
.a-fmt h3 { font-size: 17px; font-weight: 650; margin: .9em 0 .35em; color: var(--deep-800); letter-spacing: -.01em; }
.a-fmt h4 { font-size: 15px; font-weight: 650; margin: .8em 0 .3em; color: var(--deep-800); }
.a-fmt ul, .a-fmt ol { margin: 0 0 .6em; padding-left: 1.25em; }
.a-fmt li { margin: .18em 0; }
.a-fmt blockquote {
  margin: .6em 0; padding: .35em 0 .35em .9em;
  border-left: 3px solid var(--accent-600); color: #2b3b35; font-style: italic;
}
.a-fmt u { text-decoration-thickness: 1.5px; text-underline-offset: 2px; }
.a-fmt-center { text-align: center; }
.a-fmt--inline p { margin: 0; }
.a-fmthelp { margin-top: 6px; }
.a-fmthelp ul { margin: 6px 0; padding-left: 1.1em; }
.a-fmthelp code {
  background: var(--tint); padding: 1px 5px; border-radius: 4px;
  font-size: 12px; color: var(--deep-800);
}

/* Reading: the passage card --------------------------------------- */
.a-reading { padding: 22px 24px 18px; }
.a-reading .a-card__head h2 { font-size: 17px; letter-spacing: -.01em; }
.a-reading__seen {
  margin: 14px 0 0; font-size: 12.5px; color: var(--muted);
  display: inline-flex; align-items: center; gap: 7px;
}
.a-reading__seen::before {
  content: ""; width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--accent-600); flex: 0 0 auto;
  background: radial-gradient(circle at 50% 50%, var(--accent-600) 0 38%, transparent 39%);
}
@media (max-width: 560px) { .a-reading { padding: 18px 16px 14px; } }

/* Daily reading ---------------------------------------------------- */
/* Arabic gets room to breathe: large, generous line height, right to left. */
.a-arabic {
  font-size: 27px; line-height: 2.1; text-align: right; direction: rtl;
  margin: 14px 0; color: var(--deep-800);
  font-family: "Scheherazade New", "Amiri", "Traditional Arabic", serif;
}
.a-reading__tr { font-size: 16px; line-height: 1.75; margin-top: 10px; }
.a-progress {
  height: 6px; background: var(--line-2); border-radius: 3px;
  overflow: hidden; margin: 12px 0 18px;
}
.a-progress__bar { height: 100%; background: var(--accent-600); transition: width .3s ease; }
@media (max-width: 560px) { .a-arabic { font-size: 22px; line-height: 1.95; } }

/* Feed: photos and comments ---------------------------------------- */
/* Photos are constrained rather than cropped: a proportional image is
   the rule everywhere in Amaly (FSD STD-04 / FR-UI-010). */
.a-postphoto {
  display: block; max-width: 100%; height: auto; max-height: 520px;
  width: auto; border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--line-2);
}
.a-comments { margin: 12px 0 0; border-top: 1px solid var(--line-2); padding-top: 10px; }
/* A comment is a line of talk, not a card. Boxing each one gives the
   thread the weight of a form and buries the conversation. */
.a-comment {
  padding: 5px 0; margin: 0; background: none; font-size: 14.5px;
  line-height: 1.55; border-radius: 0;
}
.a-comment strong { font-weight: 650; color: var(--deep-800); margin-right: 7px; }
.a-comment .a-hint { font-size: 11.5px; }
.a-comment > div { margin-top: 1px; color: #24322d; overflow-wrap: anywhere; }
.a-comment .a-actions { gap: 12px !important; }

/* Quiet text actions under a comment. */
.a-clink {
  appearance: none; background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: 12px; font-weight: 550; color: var(--muted);
}
.a-clink:hover { color: var(--deep-800); text-decoration: underline; }
.a-clink:focus-visible { outline: 2px solid var(--accent-600); outline-offset: 2px; }
.a-replylink { font-size: 12px; font-weight: 550; }
.a-comment--reply {
  margin-left: 20px; padding-left: 12px;
  border-left: 2px solid var(--line-2); background: none;
}
.a-comments { border-top: 1px solid var(--line-2); padding-top: 10px; margin-top: 12px; }
.a-commentform { margin-top: 10px; }
.a-commentform .a-input { border-radius: 999px; padding-left: 14px; }
.a-comment strong { color: var(--deep-800); }
.a-comment .a-hint { display: inline; margin-left: 6px; }
.a-commentform { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.a-commentform .a-input { flex: 1 1 auto; }
.a-select--inline { max-width: 190px; display: inline-block; }

@media (max-width: 560px) {
  /* The comment box keeps its button beside it: a full-width send button
     on its own row reads as a form to fill in rather than a quick reply. */
  .a-commentform { flex-direction: row; align-items: center; }
  .a-commentform .a-btn { flex: 0 0 auto; }
  .a-select--inline { max-width: 100%; }
}

/* Media ------------------------------------------------------------ */
/* FSD STD-04 / FR-UI-010: images are always proportional. */
img { max-width: 100%; height: auto; }
.a-thumb { width: 84px; height: 84px; object-fit: contain; background: var(--line-2); border-radius: var(--radius-sm); }

.a-doc { line-height: 1.7; }
.a-doc h2 { color: var(--deep-800); font-size: 17px; margin: 22px 0 8px; }
.a-doc pre { background: var(--tint); padding: 12px; border-radius: var(--radius-sm); overflow-x: auto; font-family: var(--mono); font-size: 12.5px; }

/* Responsive  [FSD NFR-USE-001: usable at 360px] -------------------- */
@media (max-width: 900px) {
  .a-top__burger { display: flex; }
  .a-side {
    transform: translateX(-100%); transition: transform .2s ease;
    box-shadow: 0 0 0 100vmax rgba(0,0,0,0);
  }
  .a-side.is-open { transform: translateX(0); box-shadow: 0 0 0 100vmax rgba(11,40,30,.42); }
  .a-main { margin-left: 0; padding: 16px 14px 48px; }
  .a-top__user { display: none; }
  /* The fixed 19px override is gone: clamp() already lands on 19 at
     phone widths, and holding it flat all the way to 900px meant a
     tablet got phone-sized headings over tablet-sized body text. */
}

@media (max-width: 560px) {
  .a-top { gap: 8px; padding: 0 10px; }
  .a-top__name { display: none; }
  .a-card { padding: 14px; }
  .a-table thead { display: none; }
    /*
     * A stacked row, kept short.
     *
     * Every cell became its own line with a large uppercase label taking
     * 42% of the width, so a record of five fields cost about a third of a
     * phone screen and a list of them could not be scanned. The labels are
     * now small and narrow, the rows tight, and the detail cells wrap
     * beside each other where they fit.
     */
    .a-table tbody tr {
      display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px;
      border: 1px solid var(--line); border-radius: var(--radius-sm);
      margin-bottom: 8px; padding: 8px 10px; background: #fff;
    }
    .a-table tbody td {
      display: flex; align-items: baseline; gap: 6px;
      border: 0; padding: 2px 0; font-size: 13px; min-width: 0;
    }
    /* The first cell is the record's name: it takes the whole line and the
       rest follow underneath as one wrapped run of detail. */
    .a-table tbody td:first-child { flex: 1 0 100%; font-size: 14.5px; }
    .a-table tbody td::before {
      content: attr(data-label); font-size: 10.5px; font-weight: 600;
      text-transform: uppercase; letter-spacing: .3px; color: var(--muted);
      flex: 0 0 auto; white-space: nowrap;
    }
    /* The name needs no label, and an empty cell should not leave one. */
    .a-table tbody td:first-child::before,
    .a-table tbody td:empty::before { content: none; }
    .a-table tbody td:empty { display: none; }
    /* Buttons take their own line rather than squeezing in beside text. */
    .a-table tbody td:has(.a-actions),
    .a-table tbody td:has(.a-btn) { flex: 1 0 100%; padding-top: 4px; }
  .a-table--matrix tbody tr { display: table-row; }
  .a-table--matrix tbody td { display: table-cell; }
  .a-table--matrix tbody td::before { content: none; }
  .a-table--matrix thead { display: table-header-group; }
}

@media print {
  .a-top, .a-side, .a-actions, .a-filters { display: none !important; }
  .a-main { margin: 0; padding: 0; }
  .a-card { box-shadow: none; border-color: #ccc; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}


/* Learning ---------------------------------------------------------- */
.a-topics { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.a-topic {
  display: flex; flex-direction: column; gap: 6px;
  padding: 16px 18px; background: #fff; border: 1px solid var(--line);
  border-radius: 14px; text-decoration: none; color: inherit;
  transition: box-shadow .18s ease, border-color .18s ease;
}
.a-topic:hover { box-shadow: 0 6px 20px rgba(11,70,53,.08); border-color: var(--line-2); }
.a-topic__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.a-topic__title { font-weight: 650; color: var(--deep-800); letter-spacing: -.01em; }
.a-topic__pass {
  width: 22px; height: 22px; border-radius: 50%; flex: 0 0 auto;
  background: var(--accent-600); color: #fff; font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center;
}
.a-topic__sum { font-size: 13.5px; color: #2c3a35; line-height: 1.5; }
.a-topic__meta, .a-topic__score { font-size: 12px; color: var(--muted); }
.a-topic__score { font-weight: 600; color: var(--deep-800); }

.a-obj { margin: 6px 0; padding-left: 1.3em; }
.a-obj li { margin: .35em 0; line-height: 1.55; }
.a-obj--result { list-style: none; padding-left: 0; }
.a-obj--result li {
  display: flex; align-items: baseline; gap: 10px;
  padding: 9px 12px; border-radius: 10px; margin-bottom: 6px; background: var(--tint);
}
.a-obj--result li.is-gap { background: #fdf4e7; }
.a-obj__mark { flex: 0 0 auto; font-weight: 700; color: var(--accent-700, #14776f); }
.a-obj--result li.is-gap .a-obj__mark { color: #a5731a; }
.a-obj__text { flex: 1 1 auto; }
.a-obj__count { flex: 0 0 auto; font-variant-numeric: tabular-nums; color: var(--muted); font-size: 13px; }

.a-lesson.is-read { opacity: .92; }
.a-choices { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.a-choice {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; cursor: pointer;
}
.a-choice:hover { background: var(--tint); }
.a-choice input { margin-top: 3px; flex: 0 0 auto; }

.a-result { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.a-result__score {
  font-size: 46px; font-weight: 660; letter-spacing: -.03em; line-height: 1;
  color: var(--muted);
}
.a-result__score span { font-size: 22px; }
.a-result.is-pass .a-result__score { color: var(--accent-700, #14776f); }
.a-result__verdict { font-size: 16px; font-weight: 600; margin: 0 0 4px; color: var(--deep-800); }
.a-ans { padding: 9px 0; border-bottom: 1px solid var(--line-2); }
.a-ans.is-wrong strong { color: #8a5a12; }


/* Muhasabah, niyyah, character ------------------------------------- */
.a-carry { border-left: 3px solid var(--gold-600, #b98900); background: #fdfaf2; }
.a-carry__label { font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; color: #8a6a1e; font-weight: 650; }
.a-carry__text { margin: 4px 0 0; font-size: 16px; line-height: 1.5; color: #3a2f14; }
.a-dirs { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.a-dir input { position: absolute; opacity: 0; width: 0; height: 0; }
.a-dir span {
  display: inline-block; padding: 7px 14px; border-radius: 999px; cursor: pointer;
  border: 1.5px solid var(--line); font-size: 13.5px; color: var(--muted); background: #fff;
}
.a-dir input:checked + span { border-color: var(--deep-800); color: var(--deep-800); background: var(--tint); font-weight: 600; }
.a-dir input:focus-visible + span { outline: 2px solid var(--accent-600); outline-offset: 2px; }
.a-niyyah { padding: 11px 0; border-bottom: 1px solid var(--line-2); }
.a-niyyah:last-child { border-bottom: 0; }
.a-niyyah__act { font-weight: 640; color: var(--deep-800); }
.a-niyyah__int { color: #2c3a35; margin: 2px 0 4px; line-height: 1.5; }
.a-open__item--muhasabah { border-left-color: #8a6a1e; }


/* Qur'an programmes ------------------------------------------------- */
.a-seq { list-style: none; margin: 0; padding: 0; max-height: 420px; overflow-y: auto; }
.a-seq__item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-bottom: 1px solid var(--line-2);
}
.a-seq__item.is-read { opacity: .55; }
.a-seq__ref { flex: 1 1 auto; font-weight: 550; color: var(--deep-800); }
.a-seq__n { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 12.5px; }


/* Arabic typefaces --------------------------------------------------
   Self-hosted only: the CSP is default-src 'self', so a font from a
   third party is blocked — which also means no third party is told who
   is reading Qur'an and when. A missing file falls back through the
   stack to the system Arabic face rather than rendering boxes.
   See assets/fonts/README.txt for the filenames. */
@font-face {
  font-family: 'Amiri'; font-display: swap;
  src: url('../fonts/amiri.woff2') format('woff2');
}
@font-face {
  font-family: 'Scheherazade New'; font-display: swap;
  src: url('../fonts/scheherazade.woff2') format('woff2');
}
@font-face {
  font-family: 'Noto Naskh Arabic'; font-display: swap;
  src: url('../fonts/naskh.woff2') format('woff2');
}
@font-face {
  font-family: 'Lateef'; font-display: swap;
  src: url('../fonts/lateef.woff2') format('woff2');
}
@font-face {
  font-family: 'Reem Kufi'; font-display: swap;
  src: url('../fonts/kufi.woff2') format('woff2');
}
@font-face {
  font-family: 'Cairo'; font-display: swap;
  src: url('../fonts/cairo.woff2') format('woff2');
}
@font-face {
  font-family: 'Tajawal'; font-display: swap;
  src: url('../fonts/tajawal.woff2') format('woff2');
}
@font-face {
  font-family: 'Markazi Text'; font-display: swap;
  src: url('../fonts/markazi.woff2') format('woff2');
}
.a-ar--amiri { font-family: 'Amiri', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--scheherazade { font-family: 'Scheherazade New', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--naskh { font-family: 'Noto Naskh Arabic', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--lateef { font-family: 'Lateef', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--kufi { font-family: 'Reem Kufi', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--cairo { font-family: 'Cairo', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--tajawal { font-family: 'Tajawal', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--markazi { font-family: 'Markazi Text', 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }
.a-ar--system { font-family: 'Noto Naskh Arabic', 'Traditional Arabic', 'Geeza Pro', serif; }

/* Sizes as classes, because inline style attributes are dropped. */
.a-ar--18 { font-size: 18px; line-height: 1.86; }
.a-ar--22 { font-size: 22px; line-height: 1.81; }
.a-ar--27 { font-size: 27px; line-height: 1.75; }
.a-ar--32 { font-size: 32px; line-height: 1.69; }
.a-ar--38 { font-size: 38px; line-height: 1.62; }
.a-ar--44 { font-size: 44px; line-height: 1.55; }

.a-ayah { padding: 6px 0 12px; border-bottom: 1px solid var(--line-2); }
.a-ayah:last-child { border-bottom: 0; }
.a-ayah__no {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 26px; margin: 0 8px; padding: 0 6px;
  border: 1px solid var(--accent-600); border-radius: 50%;
  font-family: inherit; font-size: 13px; color: var(--accent-700, #14776f);
  vertical-align: middle;
}
.a-fontpick { margin: 10px 0 4px; }
.a-fontpick summary { cursor: pointer; }
@media (max-width: 560px) { .a-ar--44 { font-size: 34px; } .a-ar--38 { font-size: 30px; } }


/* Dashboard panels -------------------------------------------------- */
.a-up { list-style: none; margin: 0; padding: 0; }
.a-up__item {
  display: flex; align-items: baseline; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--line-2);
}
.a-up__item:last-child { border-bottom: 0; }
.a-up__when {
  flex: 0 0 84px; font-size: 12.5px; font-variant-numeric: tabular-nums;
  color: var(--muted);
}
/*
 * Today in dark red, everything after it as before.
 *
 * #9c2f22 is 7.4 against the panel — comfortably past the 4.5 floor for
 * body text, so this is a colour that carries meaning rather than one
 * that merely tints. It is not the only signal either: "Today" is
 * already spelled out in the time column, so a reader who cannot
 * separate the hues loses nothing.
 */
.a-up__item.is-today .a-up__when,
.a-up__item.is-today .a-up__title { color: #9c2f22; }
.a-up__item.is-today .a-up__when { font-weight: 650; }

.a-up__what { flex: 1 1 auto; min-width: 0; }
/*
 * Sized in em, not px.
 *
 * The titles were running at full body size, which since type became
 * fluid is up to 18px on a monitor — so on a wide screen they were as
 * large as the page heading and wrapped onto two lines each. .85em keeps
 * them proportional to whatever the body is doing rather than fixing
 * them at one number: about 13px on a phone, about 15px on a desk.
 */
.a-up__title { font-weight: 550; color: var(--deep-800); font-size: .85em; line-height: 1.35; }
.a-up__meta { display: block; font-size: 12px; color: var(--muted); }

/*
 * Happening now: a slow pulse, and a word.
 *
 * 1.8 seconds a cycle, fading between full and 45%. Deliberately far
 * below the three-flashes-a-second line that can trigger a seizure —
 * this is a breath, not a blink, and it never goes fully out because
 * text that disappears is text somebody is waiting to read.
 *
 * The NOW tag carries the same fact in words, so the meaning survives
 * reduced motion, a screen reader and a printout. Under
 * prefers-reduced-motion the animation stops and the tag remains, which
 * is the whole reason it exists.
 */
.a-up__item.is-now .a-up__title { animation: a-up-pulse 1.8s ease-in-out infinite; }
.a-up__nowtag { display: inline-block; margin-left: 4px; padding: 0 5px;
  border-radius: 999px; background: #9c2f22; color: #fff;
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; vertical-align: 1px; }
@keyframes a-up-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
  .a-up__item.is-now .a-up__title { animation: none; }
}

.a-mini { display: flex; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--line-2); }
.a-mini:last-child { border-bottom: 0; }
/*
 * The text column must fill the row.
 *
 * It carried `min-width: 0` — which lets a flex child shrink below its
 * content — but no `flex`, so it never grew either: the column was
 * sized by its longest line, and everything in it, photographs included,
 * was narrower than the card for no visible reason.
 */
.a-mini__body { flex: 1 1 auto; min-width: 0; }
.a-mini__who { font-weight: 600; font-size: 13.5px; color: var(--deep-800); }
.a-mini__text {
  font-size: 13.5px; color: #2c3a35; line-height: 1.45; margin-top: 1px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.a-panelpick { display: flex; flex-direction: column; gap: 6px; }
.a-panelpick label { display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 10px; }


/* Memorisation ------------------------------------------------------ */
.a-due { border-left: 3px solid var(--accent-600); }
.a-due__ref { font-size: 19px; font-weight: 650; color: var(--deep-800); margin: 4px 0 2px; }
.a-table tr.is-due td { background: #fdf7ec; }
.a-stat__of { font-size: 14px; color: var(--muted); font-weight: 500; }


/* Two translations side by side -------------------------------------- */
.a-reading__tr--second {
  border-left: 2px solid var(--line); padding-left: 12px; margin-top: 8px;
  color: #3a4a44;
}
.a-tr__who {
  display: block; margin-top: 2px; font-size: 11.5px; color: var(--muted);
  letter-spacing: .02em;
}

.a-refs { list-style: none; margin: 6px 0 0; padding: 0; }
.a-refs li { padding: 8px 0; border-bottom: 1px solid var(--line-2); }
.a-refs li:last-child { border-bottom: 0; }
.a-study { border-left: 3px solid var(--accent-600); }

.a-optrow { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.a-optrow .a-check { flex: 0 0 auto; margin: 0; }
.a-optrow .a-input { flex: 1 1 auto; }

/* Width utilities in 5% steps: style-src 'self' drops inline styles. */
.a-w0 { width: 0%; }
.a-w5 { width: 5%; }
.a-w10 { width: 10%; }
.a-w15 { width: 15%; }
.a-w20 { width: 20%; }
.a-w25 { width: 25%; }
.a-w30 { width: 30%; }
.a-w35 { width: 35%; }
.a-w40 { width: 40%; }
.a-w45 { width: 45%; }
.a-w50 { width: 50%; }
.a-w55 { width: 55%; }
.a-w60 { width: 60%; }
.a-w65 { width: 65%; }
.a-w70 { width: 70%; }
.a-w75 { width: 75%; }
.a-w80 { width: 80%; }
.a-w85 { width: 85%; }
.a-w90 { width: 90%; }
.a-w95 { width: 95%; }
.a-w100 { width: 100%; }

/* Prayer pattern ---------------------------------------------------- */
.a-pattern__row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.a-pattern__name { flex: 0 0 78px; font-size: 13.5px; font-weight: 550; color: var(--deep-800); }
.a-pattern__bar { flex: 1 1 auto; display: flex; height: 18px; border-radius: 4px; overflow: hidden; background: var(--line-2); }
.a-pattern__seg { display: block; height: 100%; }
.a-pattern__seg--jamaah     { background: #0f5c46; }
.a-pattern__seg--on_time    { background: #1f8f8a; }
.a-pattern__seg--late       { background: #b98900; }
.a-pattern__seg--missed     { background: #a8552e; }
.a-pattern__seg--unrecorded { background: #dbe6e1; }
.a-pattern__n { flex: 0 0 54px; text-align: right; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.a-legend { display: flex; flex-wrap: wrap; gap: 12px; list-style: none; padding: 0; margin: 10px 0 0; font-size: 12px; color: var(--muted); }
.a-legend li { display: flex; align-items: center; gap: 5px; }
.a-legend__sw { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }

/* Dhikr counter ----------------------------------------------------- */
.a-counter__n { font-size: 54px; font-weight: 660; letter-spacing: -.03em; color: var(--deep-800); margin: 6px 0; text-align: center; }
.a-counter__n span { font-size: 22px; color: var(--muted); font-weight: 500; }
.a-btn--big { font-size: 20px; padding: 14px 34px; }


/* Top bar: site, Hijri date, and who is signed in --------------------- */
.a-top__hijri {
  display: none; flex-direction: column; line-height: 1.2;
  padding: 0 14px; margin-left: auto; text-align: right; color: rgba(255,255,255,.9);
}
.a-top__hijri__d { font-size: 13px; font-weight: 600; }
.a-top__hijri__y { font-size: 11px; opacity: .72; }
.a-top__user { display: flex; flex-direction: column; line-height: 1.2; text-align: right; }
.a-top__user__name { font-size: 13.5px; font-weight: 600; }
.a-top__user__id { font-size: 11px; opacity: .7; }
.a-top__right { display: flex; align-items: center; gap: 12px; }
@media (min-width: 860px) { .a-top__hijri { display: flex; } }
@media (max-width: 560px) { .a-top__user__id { display: none; } }

.a-top__ver { font-size: 10.5px; opacity: .55; letter-spacing: .03em; }


/* Dhikr pace guide --------------------------------------------------- */
.a-pace { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 14px 0 4px; }
.a-pace__dot {
  width: 20px; height: 20px; border-radius: 50%; flex: 0 0 auto;
  background: var(--line); transition: background .12s ease, transform .12s ease;
}
.a-pace__dot.is-tick { background: var(--accent-600); transform: scale(1.45); }
.a-pace__slider { flex: 1 1 160px; display: flex; }
.a-pace__slider input { width: 100%; }
.a-pace__label { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.a-arabic-in { font-size: 20px; text-align: right; }
@media (prefers-reduced-motion: reduce) { .a-pace__dot { transition: none; } }

.a-table tr.is-just td { background: #e7f4ee; box-shadow: inset 3px 0 0 var(--accent-600); }


/* Calendar and taushiyah --------------------------------------------- */
.a-cal td { vertical-align: top; }
.a-obs { padding: 4px 0; }
.a-obs + .a-obs { border-top: 1px dashed var(--line-2); }
.a-tsy.is-unread { border-left: 3px solid var(--accent-600); }

.a-row--tight { align-items: flex-end; gap: 12px; }
.a-field--btn { display: flex; align-items: flex-end; }

.a-tsy__media { display: block; width: 100%; max-width: 640px; border-radius: 10px; margin: 10px 0; }
.a-badge--danger { background: #f6e2da; color: #8a3d1c; }


/* Prayer record: the buttons belong on the same line as the prayer name.
   The base table rule aligns cells to the top, which is right for the
   calendar and wrong here, where one cell holds a word and the next holds
   five buttons. */
.a-table tr.a-prayerrow td { vertical-align: middle; }
.a-actions--row { margin: 0; align-items: center; }


/* Agenda month grid --------------------------------------------------- */
.a-month { table-layout: fixed; }
.a-month th { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.a-month__cell { height: 108px; vertical-align: top; padding: 6px 7px; }
.a-month__cell.is-outside { background: #fafbfa; }
.a-month__cell.is-outside .a-month__num { opacity: .4; }
.a-month__cell.is-today { box-shadow: inset 0 0 0 2px var(--accent-600); }
.a-month__num { display: block; font-size: 12px; font-weight: 650; color: var(--muted); margin-bottom: 4px; }
.a-month__cell.is-today .a-month__num { color: var(--accent-700, #14776f); }
/*
 * Every millimetre in a month cell is a millimetre of title.
 *
 * The bracket down the left is gone, the chip sits about 2mm further
 * left, the gap between the dot and the time is closed, the time is no
 * longer bold and the whole thing is a point smaller. A month cell is
 * 108px tall and holds five of these; what an agenda is for is reading
 * the titles, and the decoration was eating them.
 *
 * The time stays tabular and stays first — it is the thing scanned down
 * a column — but it does not need weight to be found. It is already at
 * the start of the line and already the only digits there.
 */
.a-ev {
  display: block; font-size: 10.5px; line-height: 1.3; margin-bottom: 2px;
  padding: 2px 4px; border-radius: 3px; background: #e9f2ee; color: #1f3b33;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.a-ev--ext { background: #fdf3e3; }
.a-ev--cancelled { opacity: .55; text-decoration: line-through; }
.a-ev__t { font-weight: 500; margin-right: 2px; font-variant-numeric: tabular-nums; }
.a-monthname { font-size: 15px; }
@media (max-width: 700px) { .a-month__cell { height: 74px; } .a-ev { font-size: 10px; } }


/* Agenda: week, day and list runs ------------------------------------- */
.a-viewsw { display: flex; gap: 6px; }
.a-dayrun { padding: 10px 0; border-bottom: 1px solid var(--line-2); }
.a-dayrun:last-of-type { border-bottom: 0; }
.a-dayrun.is-today { box-shadow: inset 3px 0 0 var(--accent-600); padding-left: 10px; }
.a-dayrun__head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.a-evrow { display: flex; gap: 12px; padding: 7px 9px; margin-bottom: 5px;
  border-radius: 6px; background: #e9f2ee; border-left: 3px solid var(--accent-600); }
.a-evrow--ext { background: #fdf3e3; border-left-color: #b98900; }
.a-evrow--cancelled { opacity: .6; }
.a-evrow--cancelled .a-evrow__b strong { text-decoration: line-through; }
.a-evrow__t { flex: 0 0 56px; font-weight: 650; font-size: 13px; font-variant-numeric: tabular-nums; }
.a-evrow__b { min-width: 0; }
@media (max-width: 560px) { .a-viewsw { flex-wrap: wrap; } .a-evrow__t { flex-basis: 48px; } }


/* API screen ---------------------------------------------------------- */
.a-endpoint { padding: 10px 12px; background: #f3f6f4; border-radius: 8px; word-break: break-all; }
.a-pre { background: #f3f6f4; border-radius: 8px; padding: 12px 14px; overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.5; }
.a-pre--sm { font-size: 11.5px; max-height: 220px; }
.a-doclist { margin: 10px 0 0; padding-left: 18px; font-size: 13px; color: #3a4a44; }
.a-doclist li { margin-bottom: 5px; }
.a-why { display: block; margin-top: 3px; font-size: 12.5px; color: #8a3d1c; }
.a-callmeta { margin-top: 6px; }
.a-kv { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 6px 0; font-size: 12px; }
.a-kv dt { color: var(--muted); }
.a-kv dd { margin: 0; word-break: break-all; }


/* Dashboard tightening ------------------------------------------------ */
.a-page-head--tight { margin-bottom: 10px; }
.a-up__item--tight { padding: 5px 0; gap: 10px; align-items: baseline; }
.a-up__item--tight .a-up__title { font-weight: 550; }
/*
 * The photo runs the full width of the card.
 *
 * It sat inside the body column, which is indented past the avatar and
 * stops short of the card's padding — so a landscape photograph was
 * pinched from both sides for no reason anyone could see. Negative
 * margins pull it back out to the card's edges on a phone, where the
 * width is worth having; on a wider screen it stays put, because a
 * photograph stretched across a desktop card is not an improvement.
 */
.a-mini__media {
  display: block; width: 100%; max-width: 420px; margin: 8px 0 4px;
  border-radius: 8px; max-height: 260px; object-fit: cover;
}
@media (max-width: 560px) {
  .a-mini { gap: 8px; }
  .a-mini__media {
    max-width: none;
    /*
     * Left: the card's padding (14) + the avatar (40) + the row gap (8).
     * Right: the card's padding (14). Measured in the browser rather than
     * reasoned about — my first attempt cancelled the avatar but forgot
     * the padding, and left the photo 15px short on one side and 1px on
     * the other, which looks like carelessness rather than a decision.
     */
    margin-left: -62px; margin-right: -14px;
    width: calc(100% + 76px);
    border-radius: 0;
  }
}

/* Agenda: days already gone ------------------------------------------- */
/*
 * The shading was #f4f6f5, which is a contrast of 1.085 against the white
 * cell beside it — about an eighth of a step, and on most screens simply
 * not there. It said "this day has gone" to nobody.
 *
 * #e0eae5 is 1.253, roughly three times the separation, and still a
 * shade lighter than the grid line at #dbe6e1 — but only just, at 1.040,
 * so two past cells side by side would have shown almost no seam between
 * them. Their borders are darkened to #c3d5cc to keep the grid legible;
 * a darker fill needs a darker rule, or the shading eats the calendar.
 * It stays clearly apart from the
 * outside-month cells at #fafbfa, because "not this month" and "already
 * happened" are different statements and must not converge.
 *
 * The dimming goes the other way. On a paler ground, 55% on the date was
 * already faint; on a darker one it would be worse. A past day is over,
 * not unimportant — somebody looking back at what they did needs to read
 * it.
 */
.a-month__cell.is-past { background: #e0eae5; border-color: #c3d5cc; }
.a-month__cell.is-past .a-ev { opacity: .78; }
.a-month__cell.is-past .a-month__num { opacity: .72; }
/*
 * The status dot.
 *
 * Renamed from .a-dot, which was already the unread-message badge in the
 * header: absolutely positioned, 17 pixels wide, gold. The two had been
 * fighting since these dots were added, and the badge won — so the dot
 * was in the markup with the right colour and could not be seen, which is
 * why it kept being reported missing after I had checked the HTML and
 * called it done. Checking the DOM is not checking the screen.
 */
/*
 * A button, so it needs the browser's button styling stripped and a
 * target big enough to hit. The coloured circle is 9px; the button around
 * it is 20px, which is what a finger actually lands on. Padding rather
 * than a bigger circle keeps the calendar looking like a calendar.
 */
/*
 * A circle you can hit.
 *
 * `flex: 0 0 20px` set the basis and the padding was then added to it, so
 * the button came out 30px wide and 19 tall — a green pill rather than a
 * dot. The basis is the whole box now, and the colour is painted only on
 * the content box, so the target is 19px square while the mark stays 9px
 * round.
 */
.a-stdot {
  display: inline-block; flex: 0 0 auto; box-sizing: content-box;
  /* Half the size: a 5px mark, with 4px of padding around it so the tap
     target stays 13px. The target can be larger than the mark; the mark
     should not be larger than the calendar can carry. */
  width: 5px; height: 5px; padding: 4px; margin: -4px 2px -4px -2px;
  /*
   * The shorthand below sets background-clip back to border-box.
   *
   * .a-stdot--planned and friends say `background: #b98900`, and the
   * shorthand resets every background-* property it does not mention —
   * including the clip set here. So the mark painted the full 13px tap
   * target and sat beside a 5px dot meaning the same thing. Stated after
   * them, and as its own property, it survives.
   */
  border: 0; border-radius: 50%;
  vertical-align: middle; cursor: pointer; appearance: none;
}
.a-stdot:hover { outline: 1px solid var(--line); }
.a-stdot:focus-visible { outline: 2px solid var(--accent-600); outline-offset: 1px; }
.a-stdot--confirmed { background-color: #0f5c46; }
.a-stdot--planned   { background-color: #b98900; }
.a-stdot--cancelled { background-color: #a8552e; }
/* Done is a deeper, cooler green than confirmed, and the chip beside it
   is struck through as well — two signals, because these two greens are
   close and a reader who cannot separate them must still be able to
   tell a kept appointment from a finished one. */
.a-stdot--done      { background-color: #1f4fa0; }
/* background-color, not background: the shorthand would wipe the clip
   again and the mark would swell back to the size of its tap target. */
.a-stdot { background-clip: content-box; }
/* .a-ev--planned had `border-left-style: dashed` here. The chip no longer
   has a left border for that style to apply to, so the rule did nothing
   at all — removed rather than left as a fossil for somebody to puzzle
   over. Planned is now shown by a hollow dot instead. */


/* Suggestions, observance marks, waqf boxes, danger cards -------------- */
.a-suggest { margin: 8px 0 4px; }
.a-suggest__label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.a-chip {
  display: inline-block; margin: 0 6px 6px 0; padding: 6px 11px;
  border: 1px solid var(--line); border-radius: 999px; background: #f3f6f4;
  font-size: 12.5px; color: #24352f; cursor: pointer; font-family: inherit;
}
.a-chip:hover { background: #e9f2ee; border-color: var(--accent-600); }
.a-obsmark {
  display: block; font-size: 10.5px; line-height: 1.3; margin-bottom: 3px;
  padding: 2px 5px; border-radius: 3px; background: #efe7f5; color: #4a3560;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.a-dayrun__head .a-obsmark { display: inline-block; margin: 0 0 0 6px; }
.a-grid--three { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; margin: 10px 0; }
.a-wqbox { background: #f6f8f7; border-radius: 8px; padding: 10px 12px; }
.a-wqbox h3 { margin: 0 0 4px; font-size: 13px; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.a-wqbox p { margin: 0; font-size: 13.5px; }
.a-card--danger { border-left: 3px solid #a8552e; }
.a-btn--danger { background: #a8552e; color: #fff; border-color: #a8552e; }
.a-radioset { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; margin-bottom: 12px; }
.a-radioset legend { font-size: 12.5px; color: var(--muted); padding: 0 6px; }


/* Observance marks on the agenda -------------------------------------- */
.a-obsmark {
  display: inline-block; font-size: 10.5px; line-height: 1.3; padding: 2px 6px;
  margin: 0 4px 3px 0; border-radius: 999px; background: #eef0f8; color: #3b4270;
  border: 1px solid #d9deef; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 100%;
}
.a-fieldset { border: 1px solid var(--line); border-radius: 10px; padding: 10px 14px; margin: 0 0 12px; }
.a-fieldset legend { padding: 0 6px; font-size: 12.5px; color: var(--muted); }

.a-sug { margin: 10px 0; }
.a-sug__h { font-size: 13.5px; margin: 0 0 4px; color: var(--deep-800); }
.a-sug__list { margin: 0; padding-left: 18px; font-size: 13.5px; line-height: 1.6; color: #2c3a35; }
.a-card--muted { opacity: .62; }


/* Due dates on the agenda --------------------------------------------- */
.a-duemark {
  display: inline-block; font-size: 10.5px; line-height: 1.3; padding: 2px 6px;
  margin: 0 4px 3px 0; border-radius: 999px; background: #fbeee6; color: #8a3d1c;
  border: 1px solid #f0d9c9; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 100%;
}
.a-duemark--in { background: #e7f2ec; color: #165c46; border-color: #cfe4d9; }


/* Personal budget ------------------------------------------------------ */
.a-progress--sm { height: 6px; width: 120px; }
.a-progress__bar.is-over { background: #a8552e; }
.a-over { color: #a8552e; font-weight: 650; }
.a-row--wrap { flex-wrap: wrap; }
.a-yearbars { display: flex; align-items: flex-end; gap: 6px; height: 110px; margin: 14px 0 6px; }
.a-yearbar { flex: 1 1 0; display: flex; flex-direction: column; justify-content: flex-end;
  align-items: center; height: 100%; }
.a-yearbar__fill { width: 100%; background: var(--accent-600); border-radius: 3px 3px 0 0; min-height: 2px; }
.a-yearbar__lbl { font-size: 10px; color: var(--muted); margin-top: 3px; }

/* Height utilities for the year bars, in 5% steps (CSP: no inline styles). */
.a-h0 { height: 0%; }
.a-h5 { height: 5%; }
.a-h10 { height: 10%; }
.a-h15 { height: 15%; }
.a-h20 { height: 20%; }
.a-h25 { height: 25%; }
.a-h30 { height: 30%; }
.a-h35 { height: 35%; }
.a-h40 { height: 40%; }
.a-h45 { height: 45%; }
.a-h50 { height: 50%; }
.a-h55 { height: 55%; }
.a-h60 { height: 60%; }
.a-h65 { height: 65%; }
.a-h70 { height: 70%; }
.a-h75 { height: 75%; }
.a-h80 { height: 80%; }
.a-h85 { height: 85%; }
.a-h90 { height: 90%; }
.a-h95 { height: 95%; }
.a-h100 { height: 100%; }


/* Next prayer: two tight lines ---------------------------------------- */
.a-nextp {
  background: #14211d; border: 0; border-radius: 10px;
  padding: 9px 14px; margin-bottom: 12px; color: #eef3f0;
}
.a-nextp__line { display: flex; align-items: baseline; gap: 9px; margin: 0; }
.a-nextp__line--sub { margin-top: 1px; }
.a-nextp__name { font-size: 17px; font-weight: 650; color: #ffffff; }
.a-nextp__at {
  font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; color: #7fd3b4;
}
.a-nextp__day { font-size: 11.5px; color: #9fb5ac; }
.a-nextp__in { margin-left: auto; font-size: 13px; font-weight: 550; color: #d7e6df; white-space: nowrap; }
.a-nextp__place { font-size: 12px; color: #9fb5ac; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.a-nextp__loc { margin: 0 0 0 auto; }
.a-nextp__locbtn { color: #7fd3b4; font-size: 12px; }
.a-nextp__locbtn[disabled] { opacity: .6; }
/* Narrow screens keep both lines: nothing here is long enough to wrap,
   and wrapping is what made this four lines tall before. */
/* The mobile .a-card rule sets 14px on every card and is written later in
   the file, so it won that fight and the panel stayed tall. Same specificity,
   stated after it, rather than reaching for !important. */
@media (max-width: 560px) {
  .a-nextp__name, .a-nextp__at { font-size: 16px; }
  .a-nextp__in { font-size: 12px; }
}

/* A panel that scrolls instead of growing ------------------------------ */
/*
 * A panel that scrolls instead of growing.
 *
 * `overflow-y: auto` reserves a scrollbar gutter on desktop browsers even
 * when nothing overflows, and on Android it draws a permanent grey track
 * down the right edge. Neither is a scrollbar the reader can use — it is
 * a line beside the content. `scrollbar-width: none` and the WebKit
 * pseudo-element hide the track; the panel still scrolls by touch and by
 * wheel, and keyboard scrolling is unaffected.
 */
.a-scrollbox {
  max-height: 420px; overflow-y: auto;
  scrollbar-width: none;                 /* Firefox */
  -ms-overflow-style: none;              /* old Edge */
}
.a-scrollbox::-webkit-scrollbar { width: 0; height: 0; }
@media (max-width: 560px) { .a-scrollbox { max-height: 300px; } }


/* Where you stopped: two lines per sitting ---------------------------- */
.a-stops { list-style: none; margin: 0; padding: 0; }
.a-stops__item { padding: 9px 0; border-bottom: 1px solid var(--line-2); }
.a-stops__item:last-child { border-bottom: 0; }
.a-stops__top { display: flex; align-items: baseline; gap: 8px; flex-wrap: nowrap; }
.a-stops__at { font-size: 15px; }
.a-stops__when {
  margin-left: auto; font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.a-stops__sub { font-size: 12.5px; color: #46564f; margin-top: 2px; }


/* Editions list -------------------------------------------------------- */
.a-eds { list-style: none; margin: 0; padding: 0; }
.a-eds__item { padding: 9px 0; border-bottom: 1px solid var(--line-2); }
.a-eds__item:last-child { border-bottom: 0; }
.a-eds__top { display: flex; align-items: baseline; gap: 8px; }
.a-eds__n { margin-left: auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.a-eds__sub { font-size: 12px; color: var(--muted); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* An Arabic sample beside the typeface chooser. */
.a-ar--preview { margin: 10px 0 4px; padding: 10px 12px; background: #f6f8f7; border-radius: 8px; }

/*
 * Statistics on a phone.
 *
 * Each stat card was a full-width block, so three of them cost a screen
 * before the reader reached anything. Two to a row, with smaller numbers,
 * fits them above the fold without losing anything.
 */
@media (max-width: 560px) {
  .a-grid--stats { grid-template-columns: 1fr 1fr; gap: 8px; }
  .a-stat { padding: 10px 12px; }
  .a-stat__label { font-size: 10.5px; letter-spacing: .03em; }
  .a-stat__value { font-size: 22px; line-height: 1.15; }
  /* h1 is not overridden here any more: the clamp floor IS 22px, which
     is what this rule was setting. Two contradictory overrides used to
     exist — 22px under 560 and 19px under 900 — so a 700px tablet got a
     SMALLER page title than a 400px phone. One curve, no steps. */
  .a-page-head p { font-size: 13px; }
  .a-card { padding: 14px; margin-bottom: 12px; }
  .a-card__head h2 { font-size: 16px; }
  .a-card__note, .a-hint { font-size: 12.5px; }
  .a-field { margin-bottom: 10px; }
  /* A table that stacks into labelled lines is the largest thing on most
     of these screens; tightening the rows keeps it usable. */
  .a-table td { padding: 7px 10px; }
}


/* Memorisation list ---------------------------------------------------- */
.a-hifz { list-style: none; margin: 0; padding: 0; }
.a-hifz__item { padding: 10px 0; border-bottom: 1px solid var(--line-2); }
.a-hifz__item:last-child { border-bottom: 0; }
.a-hifz__item.is-due { box-shadow: inset 3px 0 0 #b98900; padding-left: 10px; }
.a-hifz__item.is-just { box-shadow: inset 3px 0 0 var(--accent-600); padding-left: 10px; }
.a-hifz__top, .a-hifz__bot { display: flex; align-items: baseline; gap: 8px; }
.a-hifz__bot { margin-top: 3px; }
.a-hifz__ref { font-size: 15px; }
.a-hifz__when, .a-hifz__meta { font-size: 12px; color: var(--muted); }
.a-hifz__when { margin-left: auto; white-space: nowrap; }
.a-hifz__act { margin-left: auto; display: flex; align-items: center; gap: 10px; white-space: nowrap; }

/*
 * Why so many lists replaced tables here.
 *
 * A responsive table stacks each cell onto its own labelled line below
 * 700px. That is right for a grid of figures and wrong for a record with
 * four fields and three buttons: one row then fills a third of the screen.
 * Where a record reads as a sentence rather than a grid, it is a list.
 */
@media (max-width: 560px) {
  .a-hifz__act .a-btn--sm { padding: 5px 10px; }
  .a-hifz__ref { font-size: 14px; }
}


/*
 * Stated last so it beats the general mobile card padding, which is
 * written further up and would otherwise make this two-line panel as
 * tall as a card of prose.
 */
.a-card.a-nextp { padding: 9px 14px; }
@media (max-width: 560px) { .a-card.a-nextp { padding: 8px 12px; } }


/* Tasks, projects and checklists --------------------------------------- */
.a-tasks { list-style: none; margin: 0; padding: 0; }
.a-tasks__item { padding: 9px 0; border-bottom: 1px solid var(--line-2); }
.a-tasks__item:last-child { border-bottom: 0; }
.a-tasks__item.is-late { box-shadow: inset 3px 0 0 #a8552e; padding-left: 10px; }
.a-tasks__item.is-done { opacity: .6; }
.a-tasks__item.is-done .a-tasks__title { text-decoration: line-through; }
.a-tasks__top, .a-tasks__bot { display: flex; align-items: baseline; gap: 8px; }
.a-tasks__bot { margin-top: 2px; }
.a-tasks__title { font-size: 14.5px; font-weight: 550; color: var(--deep-800); }
.a-tasks__due { margin-left: auto; font-size: 12px; color: var(--muted); white-space: nowrap; }
.a-tasks__due.is-late { color: #a8552e; font-weight: 600; }
.a-tasks__meta { font-size: 12px; color: var(--muted); }
.a-tasks__act { margin-left: auto; }

/* A tick box that is a real button: a checklist is tapped, often on a
   phone, so it needs a target rather than a glyph. */
.a-tick {
  width: 22px; height: 22px; flex: 0 0 22px; padding: 0; line-height: 1;
  border: 1.5px solid var(--line); border-radius: 6px; background: #fff;
  color: #fff; font-size: 13px; cursor: pointer;
}
.a-tick.is-on { background: var(--accent-600); border-color: var(--accent-600); }
.a-tick--sm { width: 18px; height: 18px; flex-basis: 18px; font-size: 11px; border-radius: 5px; }
.a-steps { list-style: none; margin: 5px 0 0 30px; padding: 0; font-size: 13px; }
.a-steps li { display: flex; align-items: center; gap: 7px; padding: 2px 0; }
.a-steps--done { text-decoration: line-through; color: var(--muted); }
.a-input--sm { padding: 5px 8px; font-size: 13px; }
a.a-stat { text-decoration: none; display: block; }

.a-taskmark {
  display: inline-block; font-size: 10.5px; line-height: 1.3; padding: 2px 6px;
  margin: 0 4px 3px 0; border-radius: 4px; background: #eef4ff; color: #2c4a7c;
  border: 1px solid #d7e3f5; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 100%;
}
.a-taskmark--proj { background: #f3eefd; color: #4b3a78; border-color: #e0d7f3; }


/* A file input dressed as a link or button ----------------------------- */
.a-pick { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 4px 0; }
.a-pick__main { font-weight: 600; }
/* The input still receives the click — a label wrapping it is what makes
   this work without JavaScript — but is not drawn. Not display:none,
   which removes it from the accessibility tree as well. */
.a-pick__input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
label.a-btn, label.a-clink { cursor: pointer; }
.a-label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 4px; color: var(--deep-800); }
.a-input--tiny { width: 72px; }

.a-dictate { margin-top: 4px; }
.a-dictate__btn.is-on { color: #a8552e; font-weight: 600; }
.a-dictate__warn { display: block; margin-top: 2px; }

/* The chosen date, spelled out beside the picker. */
.a-datehint { display: block; margin-top: 3px; font-size: 12px; color: var(--muted); }
.a-datehint:empty { display: none; }

.a-select--sm { padding: 5px 8px; font-size: 13px; max-width: 160px; }


/* Recording a payment ---------------------------------------------------
   Was an inline style attribute, which the CSP has always refused, so the
   field had been full width all along. */
.a-payform { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.a-input--amount { max-width: 130px; }
.a-payform__note { flex-basis: 100%; margin: 0; }

/* Google above the credentials, with a plain divider between. */
.a-or { display: flex; align-items: center; gap: 10px; margin: 14px 0 10px;
        font-size: 12.5px; color: var(--muted); }
.a-or::before, .a-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }


/* Utilities ------------------------------------------------------------
 *
 * These replace 115 inline style attributes that had been in the markup
 * since early on. The CSP has always been `style-src 'self'`, so every
 * one of them was silently discarded by the browser: fields that were
 * meant to be narrow ran full width, headings meant to be large were
 * ordinary size, and nothing said so. A refused inline style leaves no
 * trace on the page.
 *
 * Only the declarations actually in use are listed here.
 */
.u-d-inline-block { display: inline-block; }
.u-fs14 { font-size: 14px; }
.u-fs15 { font-size: 15px; }
.u-fs19 { font-size: 19px; }
.u-fs21 { font-size: 21px; }
.u-fs22 { font-size: 22px; }
.u-m0 { margin: 0; }
.u-mt12 { margin-top: 12px; }
.u-mt14 { margin-top: 14px; }
.u-mt16 { margin-top: 16px; }
.u-mt18 { margin-top: 18px; }
.u-mw110 { max-width: 110px; }
.u-mw120 { max-width: 120px; }
.u-mw130 { max-width: 130px; }
.u-mw140 { max-width: 140px; }
.u-mw150 { max-width: 150px; }
.u-mw170 { max-width: 170px; }
.u-mw180 { max-width: 180px; }
.u-mw190 { max-width: 190px; }
.u-mw200 { max-width: 200px; }
.u-mw210 { max-width: 210px; }
.u-mw260 { max-width: 260px; }
.u-mw280 { max-width: 280px; }
.u-mw320 { max-width: 320px; }
.u-mw340 { max-width: 340px; }
.u-ta-center { text-align: center; }
.u-w<?= (int) $pct ?>p { width: <?= (int) $pct ?>%; }
.u-w<?= (int) round($pct) ?>p { width: <?= (int) round($pct) ?>%; }
.u-w<?= (int) round((float) $cur['pct']) ?>p { width: <?= (int) round((float) $cur['pct']) ?>%; }

.u-bg-tint { background: var(--tint); }
.u-mh280 { min-height: 280px; }
.u-mh70 { min-height: 70px; }
.u-mh80 { min-height: 80px; }
.u-ov-auto { overflow: auto; }
.u-w110 { width: 110px; }

.u-mt6 { margin-top: 6px; }
.u-mt14 { margin-top: 14px; }
.u-mw240 { max-width: 240px; }
.a-stat--bare { border: 0; padding: 0 0 10px; }

/* Payments recorded against a debt. */
.a-payhist { margin-top: 6px; }
.a-payhist__list { list-style: none; margin: 6px 0 4px; padding: 0; }
.a-payhist__list li { display: flex; align-items: baseline; gap: 9px; padding: 3px 0;
  border-bottom: 1px solid var(--line-2); font-size: 13px; flex-wrap: wrap; }
.a-payhist__list li:last-child { border-bottom: 0; }
.a-payhist__date { color: var(--muted); font-size: 12px; white-space: nowrap; }
.a-payhist__amt { font-variant-numeric: tabular-nums; }
.a-payhist__note { color: var(--muted); font-size: 12px; }


/* The dashboard's two columns ------------------------------------------
 *
 * One column on a phone, where the aside simply follows the main column.
 * The second appears only when there is genuinely room for it: below this
 * width the panels beside the feed would be too narrow to read, which is
 * worse than scrolling for them.
 */
.a-dash { display: block; }
.a-dash__side > .a-card:last-child { margin-bottom: 0; }
@media (min-width: 1080px) {
  /* The side column was a flat 320px, so on a wide monitor everything
     extra went to the main column while the panels beside it stayed the
     width they had on a small laptop. It grows with the screen now, and
     stops at 420 — past that it is a second main column, not a margin. */
  .a-dash { display: grid; grid-template-columns: minmax(0, 1fr) clamp(320px, 22vw, 420px);
            gap: 16px; align-items: start; }
}

/* Progress rings ------------------------------------------------------- */
.a-perf { display: flex; flex-wrap: wrap; gap: 14px; }
.a-perf__item { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1 1 auto; }
/* A ring that leads somewhere says so on hover and on keyboard focus.
   Colour alone would not: the whole panel is already green. */
.a-perf__item--link { text-decoration: none; color: inherit; border-radius: 10px;
  padding: 4px; margin: -4px; transition: background .12s ease; }
.a-perf__item--link:hover,
.a-perf__item--link:focus-visible { background: var(--deep-050, #eef4f1); }
.a-perf__item--link:hover .a-perf__label { text-decoration: underline; }
.a-perf__ring { width: 64px; height: 64px; flex: 0 0 64px; }
.a-perf__track { fill: none; stroke: var(--line); stroke-width: 7; }
.a-perf__arc { fill: none; stroke-width: 7; stroke-linecap: round; }
.a-perf__arc--green { stroke: var(--accent-600); }
.a-perf__arc--blue { stroke: #3f6ea8; }
.a-perf__pct { font-size: 15px; font-weight: 650; fill: var(--deep-800); }
.a-perf__body { min-width: 0; }
.a-perf__label { font-size: 13.5px; font-weight: 600; color: var(--deep-800); }
.a-perf__detail { font-size: 12px; color: var(--muted); }

/* People writing in the circles on screen ------------------------------- */
.a-people { list-style: none; margin: 0; padding: 0; }
.a-people__item { display: flex; align-items: center; gap: 9px; padding: 6px 0;
  border-bottom: 1px solid var(--line-2); }
.a-people__item:last-child { border-bottom: 0; }
.a-people__body { min-width: 0; }
.a-people__name { display: block; font-size: 13.5px; font-weight: 600; color: var(--deep-800);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.a-people__where { display: block; font-size: 12px; color: var(--muted); }

.a-tsh__title { font-weight: 650; font-size: 14px; color: var(--deep-800); margin: 0 0 4px; }
.a-tsh__body { font-size: 13px; line-height: 1.55; margin: 0 0 4px; }
.a-tz__niyyah { font-size: 13.5px; line-height: 1.5; margin: 0 0 6px; color: var(--deep-800); }
.a-tz__trait { font-size: 13px; margin: 0; }

/* A typed dd/mm/yyyy field with the calendar beside it. */
.a-datefield { display: inline-flex; align-items: center; gap: 6px; width: 100%; }
.a-datefield__text { flex: 1 1 auto; min-width: 0; }
/* Only the picker's own button is wanted; the browser's text is not. */
.a-datefield__pick { width: 36px; flex: 0 0 36px; padding: 6px 2px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff;
  color: transparent; }

/* Phrases said on a post ------------------------------------------------ */
.a-react { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.a-react__counts { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; }
.a-react__tally { display: inline-flex; align-items: baseline; gap: 5px;
  font-size: 12px; padding: 3px 9px; border-radius: 999px;
  background: var(--tint); border: 1px solid var(--line-2); color: var(--deep-800); }
.a-react__tally.is-mine { border-color: var(--accent-600); font-weight: 600; }
.a-react__n { font-variant-numeric: tabular-nums; color: var(--muted); }


/* Appointments and notes ------------------------------------------------ */
.a-appt, .a-notes { list-style: none; margin: 0; padding: 0; }
.a-appt__item, .a-notes__item { padding: 10px 0; border-bottom: 1px solid var(--line-2); }
.a-appt__item:last-child, .a-notes__item:last-child { border-bottom: 0; }
.a-appt__item.is-declined, .a-appt__item.is-cancelled { opacity: .6; }
.a-appt__item.is-planned { box-shadow: inset 3px 0 0 #b98900; padding-left: 10px; }
.a-appt__top, .a-appt__bot, .a-notes__top, .a-notes__bot {
  display: flex; align-items: baseline; gap: 8px; }
.a-appt__bot, .a-notes__bot { margin-top: 3px; }
.a-appt__title, .a-notes__title { font-size: 14.5px; font-weight: 600; color: var(--deep-800); }
.a-appt__when, .a-notes__when { margin-left: auto; font-size: 12px; color: var(--muted); white-space: nowrap; }
.a-appt__meta, .a-notes__meta { font-size: 12px; color: var(--muted); }
.a-appt__act, .a-notes__act { margin-left: auto; display: flex; gap: 10px; align-items: center; }
.a-notes__body { font-size: 13.5px; line-height: 1.55; margin: 4px 0 0; }
.a-notes__drawing { display: block; width: 100%; max-width: 480px; height: auto;
  margin-top: 6px; border: 1px solid var(--line); border-radius: 8px; background: #fff; }

/* The handwriting surface. touch-action keeps a finger drawing instead of
   scrolling the page, on the canvas only. */
.a-canvas { display: block; width: 100%; height: auto; aspect-ratio: 900 / 520;
  border: 1px solid var(--line); border-radius: 8px; background: #fff;
  touch-action: none; cursor: crosshair; }
.a-hidden { display: none; }
.a-notefilter { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 0; }
.a-chip--day { font-variant-numeric: tabular-nums; }
.a-chip.is-on { background: var(--accent-600); color: #fff; border-color: var(--accent-600); }
.a-chip__n { opacity: .7; margin-left: 3px; }


/* Advertising ----------------------------------------------------------
   Set apart and labelled. A member should never have to work out whether
   what they are looking at was chosen for them or sold to them. */
.a-ad { margin: 18px 0 4px; padding: 10px; border: 1px dashed var(--line);
  border-radius: 10px; background: #fbfcfb; }
.a-ad__label { margin: 0 0 6px; font-size: 11px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); }
/*
 * How large an advertisement is allowed to be.
 *
 * Big enough to see on a desk, not so big it owns the page. Stated on
 * the wrapper rather than by squeezing the media partial, so the partial
 * keeps rendering a taushiyah at reading size and an advertisement at
 * advertising size without either knowing about the other.
 */
.a-ad .a-embed { max-width: min(100%, 520px); margin-inline: 0; }
.a-ad .a-embed--instagram { width: min(100%, 420px); }
.a-ad .a-embed--x { width: min(100%, 520px); }
.a-ad .a-embed--tiktok, .a-ad .a-embed--facebook_reel { max-width: min(100%, 300px); }

.a-ad__media { display: block; width: 100%; height: auto; max-height: 320px;
  object-fit: contain; border-radius: 8px; background: var(--line-2); }
.a-ad__link { margin: 6px 0 0; font-size: 13px; }
.a-ad__slide { display: none; }
.a-ad__slide.is-on { display: block; }
.a-ad__dots { display: flex; gap: 6px; justify-content: center; margin: 8px 0 0; }
.a-ad__dot { width: 8px; height: 8px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line); background: #fff; cursor: pointer; }
.a-ad__dot.is-on { background: var(--accent-600); border-color: var(--accent-600); }
.a-adassets { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; margin: 8px 0; padding: 0; }
.a-adassets__thumb { width: 120px; height: 80px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--line); background: var(--line-2); }
/* A linked video has no picture of its own to show, so its tile is the
   provider's name in the same box the thumbnails occupy — the row stays
   an even grid rather than gaining a hole where an image failed. */
.a-adassets__thumb--embed { display: inline-flex; align-items: center; justify-content: center;
  background: var(--deep-050, #eef4f1); border: 1px dashed var(--line, #dbe5e0);
  color: var(--deep-800); font-size: 13px; font-weight: 600; }
.a-adform { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 8px 0; }
.a-btn--wide { display: block; width: 100%; text-align: center; margin-top: 8px; }
.a-oidc { background: #fff; color: var(--deep-800); border: 1px solid var(--line); }


/* Appointments on the agenda ------------------------------------------
 *
 * The dot carries the state, and so does the border: colour alone is a
 * poor way to say anything, and one reader in twelve cannot separate
 * these two hues.
 */
.a-ev--appt { display: block; position: relative; padding-left: 9px; cursor: context-menu; }
/* 5px, to match .a-stdot beside it.
   Two dots meaning the same thing sat next to each other at 7px and 5px,
   and the difference read as significance rather than as an oversight. */
.a-ev__dot { position: absolute; left: 1px; top: 50%; width: 5px; height: 5px;
  margin-top: -2.5px; border-radius: 50%; box-sizing: border-box; }
/*
 * The dashed and solid left borders are gone with the rest of the
 * bracket, and the state they carried has moved into the dot's SHAPE
 * rather than being dropped.
 *
 * The note that used to sit here still holds: colour alone is a poor way
 * to say anything, and one reader in twelve cannot separate amber from
 * green. So planned is a hollow ring and confirmed is filled — a
 * difference that survives being printed in grey, and that costs no
 * width at all, which was the point of the exercise.
 */
.a-ev--appt.is-planned .a-ev__dot { background: transparent; border: 1.5px solid #d18b00; }
.a-ev--appt.is-confirmed .a-ev__dot { background: var(--accent-600); }
.a-ev--appt.is-planned { background: #fff8ea; }
.a-ev--appt.is-confirmed { background: #eef7f2; }

.a-weeks { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 10px 0 4px; font-size: 12.5px; color: var(--muted); }
/*
 * The dot, inside an entry.
 *
 * `.a-ev { display: block }` was added for the week chooser and turned
 * every dot into a block too: 17px wide, on its own line, and clipped
 * away by the entry's own `overflow: hidden`. It was in the DOM with the
 * right colour and could not be seen — which is why it kept being
 * reported as missing after I had checked the markup and called it done.
 *
 * The dot is stated explicitly here rather than relying on what it
 * inherits, and the entry keeps its text on one line beside it.
 */
.a-ev { display: flex; align-items: center; gap: 5px; }
.a-ev .a-stdot { margin: -4px 2px -4px -2px; }

.a-month__mon { display: inline-block; margin-left: 5px; font-size: 10.5px;
  font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--accent-600); }


/* The install button, in the header beside Exit. Quiet: it is an offer,
   not an announcement, and it removes itself once accepted. */
.a-btn--install {
  background: rgba(255,255,255,.14); color: #fff;
  border: 1px solid rgba(255,255,255,.3); font-size: 12.5px; padding: 5px 12px;
}
.a-btn--install:hover { background: rgba(255,255,255,.22); }
/* The install button's own [hidden] rule has gone: the global one at the
   top of this sheet covers it, and the same bug was patched here once
   already without anybody noticing it was general. */


/* The quick-note dialog and the counting number ------------------------- */
.a-modal { border: 0; border-radius: 14px; padding: 18px; max-width: 520px; width: calc(100% - 32px);
  box-shadow: 0 18px 48px rgba(9,32,25,.28); }
.a-modal::backdrop { background: rgba(9,32,25,.45); }
.a-modal__title { margin: 0 0 10px; font-size: 17px; color: var(--deep-800); }

.a-autocount { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 10px 0 4px; }
.a-autocount__n { font-size: 30px; font-weight: 700; color: var(--deep-800);
  font-variant-numeric: tabular-nums; min-width: 2.5ch; }
/* A short mark that the count moved, not a performance asking to be
   watched: this screen is meant to be half-attended. */
.a-autocount__n.is-beat { animation: a-beat 260ms ease-out; }
@keyframes a-beat {
  0%   { transform: scale(1);    color: var(--accent-600); }
  40%  { transform: scale(1.16); }
  100% { transform: scale(1);    color: var(--deep-800); }
}
@media (prefers-reduced-motion: reduce) {
  .a-autocount__n.is-beat { animation: none; }
}


/* The dhikr ring --------------------------------------------------------
 *
 * One control where there were six: the count inside, the progress
 * around, and two buttons. The arc moves by its dash offset, which the
 * browser animates on the compositor rather than relaying out the page.
 */
.a-ring { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 6px 0 2px; }
.a-ring__svg { width: 100%; max-width: 240px; height: auto; }
.a-ring__track { fill: none; stroke: var(--line-2); stroke-width: 10; }
.a-ring__arc {
  fill: none; stroke: var(--accent-600); stroke-width: 10; stroke-linecap: round;
  transition: stroke-dashoffset 320ms ease-out;
}
.a-ring__n { font-size: 54px; font-weight: 700; fill: var(--deep-800);
  font-variant-numeric: tabular-nums; transform-box: fill-box; transform-origin: center; }
.a-ring__n.is-beat { animation: a-ringbeat 280ms ease-out; }
@keyframes a-ringbeat {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.09); }
  100% { transform: scale(1); }
}
.a-ring__of { font-size: 20px; fill: var(--muted); }

.a-ring__ctl { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; justify-content: center; }
.a-ring__pace { display: flex; align-items: center; gap: 8px; }
/* Short, as asked: a pace control does not need the width of the card. */
.a-ring__pace input[type="range"] { width: 120px; }
.a-ring__pacen { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums;
  min-width: 3.5ch; }

@media (prefers-reduced-motion: reduce) {
  .a-ring__arc { transition: none; }
  .a-ring__n.is-beat { animation: none; }
}


/* The voice recorder --------------------------------------------------- */
.a-rec { margin: 8px 0; padding: 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--tint); }
.a-rec__row { display: flex; align-items: center; gap: 10px; }
.a-rec__time { font-variant-numeric: tabular-nums; font-size: 14px; color: var(--deep-800); }
/* A red dot while recording, pulsing — the one place a pulse is right,
   because the tab is holding a live microphone. */
.a-rec__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--line);
  flex: 0 0 10px; }
.a-rec__dot.is-on { background: #b3382a; animation: a-recpulse 1.1s ease-in-out infinite; }
@keyframes a-recpulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
.a-rec__play, .a-notes__audio { display: block; width: 100%; margin-top: 8px; }
@media (prefers-reduced-motion: reduce) { .a-rec__dot.is-on { animation: none; } }


/* A shared link, as a card ---------------------------------------------
   The whole card is the link, so the target is the size of the card
   rather than a line of text; the arrow says which way it goes. */
/* A shared link, VK-style ----------------------------------------------
 *
 * Picture on top, then a coloured bar with the title and an arrow. The
 * bar is deliberately not the card's background colour: it should read as
 * a way out of the page rather than as more of the post, which is the
 * whole job it does.
 */
.a-linkcard { display: block; margin: 8px 0 2px; border: 1px solid var(--line);
  border-radius: 10px; overflow: hidden; color: inherit; background: #fff; }
/*
 * Named in every context the card appears in.
 *
 * The feed underlines links inside a post and the dashboard panel does
 * the same inside .a-mini; each of those beats a plain `.a-linkcard`, so
 * the card's own rule lost in whichever place it had not been named.
 * That is the second time this specificity fight has cost a fix — the
 * card is now stated for both, and any third home will need adding here.
 */
.a-post .a-linkcard, .a-post .a-linkcard *,
.a-mini .a-linkcard, .a-mini .a-linkcard *,
.a-linkcard, .a-linkcard * { text-decoration: none; }

.a-linkcard__img { display: block; width: 100%; height: auto; max-height: 300px;
  object-fit: cover; background: var(--line-2); }

.a-linkcard__bar { display: flex; align-items: center; gap: 10px;
  padding: 11px 14px; background: var(--accent-600); color: #fff; }
.a-linkcard__label { flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.a-linkcard__go { flex: 0 0 auto; font-size: 22px; line-height: 1; opacity: .9; }
.a-linkcard:hover .a-linkcard__bar { background: var(--accent-700); }
.a-linkcard:hover .a-linkcard__go { opacity: 1; }

.a-linkcard__desc { display: block; padding: 9px 14px 11px; font-size: 12.5px;
  color: var(--muted); }


/* The last ten minutes ---------------------------------------------------
 *
 * Ten blocks that shorten towards the prayer, and an arrow pointing the
 * way they are going. Small: this sits inside a panel that is two lines
 * tall on a phone and must not become three.
 */
.a-nextp .a-tenmin,
.a-tenmin { display: flex; flex-direction: row; align-items: center; gap: 3px;
  margin-top: 5px; flex-wrap: nowrap; }

/*
 * Stated with enough specificity to survive the panel around it.
 *
 * The prayer panel sets its own rules for the spans inside it, and those
 * won on both width and opacity: the blocks came out 0px wide and fully
 * transparent. They were in the markup, correctly counted, and could not
 * be seen — the same failure as the agenda dots, from the same cause.
 *
 * The starting opacity is stated too. Without it a block only became
 * visible once the script had touched it, so the row was blank until the
 * first tick even when everything else was right.
 */
.a-nextp .a-tenmin__b,
.a-tenmin__b {
  /* inline-block, not block: `display: block` on a flex child is fine,
     but the row itself must stay a flex row — and stating the row's
     display here too means neither can be undone by the panel. */
  /* Three times the thickness. At 5px the row read as a hairline rule
     someone had drawn under the clock rather than as ten things being
     spent one at a time; at 15px each block is an object, and a block
     going out is something you notice from across the room. The width is
     unchanged, so the row occupies the same span and the panel keeps its
     height on a phone. */
  display: inline-block; width: 14px; min-width: 14px; height: 15px; flex: 0 0 14px;
  border-radius: 3px; background: var(--leaf); opacity: 1;
  transition: opacity 200ms ease-out;
}
.a-nextp .a-tenmin__b.is-gone,
.a-tenmin__b.is-gone { opacity: 0; }
/* The minute being spent. A slow fade, not a strobe: this is beside a
   prayer time, and it should draw the eye once rather than hold it. */
.a-tenmin__b.is-going { animation: a-tenblink 1s ease-in-out infinite; }
@keyframes a-tenblink { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
/* The arrow that used to lead the row is gone; its rule goes with it,
   rather than being left behind for somebody to wonder about later. */

/* The clock itself, in the minute the prayer arrives. */
.a-nextp__at.is-due { animation: a-dueblink 1s ease-in-out infinite; }
@keyframes a-dueblink { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

@media (prefers-reduced-motion: reduce) {
  .a-tenmin__b.is-going, .a-nextp__at.is-due { animation: none; }
  /* Still distinguishable without motion. */
  .a-tenmin__b.is-going { outline: 1px solid currentColor; }
}


/* Hadith reading -------------------------------------------------------- */
/* No font-family here: the a-ar--* class beside it carries the chosen
   face, and a family stated twice is a fight one of them has to lose. */
.a-hadith__ar { font-size: 25px; line-height: 2.05;
  margin: 10px 0 14px; color: var(--deep-800); }
.a-hadith__tr { font-size: 15px; line-height: 1.7; margin: 0 0 8px; }
.a-hlist { list-style: none; margin: 0; padding: 0; }
.a-hlist__item { display: flex; align-items: baseline; gap: 10px; padding: 7px 0;
  border-bottom: 1px solid var(--line-2); }
.a-hlist__item:last-child { border-bottom: 0; }
.a-hlist__book { font-weight: 600; color: var(--deep-800); font-size: 13.5px; }
.a-hlist__no { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.a-hlist__when { margin-left: auto; font-size: 12px; color: var(--muted); }


/* The language switcher on the sign-in screen. Small and out of the way:
   most people never need it, and the ones who do are looking for it. */
/* Centred under the logo, not pinned to a corner. The card below is
   centred, and a control hanging off one edge made the whole screen look
   as though it had slipped. */
.a-authlang { display: flex; justify-content: center; gap: 6px; margin: 8px 0 2px; }
.a-authlang__opt { font-size: 12.5px; padding: 4px 12px; border: 1px solid var(--line);
  border-radius: 999px; color: var(--muted); text-decoration: none; }
.a-authlang__opt:hover { background: var(--tint); }
.a-authlang__opt.is-on { background: var(--accent-600); color: #fff; }


/* Learning path steps --------------------------------------------------- */
.a-steps { list-style: none; margin: 0; padding: 0; }
.a-steps__item { display: flex; align-items: flex-start; gap: 12px; padding: 11px 0;
  border-bottom: 1px solid var(--line-2); }
.a-steps__item:last-child { border-bottom: 0; }
.a-steps__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.a-steps__title { font-size: 14.5px; font-weight: 600; color: var(--deep-800); }
.a-steps__detail { font-size: 12.5px; color: var(--muted); line-height: 1.55; }
/* Done is quieter, not struck through: a step already taken is not
   cancelled, and a page of struck-out lines reads as a list of failures. */
.a-steps__item.is-done .a-steps__title { color: var(--muted); font-weight: 500; }
.a-steps__item.is-done { background: linear-gradient(90deg, var(--tint), transparent 60%); }


/* Agenda, directly under the Dashboard button. Quieter than Dashboard
   itself: it is a shortcut to a screen, not the home of the app. */
.a-side__dash--sub { margin-top: 4px; font-size: 14px; font-weight: 600;
  background: transparent; color: var(--deep-800); }
.a-side__dash--sub:hover { background: var(--tint); }
.a-side__dash--sub.is-active { background: var(--tint); color: var(--deep-800); }


/* The clickable title inside a calendar entry. Inherits its colour so
   the grid does not turn into a page of blue links. */
.a-ev__link { color: inherit; text-decoration: none; }
.a-ev__link:hover, .a-ev__link:focus-visible { text-decoration: underline; }

/* The detail screen's definition list. */
.a-dl { display: grid; grid-template-columns: max-content 1fr; gap: 8px 18px; margin: 0; }
.a-dl dt { font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); }
.a-dl dd { margin: 0; font-size: 14.5px; color: var(--deep-800); }
@media (max-width: 560px) { .a-dl { grid-template-columns: 1fr; gap: 2px 0; }
  .a-dl dd { margin-bottom: 10px; } }


/* Clickable calendar marks. They keep their own colours; only the
   pointer and the underline on hover say they can be opened. */
.a-duemark--link, .a-ev--link { text-decoration: none; color: inherit; cursor: pointer; }
.a-duemark--link:hover, .a-ev--link:hover { text-decoration: underline; }

/* A proposal waiting on this member, on the dashboard. */
.a-apptrow { display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--line-2); flex-wrap: wrap; }
.a-apptrow:last-child { border-bottom: 0; }
.a-apptrow__what { flex: 1 1 190px; min-width: 0; text-decoration: none; color: inherit;
  display: flex; flex-direction: column; gap: 1px; }
.a-apptrow__what:hover .a-apptrow__title { text-decoration: underline; }
.a-apptrow__title { font-size: 14px; font-weight: 600; color: var(--deep-800); }
.a-apptrow__meta { font-size: 12px; color: var(--muted); }


/* The expression catalogue. */
.a-phlist { list-style: none; margin: 0; padding: 0; }
.a-phlist__item { display: flex; align-items: center; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line-2); }
.a-phlist__item:last-child { border-bottom: 0; }
.a-phlist__body { display: flex; flex-direction: column; gap: 1px; }
.a-phlist__tr { font-size: 14px; font-weight: 600; color: var(--deep-800); }
.a-phlist__mean { font-size: 12.5px; color: var(--muted); }
.a-phlist__ar { margin-left: auto; font-size: 19px; color: var(--deep-800); }

/* Embedded video: YouTube, TikTok, Instagram, Facebook, X ---------------- */
/*
 * Sized by the screen, not by a number I picked.
 *
 * The box was capped in pixels — 340 for a portrait player, 550 for a
 * quoted post — which is one size for a phone held in the hand and a
 * desk monitor alike. Too small on the desk, and on a narrow phone a
 * portrait clip ran taller than the screen, so the reader scrolled
 * through a video to reach the rest of the taushiyah.
 *
 * The rule below caps the HEIGHT and lets the width follow from it.
 * With aspect-ratio doing the shaping, a height budget becomes a width
 * budget by multiplying through the ratio: for a 9/16 player, 60svh of
 * height is 60svh * 9/16 of width. So the frame is as large as the
 * screen allows and never taller than it, on any device, without a
 * media query naming a single phone.
 *
 * svh, not vh: vh on a phone means the viewport with the browser bars
 * hidden, so a vh-sized video is taller than what is actually visible
 * until the reader scrolls. The vh line above it is the fallback for
 * anything too old to know svh.
 */
.a-embed { position: relative; width: 100%; margin-inline: auto;
           aspect-ratio: 16 / 9; background: #000;
           border-radius: 10px; overflow: hidden; }
.a-embed__frame { width: 100%; height: 100%; border: 0; display: block; }

/* Landscape: YouTube and Facebook video. */
.a-embed { max-width: calc(70vh * 16 / 9); }
.a-embed { max-width: calc(70svh * 16 / 9); }

/* Portrait players. Same idea, the other way up. */
.a-embed--tiktok, .a-embed--facebook_reel {
  aspect-ratio: 9 / 16;
  max-width: calc(70vh * 9 / 16);
}
.a-embed--tiktok, .a-embed--facebook_reel { max-width: calc(70svh * 9 / 16); }

/*
 * Instagram is a card, not a video.
 *
 * It was grouped with the vertical players, and it is not one: the embed
 * is a post — picture, caption, buttons — whose height depends on what
 * was written. Forced into a video's shape it rendered scrollbars inside
 * itself, which is what a card does when given less room than it needs.
 * Instagram will not lay out below about 320px, so that is the floor.
 */
.a-embed--instagram { aspect-ratio: auto; background: transparent;
  width: min(100%, 420px);
  height: clamp(480px, 62vh, 720px);
  height: clamp(480px, 62svh, 720px); }

/*
 * A quoted post is text, not video: its own height varies with how much
 * was written, so it keeps a height rather than a ratio. Bounded by the
 * screen at both ends — never taller than most of it, never so short
 * that the post is a scrolling slit.
 */
.a-embed--x { aspect-ratio: auto; background: transparent;
              width: min(100%, 550px);
              height: clamp(320px, 70vh, 620px);
              height: clamp(320px, 70svh, 620px); }

/*
 * In a dashboard panel the frame is a glance, not the article, so the
 * budget is a fraction of the screen rather than most of it. Still
 * proportional: a panel on a large monitor gets a larger frame, and one
 * on a phone does not swallow the dashboard.
 */
/*
 * Seventy per cent of the column it sits in, and centred.
 *
 * It used to be sized from the screen's HEIGHT — a third of it, turned
 * into a width through the aspect ratio — which left a clip about 180px
 * wide on a 1600px monitor, pinned to the left of a 924px column. That
 * is a thumbnail, not a video.
 *
 * Width first now, height as a ceiling. The ceiling is what stops a
 * portrait clip: 70% of that same column is 647px, and 647px of a 9:16
 * player is 1,150px tall — half as tall again as the screen it is on. So
 * landscape gets its full 70% and portrait gets as much as fits, which
 * is honest about the shape rather than obedient to the number.
 */
.a-embed--compact { width: 70%; max-width: 100%; margin: 8px auto; }
.a-embed--compact.a-embed--tiktok,
.a-embed--compact.a-embed--facebook_reel {
  aspect-ratio: 9 / 16;
  max-width: calc(80vh * 9 / 16);
}
/*
 * Floors, because proportional is not the same as usable.
 *
 * A portrait clip at a third of a short phone screen works out around
 * 115px wide — correct arithmetic, too small to see a face in. The two
 * card embeds need more than legibility: below roughly 320px Instagram
 * and X put scrollbars inside themselves, which reads as a broken
 * widget rather than a small one.
 */
/*
 * The height ceiling, in svh so it means the part of the screen actually
 * visible rather than the part behind the browser's own bars.
 *
 * 80svh of a 900px screen is 720px, which is 405px of width for a 9:16
 * player — wider than the 180px it had, narrower than the 647px that 70%
 * would ask for. That gap is the shape's doing, not the rule's.
 */
.a-embed--compact.a-embed--tiktok,
.a-embed--compact.a-embed--facebook_reel { max-width: max(150px, calc(80svh * 9 / 16)); }
/* The two card embeds keep a height of their own — they are posts whose
   height depends on what was written, not video with a fixed ratio — but
   they take the 70% width and the centring with everything else. */
.a-embed--compact.a-embed--instagram { max-width: 420px;
                                       height: clamp(400px, 62vh, 640px);
                                       height: clamp(400px, 62svh, 640px); }
.a-embed--compact.a-embed--x { max-width: 520px;
                               height: clamp(260px, 46vh, 520px);
                               height: clamp(260px, 46svh, 520px); }

/* An uploaded picture or video follows the same rule: bounded by the
   screen's height, never wider than its column. */
.a-tsy .a-tsy__media { display: block; margin: 8px 0; border-radius: 10px;
                       width: auto; max-width: 100%;
                       max-height: 32vh; max-height: 32svh; }

/* The two voluntary rows above Fajr. Set apart from the five below them
   with a lighter ground and no status buttons, so the eye reads them as
   a different kind of thing rather than as prayers missing their marks. */
/* The two voluntary prayers are rows in the prayer table now, so they are
   styled as rows: a lighter ground so the eye reads them as a different
   kind of thing, without pretending they are not part of the list. */
.a-table tr.is-voluntary > td { background: var(--deep-050, #eef4f1); }

/* The minutes after the adhan, beside the prayer's own time. Set below
   the time in weight and size: it is a note about the record, not a
   second time to read. */
/* Its own column now. Lighter than the prayer time beside it: it is a
   measurement of the record, not a second clock to read. */
.a-prayerrow__delta { color: var(--muted); font-weight: 600; white-space: nowrap; }

/* Three reminders in one panel ----------------------------------------- */
/* The older two are a list of what else is there, not things to read in
   full here — so they are set smaller and separated by a rule rather than
   repeating the first entry's weight three times over. */
.a-tsy__entry + .a-tsy__entry { border-top: 1px solid var(--line-2); margin-top: 10px; padding-top: 10px; }
.a-tsy__entry--rest .a-tsy__title { font-size: .92em; }
.a-tsy__entry--rest .a-mini__text { font-size: .88em; color: var(--muted); }
/* An unread one keeps its own mark even when the panel as a whole has
   been half read; without it, reading the newest would make the two
   below it look read as well. */
.a-tsy__entry.is-unread .a-tsy__title { font-weight: 700; }
.a-tsy__more { margin: 12px 0 0; font-size: .9em; }

/* Checklist steps with four states ------------------------------------- */
/* The state buttons sit to the right of the step so the titles stay in a
   readable column; on a phone they drop under it rather than squeezing
   the words into two characters a line. */
.a-steps__row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 4px 0; }
.a-steps__label { flex: 1 1 12em; min-width: 0; }
.a-steps__states { display: flex; gap: 4px; flex-wrap: wrap; }
.a-steps__row.is-done .a-steps__label { text-decoration: line-through; color: var(--muted); }
/* Not relevant is dimmed rather than struck through: it was not completed,
   it was set aside, and a line through it would claim otherwise. */
.a-steps__row.is-irrelevant .a-steps__label { opacity: .55; }
.a-steps__states .a-btn.is-on { box-shadow: inset 0 0 0 2px var(--deep); }

/* Compact list rows that open on demand -------------------------------- */
/* Used by the checklist screen for both templates and running lists: the
   row is for choosing between things, the panel underneath is for doing
   something with one of them. */
.a-clist { list-style: none; margin: 0; padding: 0; }
.a-clist__row { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap;
  padding: 10px 0; border-top: 1px solid var(--line-2); }
.a-clist__row:first-child { border-top: 0; }
.a-clist__main { flex: 1 1 16em; min-width: 0; }
.a-clist__main .a-hint { display: block; }
.a-clist__row.is-done .a-clist__main strong { color: var(--muted); }

/* The summary IS the button. list-style:none removes the browser's own
   triangle so it does not sit inside a button and read as two controls. */
.a-clist__more { flex: 0 0 auto; }
.a-clist__more > summary { list-style: none; cursor: pointer; display: inline-block; }
.a-clist__more > summary::-webkit-details-marker { display: none; }
/* Opened, the panel takes the full width of the row rather than the
   narrow column the summary sat in. */
.a-clist__more[open] { flex: 1 1 100%; margin-top: 8px; }
.a-clist__more[open] > summary { margin-bottom: 10px; }
.a-chk__preview { margin: 10px 0 0; padding-left: 1.2em; color: var(--muted); font-size: .9em; }

/* The SHL task frames --------------------------------------------------- */
/*
 * Two pages written to stand on their own, so each gets room to be
 * itself: the adder is a short form, the list is long and scrolls. Sized
 * from the screen rather than a fixed pixel height, like everything else
 * here.
 *
 * The box holds the height and hides the overflow. The frame inside is
 * laid out LARGER by the inverse of the zoom and then scaled down, so
 * that shrinking the content fills the same box instead of leaving it
 * three-quarters empty — which is what `zoom` or a bare transform on the
 * frame alone would have done.
 *
 * One class per step rather than a computed style attribute, because
 * this site sends style-src 'self' and an inline style would simply be
 * dropped by the browser.
 */
.a-shl__box { position: relative; overflow: hidden; border-radius: 8px; background: #fff; }
.a-shl__box--top    { height: min(560px, 60vh);  height: min(560px, 60svh); }
.a-shl__box--bottom { height: min(1100px, 82vh); height: min(1100px, 82svh); }
.a-shl__frame { display: block; border: 0; background: #fff;
  transform-origin: 0 0; width: 100%; height: 100%; }

.a-shl--z50  .a-shl__frame { width: 200.00%; height: 200.00%; transform: scale(.50); }
.a-shl--z60  .a-shl__frame { width: 166.67%; height: 166.67%; transform: scale(.60); }
.a-shl--z70  .a-shl__frame { width: 142.86%; height: 142.86%; transform: scale(.70); }
.a-shl--z80  .a-shl__frame { width: 125.00%; height: 125.00%; transform: scale(.80); }
.a-shl--z90  .a-shl__frame { width: 111.11%; height: 111.11%; transform: scale(.90); }
.a-shl--z100 .a-shl__frame { width: 100.00%; height: 100.00%; transform: none; }
.a-shl--z110 .a-shl__frame { width:  90.91%; height:  90.91%; transform: scale(1.10); }
.a-shl--z125 .a-shl__frame { width:  80.00%; height:  80.00%; transform: scale(1.25); }
.a-shl--z150 .a-shl__frame { width:  66.67%; height:  66.67%; transform: scale(1.50); }

/* Akhlak trait picker --------------------------------------------------- */
/* Thirty-odd traits in one column is a scroll; in columns it is a list
   somebody can read across and choose from. */
.a-akh__traits { display: grid; gap: 4px 16px;
  grid-template-columns: repeat(auto-fill, minmax(15em, 1fr)); }
.a-input--tiny { max-width: 6em; }

/* Journal --------------------------------------------------------------- */
.a-jr__moods { display: flex; gap: 10px 18px; flex-wrap: wrap; }
.a-jr__body { white-space: pre-wrap; margin: 8px 0 0; }
/* A strip of days, not a chart. No axis and no line: a slope drawn
   through a fortnight that had a funeral in it invites reading a trend
   into it, and hands somebody a second thing to feel bad about. */
.a-jr__strip { list-style: none; display: flex; gap: 3px; flex-wrap: wrap;
  margin: 0; padding: 0; }
.a-jr__day { width: 14px; height: 22px; border-radius: 3px;
  background: var(--line-2, #eef2f0); border: 1px solid var(--line, #dbe6e1); }
.a-jr__day--m1 { background: #c9a227; }
.a-jr__day--m2 { background: #d9c04a; }
.a-jr__day--m3 { background: #9fc7ae; }
.a-jr__day--m4 { background: #4fa87a; }
.a-jr__day--m5 { background: var(--leaf, #2fae6d); }
/* A day with writing in it gets a mark of its own, so an entry with no
   mood is still visibly an entry. */
.a-jr__day.has-text { box-shadow: inset 0 -4px 0 var(--deep, #0f5c46); }

/* Qur'an vocabulary ticker ---------------------------------------------- */
.a-qv__stage { min-height: 9em; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; text-align: center;
  padding: 18px 12px; background: var(--deep-050, #eef4f1); border-radius: 10px; }
/* The Arabic carries the screen, so it is set large enough to read at
   arm's length rather than at the size of body text. */
.a-qv__ar { font-size: clamp(34px, 28px + 2.2vw, 64px); line-height: 1.7; }
.a-qv__tr { font-size: clamp(15px, 14px + 0.3vw, 20px); color: var(--deep-800); }
/* The translation slot keeps its height while hidden, so revealing it
   does not jump the buttons underneath out from under a finger. */
.a-qv__tr[hidden] { display: block; visibility: hidden; }
.a-qv__speed { max-width: 22em; }
.a-perf__pctbig { font-size: clamp(26px, 22px + 1.2vw, 40px); font-weight: 650;
  color: var(--deep-800); line-height: 1.1; }
/* The verse a word was taken from. Set smaller and quieter than the
   reveal above it, because it is where the word lives — not what it
   means. */
.a-qv__ctx { font-size: .85em; color: var(--muted); max-width: 42em; line-height: 1.5; }
.a-qv__ctx[hidden] { display: block; visibility: hidden; }
/* Practice history: dates, with cancelled ones dimmed rather than hidden. */
.a-prac__hist { list-style: none; margin: 6px 0 0; padding: 0;
  display: grid; gap: 2px 14px; grid-template-columns: repeat(auto-fill, minmax(11em, 1fr)); }
.a-prac__hist .is-cancelled { color: var(--muted); }
/* The link out from a compact embed: present, but not competing with the
   player above it. */
.a-embed--compact + .a-embed__out { font-size: .82em; margin: 2px 0 0; }

/* The "keep me signed in" tick sits under the password, apart from the
   fields it is not one of. */
.a-login__remember { margin: 4px 0 14px; align-items: flex-start; }
.a-login__remember .a-hint { display: block; }
/* Something past its date. Named in words as well — the row says "overdue
   by 9 days" — so the colour is emphasis rather than the only signal. */
.a-clist__row.is-overdue .a-clist__main strong { color: #9c2f22; }
/* The script-free way past the Google button. Quiet — it is a fallback,
   not a competing choice — but a real link, not a footnote. */
.a-gsi__fallback { margin: 2px 0 8px; }
/* The provider readiness list: dense on purpose, it is a checklist. */
.a-table--tight td { padding: 4px 8px; }

/* The Jumu'ah map ------------------------------------------------------- */
/* Drawn on this server from coordinates already held: no tiles, no street
   names, nothing requested from anybody. What it shows is true — where the
   places sit relative to one another — and the distance across is printed
   beside it so the picture cannot be read as more precise than it is. */
.a-jmap { display: block; width: 100%; max-width: 520px; aspect-ratio: 1;
  margin: 8px auto; border-radius: 10px; }
.a-jmap__ground { fill: var(--deep-050, #eef4f1); }
.a-jmap__dot { fill: var(--deep, #0f5c46); fill-opacity: .82; }
.a-jmap__label { font-size: 4px; fill: var(--deep-800); }
/* The location control sits with the boxes it fills, and its message
   beside it rather than under — a line that appears below would push the
   rest of the form down each time it spoke. */
.a-geo { align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 6px; }
/* The birthday switch sits above the calendar, its state on its face —
   a tick when they are shown — because a button whose label never changes
   cannot say which way it is set. */
.a-bdswitch { margin: 0 0 10px; }
.a-bdswitch .a-btn.is-on { background: var(--deep-050, #eef4f1); border-color: var(--deep, #0f5c46); }

/* Overdue agenda entries ------------------------------------------------
 *
 * A <dialog>, so the browser handles the backdrop, the focus trap and
 * Escape. It is rendered with the `open` attribute and raised to a modal
 * by app.js; with scripts blocked it renders inline instead, which is
 * why these rules must look right in both — nothing here assumes a
 * backdrop exists.
 *
 * The width is capped at the readable measure rather than the viewport:
 * a row is a title and six controls, and stretched across a 27-inch
 * screen the controls end up a hand's width from the title they act on.
 */
.a-od {
  width: min(880px, calc(100vw - 32px));
  max-height: min(80vh, 720px);
  overflow-y: auto;
  padding: clamp(14px, 12.4px + 0.42vw, 24px);
  border: 1px solid var(--line);
  border-top: 4px solid var(--bad);
  border-radius: var(--radius);
  box-shadow: 0 18px 48px rgba(11, 70, 53, .22);
  background: var(--panel);
  color: var(--ink);
  margin: 16px auto;
}
.a-od::backdrop { background: rgba(11, 38, 31, .45); }
.a-od__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.a-od__head h2 { margin: 0; font-size: clamp(16px, 15px + 0.28vw, 21px); color: var(--bad); }
.a-od__note { margin: 6px 0 14px; color: var(--muted); font-size: 13px; max-width: 68ch; }
.a-od__list { list-style: none; margin: 0; padding: 0; }
.a-od__row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  padding: 10px 0; border-top: 1px solid var(--line-2);
}
.a-od__what { flex: 1 1 220px; min-width: 0; }
.a-od__title { display: block; font-weight: 650; font-size: 14px; }
.a-od__when { display: block; font-size: 12px; color: var(--muted); }
.a-od__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
/* The free date box is the one control that must not grow: beside five
   buttons it would take the whole row and push them onto a second line. */
.a-od__pick { width: 168px; flex: 0 0 168px; }
.a-od__pick .a-input { padding: 6px 8px; font-size: 13px; }
.a-od__more { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.a-od__foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line);
}
.a-od__foot .a-hint { margin: 0; flex: 1 1 240px; }

/* On a phone the row stacks: the entry above, its controls below, and
   the date box across the full width rather than squeezed to 168px. */
@media (max-width: 640px) {
  .a-od { width: calc(100vw - 16px); max-height: 92vh; margin: 8px auto; }
  .a-od__acts { width: 100%; }
  .a-od__pick { width: 100%; flex: 1 1 100%; }
}

/* Watch pairing -----------------------------------------------------
 * The code has to be readable at arm's length, because the other hand
 * is tapping a 40mm screen. Tabular figures so the two groups of three
 * stay in the same place as the digits change.
 */
.a-wt__code {
  margin: 4px 0 6px; font-size: clamp(34px, 28px + 2.2vw, 52px);
  font-weight: 700; letter-spacing: .08em; color: var(--deep);
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.a-wt__steps { margin: 14px 0 6px 18px; padding: 0; color: var(--ink-2); font-size: 14px; }
.a-wt__steps li { margin-bottom: 5px; }
