/* Design system.
 *
 * Calm, clear, health-first. One accent (indigo) for action and focus;
 * green, amber and rose only for meaning (done, late, missed). Both themes
 * are token sets on <html>, so dark mode is one attribute and the OS
 * preference is respected when the member has not chosen. Every offset is
 * logical (inline/block), so Persian mirrors the whole layout for free.
 */

/* `hidden` means hidden, whatever display a class gives the element. */
[hidden] { display: none !important; }

/* Persian: Vazirmatn, self-hosted (SIL OFL, see /fonts/Vazirmatn-OFL.txt). */
@font-face {
  font-family: 'Vazirmatn';
  src: url('/fonts/vazirmatn-arabic-wght-normal.woff2') format('woff2-variations'),
       url('/fonts/vazirmatn-arabic-wght-normal.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-08FF, U+200C-200E, U+2010-2011, U+FB50-FDFF, U+FE70-FEFC;
}
@font-face {
  font-family: 'Vazirmatn';
  src: url('/fonts/vazirmatn-latin-wght-normal.woff2') format('woff2-variations'),
       url('/fonts/vazirmatn-latin-wght-normal.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2212;
}

:root {
  --bg: #f4f6f9;
  --surface: #ffffff;
  --surface-2: #f2f4f8;
  --surface-3: #e8ecf2;
  --text: #0e1726;
  --text-dim: #5b6576;
  --text-faint: #8a93a4;
  --muted: var(--text-dim);
  --border: #e5e9f0;
  --border-strong: #d6dce5;
  --accent: #4f46e5;
  --accent-strong: #4338ca;
  --accent-text: #ffffff;
  --accent-soft: color-mix(in srgb, var(--accent) 11%, transparent);
  --ok: #129a52;
  --warn: #b86400;
  --danger: #d6344b;
  --radius: 18px;
  --radius-s: 12px;
  --gap: 12px;
  --shadow-1: 0 1px 2px rgb(16 24 40 / 0.05);
  --shadow: 0 1px 2px rgb(16 24 40 / 0.04), 0 6px 20px rgb(16 24 40 / 0.05);
  --shadow-3: 0 10px 36px rgb(16 24 40 / 0.14), 0 2px 6px rgb(16 24 40 / 0.06);
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --tabbar-h: 66px;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #0b0d12;
    --surface: #14171f;
    --surface-2: #1a1e28;
    --surface-3: #232835;
    --text: #edf0f6;
    --text-dim: #9ba4b4;
    --text-faint: #6f788a;
    --border: #252a36;
    --border-strong: #303747;
    --accent: #8e90fb;
    --accent-strong: #a5a7ff;
    --accent-text: #0b0d12;
    --ok: #3fd08a;
    --warn: #f0b04a;
    --danger: #ff6b7d;
    --shadow-1: none;
    --shadow: 0 1px 0 rgb(255 255 255 / 0.02) inset;
    --shadow-3: 0 12px 40px rgb(0 0 0 / 0.55);
    color-scheme: dark;
  }
}

:root[data-theme='dark'] {
  --bg: #0b0d12;
  --surface: #14171f;
  --surface-2: #1a1e28;
  --surface-3: #232835;
  --text: #edf0f6;
  --text-dim: #9ba4b4;
  --text-faint: #6f788a;
  --border: #252a36;
  --border-strong: #303747;
  --accent: #8e90fb;
  --accent-strong: #a5a7ff;
  --accent-text: #0b0d12;
  --ok: #3fd08a;
  --warn: #f0b04a;
  --danger: #ff6b7d;
  --shadow-1: none;
  --shadow: 0 1px 0 rgb(255 255 255 / 0.02) inset;
  --shadow-3: 0 12px 40px rgb(0 0 0 / 0.55);
  color-scheme: dark;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, 'SF Pro Text', 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

/* Persian: a typeface drawn for the script, and a little more line height. */
html[lang='fa'] body,
html[lang='fa'] button, html[lang='fa'] input, html[lang='fa'] select, html[lang='fa'] textarea {
  font-family: 'Vazirmatn', 'Segoe UI', Tahoma, system-ui, sans-serif;
}
html[lang='fa'] body { line-height: 1.75; }

.app {
  max-width: 560px;
  margin-inline: auto;
  padding: calc(14px + env(safe-area-inset-top)) 16px 28px;
}
body.has-tabs .app { padding-block-end: calc(var(--tabbar-h) + 34px + env(safe-area-inset-bottom)); }

/* A screen settles in rather than snapping: short, and never for a redraw. */
#root.enter > * { animation: rise 0.32s var(--ease) both; }
#root.enter > *:nth-child(2) { animation-delay: 0.03s; }
#root.enter > *:nth-child(3) { animation-delay: 0.06s; }
#root.enter > *:nth-child(n + 4) { animation-delay: 0.09s; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

header.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  margin-block: 4px 18px;
}

h1 { font-size: 1.55rem; line-height: 1.25; font-weight: 800; margin: 0; letter-spacing: -0.015em; }
h2 { font-size: 1.05rem; line-height: 1.35; font-weight: 700; margin: 0 0 10px; letter-spacing: -0.005em; }
h3 { font-size: 0.98rem; font-weight: 700; }
html[lang='fa'] h1, html[lang='fa'] h2 { letter-spacing: 0; }

.muted { color: var(--text-dim); font-size: 0.9rem; }
.center { text-align: center; }
a { color: var(--accent); text-underline-offset: 3px; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-block-end: var(--gap);
  box-shadow: var(--shadow);
}
.card > h2:first-child { font-size: 1rem; }

.row { display: flex; align-items: center; gap: var(--gap); }
.row.between { justify-content: space-between; }
.row.gap-s { gap: 6px; flex-wrap: wrap; }
.stack { display: flex; flex-direction: column; gap: var(--gap); }

/*
 * `a.button` exists so a control that navigates can look like a button without
 * pretending to be one: a link the browser can open in a new tab, middle-click
 * or read out as a link, rather than a button with an onclick that sets the
 * hash.
 */
button, a.button {
  font: inherit;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  padding: 10px 16px;
  cursor: pointer;
  min-height: 46px; /* comfortable tap target */
  box-shadow: var(--shadow-1);
  transition: transform 0.12s var(--ease), background-color 0.2s var(--ease), border-color 0.2s var(--ease), box-shadow 0.2s var(--ease), color 0.2s var(--ease);
  touch-action: manipulation;
}
a.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  box-sizing: border-box;
}
@media (hover: hover) {
  button:hover, a.button:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border-strong)); }
  button.primary:hover, a.button.primary:hover { background: var(--accent-strong); }
}
button:active, a.button:active { transform: scale(0.98); }
button:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, .chip:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--accent) 40%, transparent);
  outline-offset: 2px;
}

button.primary, a.button.primary {
  background: var(--accent);
  color: var(--accent-text);
  border-color: transparent;
  box-shadow: 0 1px 0 rgb(255 255 255 / 0.18) inset, 0 6px 18px color-mix(in srgb, var(--accent) 28%, transparent);
}
button.ghost, a.button.ghost { background: transparent; box-shadow: none; }
button.small, a.button.small { min-height: 38px; padding: 6px 12px; font-size: 0.88rem; border-radius: 12px; }
button.busy { position: relative; color: transparent !important; }
button.busy::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2.5px solid color-mix(in srgb, var(--accent-text) 35%, transparent);
  border-block-start-color: var(--accent-text);
  animation: spin 0.8s linear infinite;
}

input, select, textarea {
  font: inherit;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 11px 13px;
  width: 100%;
  min-height: 46px;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
input::placeholder, textarea::placeholder { color: var(--text-faint); }
label { display: block; font-size: 0.88rem; color: var(--text-dim); margin-block-end: 6px; font-weight: 500; }
.field { margin-block-end: 14px; }

/* Timeline ---------------------------------------------------------------- */

/*
 * Time and name on one line; actions on the next.
 *
 * Three columns across a phone leaves the buttons about ninety pixels each,
 * which truncates the labels and puts two tap targets within a thumb-width of
 * each other. The actions get their own row and the full width instead.
 */
.entry {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: 'time name' '. actions';
  align-items: center;
  gap: 8px var(--gap);
  padding: 13px 0;
  border-block-end: 1px solid var(--border);
}
.entry .time { grid-area: time; }
.entry .name { grid-area: name; }
.entry > .row:last-child { grid-area: actions; flex-wrap: wrap; }
.entry:last-child { border-block-end: none; }

@media (min-width: 480px) {
  /* Room for all three on one line. */
  .entry {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: 'time name actions';
  }
}

.entry .time {
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  font-size: 0.92rem;
  font-weight: 600;
  min-width: 3.5rem;
  padding: 3px 8px;
  border-radius: 8px;
  background: var(--surface-2);
  text-align: center;
}
.entry .name { font-weight: 600; }
.entry.done .name { text-decoration: line-through; text-decoration-color: var(--text-faint); color: var(--text-dim); }
.entry.done .time { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); }

.pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 600;
  line-height: 1.5;
  border: 1px solid transparent;
  background: var(--surface-2);
  color: var(--text-dim);
}
.pill.ok { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.pill.late, .pill.warn { color: var(--warn); background: color-mix(in srgb, var(--warn) 13%, transparent); }
.pill.missed { color: var(--danger); background: color-mix(in srgb, var(--danger) 11%, transparent); }
.pill.accent { color: var(--accent); background: var(--accent-soft); }

/* Progress ---------------------------------------------------------------- */

.meter {
  height: 10px;
  border-radius: 999px;
  background: var(--surface-3);
  overflow: hidden;
}
.meter > span {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.6s var(--ease);
}

.stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gap); }
.stat { padding: 10px 12px; border-radius: 14px; background: var(--surface-2); }
.stat .value { font-size: 1.35rem; font-weight: 750; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.stat .label { color: var(--text-dim); font-size: 0.8rem; font-weight: 500; }

/* Bottom navigation -------------------------------------------------------
 *
 * A floating bar with an icon and a label per section: the icon is what a
 * thumb aims at, the label is what makes it unambiguous in both languages.
 * The current section carries a soft pill behind its icon and the accent
 * colour — shape and colour, never colour alone. Safe-area aware, so it sits
 * above the iPhone home indicator.
 */

nav.tabs {
  position: fixed;
  inset-inline: 12px;
  inset-block-end: calc(10px + env(safe-area-inset-bottom));
  z-index: 50;
  max-width: 536px;
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 2px;
  padding: 6px;
  background: color-mix(in srgb, var(--surface) 84%, transparent);
  -webkit-backdrop-filter: saturate(1.6) blur(18px);
  backdrop-filter: saturate(1.6) blur(18px);
  border: 1px solid color-mix(in srgb, var(--border-strong) 70%, transparent);
  border-radius: 24px;
  box-shadow: var(--shadow-3);
  animation: tabs-in 0.35s var(--ease) both;
}
@keyframes tabs-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
nav.tabs a {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 54px;
  padding: 4px 2px;
  border-radius: 18px;
  text-decoration: none;
  color: var(--text-dim);
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1.2;
  transition: color 0.2s var(--ease);
}
nav.tabs .tab-icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 48px;
  height: 30px;
  border-radius: 999px;
  transition: background-color 0.25s var(--ease), transform 0.25s var(--ease);
}
nav.tabs svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
nav.tabs .tab-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
nav.tabs a[aria-current='page'] { color: var(--accent); }
nav.tabs a[aria-current='page'] .tab-icon { background: var(--accent-soft); }
nav.tabs a[aria-current='page'] svg { stroke-width: 2.1; }
nav.tabs a:active .tab-icon { transform: scale(0.9); }
nav.tabs .tab-badge {
  position: absolute;
  inset-block-start: -2px;
  inset-inline-end: 6px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 0.66rem;
  font-weight: 700;
  line-height: 17px;
  text-align: center;
  box-shadow: 0 0 0 2px var(--surface);
}

/* Banners ----------------------------------------------------------------- */

.banner {
  border-radius: 14px;
  padding: 11px 14px;
  margin-block-end: var(--gap);
  font-size: 0.92rem;
  line-height: 1.6;
  border: 1px solid transparent;
  border-inline-start-width: 4px;
}
.banner.info { border-color: color-mix(in srgb, var(--accent) 30%, transparent); background: color-mix(in srgb, var(--accent) 7%, var(--surface)); }
.banner.ok { border-color: color-mix(in srgb, var(--ok) 35%, transparent); background: color-mix(in srgb, var(--ok) 8%, var(--surface)); }
.banner.warn { border-color: color-mix(in srgb, var(--warn) 40%, transparent); background: color-mix(in srgb, var(--warn) 8%, var(--surface)); }
.banner.error { border-color: color-mix(in srgb, var(--danger) 35%, transparent); background: color-mix(in srgb, var(--danger) 7%, var(--surface)); }

/* Chat -------------------------------------------------------------------- */

.msg { padding: 10px 14px; border-radius: 20px; margin-block-end: 8px; max-width: 86%; line-height: 1.6; animation: rise 0.25s var(--ease) both; }
.msg.user { background: var(--accent); color: var(--accent-text); margin-inline-start: auto; border-end-end-radius: 6px; }
.msg.assistant { background: var(--surface-2); margin-inline-end: auto; white-space: pre-wrap; border-end-start-radius: 6px; }

.msg .source {
  display: block;
  width: fit-content;
  margin-block-end: 6px;
  font-size: 0.72rem;
}

/*
 * The seconds before the first token.
 *
 * A remote model can take several seconds to begin, and for those seconds a
 * disabled button and an empty bubble look exactly like a broken app. The
 * pulse is the difference between "it is working on it" and "nothing
 * happened"; it is removed the instant real text arrives, and the
 * reduced-motion rule below turns it into plain text for anyone who asked
 * for that.
 */
.msg .thinking {
  display: inline-block;
  color: var(--muted);
  font-style: italic;
  animation: pulse 1.4s ease-in-out infinite;
}

.msg .note {
  display: block;
  margin-block-start: 6px;
  font-size: 0.78rem;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

.chat-input { display: flex; gap: 8px; align-items: flex-end; }
.chat-input textarea, .chat-input input { border-radius: 22px; }
.chat-input textarea { resize: none; }
.chat-input button { border-radius: 22px; }

/* Respect a user who prefers less motion. */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

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

/* Routine adaptation review ------------------------------------------------
 *
 * Each proposal is a block with its own tick box, so accepting one change and
 * refusing another is a single tap each rather than an all-or-nothing choice.
 */

.proposal {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
  margin-block-start: 10px;
}
.proposal label { cursor: pointer; align-items: flex-start; }
.proposal input[type='checkbox'] {
  width: 22px;
  height: 22px;
  min-height: 22px;
  flex: none;
  accent-color: var(--accent);
}
.proposal .proposal-line { font-weight: 600; }
.proposal p { margin-block: 6px 0; }

p.small, span.small { font-size: 0.85rem; }

/* Dialogs ------------------------------------------------------------------
 *
 * `modal()` in lib/dom.js builds these. Without a stacking context above the
 * page the dialog renders in normal flow and the content behind it keeps
 * taking clicks, which is how a Save button ends up unpressable.
 */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: color-mix(in srgb, #000 55%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow-y: auto;
}
.modal-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 22px;
  padding: 20px;
  animation: sheet-in 0.3s var(--ease) both;
  width: min(640px, 100%);
  /* Tall forms scroll inside the dialog rather than off the screen. */
  max-height: calc(100vh - 32px);
  display: flex;
  flex-direction: column;
  box-shadow: 0 18px 48px rgb(0 0 0 / 0.35);
}
.modal-title { font-size: 1.15rem; margin: 0 0 12px; }
.modal-body { overflow-y: auto; flex: 1; min-height: 0; }
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-block-start: 14px;
  flex: none;
}

@media (max-width: 560px) {
  .modal-overlay { align-items: flex-end; padding: 0; }
  .modal-card {
    max-height: 92vh;
    border-radius: var(--radius) var(--radius) 0 0;
    width: 100%;
  }
}

/* Choice chips ------------------------------------------------------------
 *
 * One tap per answer. A select would be fewer pixels and more taps, and this
 * is a screen someone is using while standing in a shop.
 */

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  min-height: 42px;
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  color: var(--text-dim);
  font-size: 0.92rem;
  font-weight: 600;
  box-shadow: none;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease), color 0.2s var(--ease), transform 0.12s var(--ease);
}
.chip[aria-checked='true'] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.field { margin-block-end: var(--gap); }
.field label { display: block; font-size: 0.85rem; color: var(--text-dim); margin-block-end: 6px; }
.stat .delta { font-size: 0.8rem; font-variant-numeric: tabular-nums; }

/* The overdue prompt ------------------------------------------------------
 *
 * The largest thing on the screen, because it is the one thing the app is
 * waiting on. It sits in the flow rather than over it: a modal that has to be
 * dismissed to reach the rest of the app is how a reminder becomes a nag.
 */

.reminder {
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 7%, var(--surface)), var(--surface) 60%);
  border: 1.5px solid color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: 22px;
  padding: 20px 18px;
  margin-block-end: var(--gap);
  box-shadow: 0 10px 30px color-mix(in srgb, var(--accent) 16%, transparent);
  animation: rise 0.35s var(--ease) both;
}
.reminder-when {
  margin: 0;
  font-size: 0.85rem;
  color: var(--accent);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.reminder-title { font-size: 1.5rem; margin: 6px 0 2px; line-height: 1.3; }
.reminder-ask { margin: 0 0 14px; color: var(--text-dim); }
.reminder-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.reminder-actions button, .reminder-actions .button { flex: 1 1 auto; min-width: 110px; }
.reminder-actions button.primary { flex-basis: 100%; min-height: 52px; font-size: 1.05rem; }
.reminder-more { margin-block-start: 12px; margin-block-end: 0; font-size: 0.85rem; }

/* Feature lists -----------------------------------------------------------
 *
 * What a plan includes, and what it does not. The distinction is carried by a
 * mark and a colour, and also by the text itself — colour alone is not a way
 * to tell someone what they have.
 */

.feature-list { list-style: none; margin: 0; padding: 0; }
.feature-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 6px 0;
  font-size: 0.95rem;
}
.feature-list li::before { flex: none; font-weight: 700; }
.feature-list li.has::before { content: '✓'; color: var(--ok); }
.feature-list li.missing::before { content: '—'; color: var(--text-dim); }
.feature-list li.missing { color: var(--text-dim); }

/* Charts ------------------------------------------------------------------
 *
 * Shared with the consoles through lib/charts.js, so the member app needs the
 * same handful of rules. Kept here rather than in console.css because this is
 * the stylesheet both entry points load.
 */

/* Chart tokens, defined once for every page that draws one. */
:root {
  --chart-bar: color-mix(in srgb, var(--accent) 55%, transparent);
  --chart-area: color-mix(in srgb, var(--accent) 14%, transparent);
  /* Up is not good news on a weight chart, and this is where that is decided. */
  --chart-up: var(--danger);
  --chart-down: var(--ok);
}

.chart { margin: 0; }
.chart svg { width: 100%; display: block; }
.chart-empty {
  padding: 24px;
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--text-dim);
  font-size: 0.9rem;
}
.chart-caption {
  display: flex;
  justify-content: space-between;
  font-size: 0.82rem;
  padding-block-start: 6px;
  color: var(--text-dim);
}
.chart-caption .up { color: var(--chart-up); }
.chart-caption .down { color: var(--chart-down); }

/* Weekly report -----------------------------------------------------------
 *
 * A trend's direction is carried by a word and a mark, not by colour alone.
 */

.report-headline { font-size: 1.05rem; margin: 10px 0 4px; }
.trend-list { list-style: none; margin: 10px 0; padding: 0; }
.trend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  padding: 6px 0;
  border-block-end: 1px solid var(--border);
  font-size: 0.92rem;
}
.trend:last-child { border-block-end: none; }
.trend strong::before { margin-inline-end: 6px; }
.trend.up strong::before { content: '▲'; color: var(--ok); }
.trend.down strong::before { content: '▼'; color: var(--danger); }
.trend.flat strong::before { content: '—'; color: var(--text-dim); }

/*
 * A measurement reads left-to-right whatever language surrounds it.
 *
 * "0 / 1800" is a left-to-right construction. Its digits are bidi-neutral, so
 * inside a Persian sentence the browser reorders them and the screen shows
 * "1800 / 0" — the same two numbers, swapped, on exactly the figure someone is
 * checking. `dir="ltr"` on the element and an isolate here keep it intact
 * without affecting anything around it.
 */
.measurement {
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
}

/* Two facts side by side, without a character between them that a reader
   could mistake for a digit. */
.history-meta { gap: 10px; }

/* Plan intake, plan editing and onboarding --------------------------------
 *
 * These screens are the ones a member uses while standing up, one-handed,
 * holding a printed plan in the other hand. Everything below is sized for a
 * 390px viewport first and only widens where there is room, and every offset
 * is logical, so the whole set mirrors for Persian without a second rule.
 */

/* A heading with its own way in, side by side. */
.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  margin-block-end: 8px;
}
.section-head h2 { margin: 0; }
.add-plan { flex: none; white-space: nowrap; }

/*
 * A plan row is a name, a state and its actions.
 *
 * `.entry` places a time column that a plan has not got, so the row opts out
 * of that grid and stacks instead: name and pill on one line, buttons under
 * them where a thumb can reach both without hitting the wrong one.
 */
.plan-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px var(--gap);
}
.plan-row-main { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1 1 auto; }
.plan-row-main .name { overflow-wrap: anywhere; }
.plan-row-actions { display: flex; flex-wrap: wrap; gap: 8px; }

/*
 * The four ways in, as four equals.
 *
 * Full-width rows rather than a grid of small tiles: the label has to say what
 * the method is in whatever language the app is running in, and a Persian
 * label does not fit in a quarter of a phone screen.
 */
.intake-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-block: var(--gap);
}
.intake-option {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 64px;
  padding: 12px 14px;
  text-align: start;
  background: var(--surface-2);
}
.intake-option:hover { border-color: var(--accent); }
.intake-glyph { flex: none; font-size: 1.6rem; line-height: 1; }
.intake-label { display: block; font-weight: 600; font-size: 1.02rem; }
.intake-hint { display: block; font-size: 0.85rem; color: var(--text-dim); }

/* A full-width control, for the stacked actions under a form. */
.block { display: block; width: 100%; margin-block-start: 10px; }

/* The editors ------------------------------------------------------------- */

.plan-editor { display: flex; flex-direction: column; }
.editor-section { font-size: 1.05rem; margin: 14px 0 8px; }

/*
 * One card per meal, per session, per exercise.
 *
 * A meal has nine fields. As table columns that is about forty pixels each on
 * a phone; as a card it is a form someone can actually fill in, and adding
 * the tenth meal does not make the ninth harder to read.
 */
.editor-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
  margin-block-end: 10px;
}
.editor-card.nested { background: var(--surface); }
.editor-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  margin-block-end: 10px;
}
.editor-card-head h3, .editor-card-head h4 { margin: 0; font-size: 1rem; }

.repeater { display: flex; flex-direction: column; }
.add-row { width: 100%; }

.field-label {
  display: block;
  font-size: 0.85rem;
  color: var(--text-dim);
  margin-block-end: 6px;
}

/*
 * Numbers that belong together, as many per line as fit.
 *
 * The fields align on their inputs rather than on their labels: "Protein (g)"
 * wraps to two lines where "Fat (g)" does not, and in Persian a different
 * pair wraps — so aligning on the top of the label leaves a row of boxes at
 * three different heights in one language and three others in the next.
 */
.macro-grid, .field-pair {
  display: grid;
  gap: 0 10px;
}
.macro-grid { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
.field-pair { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.macro-grid .field, .field-pair .field {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* Seven days, one row, one tap each. */
.weekday-row { display: flex; flex-wrap: wrap; gap: 6px; }
.weekday-row .chip { flex: 1 1 auto; min-width: 40px; padding: 8px 4px; text-align: center; }
.chip.on {
  background: color-mix(in srgb, var(--accent) 18%, var(--surface-2));
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 500;
}

/* A single answer out of a handful, without a native select. */
.choice-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.choice {
  min-height: 44px;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 0.95rem;
}
.choice.on {
  background: color-mix(in srgb, var(--accent) 18%, var(--surface-2));
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 500;
}

/* Removing something is never the accent colour. */
.danger {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 40%, transparent);
}

/* Onboarding -------------------------------------------------------------- */

.onboard { display: flex; flex-direction: column; }
.onboard-title { font-size: 1.5rem; font-weight: 800; margin: 8px 0 12px; line-height: 1.3; }
.onboard-progress { display: flex; flex-direction: column; gap: 6px; }

/*
 * The bar fills from the reading edge.
 *
 * A flex track places its child at the inline start, so the fill grows from
 * the right in Persian and the left in English with no direction-specific
 * rule and no transform to get backwards.
 */
.progress-track {
  display: flex;
  height: 8px;
  border-radius: 999px;
  background: var(--surface-3);
  overflow: hidden;
}
.progress-fill { background: var(--accent); border-radius: 999px; transition: width 0.5s var(--ease); }

.onboard-plan { display: flex; flex-direction: column; }

/* Profile, body measurements, notifications ------------------------------- */

.back-link {
  font-size: 1.6rem;
  line-height: 1;
  text-decoration: none;
  color: var(--text-dim);
  padding: 4px 8px;
}
/* The chevron points back along the reading direction. */
[dir='rtl'] .back-link { transform: scaleX(-1); display: inline-block; }

.profile-form .card h2 { margin-block-end: 12px; }
.profile-form select, .profile-form input { width: 100%; }
.pill.locked { display: inline-block; margin-block-end: var(--gap); white-space: normal; }

.measure-form { display: flex; flex-direction: column; }
.measure-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--gap);
}
.measure-field.extra { display: none; }
.measure-grid.show-extra .measure-field.extra { display: block; }
.measure-field .field-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.input-unit { display: flex; align-items: center; gap: 6px; }
.input-unit input { flex: 1 1 auto; min-width: 0; width: 100%; }
.input-unit .unit { color: var(--text-dim); font-size: 0.85rem; flex: 0 0 auto; }
input[aria-invalid='true'] { border-color: var(--danger); }
.measure-form > .ghost.small { align-self: flex-start; margin-block-end: var(--gap); }

.body-stats { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); margin-block: 12px; }
.insights { margin: 12px 0 4px; padding-inline-start: 18px; }
.insights li { margin-block-end: 6px; line-height: 1.5; }
.insight.weight_down_muscle_down, .insight.goal_mismatch_weight_up,
.insight.goal_mismatch_muscle_down { color: var(--warn); }
.accuracy { margin-block-start: 10px; line-height: 1.5; }

.body-chart h3 { font-size: 0.95rem; margin: 8px 0 4px; }
.measure-list { list-style: none; margin: 0; padding: 0; }
.measure-item { padding-block: 12px; border-block-end: 1px solid var(--border); }
.measure-item:last-child { border-block-end: 0; }
.measure-values { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.measure-values .chip { cursor: default; font-size: 0.85rem; }

/* A measurement sheet scrolls inside itself on a phone. */
.modal-overlay.sheet .modal-card { max-height: 92vh; }

/* Opened from a notification: the activity it was about. */
.entry.focused {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 12px;
}

.push-kv { display: grid; grid-template-columns: 1fr auto; gap: 8px var(--gap); margin-block-end: 12px; }
.push-kv dt { color: var(--text-dim); }
.push-kv dd { margin: 0; font-weight: 600; text-align: end; }
.device-list { list-style: none; margin: 0 0 12px; padding: 0; }
.device-list li { padding-block: 6px; border-block-end: 1px solid var(--border); font-size: 0.9rem; }
.button-stack { display: flex; flex-direction: column; gap: 8px; }
.button-stack > * { width: 100%; }
.onboard-choice { display: flex; flex-direction: column; gap: 8px; margin-block-end: var(--gap); }

/* Device setup: install the app, then notifications ------------------------ */

.setup-page {
  min-height: calc(100dvh - 32px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  max-width: 480px;
  margin-inline: auto;
  padding-block: 24px;
}
.setup-brand { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-block-end: 6px; }
.setup-logo { border-radius: 22px; box-shadow: 0 10px 34px color-mix(in srgb, var(--accent) 30%, transparent), 0 2px 6px rgb(0 0 0 / 0.12); }
.setup-name { font-weight: 700; letter-spacing: 0.02em; color: var(--text-dim); }
.setup-title { font-size: 1.6rem; font-weight: 800; line-height: 1.35; text-align: center; margin: 0; }
.setup-lead { text-align: center; color: var(--text-dim); line-height: 1.7; margin: 0 0 6px; }
button.large { min-height: 54px; font-size: 1.05rem; font-weight: 600; }
.setup-guide { display: flex; flex-direction: column; gap: 12px; }
.setup-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.setup-step {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 13px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  line-height: 1.65;
  box-shadow: var(--shadow-1);
}
.setup-step-no {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 800;
  font-size: 0.9rem;
}
.setup-area { display: flex; flex-direction: column; gap: 12px; }
.setup-progress { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.setup-progress-row { display: flex; align-items: center; gap: 10px; color: var(--text-dim); }
.setup-progress-row.ok { color: var(--ok); }
.setup-progress-row.fail { color: var(--warn); }
.setup-progress-row.wait { color: var(--text); }
.setup-progress-mark { width: 22px; text-align: center; font-weight: 700; }

/* Start-up placeholder, shown before the language is known. */
#boot { text-align: center; letter-spacing: 0.3em; margin-top: 30vh; animation: boot-pulse 1.2s ease-in-out infinite; }
@keyframes boot-pulse { 50% { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) { #boot { animation: none; } }

@keyframes sheet-in { from { opacity: 0; transform: translateY(14px) scale(0.99); } to { opacity: 1; transform: none; } }
@keyframes spin { to { transform: rotate(360deg); } }

.spinner {
  display: inline-block;
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2.5px solid color-mix(in srgb, var(--accent) 22%, transparent);
  border-block-start-color: var(--accent);
  animation: spin 0.8s linear infinite;
}

/* Installing: Android ----------------------------------------------------- */

.install-host { display: flex; flex-direction: column; gap: 12px; }
.install-cta { min-height: 58px; font-size: 1.1rem; border-radius: 18px; }
.install-progress {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  font-weight: 600;
}
details.install-alt {
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--surface);
  padding: 4px 14px;
}
details.install-alt > summary {
  cursor: pointer;
  list-style: none;
  padding: 10px 0;
  font-weight: 600;
  color: var(--accent);
}
details.install-alt > summary::-webkit-details-marker { display: none; }
details.install-alt > summary::after { content: '▾'; float: inline-end; transition: transform 0.2s var(--ease); }
details.install-alt[open] > summary::after { transform: rotate(180deg); }
details.install-alt[open] { padding-block-end: 12px; }

/* Installing: iPhone and iPad walkthrough ---------------------------------- */

.ios-install { display: flex; flex-direction: column; gap: 12px; }
.ios-walk {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 22px;
  padding: 20px 18px 16px;
  box-shadow: var(--shadow);
  text-align: center;
  animation: rise 0.3s var(--ease) both;
}
.ios-walk-count { font-size: 0.78rem; font-weight: 700; color: var(--accent); letter-spacing: 0.02em; }
.ios-walk-title { font-size: 1.2rem; margin: 10px 0 6px; }
.ios-walk-text { margin: 0 0 12px; color: var(--text-dim); line-height: 1.7; }
.ios-art {
  width: 108px;
  height: 108px;
  margin: 14px auto 4px;
  display: grid;
  place-items: center;
  border-radius: 28px;
  background: var(--accent-soft);
  color: var(--accent);
}
.ios-art svg { width: 58px; height: 58px; }
.ios-art-confirm { width: 170px; }
.ios-art-confirm svg { width: 140px; height: 76px; }
.ios-art-icon { background: transparent; gap: 6px; height: auto; }
.ios-art-icon img { border-radius: 16px; box-shadow: 0 8px 24px rgb(0 0 0 / 0.18); }
.ios-art-icon span { font-size: 0.8rem; font-weight: 600; color: var(--text); }
.ios-dots { display: flex; justify-content: center; gap: 6px; margin: 6px 0 12px; }
.ios-dots span { width: 7px; height: 7px; border-radius: 999px; background: var(--surface-3); transition: width 0.25s var(--ease), background-color 0.25s var(--ease); }
.ios-dots span.on { width: 22px; background: var(--accent); }
.ios-walk-nav { display: flex; justify-content: space-between; gap: 10px; }
.ios-walk-nav button { flex: 1 1 0; }

/* Where Share is: under the page on an iPhone, top right on an iPad. Physical
   positions on purpose: Safari's toolbar does not mirror with the page. */
.ios-pointer {
  position: fixed;
  z-index: 60;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 40%, transparent);
  pointer-events: none;
}
.ios-pointer::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 12px;
  height: 12px;
  border-inline-end: 3px solid var(--accent-text);
  border-block-end: 3px solid var(--accent-text);
  transform: translateY(-2px) rotate(45deg);
}
.ios-pointer.at-bottom { left: calc(50% - 23px); bottom: calc(12px + env(safe-area-inset-bottom)); animation: nudge-down 1.2s var(--ease) infinite; }
.ios-pointer.at-top { right: 18px; top: calc(12px + env(safe-area-inset-top)); animation: nudge-up 1.2s var(--ease) infinite; }
.ios-pointer.at-top::after { transform: translateY(2px) rotate(-135deg); }
@keyframes nudge-down { 50% { transform: translateY(6px); } }
@keyframes nudge-up { 50% { transform: translateY(-6px); } }

/* Meal replacement -------------------------------------------------------- */

.ingredient-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 12px; }
.ingredient {
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-size: 0.82rem;
  color: var(--text);
}
.safety-note { display: flex; align-items: center; gap: 8px; margin-block: 0 12px; }

@media (prefers-reduced-motion: reduce) {
  .ios-pointer { animation: none !important; }
}

.empty-state { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 18px 8px; text-align: center; }
.empty-state .button { min-width: 180px; }

/* Coaching notes: a suggestion the member can take or leave. */
.coach-note {
  margin-block: 4px 12px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.coach-note:empty { display: none; }
.coach-note p { margin: 0; line-height: 1.65; }
.field-note { margin: -8px 0 12px; }
.food-rule.allergy .field-label::before { content: '⚠ '; color: var(--danger); }
.food-rule.allergy input { border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); }

/* Professionals: cards, consent lists, the two slots, conversations -------- */

.pro-card { display: flex; gap: 14px; align-items: flex-start; }
.pro-avatar {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 16px;
  display: grid;
  place-items: center;
  font-weight: 800;
  font-size: 1.2rem;
  color: var(--accent);
  background: var(--accent-soft);
}
.pro-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.pro-main p { margin: 0; }
.pro-name { font-weight: 750; font-size: 1.05rem; overflow-wrap: anywhere; }
.scope-list { list-style: none; margin: 4px 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.scope-list li { display: flex; gap: 8px; align-items: flex-start; font-size: 0.88rem; line-height: 1.55; }
.scope-list li.no { color: var(--text-faint); }
.scope-mark { flex: none; width: 20px; height: 20px; border-radius: 6px; display: grid; place-items: center; font-size: 0.72rem; font-weight: 800; }
.scope-list li.yes .scope-mark { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok); }
.scope-list li.no .scope-mark { background: var(--surface-2); }
.pro-slot { padding-block: 14px; border-block-start: 1px solid var(--border); display: flex; flex-direction: column; gap: 10px; }
.pro-slot:first-of-type { border-block-start: 0; }
.slot-head h3 { margin: 0; font-size: 0.95rem; color: var(--text-dim); text-transform: none; }
.id-entry { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: end; }
.id-entry .field { margin: 0; }
.id-entry input { font-variant-numeric: tabular-nums; letter-spacing: 0.08em; }
.badge {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  margin-inline-start: 6px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 800;
}
.pro-entry { margin-block-start: 16px; text-align: center; }
.pro-entry .row { justify-content: center; }
.history-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.history-list li { display: flex; flex-direction: column; gap: 2px; }
blockquote.note {
  margin: 8px 0;
  padding: 10px 14px;
  border-radius: 14px;
  background: var(--surface-2);
  border-inline-start: 3px solid var(--accent);
}
blockquote.note p { margin: 0 0 4px; }
.thread-card { min-height: 40vh; display: flex; flex-direction: column; }
.pro-thread { display: flex; flex-direction: column; gap: 2px; }
.msg-time { display: block; margin-block-start: 4px; font-size: 0.7rem; opacity: 0.7; }
.msg-ref { display: inline-block; margin-block-end: 6px; }
.msg.user .msg-ref { background: rgb(255 255 255 / 0.2); color: inherit; }

/* ── Coach: the first visit ── */
.coach-intro { display: grid; gap: 8px; padding: 6px 2px; }
.coach-intro-title { font-weight: 600; font-size: 1.02rem; line-height: 1.6; margin: 0; }
.coach-intro .muted { margin: 0; }
.coach-intro .suggestions { display: flex; flex-direction: column; align-items: stretch; gap: 8px; margin-block-start: 6px; }
.coach-intro .suggestions .chip { text-align: start; white-space: normal; line-height: 1.5; min-height: 44px; }
