/* ==========================================================================
   goals-app — styles.css
   Identity: paper and ink, one thread of deep teal. Calm, unhurried, for years.
   Every colour, size, radius and duration a view may use is a token below; the
   markup for every component is in docs/UI-KIT.md. Views add no colours, radii
   or font sizes.

   House rules this file keeps (and views must too):
   - logical properties only (inline/block, start/end), never physical sides
   - text-align: start; hover only under @media (hover: hover)
   - transitions name their properties; nothing animates without a reason, and
     prefers-reduced-motion flattens all of it (end of file)
   - boxes are sized by their content: min-height, never a fixed height on text
   - buttons are rounded rectangles in three sizes (52/44/36, r16/12/10,
     15/14/13 px), weight 600; no circles anywhere in the identity
   ========================================================================== */

/* ---------- Tokens: theme-invariant ---------- */
:root {
  --font: 'Readex Pro', system-ui, -apple-system, 'Segoe UI', Tahoma, 'Geeza Pro', 'Noto Sans Arabic', sans-serif;

  /* Type scale. Arabic first: 16 px body at a generous line height. */
  --fs-xs: 13px;    /* meta, tags, counters, level labels */
  --fs-sm: 14px;    /* secondary text, hints, field labels, list meta */
  --fs-md: 16px;    /* body, inputs (never smaller: iOS zooms a smaller field) */
  --fs-lg: 18px;    /* card and section titles, sheet titles */
  --fs-xl: 22px;    /* view title, the due card's headline */
  --fs-2xl: 28px;   /* one hero figure per screen (a review's percent) */
  --fs-btn-l: 15px;
  --fs-btn-m: 14px;
  --fs-btn-s: 13px;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;   /* the ceiling; the font itself stops at 700 */

  --lh-tight: 1.35; /* titles */
  --lh-ui: 1.45;    /* labels, buttons, single lines */
  --lh-body: 1.7;   /* running text; Arabic needs the room. English: 1.55 below */

  /* Spacing rhythm */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;
  --gutter: 16px;
  --view-max: 560px;

  /* Sizes and radii */
  --btn-h-l: 52px;
  --btn-h-m: 44px;
  --btn-h-s: 36px;
  --touch: 44px;
  --radius-btn-l: 16px;
  --radius-btn-m: 12px;
  --radius-btn-s: 10px;
  --radius-card: 16px;   /* = the large button */
  --radius-field: 12px;  /* = the medium button */
  --radius-sheet: 20px;
  --radius-tag: 6px;
  --radius-mark: 3px;
  --radius-bar: 2px;     /* also the small squares: loading dots, bullets */
  --radius-thumb: 7px;   /* the switch thumb and the chooser tick */

  /* Motion */
  --dur-fast: 150ms;
  --dur-base: 200ms;
  --dur-slow: 250ms;
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);

  /* Layers */
  --z-bar: 10;
  --z-modal: 200;
  --z-toast: 300;

  /* The switch thumb travels toward inline-end */
  --switch-shift: 20px;
}
:root[lang="en"] { --lh-body: 1.55; }
:root[dir="rtl"] { --switch-shift: -20px; }
@media (min-width: 400px) { :root { --gutter: 20px; } }

/* ---------- Tokens: dark (the default surface) ----------
   Contrast, measured (docs/UI-KIT.md has the full table): text 15.9:1 on bg; text-2 8.9;
   text-3 6.3 (5.4 on surface-2); accent 8.7 on bg, 7.5 on surface-2; on-accent 7.9 on
   accent; warn 9.8; danger 7.7; control edges (line-strong) 3.3 on surface-1. */
:root, body.theme-dark {
  color-scheme: dark;
  --bg: #0e1312;
  --surface-1: #151b1a;   /* cards, sheets, lists */
  --surface-2: #1b2322;   /* fields, wells, segmented track, tags */
  --surface-3: #242e2c;   /* pressed */
  --seg-on: #313e3b;      /* the chosen segment in a neutral segmented control */
  --track: #2c3836;       /* progress track */
  --line: #253130;        /* hairlines that separate (decorative) */
  --line-strong: #5f6e6a; /* control edges: 3.3:1 on surface-1 */

  --text: #e7eeeb;
  --text-2: #a9b6b2;
  --text-3: #8b9894;

  --accent: #5cc2ac;
  --accent-hover: #74cfbb;
  --accent-press: #4bb19b;
  --on-accent: #05211b;
  --accent-soft: rgba(92, 194, 172, 0.14);
  --accent-line: rgba(92, 194, 172, 0.38);
  --ring: rgba(92, 194, 172, 0.35);

  --warn: #e2b45e;
  --warn-soft: rgba(226, 180, 94, 0.12);
  --warn-line: rgba(226, 180, 94, 0.40);

  --danger: #f08a7e;
  --danger-hover: #f4a197;
  --danger-press: #e57769;
  --on-danger: #2a0c08;
  --danger-soft: rgba(240, 138, 126, 0.12);
  --danger-line: rgba(240, 138, 126, 0.40);

  --field-bg: #1b2322;
  --switch-off: #5f6e6a;
  --switch-thumb: #e7eeeb;
  --switch-thumb-on: #05211b;
  --scrim: rgba(4, 8, 7, 0.66);
  --toast-bg: #2b3634;
  --toast-fg: #eef3f1;
  --toast-action: #7fd6c3;
  --toast-warn: #e9c27a;
  --toast-error: #f4a197;
  --toast-press: rgba(255, 255, 255, 0.10);
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.45);
  --shadow-2: 0 12px 32px rgba(0, 0, 0, 0.5);
}

/* ---------- Tokens: light ----------
   Contrast, measured: text 15.3:1 on bg; text-2 7.0; text-3 5.8 (5.4 on surface-2);
   accent 6.0 on bg, 5.6 on surface-2; white on accent 6.6; warn 5.7; danger 6.0;
   control edges (line-strong) 3.1 on bg. */
body.theme-light {
  color-scheme: light;
  --bg: #f6f5f1;
  --surface-1: #ffffff;
  --surface-2: #eeece6;
  --surface-3: #e3e1da;
  --seg-on: #ffffff;
  --track: #e0ddd5;
  --line: #e4e2db;
  --line-strong: #858e8b;

  --text: #17201e;
  --text-2: #4a5653;
  --text-3: #57625f;

  --accent: #17695a;
  --accent-hover: #125a4d;
  --accent-press: #0f4f43;
  --on-accent: #ffffff;
  --accent-soft: rgba(23, 105, 90, 0.09);
  --accent-line: rgba(23, 105, 90, 0.32);
  --ring: rgba(23, 105, 90, 0.28);

  --warn: #855800;
  --warn-soft: rgba(196, 140, 30, 0.13);
  --warn-line: rgba(133, 88, 0, 0.35);

  --danger: #b02a20;
  --danger-hover: #9c241b;
  --danger-press: #8a1f17;
  --on-danger: #ffffff;
  --danger-soft: rgba(176, 42, 32, 0.08);
  --danger-line: rgba(176, 42, 32, 0.32);

  --field-bg: #ffffff;
  --switch-off: #858e8b;
  --switch-thumb: #ffffff;
  --switch-thumb-on: #ffffff;
  --scrim: rgba(23, 32, 30, 0.38);
  --toast-bg: #1e2826;
  --toast-fg: #f1f4f3;
  --toast-action: #86dcc8;
  --toast-warn: #e9c27a;
  --toast-error: #f4a197;
  --toast-press: rgba(255, 255, 255, 0.10);
  --shadow-1: 0 1px 2px rgba(23, 32, 30, 0.14), 0 1px 1px rgba(23, 32, 30, 0.06);
  --shadow-2: 0 12px 32px rgba(23, 32, 30, 0.16), 0 2px 6px rgba(23, 32, 30, 0.06);
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* A focused field scrolls clear of the sticky .actionbar (12 + 52 + 12 px and the safe
     area), with a little air; on a page without one it simply stops short of the edge. */
  scroll-padding-block-end: calc(var(--btn-h-l) + var(--sp-6) + env(safe-area-inset-bottom));
}
/* The bar's one-line reason (.actionbar__note) makes it taller: room for two lines of it. */
html:has(.view:not([hidden]) > .actionbar > .actionbar__note:not([hidden])) {
  scroll-padding-block-end: calc(var(--btn-h-l) + var(--sp-7) + var(--sp-6) + env(safe-area-inset-bottom));
}
html.has-modal { overflow: hidden; }
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-md);
  font-weight: var(--fw-regular);
  line-height: var(--lh-body);
  text-align: start;
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}
h1, h2, h3, h4, p, ul, ol, dl, dd, figure, fieldset { margin: 0; }
ul, ol { padding: 0; list-style: none; }
fieldset { padding: 0; border: 0; min-inline-size: 0; }
button, input, select, textarea { font: inherit; color: inherit; letter-spacing: inherit; }
button { cursor: pointer; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
::selection { background: var(--accent-soft); }
bdi { unicode-bidi: isolate; }

.sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Layout ---------- */
#app { min-height: 100vh; min-height: 100dvh; }
.view {
  inline-size: 100%;
  max-inline-size: var(--view-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-block-start: max(var(--sp-2), env(safe-area-inset-top));
  padding-block-end: calc(var(--sp-7) + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}
.view:has(> .actionbar) { padding-block-end: 0; }

.stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.stack--1 { gap: var(--sp-1); }
.stack--2 { gap: var(--sp-2); }
.stack--3 { gap: var(--sp-3); }
.stack--5 { gap: var(--sp-5); }
.stack--6 { gap: var(--sp-6); }
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.cluster--end { justify-content: flex-end; }
.cluster > .btn--grow { flex: 1 1 auto; }

/* App header: a back button and, optionally, actions at the end. The view title is
   its own line below (a goal title can be long; it wraps, never truncates). */
.appbar {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-block-size: var(--btn-h-m);
  margin-inline: calc(var(--sp-2) * -1);
}
.appbar__end { display: flex; align-items: center; gap: var(--sp-1); margin-inline-start: auto; }
.view-head { display: flex; flex-direction: column; gap: var(--sp-1); }
.view-title {
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
}
.view-sub { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-ui); }

/* A titled group of content */
.section { display: flex; flex-direction: column; gap: var(--sp-3); }
.section__head { display: flex; align-items: center; gap: var(--sp-2); min-block-size: var(--btn-h-s); }
.section__title {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
}
.section__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-2);
  line-height: var(--lh-ui);
  padding-inline: var(--sp-1);
}

/* Sticky action bar at the end of a long form (check-in Next / Confirm, plan Approve) */
.actionbar {
  position: sticky;
  inset-block-end: 0;
  z-index: var(--z-bar);
  margin-inline: calc(var(--gutter) * -1);
  margin-block-start: auto;
  padding-block: var(--sp-3) calc(var(--sp-3) + env(safe-area-inset-bottom));
  padding-inline: var(--gutter);
  background: var(--bg);
  border-block-start: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.actionbar > .btn { flex: 1 1 0; }
.actionbar__note { flex: 1 1 100%; font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-ui); }

/* ---------- Text ---------- */
.text-sm { font-size: var(--fs-sm); line-height: var(--lh-ui); }
.text-xs { font-size: var(--fs-xs); line-height: var(--lh-ui); }
.muted { color: var(--text-2); }
.faint { color: var(--text-3); }
.num { font-variant-numeric: tabular-nums; }
.strong { font-weight: var(--fw-semibold); }
.prose { line-height: var(--lh-body); white-space: pre-line; }

/* ---------- Icons ---------- */
.icon {
  inline-size: 20px;
  block-size: 20px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
[dir="rtl"] .icon--flip { transform: scaleX(-1); }

/* ---------- Buttons ----------
   .btn + one size (.btn--l | .btn--m | .btn--s) + one variant
   (.btn--primary | .btn--secondary | .btn--quiet | .btn--danger | .btn--danger-quiet).
   min-height, so a long label wraps and the button grows rather than clipping. */
.btn {
  --btn-h: var(--btn-h-m);
  --btn-r: var(--radius-btn-m);
  --btn-fs: var(--fs-btn-m);
  --btn-px: var(--sp-4);
  --btn-fg: var(--text);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-block-size: var(--btn-h);
  padding-block: var(--sp-1);
  padding-inline: var(--btn-px);
  margin: 0;
  border: 1px solid transparent;
  border-radius: var(--btn-r);
  background: transparent;
  color: var(--btn-fg);
  font-size: var(--btn-fs);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-ui);
  text-decoration: none;
  user-select: none;
  -webkit-user-select: none;
  transition:
    background-color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}
.btn .icon { inline-size: 20px; block-size: 20px; }
.btn--l { --btn-h: var(--btn-h-l); --btn-r: var(--radius-btn-l); --btn-fs: var(--fs-btn-l); --btn-px: var(--sp-5); }
.btn--m { --btn-h: var(--btn-h-m); --btn-r: var(--radius-btn-m); --btn-fs: var(--fs-btn-m); --btn-px: var(--sp-4); }
.btn--s { --btn-h: var(--btn-h-s); --btn-r: var(--radius-btn-s); --btn-fs: var(--fs-btn-s); --btn-px: var(--sp-3); }
.btn--s .icon { inline-size: 18px; block-size: 18px; }
.btn--s.btn--icon { inline-size: var(--touch); }
/* No min-width on .btn: a flex row may shrink a button only to its own label, never
   below it. Width for touch comes from padding (a .btn--s label is a word, never a
   single glyph: that is .btn--icon). A 36 px button answers a 44 px touch through a
   halo 5 px beyond each block edge. The halo never reaches past the inline edges, so
   it adds nothing to scrollWidth (the flow test's clipping check). */
.btn--s::after { content: ""; position: absolute; inset-block: -5px; inset-inline: 0; }
.btn--icon { flex: none; padding-inline: 0; inline-size: var(--btn-h); }
.btn--block { display: flex; inline-size: 100%; }
/* In a column a button keeps its own width; only .btn--block spans the line. */
:where(.card, .stack, .section, .plan-sec, .item, .due__actions, .modal__body, .callout__body, .view) > .btn:not(.btn--block) { align-self: flex-start; }
.btn:active { transform: translateY(1px); }

.btn--primary { --btn-fg: var(--on-accent); background: var(--accent); }
.btn--primary:active { background: var(--accent-press); }
.btn--secondary { border-color: var(--line-strong); }
.btn--secondary:active { background: var(--surface-3); }
.btn--quiet { --btn-fg: var(--text); }
.btn--quiet:active { background: var(--surface-3); }
.btn--danger { --btn-fg: var(--on-danger); background: var(--danger); }
.btn--danger:active { background: var(--danger-press); }
.btn--danger-quiet { --btn-fg: var(--danger); }
.btn--danger-quiet:active { background: var(--danger-soft); }

@media (hover: hover) {
  .btn--primary:hover { background: var(--accent-hover); }
  .btn--secondary:hover { background: var(--surface-2); }
  .btn--quiet:hover { background: var(--surface-2); }
  .btn--danger:hover { background: var(--danger-hover); }
  .btn--danger-quiet:hover { background: var(--danger-soft); }
}

.btn:disabled,
.btn[aria-disabled="true"]:not(.is-busy) { opacity: 0.45; cursor: not-allowed; transform: none; }
.btn[aria-disabled="true"] { cursor: not-allowed; }

/* Loading: the label keeps the button's width; three quiet squares take its place. */
.btn.is-busy { color: transparent; cursor: progress; transform: none; }
.btn.is-busy > * { visibility: hidden; }
.btn.is-busy::before {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: 6px;
  block-size: 6px;
  margin-block-start: -3px;
  margin-inline-start: -3px;
  border-radius: var(--radius-bar);
  background: var(--btn-fg);
  box-shadow: -11px 0 0 var(--btn-fg), 11px 0 0 var(--btn-fg);
  animation: pulse 900ms var(--ease) infinite alternate;
}

/* The reason a button is disabled, directly under it */
.reason { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-ui); }

/* A text-only control inside running text */
.link {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font-weight: var(--fw-medium);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: var(--sp-2); min-inline-size: 0; }
.field__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
  color: var(--text);
}
.field__label .faint { font-weight: var(--fw-regular); }
/* The label line with an action at its end (a milestone label and its remove button) */
.field__head { display: flex; align-items: center; gap: var(--sp-2); min-block-size: var(--btn-h-s); }
.field__head > .field__label { flex: 1 1 auto; min-inline-size: 0; }
.field__head > .btn { flex: none; }
.field__foot { display: flex; align-items: baseline; gap: var(--sp-3); }
.field__hint {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
  color: var(--text-2);
}
.field__count {
  flex: none;
  margin-inline-start: auto;
  font-size: var(--fs-xs);
  line-height: var(--lh-ui);
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.field__count.is-near { color: var(--warn); }
.field__count.is-over { color: var(--danger); font-weight: var(--fw-semibold); }
/* For short fields (a unit): the count appears only from 90% of the limit. */
.field__count--near:not(.is-near):not(.is-over) { display: none; }
.field__error {
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
  color: var(--danger);
}

.input,
.textarea,
.select {
  display: block;
  inline-size: 100%;
  min-block-size: var(--btn-h-l);
  margin: 0;
  padding-block: var(--sp-3);
  padding-inline: 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-field);
  background: var(--field-bg);
  color: var(--text);
  font-size: var(--fs-md);
  line-height: 1.5;
  text-align: start;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.input::placeholder,
.textarea::placeholder { color: var(--text-3); opacity: 1; }
.input:focus,
.textarea:focus,
.select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.input[aria-invalid="true"],
.textarea[aria-invalid="true"],
.select[aria-invalid="true"],
.input.is-over,
.textarea.is-over { border-color: var(--danger); }
.input[aria-invalid="true"]:focus,
.textarea[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--danger-soft); }
.input:disabled,
.textarea:disabled,
.select:disabled { opacity: 0.55; cursor: not-allowed; }
.input[readonly] { background: var(--surface-2); }

.textarea {
  resize: none;
  min-block-size: calc(1.5em * 2 + var(--sp-3) * 2 + 2px);
  field-sizing: content;
}
.textarea--1 { min-block-size: var(--btn-h-l); }

/* Numbers read LTR in both languages; in Arabic they keep to the end edge.
   Use type="text" inputmode="decimal" (Shapes.parseNumber reads Arabic digits). */
.input--num { font-variant-numeric: tabular-nums; }
[dir="rtl"] .input--num { direction: ltr; text-align: end; }

/* Native date and time pickers, aligned to start like every other field */
.input::-webkit-date-and-time-value { text-align: start; }
.input::-webkit-calendar-picker-indicator { opacity: 0.7; cursor: pointer; }

/* Select: a chevron at the inline end, drawn without a background-position */
.select-wrap { position: relative; display: block; }
.select-wrap::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: 16px;
  inline-size: 12px;
  block-size: 12px;
  margin-block-start: -6px;
  background: var(--text-2);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 4.5 6 8.5l4-4' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 4.5 6 8.5l4-4' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  pointer-events: none;
}
.select { padding-inline-end: 44px; cursor: pointer; }

/* A field with an action inside its end edge (password Show / Hide) */
.input-group { position: relative; display: block; }
.input-group > .input { padding-inline-end: 84px; }
.input-group__action {
  position: absolute;
  inset-block-start: 4px;
  inset-inline-end: 4px;
}

/* Number fields in a row: start / target / unit. Three to a row on six tracks; below a
   300 px row (a 375 px phone's quarter result is 283) a number needs more than a third, so
   start and target share the row and the unit takes its own. Any child counts, so a lone
   input (the check-in's reading) is a third, or a half when narrow. */
.field-row {
  container: field-row / inline-size;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--sp-3) var(--sp-2);   /* a folded row's label sits nearer its own field than the one above */
}
.field-row > * { grid-column: span 2; min-inline-size: 0; }
@container field-row (max-width: 299px) {
  .field-row > * { grid-column: span 3; }
  .field-row > :nth-child(3) { grid-column: 1 / -1; }
}
.field-row .field__label { font-size: var(--fs-xs); color: var(--text-2); }

/* ---------- Segmented control ----------
   Radios in a track. Neutral by default (settings); .seg--accent fills the chosen
   answer with the accent (yes / partly / no). Track 52 / r16; segments 44 / r12 / 14px. */
.seg {
  display: flex;
  gap: var(--sp-1);
  padding: var(--sp-1);
  border-radius: var(--radius-btn-l);
  background: var(--surface-2);
}
.seg__opt { position: relative; flex: 1 1 0; min-inline-size: 0; display: flex; }
.seg__input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}
.seg__label {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-block-size: var(--btn-h-m);
  padding-block: var(--sp-1);
  padding-inline: var(--sp-2);
  border-radius: var(--radius-btn-m);
  color: var(--text-2);
  font-size: var(--fs-btn-m);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-ui);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
/* The chosen neutral segment: the lifted surface alone is 1.44:1 (dark) / 1.18:1 (light)
   on the track, so a 2 px inset ring in text-3 carries the state: 3.73 / 6.33 against the
   segment, 5.36 / 5.36 against the track (text-2 measured louder than the accent answer in
   dark). The accent variant needs no ring: its fill is 7.46 / 5.55 on the track. */
.seg__input:checked + .seg__label { background: var(--seg-on); color: var(--text); box-shadow: inset 0 0 0 2px var(--text-3), var(--shadow-1); }
.seg--accent .seg__input:checked + .seg__label { background: var(--accent); color: var(--on-accent); box-shadow: none; }
@media (forced-colors: active) {
  .seg__input:checked + .seg__label { outline: 2px solid CanvasText; outline-offset: -2px; }
}
.seg__input:focus-visible + .seg__label { outline: 2px solid var(--accent); outline-offset: 2px; }
.seg__input:disabled + .seg__label { opacity: 0.45; cursor: not-allowed; }
@media (hover: hover) {
  .seg__input:not(:checked):not(:disabled) + .seg__label:hover { color: var(--text); background: var(--surface-3); }
}

/* ---------- Switch ----------
   A checkbox with role="switch" inside a .row--switch label (the row is the target). */
.switch {
  position: relative;
  flex: none;
  inline-size: 52px;
  block-size: 32px;
  margin: 0;
  border: 0;
  border-radius: var(--radius-btn-s);
  background: var(--switch-off);
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  transition: background-color var(--dur-base) var(--ease);
}
.switch::before {
  content: "";
  position: absolute;
  inset-block-start: 4px;
  inset-inline-start: 4px;
  inline-size: 24px;
  block-size: 24px;
  border-radius: var(--radius-thumb);
  background: var(--switch-thumb);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-base) var(--ease), background-color var(--dur-base) var(--ease);
}
.switch:checked { background: var(--accent); }
.switch:checked::before { transform: translateX(var(--switch-shift)); background: var(--switch-thumb-on); }
.switch:disabled { opacity: 0.45; cursor: not-allowed; }

/* ---------- Card ---------- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}
@media (min-width: 400px) { .card { padding: 20px; } }
.card__title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); line-height: var(--lh-tight); }
.card__text { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-body); }
.card__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* A whole card that opens something: the title holds a .stretch button whose ::after
   covers the card. Anything else interactive inside sits above it (.card__above). */
.stretch {
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: start;
}
.stretch::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-card); }
.stretch:focus-visible { outline: none; }
.card:has(.stretch:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.card:has(.stretch) { transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease); }
.card:has(.stretch:active) { background: var(--surface-2); }
.card__above { position: relative; z-index: 1; }
@media (hover: hover) {
  .card:has(.stretch):hover { border-color: var(--line-strong); }
}
/* Without :has() (Safari before 15.4, Firefox before 121) the card's and the row's ring above
   never draws: the stretch's own cover carries it instead, the same shape in the same place. */
@supports not selector(:has(*)) {
  .stretch:focus-visible::after { outline: 2px solid var(--accent); outline-offset: 2px; }
  .cm-row .stretch:focus-visible::after { outline-offset: -2px; border-radius: 0; }
}

/* A repeated block inside a card (a quarter result, a conflict answer set) */
.item {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-field);
}

/* ---------- Tags and outcome marks ---------- */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  min-block-size: 24px;
  padding-inline: var(--sp-2);
  border-radius: var(--radius-tag);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
}
.tag--accent { background: var(--accent-soft); color: var(--accent); }
.tag--warn { background: var(--warn-soft); color: var(--warn); }

/* Yes = filled, partly = half filled from inline-start, no = an empty frame. The word
   always sits beside the mark (UI.outcome): colour never carries the meaning alone. */
.outcome { display: inline-flex; align-items: center; gap: 6px; }
.mark {
  position: relative;
  flex: none;
  display: inline-block;
  inline-size: 10px;
  block-size: 10px;
  border: 1.5px solid var(--accent);
  border-radius: var(--radius-mark);
  overflow: hidden;
}
.mark--yes { background: var(--accent); }
.mark--partly::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 50%;
  background: var(--accent);
}
.mark--no { border-color: var(--text-3); }

/* ---------- Progress bar ---------- */
.bar {
  display: block;
  inline-size: 100%;
  block-size: 4px;
  border: 0;
  border-radius: var(--radius-bar);
  background: var(--track);
  color: var(--accent);
  overflow: hidden;
  appearance: none;
  -webkit-appearance: none;
}
.bar::-webkit-progress-bar { background: var(--track); border-radius: var(--radius-bar); }
.bar::-webkit-progress-value { background: var(--accent); border-radius: var(--radius-bar); }
.bar::-moz-progress-bar { background: var(--accent); border-radius: var(--radius-bar); }
.bar--l { block-size: 8px; }

/* ---------- Home: the due card ----------
   The first thing on Home. States: .due--checkin | --restart | --review (accent tint),
   .due--none (plain), .due--conflict (warn tint). .due__status carries the send state. */
.due {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: 20px var(--sp-4) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}
.due--checkin,
.due--restart,
.due--review { background: var(--accent-soft); border-color: var(--accent-line); }
.due--conflict { background: var(--warn-soft); border-color: var(--warn-line); }
.due__eyebrow {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
  color: var(--text-2);
}
.due--checkin .due__eyebrow,
.due--restart .due__eyebrow,
.due--review .due__eyebrow { color: var(--accent); }
.due__title {
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
}
.due--none .due__title { font-size: var(--fs-lg); }
.due__text { font-size: var(--fs-sm); line-height: var(--lh-body); color: var(--text-2); }
.due--checkin .due__text,
.due--restart .due__text,
.due--review .due__text,
.due--conflict .due__text { color: var(--text); }
.due__attach { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-block-start: var(--sp-2); }
.due__status {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-block-start: var(--sp-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
  color: var(--text-2);
}
.due__status .icon { inline-size: 18px; block-size: 18px; }
.due__status--conflict { color: var(--warn); font-weight: var(--fw-medium); }
.due__status--error { color: var(--danger); }
.due__actions { display: flex; flex-direction: column; gap: var(--sp-2); margin-block-start: var(--sp-3); }

/* ---------- Goal card ---------- */
.goal-card { container: goal / inline-size; }
.goal-card__head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
.goal-card__title {
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
}
.goal-card__step {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}
.goal-card__step-k { font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--text-2); line-height: var(--lh-ui); }

/* The five levels: week (last outcome), month, quarter, year, overall.
   A null level shows "—" in --text-3 and draws no bar. */
.levels {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--sp-3) var(--sp-3);
  padding-block-start: var(--sp-3);
  border-block-start: 1px solid var(--line);
}
.lvl { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
.lvl__k { font-size: var(--fs-xs); line-height: var(--lh-ui); color: var(--text-2); }
.lvl__v {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-ui);
  font-variant-numeric: tabular-nums;
}
.lvl--week .lvl__v { font-size: var(--fs-sm); }
.lvl.is-empty .lvl__v { color: var(--text-3); font-weight: var(--fw-regular); }
.lvl__bar { margin-block-start: var(--sp-1); }
@container goal (max-width: 340px) {
  .levels { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .lvl--week { grid-column: 1 / -1; flex-direction: row; align-items: baseline; gap: var(--sp-2); }
}
@container goal (max-width: 220px) {
  .levels { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* A single figure with its label and an optional bar (the review's level percent) */
.stat { display: flex; flex-direction: column; gap: var(--sp-1); }
.stat__k { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-ui); }
.stat__v {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums;
}
.stat__v.is-empty { color: var(--text-3); font-weight: var(--fw-regular); }

/* Definition lines: goal fields, answer sets */
.facts { display: flex; flex-direction: column; gap: var(--sp-3); }
.fact { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
.fact__k { font-size: var(--fs-xs); color: var(--text-2); line-height: var(--lh-ui); }
.fact__v { font-size: var(--fs-md); line-height: var(--lh-body); white-space: pre-line; }

/* ---------- Callout ---------- */
.callout {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-2);
}
.callout > .icon { margin-block-start: 2px; color: var(--text-2); }
.callout__body { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: var(--sp-1); }
.callout__title { font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: var(--lh-tight); }
.callout__text { font-size: var(--fs-sm); line-height: var(--lh-body); }
.callout__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-block-start: var(--sp-2); }
.callout--info { background: var(--accent-soft); border-color: var(--accent-line); }
.callout--info > .icon { color: var(--accent); }
.callout--warn { background: var(--warn-soft); border-color: var(--warn-line); }
.callout--warn > .icon { color: var(--warn); }
.callout--error { background: var(--danger-soft); border-color: var(--danger-line); }
.callout--error > .icon { color: var(--danger); }

/* ---------- One-line hint banner ---------- */
.hint {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: var(--btn-h-l);
  padding-block: var(--sp-1);
  padding-inline: var(--sp-4) var(--sp-1);
  border-radius: var(--radius-field);
  background: var(--surface-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
}
.hint__text { flex: 1 1 auto; min-inline-size: 0; padding-block: var(--sp-2); }

/* ---------- Lists and rows ---------- */
.list {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}
.list > * + * { border-block-start: 1px solid var(--line); }
.row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  inline-size: 100%;
  min-block-size: var(--btn-h-l);
  margin: 0;
  padding-block: var(--sp-3);
  padding-inline: var(--sp-4);
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: start;
  text-decoration: none;
}
.list > .row:first-child { border-start-start-radius: var(--radius-card); border-start-end-radius: var(--radius-card); }
.list > .row:last-child { border-end-start-radius: var(--radius-card); border-end-end-radius: var(--radius-card); }
.row__main { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }
.row__title { font-size: var(--fs-md); line-height: var(--lh-ui); }
.row__meta { font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--text-2); }
.row__end {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  max-inline-size: 55%;
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.row__end > .icon { color: var(--text-3); }
.row__note { flex: 1 1 100%; font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--text-2); }
.row--wrap { flex-wrap: wrap; }
.row--stack { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
.row--danger .row__title { color: var(--danger); }
button.row, a.row, label.row { cursor: pointer; transition: background-color var(--dur-fast) var(--ease); }
button.row:active, a.row:active, label.row:active { background: var(--surface-2); }
.list > .row:focus-visible { outline-offset: -2px; }
@media (hover: hover) {
  button.row:hover, a.row:hover, label.row:hover { background: var(--surface-2); }
}

/* ---------- Plan editor ---------- */
.plan-sec { display: flex; flex-direction: column; gap: var(--sp-3); }
.plan-sec__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--sp-1) var(--sp-2); }
.plan-sec__title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); line-height: var(--lh-tight); }
.plan-sec__period { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-ui); }

/* One milestone: its field and a remove button at the inline end */
.ms-row { display: flex; align-items: flex-start; gap: var(--sp-2); }
.ms-row > .field { flex: 1 1 auto; }
.ms-row__remove { flex: none; }

/* A quarter result with its measure editor */
.result.is-flagged { border-color: var(--warn-line); background: var(--warn-soft); }
.result__flag {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
  color: var(--warn);
  font-weight: var(--fw-medium);
}
.result__flag .icon { inline-size: 18px; block-size: 18px; margin-block-start: 1px; }

/* ---------- Review ---------- */
.rv-group { display: flex; flex-direction: column; gap: var(--sp-2); }
.rv-group__title { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text-2); line-height: var(--lh-ui); }
.rv-line {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}
.rv-line > .mark { align-self: center; }
.rv-line__text { flex: 1 1 auto; min-inline-size: 0; }
.rv-line__fig { flex: none; color: var(--text-2); font-variant-numeric: tabular-nums; }
.rv-line--moved .rv-line__fig { color: var(--text); font-weight: var(--fw-medium); }
.rv-line--stalled .rv-line__text { color: var(--text-2); }
.counts { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--text-2); }
.counts__n { color: var(--text); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
.sub-lines { display: flex; flex-direction: column; gap: var(--sp-1); }
.sub-line { display: flex; justify-content: space-between; gap: var(--sp-3); font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--text-2); }
.sub-line__v { color: var(--text); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
.suggest { display: flex; flex-direction: column; gap: var(--sp-3); }
.suggest__item {
  position: relative;
  padding-inline-start: var(--sp-4);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
}
.suggest__item::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.7em;
  inline-size: 6px;
  block-size: 6px;
  border-radius: var(--radius-bar);
  background: var(--accent);
}

/* ---------- Conflict chooser ----------
   Per goal, two answer sets as radio cards: stacked on a phone, side by side from a
   440 px container. The newer one is checked by default. */
.conflict { display: flex; flex-direction: column; gap: var(--sp-3); container: conflict / inline-size; }
.conflict__title { font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: var(--lh-tight); }
.conflict__note { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-ui); }
.choices { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-2); }
@container conflict (min-width: 440px) { .choices { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.choice { position: relative; display: flex; cursor: pointer; }
.choice__input { position: absolute; inset: 0; margin: 0; opacity: 0; pointer-events: none; }
.choice__body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-field);
  background: var(--surface-1);
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.choice__head { display: flex; align-items: center; gap: var(--sp-2); min-block-size: 24px; }
.choice__name { flex: 1 1 auto; min-inline-size: 0; font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: var(--lh-ui); }
.choice__meta { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.choice__tick {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 22px;
  block-size: 22px;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-thumb);
  color: transparent;
}
.choice__tick .icon { inline-size: 16px; block-size: 16px; stroke-width: 2.25; }
.choice__input:checked + .choice__body { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: var(--accent-soft); }
.choice__input:checked + .choice__body .choice__tick { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.choice__input:focus-visible + .choice__body { outline: 2px solid var(--accent); outline-offset: 2px; }
.answers { display: flex; flex-direction: column; gap: var(--sp-2); }
.answer { display: flex; flex-direction: column; gap: 0; min-inline-size: 0; }
.answer__k { font-size: var(--fs-xs); color: var(--text-2); line-height: var(--lh-ui); }
.answer__v { font-size: var(--fs-sm); line-height: var(--lh-body); white-space: pre-line; }

/* ---------- Empty state ---------- */
.empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
  padding-block: var(--sp-6) var(--sp-4);
}
.empty__title { font-size: var(--fs-xl); font-weight: var(--fw-semibold); line-height: var(--lh-tight); }
.empty__text { font-size: var(--fs-md); color: var(--text-2); line-height: var(--lh-body); max-inline-size: 36em; }
.empty__action { margin-block-start: var(--sp-3); }

/* ---------- Loading ---------- */
.loading {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-block-size: var(--btn-h-m);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
  color: var(--text-2);
}
.dots { display: inline-flex; align-items: center; gap: 5px; flex: none; }
.dots > span {
  inline-size: 6px;
  block-size: 6px;
  border-radius: var(--radius-bar);
  background: var(--accent);
  animation: pulse 900ms var(--ease) infinite alternate;
}
.dots > span:nth-child(2) { animation-delay: 150ms; }
.dots > span:nth-child(3) { animation-delay: 300ms; }

.skel {
  display: block;
  border-radius: var(--radius-tag);
  background: var(--surface-2);
  animation: breathe 1600ms ease-in-out infinite;
}
.skel--title { block-size: 22px; inline-size: 60%; }
.skel--line { block-size: 14px; inline-size: 100%; }
.skel--short { inline-size: 40%; }
.skel--block { block-size: 96px; border-radius: var(--radius-card); }
.skel-group { display: flex; flex-direction: column; gap: var(--sp-3); }

/* ---------- Toast ---------- */
#toast-root {
  position: fixed;
  z-index: var(--z-toast);
  inset-inline: 0;
  inset-block-end: 0;
  display: flex;
  justify-content: center;
  padding-inline: var(--gutter);
  padding-block-end: calc(var(--sp-4) + env(safe-area-inset-bottom));
  pointer-events: none;
}
html:not(.has-modal) body:has(.view:not([hidden]) > .actionbar) #toast-root { padding-block-end: calc(88px + env(safe-area-inset-bottom)); }
/* A sheet owns the bottom of the screen (its action row), so while one is open the toast
   rides at the top instead. Derived from html.has-modal: no state of its own, and a page
   without a sheet never meets this rule. */
html.has-modal #toast-root {
  inset-block: 0 auto;
  padding-block: calc(var(--sp-4) + env(safe-area-inset-top)) 0;
}
html.has-modal .toast:not(.is-in) { transform: translateY(-8px); }
.toast {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  inline-size: 100%;
  max-inline-size: 480px;
  min-block-size: var(--btn-h-l);
  padding-block: var(--sp-1);
  padding-inline: var(--sp-4) var(--sp-1);
  border-radius: var(--radius-card);
  background: var(--toast-bg);
  color: var(--toast-fg);
  box-shadow: var(--shadow-2);
  pointer-events: auto;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.toast.is-in { opacity: 1; transform: none; }
.toast__mark { flex: none; display: flex; color: var(--toast-action); }
.toast--warn .toast__mark { color: var(--toast-warn); }
.toast--error .toast__mark { color: var(--toast-error); }
.toast__msg { flex: 1 1 auto; min-inline-size: 0; padding-block: var(--sp-2); font-size: var(--fs-sm); line-height: var(--lh-ui); }
.toast__action.btn { --btn-fg: var(--toast-action); flex: none; }
@media (hover: hover) { .toast__action.btn:hover { background: var(--toast-press); } }
.toast__action.btn:active { background: var(--toast-press); }
/* The one moment of delight: a confirmation's check draws itself. */
.toast--ok .toast__icon path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: draw 360ms var(--ease) 120ms forwards; }

/* ---------- Modal / bottom sheet ---------- */
.overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: var(--scrim);
  animation: fade-in var(--dur-base) var(--ease);
}
.overlay.is-out { pointer-events: none; animation: fade-out var(--dur-base) var(--ease-in) forwards; }
.modal {
  display: flex;
  flex-direction: column;
  inline-size: 100%;
  max-inline-size: var(--view-max);
  max-block-size: calc(100dvh - var(--sp-5));
  padding-block-end: env(safe-area-inset-bottom);
  border-start-start-radius: var(--radius-sheet);
  border-start-end-radius: var(--radius-sheet);
  background: var(--surface-1);
  color: var(--text);
  box-shadow: var(--shadow-2);
  outline: none;
  animation: sheet-in var(--dur-slow) var(--ease);
}
.overlay.is-out .modal { animation: sheet-out var(--dur-base) var(--ease-in) forwards; }
.modal__head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding-block: var(--sp-4) var(--sp-2);
  padding-inline: var(--gutter) var(--sp-2);
  min-block-size: 60px;
}
.modal__title {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
}
.modal__head:not(:has(.btn)) { padding-inline-end: var(--gutter); }
.modal__body {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding-block: var(--sp-2);
  padding-inline: var(--gutter);
}
.modal__text { font-size: var(--fs-md); line-height: var(--lh-body); color: var(--text-2); }
.modal__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  padding-block: var(--sp-4);
  padding-inline: var(--gutter);
}
.modal__actions > .btn { flex: 1 1 8rem; }
@media (min-width: 600px) {
  .overlay { align-items: center; padding: var(--sp-5); }
  .modal {
    max-inline-size: 480px;
    max-block-size: calc(100dvh - var(--sp-7));
    padding-block-end: 0;
    border-radius: var(--radius-sheet);
    animation-name: dialog-in;
  }
  .overlay.is-out .modal { animation-name: dialog-out; }
}

/* ---------- Auth ---------- */
.auth { display: flex; flex-direction: column; gap: var(--sp-5); padding-block-start: var(--sp-6); }
.brand { font-size: var(--fs-2xl); font-weight: var(--fw-semibold); line-height: var(--lh-tight); }
.brand__mark {
  display: inline-block;
  inline-size: 10px;
  block-size: 10px;
  margin-inline-start: var(--sp-2);
  border-radius: var(--radius-mark);
  background: var(--accent);
  vertical-align: 0.15em;
}

/* ==========================================================================
   Slice 2: commitments with their own rhythm (docs/UI-KIT.md, "Commitments").
   Existing tokens only. Done reads as calm completion: a soft accent tint, never a
   burst. The streak is small and quiet, never a badge, and never drawn at zero.
   ========================================================================== */

/* ---------- Home: the today card ----------
   One card under the due card. States: rows due | all done (.today-card__note above
   the done rows) | nothing today (.today-card--none: one quiet line, no head).
   Rows run edge to edge like a .list, so a pressed row fills the card's width. */
.today-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}
.today-card__head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-4) var(--sp-1);
}
.today-card__title {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
}
.today-card__note {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-4) var(--sp-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
  color: var(--text-2);
}
.today-card__note > .icon { inline-size: 18px; block-size: 18px; margin-block-start: 1px; color: var(--accent); stroke-width: 2.25; }
.today-card--none { justify-content: center; min-block-size: var(--btn-h-l); }
.today-card--none .today-card__note { padding: var(--sp-3) var(--sp-4); }

/* A commitment row: text, goal, meta (figure + streak), and the Done toggle at the end.
   The text holds a .stretch button (data-cm-act="focus") whose ::after covers the row;
   the Done button sits above it. */
.cm-list { display: flex; flex-direction: column; }
.cm-list > .cm-row + .cm-row { border-block-start: 1px solid var(--line); }
.cm-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-block-size: var(--btn-h-l);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-4);
  transition: background-color var(--dur-fast) var(--ease);
}
.cm-list > .cm-row:last-child { border-end-start-radius: var(--radius-card); border-end-end-radius: var(--radius-card); }
.cm-row__main { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }
.cm-row:has(.stretch:active) { background: var(--surface-2); }
.cm-row:has(.stretch:focus-visible) { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (hover: hover) {
  .cm-row:has(.stretch:hover) { background: var(--surface-2); }
}

/* The parts, shared by the row, the focus sheet and the goal screen's list */
.cm-text { font-size: var(--fs-md); font-weight: var(--fw-medium); line-height: var(--lh-ui); }
.cm-goal { font-size: var(--fs-xs); line-height: var(--lh-ui); color: var(--text-2); }
.cm-rhythm { font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--text-2); font-variant-numeric: tabular-nums; }
.cm-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  margin-block-start: 2px;
  font-size: var(--fs-xs);
  line-height: var(--lh-ui);
  color: var(--text-2);
}
.cm-meta > .tag { align-self: center; }
.cm-figure { font-size: var(--fs-sm); color: var(--text); font-variant-numeric: tabular-nums; }
/* Small and quiet: a 6 px square (done = a filled square, the outcome mark's language)
   and its words in text-3. An empty span (a run of zero) draws nothing at all. */
.cm-streak { display: inline-flex; align-items: center; gap: 6px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.cm-streak::before {
  content: "";
  flex: none;
  inline-size: 6px;
  block-size: 6px;
  border-radius: var(--radius-bar);
  background: var(--accent);
}
.cm-streak:empty { display: none; }
.cm-row.is-done .cm-text { color: var(--text-2); }

/* The Done toggle: .btn.btn--m.btn--icon.cm-done (44 x 44, r12; .cm-done is its variant).
   The state is a shape, never a hue alone, and is read from aria-pressed (no extra class):
   not pressed = an empty frame (line-strong, 3.26 / 3.37:1 on surface-1), no glyph;
   pressed = the check (accent, 6.26 / 5.74:1 on its tint) in an accent edge (8.12 / 6.55:1).
   Tapping it again undoes. */
.cm-done { --btn-fg: var(--text-2); z-index: 1; border-color: var(--line-strong); }
.cm-done .icon { stroke-width: 2.25; transition: opacity var(--dur-fast) var(--ease); }
.cm-done:not([aria-pressed="true"]) .icon { opacity: 0; }
.cm-done:active { background: var(--surface-3); }
.cm-done[aria-pressed="true"] { --btn-fg: var(--accent); background: var(--accent-soft); border-color: var(--accent); }
@media (hover: hover) {
  .cm-done:hover { --btn-fg: var(--text); background: var(--surface-2); }
  .cm-done[aria-pressed="true"]:hover { --btn-fg: var(--accent-hover); background: var(--accent-soft); }
}

/* ---------- Focus sheet (one occurrence, inside openModal) ----------
   The text is the sheet's title; one 52 px primary Done. Once done, a tinted band of
   the same footprint takes the button's place: the sheet settles, nothing jumps. */
.cm-focus__title { font-size: var(--fs-xl); }
.modal__body.cm-focus { gap: var(--sp-2); }
.cm-focus .cm-goal { font-size: var(--fs-sm); }
.cm-focus__done {
  flex: 1 1 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-block-size: var(--btn-h-l);
  padding-block: var(--sp-1);
  padding-inline: var(--sp-4) var(--sp-1);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius-btn-l);
  background: var(--accent-soft);
}
.cm-focus__done > .icon { color: var(--accent); stroke-width: 2.25; }
.cm-focus__msg {
  flex: 1 1 auto;
  min-inline-size: 0;
  padding-block: var(--sp-2);
  font-size: var(--fs-btn-l);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-ui);
}
.cm-focus__done > .btn { flex: none; }

/* ---------- Commitment editor (inside openModal) ---------- */
/* A segmented control with four options folds into two rows on a narrow container.
   Measured with the rhythm labels at 14 px: one row needs a 346 px track content box
   (Arabic "أيام محددة" unwrapped); English "Monthly" clips below 302. */
.seg--wrap { container: seg / inline-size; flex-wrap: wrap; }
@container seg (max-width: 349px) {
  .seg--wrap > .seg__opt { flex: 1 1 calc(50% - var(--sp-1)); }
}
/* Weekday toggles, ordered from the person's week start. Seven in one row from a 332 px
   container (7 x 44 + 6 x 4); below that four, then three. Each is 44 x 44 at least. */
.dow-chips { container: dow / inline-size; display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.dow-chip {
  flex: 0 0 calc((100% - 3 * var(--sp-1)) / 4);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--touch);
  min-block-size: var(--btn-h-m);
  margin: 0;
  padding-block: var(--sp-1);
  padding-inline: var(--sp-1);
  border: 1px solid transparent;
  border-radius: var(--radius-btn-m);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: var(--fs-btn-m);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-ui);
  user-select: none;
  -webkit-user-select: none;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
@container dow (min-width: 332px) {
  .dow-chip { flex: 1 1 0; }
}
.dow-chip:active { background: var(--surface-3); }
.dow-chip[aria-pressed="true"], .dow-chip[aria-checked="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
/* No day picked: UI.fieldError(chipsEl, msg) marks the group, as a field's border turns red */
.dow-chips[aria-invalid="true"] > .dow-chip { border-color: var(--danger-line); }
@media (hover: hover) {
  .dow-chip:not([aria-pressed="true"]):not([aria-checked="true"]):hover { background: var(--surface-3); color: var(--text); }
}
/* The reason Save (or Add) is blocked, on its own line above the dialog's buttons */
.modal__actions > .reason { flex: 1 1 100%; }

/* ---------- Goal screen: the commitments list ----------
   Active items in a .list; the actions sit at the inline end, beside the text when
   there is room and on their own line when there is not. Ended ones in details.cm-ended. */
.cm-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  min-block-size: var(--btn-h-l);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-4);
}
.cm-item__main { flex: 1 1 13rem; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }
.cm-item__actions { flex: none; display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-inline-start: auto; }
.cm-item > .reason { flex: 1 1 100%; }
.cm-item.is-ended .cm-text { color: var(--text-2); font-weight: var(--fw-regular); }

.cm-ended__summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  inline-size: fit-content;
  min-block-size: var(--touch);
  padding-inline: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-btn-m);
  color: var(--text-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
  list-style: none;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.cm-ended__summary::-webkit-details-marker { display: none; }
.cm-ended__summary::marker { content: ""; }
.cm-ended__summary .icon { inline-size: 18px; block-size: 18px; color: var(--text-3); transition: transform var(--dur-fast) var(--ease); }
/* The chevron is symmetric, so RTL's mirror is a half turn: opening is then a quarter turn in both directions. */
[dir="rtl"] .cm-ended__summary .icon--flip { transform: rotate(180deg); }
.cm-ended[open] > .cm-ended__summary .icon { transform: rotate(90deg); }
.cm-ended[open] > .cm-ended__summary { margin-block-end: var(--sp-2); }
.cm-ended__summary:active { background: var(--surface-3); }
@media (hover: hover) {
  .cm-ended__summary:hover { background: var(--surface-2); color: var(--text); }
}

/* ---------- Read-only line: the check-in ("this week: 5 of 7") and the review ----------
   One line, no input, no streak: key in text-2, the value in ink. */
.cm-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px var(--sp-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
  color: var(--text-2);
}
.cm-line__v { color: var(--text); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
.cm-line__n { font-variant-numeric: tabular-nums; }

/* ---------- Motion ---------- */
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes sheet-in { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes sheet-out { from { transform: none; opacity: 1; } to { transform: translateY(24px); opacity: 0; } }
@keyframes dialog-in { from { transform: scale(0.98); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes dialog-out { from { transform: none; opacity: 1; } to { transform: scale(0.98); opacity: 0; } }
@keyframes pulse { from { opacity: 1; } to { opacity: 0.3; } }
@keyframes breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
@keyframes draw { to { stroke-dashoffset: 0; } }

@media (prefers-reduced-motion: reduce) {
  :root, body.theme-dark, body.theme-light {
    --dur-fast: 0ms;
    --dur-base: 0ms;
    --dur-slow: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }
  /* The pulsing squares stop at a steady mid tone; the words beside them say "loading". */
  .dots > span, .btn.is-busy::before, .skel { animation: none !important; opacity: 0.7; }
  .toast--ok .toast__icon path { stroke-dashoffset: 0; }
}
