/* ══════════════════════════════════════════════════════════════════════
   HeartDaily · APP PATTERNS — components that exist on the patient app ONLY
   heartdailyapp.org · v1 (28/09/2026)

   Moved verbatim out of heartdaily/src/index.css so /styleguide/ can link and render the REAL thing
   (the dashboard already does this with dashboard-components.css). Shared components — the ones the
   dashboard/admin also render — live in components.css, never here. Class selectors only.

     • /app/        heartdaily/src/index.css does @import '../../assets/app-patterns.css' (Vite inlines it)
     • /styleguide/ links this file directly

   Requires tokens.css (+ components.css for the shared bits these compose with).
   ══════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════
   v24 — Home + History redesign (visual only; logic unchanged)
   ═══════════════════════════════════════════════════════════════ */

/* Hero card + .hero-num/.hero-pulse + .cmp-banner → /assets/components.css */

/* Streak milestone celebration card */
.milestone-card { display: flex; align-items: center; gap: 12px; margin-bottom: 12px;
  padding: 12px 14px; border-radius: var(--r); color: #fff;
  background: var(--grad); box-shadow: 0 6px 18px rgba(15,184,184,.30); }
.milestone-card .ms-emoji { font-size: 26px; line-height: 1; flex-shrink: 0; }
.milestone-card .ms-txt { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.milestone-card .ms-txt b { font-size: var(--text-base); font-weight: 800; }
.milestone-card .ms-txt span { font-size: var(--text-sm); color: rgba(255,255,255,.9); line-height: 1.4; }
.milestone-card .ms-close { flex-shrink: 0; align-self: flex-start; background: none; border: none;
  cursor: pointer; padding: 2px; display: flex; }

/* §29.6 HBPM trend nudge — gentle amber advisory (not a diagnosis) */
.trend-card { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px;
  padding: 12px 14px; border-radius: var(--r); background: var(--amber-bg);
  border: 1px solid var(--amber); }
.trend-card svg { flex-shrink: 0; margin-top: 1px; }
.trend-card .trend-txt { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.trend-card .trend-txt b { font-size: var(--text-base); font-weight: 700; color: var(--amber-tx); }
.trend-card .trend-txt span { font-size: var(--text-sm); color: var(--amber-tx); line-height: 1.45; }

/* BP risk scale bar (.hd-scale*) → moved to /assets/components.css */

/* "Kiểm soát tuần" panel chìm */
.ctrl { margin-top: var(--sp-4); background: var(--color-surface-subtle); border-radius: var(--rs); padding: 12px 14px 13px; }
.ctrl-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 3px; }
.ctrl-title { font-size: var(--text-sm); font-weight: 700; color: var(--color-text); }
.ctrl-sub { font-size: var(--text-xs); color: var(--color-text-secondary); padding-bottom: 10px; margin-bottom: 10px;
  border-bottom: 1px solid var(--color-border); }
.ctrl-row { display: flex; align-items: baseline; gap: 10px; }
.ctrl-row + .ctrl-row { margin-top: 7px; }
.ctrl-k { font-size: var(--text-sm); color: var(--color-text-secondary); }
.ctrl-v { margin-left: auto; font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: var(--text-md);
  font-weight: 600; color: var(--color-text); white-space: nowrap; }
.ctrl-v .sl { color: var(--color-text-muted); font-weight: 400; }
.ctrl-ok { flex-shrink: 0; font-size: var(--text-xs); font-weight: 700; color: var(--green-tx);
  background: var(--green-bg); padding: 3px 10px; border-radius: var(--rpill); white-space: nowrap; }
.ctrl-empty { margin-top: 9px; font-size: var(--text-xs); color: var(--color-text-secondary); line-height: 1.5; }
.ctrl-empty b { color: var(--color-text-body); font-weight: 600; }

/* Raw BP-target number, folded behind a tap — the qualitative on/off-target line
   above (.ctrl-head) already carries the signal; this is the self-interpreted
   number for whoever wants it. Native <details>, same fold interaction as the
   dashboard's .rc-fold (bordered row + chevron + hover/press). */
.ctrl-fold { margin-top: 7px; border: 1px solid var(--color-border); border-radius: var(--rxs); overflow: hidden; }
.ctrl-fold > summary { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 10px; cursor: pointer; list-style: none; font-size: var(--text-sm); color: var(--color-text-secondary); }
.ctrl-fold > summary::-webkit-details-marker { display: none; }
.ctrl-fold > summary:active { background: var(--color-surface-subtle); }
.ctrl-fold-chev { flex-shrink: 0; color: var(--color-text-muted); transition: transform var(--motion-fast); }
.ctrl-fold[open] .ctrl-fold-chev { transform: rotate(90deg); }
.ctrl-fold > .ctrl-fold-body { padding: 0 10px 9px; display: flex; justify-content: flex-end; }

/* header notification bell — neutral chip now the header itself is neutral (was a translucent-white
   chip meant to sit on the gradient; inverted so it still reads on a light background). */
.hd-hbtn, .hd-bell { position: relative; width: 42px; height: 42px; background: var(--color-surface-subtle); color: var(--color-text-secondary);
  border-radius: var(--rm); border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.hd-bell-count { position: absolute; top: -3px; right: -3px; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 9px; background: var(--b); color: #fff;
  font-size: calc(11px * var(--fs)); font-weight: 800; line-height: 18px; text-align: center;
  box-shadow: 0 2px 5px rgba(15,23,42,.30); box-sizing: border-box; }

/* ── History / Nhật ký huyết áp ── */

.sum-stats { display: flex; gap: 10px; }
.sum-stats .st { flex: 1; }
.sum-stats .st + .st { padding-left: 12px; border-left: 1px solid var(--color-border); }
.sum-stats .k { font-size: var(--text-xs); color: var(--color-text-secondary); }
.sum-stats .sv { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: var(--text-lg); font-weight: 600;
  color: var(--color-text); margin-top: 2px; white-space: nowrap; }
.sum-stats .sv .sl { color: var(--color-text-muted); font-weight: 400; }
.sum-stats .n { font-size: var(--text-xs); color: var(--color-text-muted); margin-top: 1px; }

.chartwrap { margin-top: 12px; border-top: 1px solid var(--color-border); padding-top: 2px; }
.chartwrap summary { list-style: none; display: flex; align-items: center; gap: 8px; padding: 10px 2px 8px;
  cursor: pointer; font-size: var(--text-sm); font-weight: 700; color: var(--t); user-select: none; }
.chartwrap summary::-webkit-details-marker { display: none; }
.chartwrap summary .chev { margin-left: auto; transition: transform var(--motion-base); color: var(--color-text-muted); }
.chartwrap[open] summary .chev { transform: rotate(180deg); }
.chartwrap summary .lbl-open { display: none; }
.chartwrap[open] summary .lbl-closed { display: none; }
.chartwrap[open] summary .lbl-open { display: inline; }
.chart svg { width: 100%; height: auto; display: block; overflow: visible; }
.chart-lg { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; font-size: var(--text-xs); color: var(--color-text-secondary); }
.chart-lg span { display: inline-flex; align-items: center; }
.chart-lg i { display: inline-block; width: 12px; height: 3px; border-radius: 2px; margin-right: 5px; }
.chart-lg i.dash { background: none; border-top: 2px dashed var(--amber); height: 0; }

.day-head { display: flex; align-items: baseline; justify-content: space-between; margin: 16px 2px 9px; }
.day-head .d { font-size: var(--text-base); font-weight: 700; color: var(--color-text); }
.day-head .avg { font-size: var(--text-xs); color: var(--color-text-secondary); }
.day-head .avg b { font-family: var(--font-num); font-variant-numeric: tabular-nums; color: var(--color-text-body); font-weight: 600; }
.ritem { display: flex; align-items: center; gap: 11px; border-radius: 12px; padding: 11px 13px; margin-bottom: 8px; }
.ritem.am { background: var(--amber-bg); }
.ritem.gr { background: var(--green-bg); }
.ritem.rd { background: var(--red-bg); }
.ritem.bl { background: var(--blue-bg); }
.ritem .rdot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.ritem .rinfo { flex: 1; min-width: 0; }
.ritem .rl1 { display: flex; align-items: baseline; gap: 6px; }
.ritem .rbp { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: var(--text-md); font-weight: 500; line-height: 1.1; }
.ritem .rbp .sl { opacity: .55; font-weight: 400; }
.ritem.am .rbp { color: var(--amber-tx); } .ritem.gr .rbp { color: var(--green-tx); }
.ritem.rd .rbp { color: var(--color-text-danger); } .ritem.bl .rbp { color: var(--blue-tx); }
.ritem .rbpm { font-size: var(--text-xs); color: var(--color-text-muted); }
.ritem .rtm { font-size: var(--text-xs); color: var(--color-text-secondary); margin-top: 3px; }
.ritem .rtm .sep { color: var(--color-text-muted); }

/* Standardized header — đồng đều mọi trang (hết "nhảy" khi chuyển tab).
   column + justify-center: nội dung 1 hay 2 dòng đều canh giữa trong cùng chiều cao.
   Neutral, not gradient (improve.md §D Exhibit D, decided 03/10) — the gradient was the single most
   "always-on" colour source in the app, before any clinical content loads. Gradient now lives only in
   the small BrandLogo mark and (via .hd-brandname below) the user's own name — same move as the
   30/09 dashboard sidebar, which tried a coloured band first and settled on colour-in-the-mark-only. */
.app-header { background: var(--color-surface-card); border-bottom: 1px solid var(--color-border); display: flex; flex-direction: column; justify-content: center;
  min-height: 76px; padding: 14px 20px;
  /* Edge-to-edge (Android gesture nav / notch): keep header content below the status bar.
     env() is 0 when not edge-to-edge, so this is a no-op on normal devices. */
  padding-top: calc(14px + env(safe-area-inset-top)); }

/* The app header's title + subtitle. (0,1,1) on purpose: it must out-rank Tailwind preflight's `h1{font-size:inherit;font-weight:inherit}`;
   inline styles still win, so do NOT put text-size/weight utilities on an h1 inside .app-header — they would lose to this rule. */
.app-header h1 { color: var(--color-text); font-size: var(--text-lg); font-weight: 800; letter-spacing: -.01em; }
.app-header .sub { color: var(--color-text-secondary); font-size: var(--text-sm); margin-top: 2px; }
/* The ONE piece of "this is yours" text in the header carries the brand gradient — same gradient as
   the logo mark, via background-clip:text (fallback: flat --td where that's unsupported). */
.app-header h1.hd-brandname { color: var(--color-text-action); background: var(--grad); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; }

/* "Chưa đạt" pill (amber) — cạnh ctrl-ok */
.ctrl-warn { flex-shrink: 0; font-size: var(--text-xs); font-weight: 700; color: var(--amber-dk);
  background: var(--amber-bg); padding: 3px 10px; border-radius: var(--rpill); white-space: nowrap; }

/* Link card "Nhật ký huyết áp" trên Home → mở trang Lịch sử */
.hd-linkcard { display: flex; align-items: center; gap: 12px; width: 100%; background: var(--color-surface-card);
  border: none; text-align: left; border-radius: 14px; min-height: 62px; padding: 6px 14px;
  margin-bottom: 18px; box-shadow: var(--sh-1); cursor: pointer; }
.hd-linkcard .lc-ico { width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; background: var(--tl); }
.hd-linkcard .lc-txt { flex: 1; min-width: 0; }
.hd-linkcard .lc-txt b { display: block; font-size: var(--text-base); font-weight: 600; color: var(--color-text); }
.hd-linkcard .lc-txt span { font-size: var(--text-xs); color: var(--color-text-secondary); }
/* Weekly on-target pill, moved here off the hero (07/10) — the journal card already opens the history
   that pill is a summary of. */
.hd-linkcard .lc-ctrl { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 1px; }
.hd-linkcard .lc-ctrl .ctrl-ok { color: var(--green-tx); }
.hd-linkcard .lc-ctrl .ctrl-warn { color: var(--amber-dk); }

/* Home "Today" card (P41, 21/10) — Journal/Follow-up/Medication as rows of ONE card instead of three
   separate shadowed cards. Each row keeps its own .hd-linkcard markup; nested in .today-card it drops its
   own shadow/radius/margin for a plain divided row. */
.today-card { padding: 2px 4px; margin-bottom: 10px; }
.today-card .hd-linkcard { box-shadow: none; border-radius: 0; margin-bottom: 0; min-height: 56px;
  padding: 12px 10px; border-bottom: 1px solid var(--color-border-subtle); }
.today-card .hd-linkcard:last-child { border-bottom: none; }
.today-card .lc-chev { color: var(--color-text-muted); transition: transform var(--motion-fast); flex-shrink: 0; }

/* Stale-reading strip (07/10, P20 row 4) — on Home when the latest reading is 3+ days old; replaces the
   comparison banner and the on-target pill above, both misleading off old data. */
.stale-strip { align-items: center; gap: 12px; margin-bottom: 12px; }
.stale-strip button { flex-shrink: 0; white-space: nowrap; }

/* ── Caregiver / CHW — simple one-row list card ── */
.plist { display: flex; align-items: center; gap: 9px; background: var(--color-surface-card); border-radius: var(--r);
  box-shadow: var(--sh-1); padding: 10px; margin-bottom: 10px; cursor: pointer; }
.plist .p-mid { flex: 1; min-width: 0; }
.plist .p-nm { font-size: calc(14px * var(--fs)); font-weight: 700; color: var(--color-text); line-height: 1.25; letter-spacing: -.01em; }
.plist .p-meta { font-size: calc(11.5px * var(--fs)); color: var(--color-text-muted); margin-top: 2px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; row-gap: 3px; }
.plist .p-rt { flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; padding-left: 3px; text-align: right; }
.plist .p-bp { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: calc(13.5px * var(--fs)); font-weight: 600; color: var(--color-text); line-height: 1; white-space: nowrap; }
.plist .p-dt { font-size: calc(10.5px * var(--fs)); color: var(--color-text-muted); white-space: nowrap; }
.plist .p-dt.over { color: var(--color-text-danger); font-weight: 600; }
.attn-x { position: absolute; top: 8px; right: 9px; width: 22px; height: 22px; border: none;
  background: var(--red-bg); color: var(--red); border-radius: 6px; font-size: 14px; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center; font-family: inherit; }
/* P41 (21/10): the routine overdue notice moved off red onto amber (notice-warn) — its own dismiss
   button follows, so it is not the one red thing left on an otherwise amber strip. */
.notice-warn .attn-x { background: var(--amber-bg); color: var(--amber-dk); }

/* Bottom nav raised CTA (Đo HA) — nút tròn gradient nổi lên */
.bnav-cta-ico, .nav-cta-ico { width: 50px; height: 50px; border-radius: 50%; background: var(--grad); color: #fff;
  display: flex; align-items: center; justify-content: center; margin-top: -26px; margin-bottom: 2px;
  border: 3px solid var(--color-surface-card); box-shadow: 0 0 0 1px var(--color-border), 0 3px 8px rgba(15,23,42,.16); }

/* ── Bottom nav (BottomNav.jsx) — slate selected state (04/10), raised gradient CTA ─────────────────────── */
.bnav { flex-shrink: 0; display: flex; align-items: stretch; background: var(--color-surface-card); border-top: 1px solid var(--color-border);
  height: 72px; box-sizing: content-box; position: relative; z-index: var(--z-raised); }
.bnav-it { flex: 1; position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  padding: 8px 4px; border: none; background: transparent; cursor: pointer; font-family: inherit;
  font-size: var(--text-xs); font-weight: 500; line-height: 1; color: var(--color-text-muted); }
.bnav-it.on { color: var(--color-text-secondary); font-weight: 700; }
.bnav-it.cta { justify-content: flex-end; gap: 2px; color: var(--color-text-muted); font-weight: 500; }
.bnav-it.cta.on { color: var(--color-text-secondary); font-weight: 700; }
.bnav-dot { position: absolute; top: 8px; right: calc(50% - 18px); width: 7px; height: 7px; border-radius: 50%;
  background: var(--red); border: 1.5px solid var(--wh); }

/* ── Home "Today's medication" (P41, 21/10, replaces the P20 row 5a full-width-button design) ──
   Collapsed into one row of .today-card (icon + title + one-line summary + chevron, same as Journal/
   Follow-up); tapping it opens this compact list in place — one row per dose TIME, action trailing
   instead of a full-width button: an outline "Taken" pill (read-only, already confirmed) or an outline
   tap-circle (not yet taken). A time with 2+ drugs stacks the names under one row, the action aligned to
   the row, not repeated per drug. Shared with the styleguide / landing / demo mirror (app-screens.js). */
.dose-compact { padding: 2px 14px 12px; }
.dose-crow { display: flex; align-items: center; gap: 12px; padding: 9px 0; }
.dose-crow + .dose-crow { border-top: 1px solid var(--color-border-subtle); }
.dose-ctime { font-size: var(--text-base); font-weight: 800; color: var(--color-text); min-width: 40px; flex-shrink: 0;
  font-variant-numeric: tabular-nums; }
.dose-cnames { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.dose-cname { font-size: var(--text-base); font-weight: 600; color: var(--color-text); }
.dose-cmg { font-weight: 400; color: var(--color-text-secondary); }
.dose-ctag { flex-shrink: 0; display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-xs); font-weight: 700;
  color: var(--color-text-action); background: none; border: 1.5px solid var(--td); border-radius: var(--rpill); padding: 4px 11px; white-space: nowrap; }
.dose-ctick { flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%; background: none; border: 1.5px solid var(--td);
  color: var(--color-text-action); display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; }
.dose-ctick:active { background: var(--td-bg); }
.dose-err { margin-top: 8px; font-size: var(--text-sm); color: var(--color-text-danger); }
