/* ==========================================================================
   EaseFocus — Design tokens (NeuPractix shared "Calm Premium Wellness" system)
   Copied from the EyeFocus reference; only the accent hue was changed.
   ========================================================================== */
:root {
  /* Core Color Palette */
  --bg: #F0F4F8;              /* Soft Blue-Grey — base background */
  --white: #FFFFFF;
  --border: #E2E8F0;
  --circle-bg: #E1E8F0;
  --circle-rim: #B9C6D6;
  --text: #1E293B;            /* Deep Slate — primary text */
  --muted: #526079;
  --muted-text: #475569;      /* darker body-copy shade used inside expanded welcome-screen cards, matched to reference */
  --muted-light: #526079;     /* welcome-hero subtitle. Was #64748B to match the reference exactly; that value measures 4.31:1 on this
                                 background and so fails WCAG AA at the 14.5px it is used at. #526079 is the same hue two steps darker
                                 (5.60:1) — the same correction the design system records EyeFocus having had to make to --muted. */
  --gold: #e8b800;
  --gold-dark: #c09600;
  --green: #14B8A6;           /* Healing Mint-Teal — shared success/healthy state, also EaseFocus's own teal */
  --yellow-m: #d4a000;
  --orange-m: #e07020;
  --red-m: #F43F5E;
  --accent: #A9E43C;          /* EaseFocus PRIMARY BRAND COLOR — lime-green, from the new play-button logo's gradient (2026-09-07 rebrand, was periwinkle #9C8FF0) */
  --accent-dark: #96D71E;
  --accent-rgb: 169,228,60;   /* same color as --accent, as an r,g,b triplet — every rgba(accent, alpha) below reads this var instead of hardcoding the triplet, so re-theming a sibling app only means editing this block */
  --accent-soft: rgba(var(--accent-rgb), 0.08);

  /* Accessible TEXT-ONLY variants — never used as backgrounds/borders */
  --accent-text: #517410;     /* darkened lime-green — 5.4:1 on white, passes WCAG AA (see neupractix-design-system's accent-text pattern) */
  --green-text: #0F766E;
  --red-text: #BE123C;
  --yellow-text: #8A6000;
  --orange-text: #A04C17;

  --navy: #1E293B;
  --indigo-deep: #1E1B4B;
  --teal: #14B8A6;
  /* Logo gradient: lime-green (--accent) -> teal (--green), matching the new
     play-button icon exactly (2026-09-07, per Lea's full-rebrand request —
     only the button/brand gradient direction+hue changed; --green/--teal
     stay the shared cross-app token, already almost identical to the icon's
     own teal stop). */
  --gradient-brand: linear-gradient(135deg, #A9E43C 0%, #14B8A6 100%);
  --gradient-focus: linear-gradient(90deg, #A9E43C 0%, #14B8A6 100%);
  --gradient-cta: linear-gradient(135deg, #A9E43C 0%, #14B8A6 100%);

  --font-body: 'Assistant', sans-serif;
  --font-ui: 'Rubik', sans-serif;

  --glow-primary: 0 0 25px rgba(var(--accent-rgb),0.2), 0 4px 12px rgba(var(--accent-rgb),0.15);
  --glow-accent: 0 0 25px rgba(20,184,166,0.25), 0 4px 12px rgba(20,184,166,0.15);

  --glass-bg: rgba(255,255,255,0.85);
  --glass-border: rgba(255,255,255,0.6);
}

* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0;
  background: #D7DBE3; /* empirically-measured EyeFocus reference background, not the --bg token */
  color: var(--text);
  font-family: var(--font-body);
  min-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
}
body { position: relative; min-height: 100vh; min-height: 100dvh; }
img { max-width: 100%; display: block; }
a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font-family: var(--font-ui); cursor: pointer; }
h1, h2, h3 { font-family: var(--font-ui); margin: 0; }

/* 2026-09-10: the admin test banner is position:fixed at the top, so the
   screens have to start below it or it sits on the session title. Applied to
   .screen, not to .app-shell's padding — .screen is absolutely positioned,
   and inset:0 resolves against the padding BOX, so padding would not move it. */
body.ef-test-mode .screen { top: 30px; }
body.ef-test-mode .tr-session-chrome { padding-top: 8px; }

.app-shell {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
  position: relative;
  box-shadow: var(--border) 0 0 0 1px, rgba(0,15,71,0.16) 0 12px 60px 0;
}

/* ---------- Icons ---------- */
/* 2026-09-16 (Lea: "the icons are enormous and out of proportion"). Until now
   .icon-inline had NO base rule — only seven scoped ones (.replay-btn,
   .reminder-link, .home-link-cta, .tr-game-id, .sum-row-icon, .sum-rank-badge,
   .solo-btn) plus a couple of rules that size the image without naming the
   class at all (.tr-instruction img). Every usage outside those fell through to
   the PNG's natural size, 128px for the exercise icons — which is what Lea saw
   on the day-detail rows. The design system defines .icon-inline as
   "scales with the surrounding text", so that is the base; each scoped rule
   above is more specific and still wins where a fixed pixel size is wanted. */
.icon-inline { width: 1em; height: 1em; vertical-align: -0.15em; object-fit: contain; flex: 0 0 auto; }

/* ---------- Screens ---------- */
.screen { display: none; position: relative; flex-direction: column; min-height: 100vh; min-height: 100dvh; }
.screen.active { display: flex; animation: screenFadeIn 350ms cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes screenFadeIn {
  from { opacity: 0; transform: translateY(6px) scale(0.99); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .screen.active { animation: none; }
}

/* ---------- Buttons ---------- */
.btn-primary {
  padding: 14px 22px;
  background: var(--gradient-cta);
  color: var(--navy);
  border: none;
  border-radius: 999px;
  font-weight: 900;
  font-size: 16px;
  box-shadow: var(--glow-primary);
  transition: transform .12s, filter .15s;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn-primary:hover { filter: brightness(0.96); }
.btn-primary:active { transform: scale(0.96); }

/* Same size/font/weight/shadow as .btn-primary — only the color changes.
   Used where two actions must carry equal visual weight (the cookie-consent
   gate's accept/decline pair), so neither reads as the "real" choice. */
.btn-primary-neutral {
  background: var(--navy);
  color: #fff;
  box-shadow: 0 4px 14px rgba(30,41,59,0.28);
}
.btn-primary-neutral:hover { filter: brightness(1.15); }

.btn-quiet {
  padding: 12px 18px;
  background: var(--accent-soft);
  color: var(--accent-text);
  border: 1.5px solid rgba(var(--accent-rgb),0.25);
  border-radius: 999px;
  font-weight: 700;
  font-size: 14px;
}

/* ---------- Top bar / language picker ---------- */
.welcome-top {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px 6px;
}
.welcome-top .wordmark { height: 34px; width: auto; }
.lang-picker { display: flex; align-items: center; gap: 8px; }
.lang-dd { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.langSel {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 700;
  padding: 5px 10px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background-color: var(--white);
  box-shadow: none;
  color: var(--navy);
}

/* ---------- Hero ---------- */
.welcome-hero-wrap {
  width: 100%;
  padding: 4px 16px;
}
.welcome-hero-wrap img {
  width: 100%; aspect-ratio: 16/9; object-fit: cover; display: block;
  border-radius: 14px;
}

.welcome-intro { padding: 22px 22px 8px; text-align: center; }
.welcome-intro h1 {
  font-family: var(--font-body); font-size: 21px; font-weight: 700; line-height: 1.3; color: var(--navy);
  outline: none;
}
.welcome-intro p.subtitle {
  margin: 12px 0 20px; color: var(--muted-light); font-size: 14.5px; line-height: 1.6;
}

/* ---------- Sections ---------- */
.welcome-section { padding: 26px 22px; border-top: 1px solid var(--border); }
.welcome-section h2 { font-family: var(--font-body); font-size: 15.5px; font-weight: 700; color: var(--navy); margin-bottom: 12px; }
.welcome-section p { color: var(--muted-text); font-size: 13.5px; line-height: 1.7; margin: 0 0 6px; }

.more-toggle {
  display: inline; color: var(--accent-text); font-weight: 700; font-size: 13.5px;
  font-family: var(--font-body); cursor: pointer; border: none; background: none; padding: 0;
}
.more-content { display: none; margin-top: 10px; }
.more-content.open { display: block; }
.more-content ul { margin: 10px 0; padding-inline-start: 20px; }
.more-content li { color: var(--muted); font-size: 14.5px; line-height: 1.7; margin-bottom: 8px; }

/* Research card */
.research-card {
  margin-top: 8px; border: 1.25px solid #EEF0F3; border-radius: 14px;
  background: var(--white); padding: 12px 16px;
}
.research-card summary {
  cursor: pointer; padding: 0; font-weight: 700; font-size: 13.5px; color: var(--accent-text);
  list-style: none; display: flex; align-items: center; justify-content: space-between;
}
.research-card summary::-webkit-details-marker { display: none; }
.research-card .research-intro { color: var(--muted-text); font-size: 13.5px; line-height: 22.95px; margin: 10px 0 0; }
.research-card .research-intro:empty { display: none; }
.research-list { list-style: none; margin: 10px 0 0; padding: 0; }
.research-item { margin: 0 0 14px; }
.research-item:last-child { margin-bottom: 0; }
.research-item .r-title { font-weight: 400; font-size: 12.5px; line-height: 20px; color: var(--muted-text); margin: 0 0 4px; }
.research-item .r-title strong { font-weight: 700; }
.research-item .r-cite { font-size: 11.5px; color: #94A3B8; margin: 0; }
.research-item .r-links a { color: var(--accent-text); text-decoration: underline; margin-inline-end: 8px; }

/* Method steps */
.welcome-step {
  border: 1.25px solid #EEF0F3; border-radius: 14px; background: var(--white);
  margin: 8px 0; padding: 12px 16px;
}
.welcome-step summary {
  list-style: none; cursor: pointer; padding: 0; display: flex; align-items: center; gap: 10px;
  font-weight: 700; font-size: 13.5px; color: var(--accent-text);
}
.welcome-step summary::-webkit-details-marker { display: none; }
.welcome-step .step-icon { width: 30px; height: 30px; flex-shrink: 0; }
.welcome-step .step-num {
  font-family: var(--font-ui); font-weight: 900; color: var(--accent-text); font-size: 13px;
}
.welcome-step .step-detail { color: var(--muted-text); font-size: 13.5px; line-height: 22.95px; margin: 10px 0 0; padding: 0; }
[dir="rtl"] .welcome-step .step-detail { margin: 10px 0 0; padding: 0; }

/* Explore tiles */
.welcome-explore-section h2 a { color: var(--navy); }
.explore-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px;
}
.explore-tile { position: relative; border-radius: 16px; overflow: hidden; aspect-ratio: 4/3; }
.explore-tile img { width: 100%; height: 100%; object-fit: cover; }
.explore-tile .tile-label {
  position: absolute; inset-inline-start: 0; bottom: 0; width: 100%;
  padding: 8px 10px; font-size: 12.5px; font-weight: 800; color: #fff;
  background: linear-gradient(0deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0) 100%);
}

/* CTA bubble — matched against MoveFocus's real welcome CTA per Lea's
   2026-08-20 screenshots. First pass used width:84%/max-width:340px,
   which read narrower than the reference on a wider column since the cap
   bound before the percentage did. Fixed by dropping the independent
   cap entirely: the button now fills its wrap at width:100%, so its side
   margins are simply .welcome-intro's own 22px padding — "these margins"
   Lea pointed at, not a separately-invented value. */
.welcome-cta-wrap { text-align: center; margin-top: 4px; }
.welcome-cta-wrap .btn-primary { display: flex; width: 100%; margin: 0 auto; }

/* Footer */
.app-footer {
  margin-top: auto; padding: 22px; text-align: center;
  font-size: 12px; color: var(--muted); position: relative;
}
.app-footer .footer-link { color: var(--muted); text-decoration: underline; pointer-events: auto; }

/* ---------- Auth screen (ground-truth: MoveFocus's real css/styles.css + js/auth.js) ---------- */
#auth { background: var(--bg); align-items: center; justify-content: center; overflow-y: auto; padding: 28px 24px 40px; }
.auth-top { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px; margin-bottom: 28px; }
.auth-top .lang-picker { align-self: center; }
.auth-logo { cursor: pointer; border-radius: 18px; }
.auth-logo-img {
  width: 150px; height: 150px; object-fit: contain; background: var(--white);
  border-radius: 18px; box-shadow: 0 4px 20px rgba(var(--accent-rgb),0.14);
}
.auth-logo:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 18px; }
.auth-top .auth-sub { color: var(--muted); font-size: 13px; margin: 0; max-width: 260px; text-align: center; line-height: 1.5; }
.field-label { font-size: 12px; font-weight: 700; color: var(--muted); margin: 0 0 6px; display: block; }
.text-input {
  width: 100%; padding: 13px 16px; border-radius: 14px; border: 1.5px solid var(--border);
  background: var(--white); font-size: 15px; box-shadow: 0 1px 4px rgba(0,0,0,0.04);
  font-family: var(--font-body);
}
.text-input.err { border-color: var(--red-m); box-shadow: 0 0 0 3px rgba(244,63,94,0.1); }
/* The soft lime ring alone is not a focus indicator anyone can see: #A9E43C on
   white measures 1.08:1, where WCAG 2.2 SC 1.4.11 asks for 3:1. The ring stays
   — it is the family's visual language — but the thing that actually marks
   focus is the dark-green outline on top of it (--accent-text, 5.4:1). */
.text-input:focus { outline: none; box-shadow: 0 0 0 3px rgba(var(--accent-rgb),0.18); border-color: var(--accent-text); }
.text-input:focus-visible {
  outline: 2px solid var(--accent-text); outline-offset: 1px;
}

/* Same problem, everywhere else keyboard focus can land. Anything that already
   declares its own :focus-visible above keeps it; this is the floor. */
button:focus-visible, a:focus-visible, select:focus-visible,
textarea:focus-visible, input:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent-text); outline-offset: 2px;
}
/* On the dark in-session screens the dark-green outline would disappear into
   the background, so those get the bright lime instead — which is the high-
   contrast choice there, not the low-contrast one. */
.tr-session:focus-visible, .tr-session button:focus-visible, .tr-session a:focus-visible,
.tr-session [tabindex]:focus-visible, .tr-ex-nightflow button:focus-visible {
  outline-color: var(--accent);
}

.name-input-row {
  display: flex; flex-direction: row; gap: 8px; align-items: stretch;
  width: 100%; max-width: 340px; margin: 0 0 20px;
}
.name-input-row .text-input { flex: 1; min-width: 0; }
.name-input-row .btn-primary, .name-input-row .btn-quiet { flex-shrink: 0; white-space: nowrap; }
.err-msg { display: none; color: var(--red-text); font-size: 12px; margin: -14px 0 8px; padding-inline-start: 4px; width: 100%; max-width: 340px; }
.err-msg.show { display: block; }
/* Restore-by-code modal: warning shown only when the existing profile already
   has its own active subscription under a different code (brief-restore-profile-choice.md) */
.restore-warning { background: rgba(244,63,94,0.06); border: 1.5px solid rgba(244,63,94,0.25);
  border-radius: 10px; padding: 10px 12px; color: var(--red-text); font-size: 13px; line-height: 1.5; margin-bottom: 12px; }

.home-link {
  display: block; background: none; border: none; padding: 0 0 4px; margin: 0 0 4px;
  color: var(--muted); font-size: 14px; font-family: var(--font-body); text-decoration: underline;
  text-align: center; cursor: pointer;
}
.restore-section { display: none; width: 100%; max-width: 340px; border-top: 1px dashed var(--border); padding-top: 14px; margin-top: 4px; }
.restore-section.show { display: block; }
.restore-label { font-size: 12px; font-weight: 700; color: var(--muted); margin: 0 0 8px; text-align: start; }

.section-label { width: 100%; max-width: 340px; font-size: 11px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase; color: var(--muted); margin: 22px 0 10px; }
.users-list { width: 100%; max-width: 340px; display: flex; flex-direction: column; gap: 8px; }
.user-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 16px;
  background: var(--white); border: 1px solid var(--border); box-shadow: 0 1px 4px rgba(0,0,0,0.04);
  cursor: pointer;
}
.user-avatar {
  width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0;
  background: var(--gradient-cta); display: flex; align-items: center; justify-content: center;
  overflow: hidden; font-family: var(--font-ui); font-weight: 900; font-size: 15px; color: var(--navy);
  border: none; cursor: pointer;
}
.user-avatar:hover { box-shadow: 0 0 0 3px rgba(var(--accent-rgb),0.18); }
.user-avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar-emoji { font-size: 18px; line-height: 1; }
.user-info { flex: 1; min-width: 0; }
.user-name { font-size: 14px; font-weight: 700; color: var(--navy); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.user-arrow { font-size: 18px; color: var(--border); flex-shrink: 0; transform: scaleX(var(--dir-flip, 1)); }
[dir="rtl"] .user-arrow { transform: scaleX(-1); }
.empty-state { text-align: center; color: var(--muted); font-size: 13.5px; line-height: 1.7; padding: 18px 10px; }
.empty-state .es-icon { display: block; font-size: 26px; margin-bottom: 6px; }

/* Recolored 2026-08-20 per Lea: the red/rose styling read as an alarm in a
   calming breathing app ("כואב בעיניים" — hurts the eyes). Swapped for a soft
   yellow bubble + warm brown text, using the existing --gold/--yellow-text
   design-system tokens rather than inventing new colors. */
.device-notice {
  margin: 16px 22px; padding: 12px 14px; border-radius: 14px; background: rgba(232,184,0,0.10);
  border: 1px solid rgba(232,184,0,0.28); font-size: 12.5px; color: var(--yellow-text); font-weight: 700;
  text-align: center;
}

/* ---------- Consent screen ---------- */
.consent-wrap { padding: 28px 22px 30px; flex: 1; }
.consent-card {
  background: var(--glass-bg); border: 1.5px solid var(--glass-border); border-radius: 22px;
  padding: 24px 20px; display: flex; flex-direction: column; gap: 14px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);
}
.consent-title { font-family: var(--font-ui); font-size: 18px; font-weight: 900; text-align: center; margin: 0; }
.consent-sub { font-size: 13px; color: var(--muted); text-align: center; margin: -8px 0 0; font-weight: 400; }
.consent-sub strong { font-weight: 800; color: var(--text); }
.consent-scroll {
  max-height: 44vh; overflow-y: auto; font-size: 13px; line-height: 1.65;
  background: var(--bg); border-radius: 14px; padding: 14px; border: 1px solid var(--border);
}
.consent-scroll p { margin: 0 0 10px; color: var(--text); }
.consent-scroll a { color: var(--accent-text); font-weight: 700; text-decoration: underline; font-size: 13px; }
.consent-danger {
  background: rgba(244,63,94,0.06); border: 1.5px solid rgba(244,63,94,0.25); border-radius: 12px;
  padding: 10px 12px; color: var(--red-text) !important;
}
.consent-danger strong { display: block; margin-bottom: 4px; }
.consent-check { display: flex; align-items: flex-start; gap: 10px; font-size: 12px; line-height: 1.55; color: var(--text); cursor: pointer; }
.consent-check input { margin-top: 3px; width: 17px; height: 17px; flex-shrink: 0; accent-color: var(--accent); }
#consentAgree:disabled { background: var(--border); color: var(--muted); box-shadow: none; opacity: 1; cursor: not-allowed; filter: none; }

/* ---------- Avatar picker modal ---------- */
.avatar-emoji-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; margin: 4px 0 14px; }
.avatar-emoji-btn { font-size: 22px; padding: 6px 0; background: var(--bg);
  border: 1.5px solid transparent; border-radius: 10px; cursor: pointer; transition: border-color .15s, background .15s; }
.avatar-emoji-btn:hover, .avatar-emoji-btn:focus-visible { border-color: var(--accent); background: var(--accent-soft); }
.avatar-upload-label {
  display: block; text-align: center; padding: 12px 18px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-text); border: 1.5px solid rgba(var(--accent-rgb),0.25);
  font-weight: 700; font-size: 14px; cursor: pointer;
}

/* ---------- User topbar (present on every screen after login) ---------- */
.user-topbar { display: flex; align-items: center; gap: 10px; padding: 14px 18px; }
.ut-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; background: var(--gradient-cta);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  font-family: var(--font-ui); font-weight: 900; color: var(--navy); border: none; cursor: pointer; font-size: 14px;
}
.ut-avatar img { width: 100%; height: 100%; object-fit: cover; }
.ut-name { flex: 1; min-width: 0; font-weight: 700; font-size: 14px; color: var(--navy); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ut-icon-btn {
  width: 32px; height: 32px; border-radius: 50%; background: var(--accent-soft); border: none;
  font-size: 14px; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.ut-logout { background: none; border: none; color: var(--muted); font-size: 12.5px; text-decoration: underline; flex-shrink: 0; }

/* ---------- My-code modal ---------- */
.my-code-value {
  text-align: center; font-family: var(--font-ui); font-weight: 900; font-size: 22px; letter-spacing: 1px;
  color: var(--accent-text); background: var(--accent-soft); border-radius: 14px; padding: 14px; margin-top: 10px;
}

/* ---------- Home placeholder screen ---------- */
.home-card {
  margin: 20px 22px; padding: 22px; border-radius: 18px; background: var(--glass-bg);
  border: 1px solid var(--glass-border); text-align: center;
}
.home-card h2 { font-size: 17px; margin-bottom: 8px; }
.home-card p { color: var(--muted); font-size: 14px; line-height: 1.6; }
.home-greeting { padding: 22px 22px 0; text-align: center; }
.home-greeting h1 { font-size: 20px; }

/* ---------- Modal ---------- */
.app-modal { position: fixed; inset: 0; background: rgba(15,20,35,0.5); display: none; align-items: center; justify-content: center; z-index: 800; padding: 20px; }
.app-modal.open { display: flex; }
.app-modal-inner { background: var(--white); border-radius: 20px; max-width: 440px; width: 100%; max-height: 82vh; overflow-y: auto; padding: 24px; position: relative; }
.app-modal-title { font-size: 18px; margin-bottom: 12px; padding-inline-end: 30px; }
.app-modal-body { font-size: 14px; line-height: 1.7; color: var(--muted); }
.app-modal-body p { margin: 0 0 12px; }
.app-modal-close { position: absolute; top: 16px; inset-inline-end: 16px; background: none; border: none; font-size: 22px; color: var(--muted); line-height: 1; }
.app-modal-actions { margin-top: 18px; text-align: center; }

/* ---------- Floating action buttons ---------- */
.fab {
  position: fixed; inset-inline-end: 16px; width: 48px; height: 48px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; border: none; z-index: 500;
  box-shadow: 0 4px 14px rgba(0,0,0,0.18); color: #fff;
}
.fab svg { width: 22px; height: 22px; }
#fabShare { bottom: 64px; background: #4083F3; }
#fabFeedback { bottom: 120px; background: #20B8A6; }
#fabInstall { bottom: 176px; background: #6435D9; display: none; }

/* ---------- Legal pages (accessibility.html / terms.html) — matched to MoveFocus's live legal-page design ---------- */
body.legal-page { background: #F3F5FA; padding: 32px 18px 80px; box-sizing: border-box; min-height: 100vh; min-height: 100dvh; }
.legal-wrap {
  max-width: 760px; margin: 0 auto; background: var(--white);
  border: 1px solid #E2E5F3; border-radius: 18px; padding: 32px 28px;
  color: #000F47;
}
.legal-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.legal-back { font-size: 13px; font-weight: 700; color: #2A75D0; text-decoration: none; }
.legal-wrap h1 { font-size: 22px; font-weight: 900; color: #000F47; line-height: 1.75; margin: 0 0 4px; }
.legal-updated { color: #38425A; font-size: 12px; margin-bottom: 24px; }
.legal-wrap h2 { font-size: 16px; font-weight: 900; margin: 26px 0 8px; color: #9A3412; }
.legal-wrap p { color: #000F47; font-size: 14px; line-height: 1.75; margin: 0 0 8px; }
.legal-wrap ul { color: #000F47; font-size: 14px; line-height: 1.75; margin: 0 0 8px; padding-inline-start: 22px; }
.legal-wrap ul li { margin: 0 0 8px; }
.legal-wrap .legal-intro { font-size: 14px; color: #000F47; line-height: 1.75; margin-bottom: 8px; }
#tS3.danger {
  background: rgba(244,63,94,0.06); border: 1px solid rgba(244,63,94,0.25);
  border-radius: 12px; padding: 14px 16px; margin: 14px 0;
}
.legal-forward { display: block; margin-top: 28px; font-weight: 700; font-size: 13px; color: #2A75D0; text-decoration: none; }

/* ---------- Baseline assessment (self-assessment, 4 phases) ---------- */
.bl-progress-wrap { padding: 14px 22px 0; }
.bl-progress-track { height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; }
.bl-progress-fill { height: 100%; background: var(--gradient-cta); border-radius: 999px; transition: width .4s ease; }
.bl-phase-label { margin-top: 8px; font-size: 12px; font-weight: 700; color: var(--muted); text-align: center; }

.bl-view { display: none; flex: 1; flex-direction: column; }
.bl-view.active { display: flex; }

.bl-intro-wrap { padding: 18px 22px 26px; flex: 1; }
.bl-intro-logo { display: block; width: 64px; height: 64px; object-fit: contain; margin: 4px auto 14px; }
.bl-title { font-size: 20px; text-align: center; margin: 6px 0 10px; }
.bl-body { font-size: 14px; line-height: 1.65; color: var(--muted-text); text-align: center; margin: 0 0 18px; }
.bl-steps { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.bl-steps li { display: flex; align-items: center; gap: 12px; background: var(--white); border: 1px solid var(--border); border-radius: 14px; padding: 12px 14px; font-size: 13.5px; color: var(--text); text-align: start; }
.bl-step-num { width: 24px; height: 24px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-text); font-family: var(--font-ui); font-weight: 900; font-size: 12px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.bl-privacy { font-size: 12px; color: var(--muted); text-align: center; margin: 0 0 18px; line-height: 1.55; }
.bl-note { font-size: 12.5px; color: var(--muted); text-align: center; line-height: 1.55; margin: 0 0 12px; }
.bl-note-danger { color: var(--red-text); }

.bl-card { padding: 20px 22px; flex: 1; display: flex; flex-direction: column; position: relative; z-index: 2; }
.bl-card-center { align-items: center; justify-content: center; text-align: center; }
.bl-h2 { font-size: 17px; margin: 0 0 14px; text-align: center; }
.bl-center { text-align: center; }

.bl-slider-block { margin-bottom: 22px; }
.bl-slider-label { font-size: 13.5px; font-weight: 700; color: var(--text); margin-bottom: 10px; }
/* 2026-10-06 (Lea): "make it clear you drag the right way". The track is a
   faint calm->aroused gradient so the two ends read at a glance, the part up
   to the thumb fills with the colour of the CURRENT value, and a number
   bubble rides above the thumb. --p (0..1) and --c are set by blSliderPaint()
   in js/baseline.js. Colour is never the only cue: the number and the two
   end words (below) say the same thing. Thumb is 24px; the fill/bubble maths
   uses 12px (half) so they land on the thumb centre. */
.bl-slider-wrap { position: relative; padding-top: 36px; --p: .44; --c: rgb(232,184,0); }
.bl-slider-val { position: absolute; top: 0; inset-inline-start: calc(12px + (100% - 24px) * var(--p)); transform: translateX(-50%); pointer-events: none; }
html[dir="rtl"] .bl-slider-val { transform: translateX(50%); }
.bl-sv-num { position: relative; display: inline-block; min-width: 34px; text-align: center; padding: 2px 8px; border-radius: 12px; background: var(--c); color: var(--navy); font-family: var(--font-ui); font-weight: 800; font-size: 19px; line-height: 1.25; box-shadow: 0 2px 8px rgba(0,15,71,0.18); }
.bl-sv-num::after { content: ""; position: absolute; left: 50%; bottom: -5px; width: 10px; height: 10px; background: var(--c); transform: translateX(-50%) rotate(45deg); border-radius: 2px; z-index: -1; }
.bl-slider { width: 100%; display: block; margin: 0; -webkit-appearance: none; appearance: none; height: 10px; border-radius: 999px; outline: none; cursor: pointer; touch-action: pan-y;
  background:
    linear-gradient(var(--c), var(--c)) left center / calc(12px + (100% - 24px) * var(--p)) 100% no-repeat,
    linear-gradient(90deg, rgba(244,63,94,0.28), rgba(232,184,0,0.28), rgba(20,184,166,0.28)); }
html[dir="rtl"] .bl-slider {
  background:
    linear-gradient(var(--c), var(--c)) right center / calc(12px + (100% - 24px) * var(--p)) 100% no-repeat,
    linear-gradient(270deg, rgba(244,63,94,0.28), rgba(232,184,0,0.28), rgba(20,184,166,0.28)); }
.bl-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 24px; height: 24px; border-radius: 50%; background: var(--c); border: 3px solid #fff; box-shadow: 0 1px 6px rgba(0,15,71,0.35); cursor: grab; transition: transform .12s; }
.bl-slider::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: var(--c); border: 3px solid #fff; box-shadow: 0 1px 6px rgba(0,15,71,0.35); cursor: grab; }
.bl-slider:active::-webkit-slider-thumb { transform: scale(1.2); cursor: grabbing; }
.bl-slider:focus-visible { box-shadow: 0 0 0 3px rgba(14,165,233,0.35); }
/* wobble on every step, leaning the way the thumb is moving */
@keyframes blTickR { 0% { transform: scale(1.16) rotate(-5deg); } 55% { transform: scale(1.06) rotate(3deg); } 100% { transform: scale(1) rotate(0); } }
@keyframes blTickL { 0% { transform: scale(1.16) rotate(5deg); } 55% { transform: scale(1.06) rotate(-3deg); } 100% { transform: scale(1) rotate(0); } }
@media (prefers-reduced-motion: no-preference) {
  .bl-slider-val.tick-r .bl-sv-num { animation: blTickR .18s ease-out; }
  .bl-slider-val.tick-l .bl-sv-num { animation: blTickL .18s ease-out; }
}
.bl-slider-anchors { display: flex; justify-content: space-between; font-size: 12px; font-weight: 700; color: var(--muted); margin-top: 8px; }
.bl-slider-anchors span { display: inline-flex; align-items: center; gap: 5px; }
.bl-slider-anchors span::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--red-m); }
.bl-slider-anchors span:last-child::before { background: var(--green); }
.bl-slider-anchors span:first-child { color: var(--red-text); }
.bl-slider-anchors span:last-child { color: var(--green-text); }

.bl-ppg-ring-wrap { position: relative; width: 140px; height: 140px; margin: 10px auto 16px; }
.bl-ring, .bl-ring-lg { width: 100%; height: 100%; transform: rotate(-90deg); }
.bl-ring-bg { fill: none; stroke: var(--border); stroke-width: 8; }
.bl-ring-fg { fill: none; stroke: var(--accent); stroke-width: 8; stroke-linecap: round; transition: stroke-dashoffset .3s linear; }
.bl-ring-fg.bl-ring-low { stroke: var(--red-m); }
.bl-ring-fg.bl-ring-mid { stroke: var(--gold); }
.bl-ring-fg.bl-ring-high { stroke: var(--green); }
.bl-ring-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.bl-ring-hr { font-family: var(--font-ui); font-weight: 900; font-size: 26px; color: var(--navy); }
.bl-ring-hr-label { font-size: 10px; color: var(--muted); margin-top: 2px; }
.bl-ppg-status { font-size: 13px; font-weight: 700; color: var(--accent-text); margin-bottom: 14px; min-height: 18px; }

.bl-bolt-timer { font-family: var(--font-ui); font-weight: 900; font-size: 40px; color: var(--navy); margin: 18px 0; }
.bl-hold-btn {
  width: 140px; height: 140px; border-radius: 50%; border: none; background: var(--gradient-cta);
  color: var(--navy); font-weight: 900; font-size: 15px; box-shadow: var(--glow-primary);
  transition: transform .15s, filter .15s; touch-action: none; user-select: none; -webkit-user-select: none;
}
.bl-hold-btn.holding { transform: scale(1.08); filter: brightness(0.97); }
.bl-hold-btn.bolt-warn { animation: blWarnPulse 1s ease-in-out infinite; }
@keyframes blWarnPulse { 0%,100% { box-shadow: var(--glow-primary); } 50% { box-shadow: 0 0 0 10px rgba(244,63,94,0.18); } }

.bl-tapsync-arena { cursor: pointer; user-select: none; -webkit-user-select: none; touch-action: manipulation; }
.bl-tapsync-pulse {
  width: 90px; height: 90px; border-radius: 50%; margin: 18px auto; background: var(--accent-soft);
  border: 2px solid rgba(var(--accent-rgb),0.3); animation: blAmbientBreath 7s ease-in-out infinite;
}
@keyframes blAmbientBreath { 0%,100% { transform: scale(0.85); opacity: .6; } 50% { transform: scale(1.05); opacity: 1; } }
.bl-pulse-tap { animation: blTapFlash .35s ease-out; }
@keyframes blTapFlash { 0% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0.4);} 100% { box-shadow: 0 0 0 22px rgba(var(--accent-rgb),0);} }
.bl-tapsync-counter { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
.bl-tapsync-timer { font-family: var(--font-ui); font-weight: 900; font-size: 22px; color: var(--accent-text); margin-bottom: 12px; }

.bl-spinner {
  width: 42px; height: 42px; border-radius: 50%; border: 4px solid var(--border); border-top-color: var(--accent);
  animation: blSpin .9s linear infinite; margin: 10px auto 18px;
}
@keyframes blSpin { to { transform: rotate(360deg); } }

.bl-results-wrap { padding: 18px 22px 28px; flex: 1; }

/* ============================================================
   Results dashboard — ported verbatim (structure/CSS values) from
   EyeFocus's real live #results screen per Lea's 2026-08-20 request
   ("זה צריך להיות זהה מבחינת נראות!! כולל האייקונים וכולל הכל"),
   with KPI/copy content adapted to EaseFocus's own baseline metrics.
   See js/baseline.js blRenderResults()/blDrawGauge() for the JS half
   (canvas gauge + easing ported from EyeFocus's results.js, unaltered
   per neupractix-design-system's "never touch animateGauge() easing").
   ============================================================ */
.res-dash-header {
  background: var(--white); border-bottom: 1px solid var(--border);
  padding: 16px 20px 14px; display: flex; align-items: center; gap: 14px; flex-shrink: 0;
}
.rdh-icon {
  width: 44px; height: 44px; border-radius: 12px; background: var(--accent-soft);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.rdh-icon-img { width: 26px; height: 26px; object-fit: contain; }
.rdh-title { font-size: 20px; font-weight: 800; font-family: var(--font-ui); color: var(--text); margin: 0; }
.rdh-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.rdh-badge { margin-inline-start: auto; padding: 5px 12px; border-radius: 20px; font-size: 13px; font-weight: 900; flex-shrink: 0; }

.gauge-card {
  background: var(--white); margin: 12px 14px 0;
  border-radius: 18px; border: 1px solid var(--border);
  padding: 16px 16px 14px; display: flex; flex-direction: column;
  align-items: center; gap: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.gauge-card-title { font-size: 11px; font-weight: 700; letter-spacing: 1px; color: var(--muted); text-transform: uppercase; }
.info-row { display: flex; align-items: center; justify-content: center; gap: 5px; }
.info-btn-hint { animation: infoHintPulse 1.8s ease-in-out infinite; }
@keyframes infoHintPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0.35); }
  50% { box-shadow: 0 0 0 5px rgba(var(--accent-rgb),0); }
}
.gauge-wrap { position: relative; width: 200px; height: 108px; }
#resultsGaugeCanvas { position: absolute; top: 0; left: 0; }
/* the % sits fully below the arc/needle, never inside it, so the needle
   can never pass through the number at any score */
.gauge-center { margin-top: -4px; text-align: center; white-space: nowrap; }
.gauge-pct { font-size: 30px; font-weight: 900; color: var(--text); line-height: 1; }
.gauge-lbl { font-size: 12px; color: var(--muted); margin-top: 2px; }
.gauge-verdict { font-size: 13px; color: var(--muted); text-align: center; margin: 0; }

/* KPI cards — per neupractix-assessment-stage's results-dashboard grid, one
   card per measured sub-score, each with a star rating and an info-pop. */
.game-kpi-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 10px 14px 0; }
.game-kpi {
  position: relative; min-height: 80px;
  background: var(--white); border: 1.5px solid var(--border);
  border-radius: 16px; padding: 14px 12px 12px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.04); text-align: center;
}
.gk-stars { font-size: 12px; letter-spacing: 1px; line-height: 1; min-height: 14px; color: var(--gold); }
.gk-stars.kpi-stars-unmeasured { color: var(--border); }
.gk-label { font-size: 10px; font-weight: 800; font-family: var(--font-ui); letter-spacing: 0.5px; color: var(--muted); text-transform: uppercase; }
.gk-val { font-size: 22px; font-weight: 900; color: var(--text); line-height: 1; font-family: var(--font-ui); }
.gk-val-word { font-size: 13px; font-weight: 800; }

.info-btn {
  width: 15px; height: 15px; flex-shrink: 0; border-radius: 50%;
  border: 1.3px solid var(--muted); background: none; color: var(--muted);
  font-size: 10px; font-style: italic; font-weight: 700; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  padding: 0; cursor: pointer; font-family: var(--font-ui);
  transition: transform .1s, border-color .15s, color .15s;
}
.info-btn:hover, .info-btn:focus-visible { border-color: var(--accent); color: var(--accent-text); }
.info-btn:active { transform: scale(0.9); }
.info-btn img { width: 11px; height: 11px; object-fit: contain; }
.info-pop {
  font-size: 11.5px; line-height: 1.55; color: var(--muted-text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; margin-top: 6px;
  text-align: start;
}
.info-pop[hidden] { display: none; }

/* Training-program teaser card — the one primary gradient action on this
   screen (per neupractix-design-system's "exactly one primary button"). */
.train-card {
  margin: 10px 14px 0; background: var(--white);
  border: 1.5px solid var(--border); border-radius: 16px; padding: 14px 16px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.train-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.train-icon { font-size: 20px; }
.train-title { font-size: 14px; font-weight: 900; color: var(--text); font-family: var(--font-ui); }
.train-teaser-text { font-size: 13px; color: var(--muted); line-height: 1.55; margin: 0 0 10px; }
.train-cta-btn {
  width: 100%; padding: 14px; background: var(--gradient-cta); color: var(--navy);
  border: none; border-radius: 999px;
  font-family: var(--font-body); font-size: 15px; font-weight: 900;
  cursor: pointer; box-shadow: var(--glow-primary);
  transition: transform .12s, filter .15s;
}
.train-cta-btn:hover { filter: brightness(0.95); }
.train-cta-btn:active { transform: scale(0.96); }

/* Soft-glass card treatment — ported from EyeFocus's own shared rule
   (neupractix-design-system's "Soft Glass" pattern), which these results-
   screen cards were missing entirely (solid opaque --white instead). This
   is the source of the "missing halo" Lea reported: a frosted, softly-lit
   card reads as gently glowing against the page background; a flat opaque
   card does not, even with an identical box-shadow underneath it. */
.gauge-card, .game-kpi, .train-card {
  background: var(--glass-bg);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-color: var(--glass-border);
}

.dash-btns { padding: 14px 14px 32px; display: flex; flex-direction: column; gap: 10px; }
/* a quieter bubble than .train-cta-btn — retaking the check is a secondary
   action here, not the screen's primary one. */
.replay-btn {
  width: 100%; padding: 13px; background: var(--accent-soft); color: var(--accent-text);
  border: 1.5px solid rgba(var(--accent-rgb),0.22); border-radius: 999px;
  font-size: 14px; font-weight: 800; font-family: var(--font-ui);
  cursor: pointer; box-shadow: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: transform .12s, background .15s;
}
.replay-btn .icon-inline { width: 1.1em; height: 1.1em; }
.replay-btn:hover { background: rgba(var(--accent-rgb),0.14); }
.replay-btn:active { transform: scale(0.97); }

.bl-goal-row { font-size: 13.5px; color: var(--text); margin-bottom: 6px; display: flex; gap: 8px; align-items: center; }
.bl-goal-row:last-child { margin-bottom: 0; }

.bl-pacer-wrap { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px 0; }
.bl-pacer-circle { width: 140px; height: 140px; border-radius: 50%; background: var(--gradient-cta); box-shadow: var(--glow-primary); transform: scale(0.55); }
.bl-pacer-label { margin-top: 20px; font-family: var(--font-ui); font-weight: 900; font-size: 18px; color: var(--navy); }

/* Front-camera PPG fallback (iOS/no-torch devices): a bright full-screen white
   flash behind the still-visible ring/status UI (raised via .bl-card's z-index)
   acts as an alternative light source for the fingertip. */
body.bl-flash-fallback::before { content: ""; position: fixed; inset: 0; background: #FFFFFF; z-index: 1; }

/* ---------- Utility ---------- */
.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;
}

/* ==========================================================================
   Training program (14-day sprint + maintenance) — new this round.
   Reuses .bl-intro-wrap / .bl-title / .bl-body / .bl-steps / .bl-step-num /
   .bl-h2 / .bl-center / .bl-results-wrap / .bl-note / .device-notice from
   the baseline-assessment + shared design-system rules above; only the
   dashboard/session-runner-specific pieces are new (.tr-*).
   ========================================================================== */

.tr-view { display: none; flex: 1; flex-direction: column; }
.tr-view.active { display: flex; }

/* 2026-09-11 (Lea, matching her EyeFocus reference): the dashboards and the
   session summary sit in a bounded white card on the page's own background,
   not as a full-bleed panel filling the screen. Two reasons, and the second
   is the one that matters: it is how the rest of the family looks, and the
   SECRET SPACE card is going in underneath — which needs the screen to be a
   column of cards rather than one panel with nothing below it.

   `flex: 1` is deliberately NOT inherited here: a card that stretches to
   fill the viewport pushes whatever follows it off the bottom of the
   screen, which is precisely what has to stop. */
.tr-card-screen {
  flex: 1;
  /* 2026-09-11 (Lea, second pass: "make the frame a bit smaller still") —
     the card is inset from the column's edges rather than nearly filling it,
     which is what makes it read as a card sitting ON the page instead of as
     the page. Matched to her EyeFocus reference, where the card is roughly
     four fifths of the column's width. */
  padding: 18px 40px 28px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow-y: auto;
}
.tr-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow: 0 4px 18px rgba(30,41,59,0.06);
  padding: 22px 20px 24px;
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
}
@media (max-width: 380px) { .tr-card-screen { padding: 14px 22px 22px; } .tr-card { padding: 18px 14px 20px; } }

.tr-dash-wrap { padding: 22px 22px 28px; flex: 1; display: flex; flex-direction: column; }
/* The wrapper IS the card on these screens (class="tr-card tr-dash-wrap"),
   so its own page-level padding and its flex:1 stretch have to go — the
   stretch is what leaves a tall empty gap inside the card and pushes
   whatever follows off the bottom of the screen. */
.tr-card.tr-dash-wrap,
.tr-card.bl-results-wrap { padding: 22px 20px 24px; flex: 0 0 auto; }
@media (max-width: 380px) { .tr-card.tr-dash-wrap, .tr-card.bl-results-wrap { padding: 18px 14px 20px; } }
.tr-day-badge { font-family: var(--font-ui); font-weight: 900; font-size: 22px; color: var(--navy); text-align: center; margin: 4px 0 14px; }
.tr-progress-track { height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; }
.tr-progress-fill { height: 100%; background: var(--gradient-cta); border-radius: 999px; transition: width .4s ease; width: 0%; }
.tr-phase-label { margin: 10px 0 20px; font-size: 12.5px; font-weight: 700; color: var(--muted); text-align: center; }
/* 2026-08-20: restyled per Lea — the two secondary actions were both
   full-weight .btn-quiet pills, side by side and visually identical, which
   read as "two buttons of the same importance" against MoveFocus's real
   dashboard (fetched from movefocus.net/js/training/training.js), where
   they're two clearly different weights: the reminder is a plain text link
   (.home-link/.reminder-link) and "last results" is the only pill-styled
   secondary action (.home-link-cta) — stacked, not side by side. */
.tr-dash-actions { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 12px; }

/* ── שורת שעת התזכורת (Lea, 23/09/2026) ──────────────────────────────
   לפי העיצוב שהיא שלחה מ-MoveFocus: תווית קטנה ושדה שעה, זה לצד זה,
   ממורכזים מעל הקישור "שמור תזכורת ביומן". היא ביקשה במפורש שזה יהיה
   גלוי במסך ולא מאחורי חלונית.
   flex-direction: row עם logical gap — הסדר מתהפך לבד ב-RTL. */
.tr-reminder-row {
  display: flex; align-items: center; justify-content: center;
  gap: 10px; margin-top: 14px; flex-wrap: wrap;
}
.tr-reminder-label {
  font-family: var(--font-ui);
  font-size: 12px; font-weight: 700; color: var(--muted);
  letter-spacing: .3px;
}
/* אותה שפה עיצובית של שאר שדות הקלט: פינות 14px, מסגרת דקה, צל רך
   וטבעת מיקוד — רק צר יותר, כי זו שעה ולא משפט. */
.tr-reminder-time {
  font-family: var(--font-ui);
  font-size: 14px; font-weight: 700; color: var(--text);
  padding: 8px 12px; border-radius: 14px;
  border: 1.5px solid var(--border); background: var(--white);
  box-shadow: 0 1px 4px rgba(0,0,0,0.04);
  min-height: 40px;                     /* יעד מגע, גם כשהשדה צר */
}
.tr-reminder-time:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* ב-iOS שדה time נראה כברירת מחדל כמו טקסט חופשי בלי גובה קבוע. */
.tr-reminder-time::-webkit-date-and-time-value { text-align: center; }
/* 2026-08-20 follow-up: swapped the raw 🔔 emoji for the real alarm-bell
   icon asset (per the design system's "no raw emoji" icon rule) and
   dropped .home-link's inherited underline — Lea wants this as a plain,
   un-underlined icon+text link. Icon lives in a sibling <img>, not baked
   into the translated string, so data-i18n swapping languages never
   clobbers it (see index.html). */
.reminder-link {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--accent-text); font-weight: 700; text-decoration: none;
}
.reminder-link .icon-inline { width: 1.1em; height: 1.1em; }
/* .reminder-link is inline-flex (for the icon+text usages above), which
   blockifies to "flex" as a flex-column child and packs its content to
   justify-content's default (flex-start) — text-align:center has no effect
   there. This icon-less "Back to home" usage on #blResults needs its own
   centering + a lighter weight than the icon links (Lea 2026-09-07). */
.results-back-link { justify-content: center; font-weight: 400; }
.home-link-cta {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 800; color: var(--accent-text);
  background: var(--accent-soft); border: 1.5px solid rgba(var(--accent-rgb),0.3);
  border-radius: 20px; padding: 8px 18px; text-align: center;
  font-family: var(--font-body); cursor: pointer; transition: transform .1s, background .15s;
}
.home-link-cta .icon-inline { width: 1.1em; height: 1.1em; }
.home-link-cta:hover { background: rgba(var(--accent-rgb),0.14); }
.home-link-cta:active { transform: scale(0.97); }

/* 3-2-1-GO countdown overlay — restyled 2026-08-20 to match EyeFocus's real
   countdown screen (fetched directly from eye-focus.vercel.app/css/styles.css:
   .countdown-overlay uses background:var(--bg), and .countdown-num is
   96px/900/var(--accent-text) — a plain light screen with a big accent-
   colored numeral, not the dark-navy/white-text overlay this used to be.
   Lea flagged the previous dark version as jarring for a calming breathing
   app. The device-notice now flows naturally below the number (like
   EyeFocus's .countdown-hint under .countdown-num) instead of being pinned
   to the bottom of a dark screen. */
/* 2026-09-07 (Lea): the pre-session countdown is BEFORE the session goes
   into its own dark theme (efShowTrView() hasn't put "dark-session" on
   #training yet at this point), so it needs its own always-dark styling
   here rather than relying on that class — black background, light-on-dark
   text throughout. (This reverses the 2026-08-xx "light background, jarring
   in dark" fix — Lea confirmed on 2026-09-07 that EyeFocus's real countdown
   IS dark and that's what she wants here too.)
   2026-09-07: number sitting near the TOP, not vertically centered.
   2026-09-28 (Lea, "true for every exercise"): reversed again — the
   countdown should be vertically centered on the screen. */
.tr-countdown-overlay {
  position: absolute; inset: 0; z-index: 50; background: #070F18;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px;
}
.tr-countdown-num { font-family: var(--font-ui); font-weight: 900; font-size: 96px; color: #5EEAD4; line-height: 1; }
/* Applied via JS on each digit change (remove/reflow/add), not baked into
   .tr-countdown-num permanently — a class that's already present when the
   text changes never replays its animation, so 3-2-1 would only pop once. */
.tr-countdown-num.countdown-pop { animation: trCountdownPop 900ms ease; }
@keyframes trCountdownPop { 0% { transform: scale(0.6); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); } }
.tr-countdown-notice, .bl-countdown-notice { max-width: 300px; }
/* GO now waits for a tap, and this is the moment to get a fingertip onto
   the camera — 2026-09-10 (Lea). */
.tr-countdown-tap { margin-top: 14px; font-family: var(--font-ui); font-weight: 800; font-size: 16px; color: #EAFBFF; }

/* Fingertip-on-camera reminder. Deliberately loud — it is the one thing a
   trainee has to DO for the pulse reading to work at all, and Lea's note
   was that it wasn't clear when to do it. Same chip on the GO screen (large)
   and inside the session (compact), so the two read as one instruction. */
.tr-cam-chip {
  display: inline-flex; align-items: center; gap: 8px; text-align: start;
  padding: 8px 12px; border-radius: 14px;
  background: rgba(94,234,212,0.10); border: 1px solid rgba(94,234,212,0.45);
  color: #A7F3D0; font-weight: 800; line-height: 1.45;
  box-shadow: 0 0 0 0 rgba(94,234,212,0.35);
  animation: efCamPulse 2.4s ease-in-out infinite;   /* 0.42Hz — far under the 3Hz flicker floor */
}
/* 2026-09-30: found while adding the breath-steps indicator just below this
   chip. `display: inline-flex` above has real specificity, so it always
   beats the UA stylesheet's own (specificity-less) `[hidden] { display:
   none }` rule — the `.hidden`/`hidden` attribute toggle in js/training.js
   was therefore never actually hiding this chip, just leaving it empty
   (no icon caption text) on every non-camera exercise (pacer, sigh). This
   explicit, more-specific override restores what `hidden` was always
   supposed to do. */
.tr-cam-chip[hidden] { display: none; }
.tr-cam-chip-icon { flex: 0 0 auto; }
@keyframes efCamPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(94,234,212,0.30); }
  50%      { box-shadow: 0 0 0 6px rgba(94,234,212,0); }
}
@media (prefers-reduced-motion: reduce) { .tr-cam-chip { animation: none; } }
.tr-cam-chip-lg { margin-top: 12px; max-width: 320px; font-size: 13.5px; padding: 11px 14px; }
.tr-camera-hint { margin: 8px 0 2px; font-size: 12.5px; }
.tr-intro-camera { margin: 4px auto 2px; }
.tr-intro-notice { margin: 10px auto 4px; max-width: 320px; }

/* Tap-to-start gate over the exercise area — 2026-09-10 (Lea): arriving at
   an exercise should be calm, so nothing runs and no clock starts until the
   trainee taps. Fills the exercise area rather than being a small target,
   so the tap is effortless. */
.tr-tap-start {
  position: absolute; inset: 0; z-index: 4;
  display: flex; align-items: center; justify-content: center;
  border-radius: 18px; cursor: pointer;
  /* Barely-there scrim: the exercise's own frozen first frame has to stay
     clearly visible behind the button (Lea's reference), so this only takes
     the edge off the contrast rather than hiding the scene. */
  background: rgba(7,15,24,0.10);
  -webkit-tap-highlight-color: transparent;
}
.tr-tap-start-inner { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 0 16px; }
.tr-tap-start-alt { max-width: 260px; text-align: center; font-size: 12.5px; font-weight: 700; line-height: 1.45; color: rgba(226,240,247,0.72); }
/* Brightens while a fingertip is actually detected on the lens, so the
   trainee gets immediate confirmation they have it in the right place. */
.tr-tap-start.is-detecting .tr-tap-start-btn {
  border-color: #86EFAC; color: #D9FBE7;
  box-shadow: 0 0 26px rgba(134,239,172,0.45), inset 0 0 18px rgba(134,239,172,0.18);
}
.tr-tap-start-btn {
  pointer-events: none;                 /* the whole gate is the target */
  max-width: 260px; text-align: center;
  /* 2026-09-10 (Lea): transparent and lifted above centre, so the frozen
     frame reads through it — the same ghost-pill treatment as her EyeFocus
     reference rather than a solid gradient bubble covering the scene. */
  padding: 13px 26px; border-radius: 999px;
  border: 2px solid rgba(94,234,212,0.85);
  background: transparent; color: #A7F3D0;
  font-family: var(--font-ui); font-weight: 900; font-size: 16px;
  text-shadow: 0 1px 10px rgba(7,15,24,0.85);
  box-shadow: 0 0 18px rgba(94,234,212,0.28), inset 0 0 14px rgba(94,234,212,0.10);
  transform: translateY(-14%);
  animation: efTapPulse 2.4s ease-in-out infinite;   /* 0.42Hz, well under the 3Hz floor */
}
@keyframes efTapPulse {
  0%, 100% { transform: translateY(-14%) scale(1); }
  50%      { transform: translateY(-14%) scale(1.04); }
}
@media (prefers-reduced-motion: reduce) { .tr-tap-start-btn { animation: none; } }


.tr-countdown-overlay .device-notice { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.18); color: #E6E8EC; }

/* Session runner chrome — 2026-09-07: restructured to match Lea's reference
   (an EyeFocus live game screen): a top bar (this exercise's own icon+name
   at the start edge, the running score pill at the end edge — was a
   separately-centered .tr-hud below the timeline), then the 3-segment
   timeline where each segment now shows an actual progress BAR (not just a
   dimmed/undimmed icon+label) that fills smoothly over that segment's real
   duration via a plain CSS width transition timed by JS (see
   efSetTimelineSegment() in js/training.js) — no per-exercise engine change
   needed, .tr-seg-bar-fill just animates on its own clock. */
.tr-session-chrome { flex: 1; display: flex; flex-direction: column; padding: 16px 20px 24px; }
/* 2026-09-10 (Lea): titles can now be a full sentence ("Square Breathing:
   Inhale - Hold - Exhale - Hold"), so the title block wraps and shrinks
   inside its own column instead of running under the score pill. */
.tr-game-topbar { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.tr-game-id { display: flex; align-items: flex-start; gap: 8px; min-width: 0; flex: 1 1 auto;
  font-family: var(--font-ui); font-weight: 900; font-size: 13.5px; line-height: 1.35; color: var(--text); }
.tr-game-id span { min-width: 0; overflow-wrap: anywhere; }
.tr-game-id img.icon-inline { width: 22px; height: 22px; border-radius: 50%; flex: 0 0 auto; margin-top: 1px; }
.tr-game-topbar .tr-hud { flex: 0 0 auto; }
.tr-timeline { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.tr-timeline-seg { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.tr-seg-bar { width: 100%; height: 4px; border-radius: 999px; background: var(--border); overflow: hidden; }
.tr-seg-bar-fill { display: block; height: 100%; width: 0%; background: var(--teal); border-radius: 999px; }
/* 2026-09-07: segment icons are now real full-color assets (walking/
   lightning/trophy, from Lea's own icon set) — the dim/active states dim
   via opacity only, never grayscale, or the color that's the whole point
   of using these specific files gets washed out. */
.tr-seg-label { display: flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 700; color: var(--muted); text-align: center; opacity: .55; transition: opacity .3s; }
.tr-seg-label img { width: 16px; height: 16px; }
.tr-timeline-seg.tr-seg-active .tr-seg-label { opacity: 1; color: var(--accent-text); font-weight: 900; }
.tr-timeline-seg.tr-seg-dim .tr-seg-label { opacity: .4; }
.tr-instruction { font-family: var(--font-ui); font-size: 17px; font-weight: 900; color: var(--accent-text); text-align: center; margin-bottom: 12px; display: flex; align-items: center; justify-content: center; gap: 8px; }
.tr-instruction img { width: 20px; height: 20px; }
.tr-hud { font-family: var(--font-ui); font-weight: 900; font-size: 15px; color: var(--accent-text); background: var(--accent-soft); border-radius: 999px; padding: 4px 14px; flex-shrink: 0; }
.tr-exercise-container { position: relative; flex: 1; display: flex; align-items: center; justify-content: center; min-height: 300px; }

/* Per-exercise intro screen — 2026-09-07 (Lea), matched against her
   EyeFocus reference screenshot. Dark by default via #training.dark-session
   (efShowTrView() now includes "trExerciseIntro" in its dark-screen set —
   see js/training.js), so colors below are the dark-theme values directly,
   not a light default later overridden. */
.tr-intro-chrome { display: flex; flex-direction: column; align-items: center; justify-content: center; flex: 1; padding: 24px 20px; }
.tr-intro-gameof { font-family: var(--font-ui); font-size: 11px; font-weight: 800; letter-spacing: 1.5px; text-transform: uppercase; color: #97A0B2; margin-bottom: 16px; text-align: center; }
.tr-intro-card {
  width: 100%; max-width: 340px; background: rgba(255,255,255,0.04);
  border: 1px solid rgba(224,225,221,0.12); border-radius: 24px;
  padding: 28px 22px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.tr-intro-play {
  width: 56px; height: 56px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
/* The play triangle is the FALLBACK — it only appears when the exercise has
   no icon of its own registered, so the badge is never empty. The gradient
   circle now belongs only to that fallback: 2026-09-28 (Lea, "true for
   every exercise") — when there IS an icon, it should stand on its own,
   not sit inside a gradient circle. */
.tr-intro-play:not(.has-icon) {
  border-radius: 50%; background: var(--gradient-cta); box-shadow: var(--glow-primary);
}
.tr-intro-play:not(.has-icon)::after {
  content: ""; display: block; width: 0; height: 0;
  border-style: solid; border-width: 9px 0 9px 15px;
  border-color: transparent transparent transparent var(--navy);
  margin-inline-start: 3px;
}
.tr-intro-play img { width: 32px; height: 32px; object-fit: contain; }
/* Standing alone (no badge behind it), the icon reads small at 32px — give
   it the room the circle used to fill. */
.tr-intro-play.has-icon img { width: 64px; height: 64px; }
.tr-intro-play.has-icon { width: auto; height: auto; }
.tr-intro-title { font-family: var(--font-ui); font-size: 20px; font-weight: 900; color: #F2F4F7; margin: 0; }
.tr-intro-subtitle { font-size: 13px; font-weight: 700; color: #FBBF24; margin: -6px 0 0; line-height: 1.4; }
.tr-intro-instruction { font-size: 13.5px; color: #C2C8D4; line-height: 1.6; margin: 0; }
.tr-intro-cta { width: 100%; margin-top: 4px; }

/* Rest interstitial — dark card matching the reference (moon icon, "Rest"
   title, a live countdown number, an "Up next" line naming the next
   exercise). Also dark via #training.dark-session's "trRest" membership. */
/* Start-vs-end pulse comparison screen — 2026-09-08 (Lea). Same dark card
   language as the rest interstitial, so it reads as part of the same
   in-session flow rather than as a separate report. */
.tr-hrc-card {
  margin: auto; width: 100%; max-width: 330px; text-align: center;
  background: rgba(255,255,255,0.04); border: 1px solid rgba(224,225,221,0.12);
  border-radius: 24px; padding: 26px 22px;
}
.tr-hrc-title { font-family: var(--font-ui); font-size: 17px; font-weight: 900; color: #F2F4F7; }
.tr-hrc-ex { font-size: 12.5px; color: #9AA6B8; margin-top: 4px; }
.tr-hrc-body { margin: 18px 0 20px; }
.tr-hrc-pair { display: flex; align-items: center; justify-content: center; gap: 10px; }
.tr-hrc-cell { flex: 1 1 0; min-width: 0; }
.tr-hrc-cell-label { font-size: 12px; color: #9AA6B8; margin-bottom: 4px; }
.tr-hrc-cell-val { font-family: var(--font-ui); font-size: 34px; font-weight: 900; color: #5EEAD4; line-height: 1.1; }
.tr-hrc-cell-unit { font-size: 11px; color: #8D99AB; margin-top: 2px; }
.tr-hrc-arrow { flex: 0 0 auto; font-size: 22px; color: #7C8B99; }
[dir="rtl"] .tr-hrc-arrow { transform: scaleX(-1); }
.tr-hrc-delta { margin-top: 16px; font-size: 13.5px; font-weight: 700; color: #C2C8D4; line-height: 1.5; }
.tr-hrc-delta.is-down { color: #86EFAC; }
.tr-hrc-none { font-size: 14px; font-weight: 700; color: #E4E9F0; line-height: 1.55; }
.tr-hrc-none-sub { margin-top: 8px; font-size: 12.5px; font-weight: 400; color: #9AA6B8; line-height: 1.55; }
.tr-hrc-btn { max-width: 220px; margin: 0 auto; }

/* 2026-09-28 (Lea, "true for every exercise"): the rest screen between
   exercises should sit at the TOP of the screen — the opposite of the
   countdown above, which she wants vertically centered. Was `margin: auto`
   on the card, which (being a flex child of #trRest, itself `flex:1;
   flex-direction:column`) centers vertically regardless of the parent's own
   justify-content, since auto margins always win over it. Dropping to
   `margin: 0 auto` keeps the horizontal centering and lets #trRest's own
   top-anchoring below take effect. */
#trRest { justify-content: flex-start; padding-top: 56px; }
.tr-rest-card {
  margin: 0 auto; width: 100%; max-width: 300px; text-align: center;
  background: rgba(255,255,255,0.04); border: 1px solid rgba(224,225,221,0.12);
  border-radius: 24px; padding: 30px 24px;
}
.tr-rest-icon { font-size: 40px; margin-bottom: 8px; }
.tr-rest-title { font-family: var(--font-ui); font-size: 16px; font-weight: 900; color: #F2F4F7; }
.tr-rest-num { font-family: var(--font-ui); font-size: 44px; font-weight: 900; color: #FBBF24; line-height: 1.2; margin: 6px 0; }
.tr-rest-instruction { font-size: 13px; color: #C2C8D4; line-height: 1.5; margin: 0 0 8px; }
.tr-rest-upnext { font-size: 13px; font-weight: 700; color: #97A0B2; display: flex; align-items: center; justify-content: center; gap: 6px; }
.tr-rest-upnext-icon {
  display: inline-flex; width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0;
  background: var(--gradient-cta); align-items: center; justify-content: center;
}
.tr-rest-upnext-icon::after {
  content: ""; display: block; width: 0; height: 0;
  border-style: solid; border-width: 4px 0 4px 6px;
  border-color: transparent transparent transparent var(--navy);
  margin-inline-start: 1px;
}

/* 2026-08-20: sprint dashboard rebuilt as a real day-grid (14 cells, ✓ for
   done, pulsing highlight on next, click a done day to expand its detail)
   and the day summary rebuilt with a per-exercise breakdown — both matched
   exactly against MoveFocus's real, live css/styles.css (fetched directly
   from movefocus.net), not approximated from notes. Values below are the
   verbatim reference rules; only color tokens are EaseFocus's own. */
.day-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 7px; width: 100%; margin-bottom: 4px; }
.day-cell { aspect-ratio: 1; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-family: var(--font-ui); font-size: 13px; font-weight: 900; background: var(--bg); color: var(--muted); border: 1.5px solid var(--border); }
.day-cell.done { background: rgba(20,184,166,0.12); color: var(--green-text); border-color: rgba(20,184,166,0.35); cursor: pointer; transition: transform .12s, box-shadow .15s; }
.day-cell.done:hover { transform: scale(1.06); box-shadow: 0 2px 10px rgba(20,184,166,0.25); }
.day-cell.next { background: var(--accent-soft); color: var(--accent-text); border-color: var(--accent); animation: nextPulse 1.6s infinite; }
@keyframes nextPulse { 50% { box-shadow: 0 0 0 4px rgba(14,165,233,0.12); } }

.day-detail { width: 100%; background: var(--bg); border: 1.5px solid var(--border); border-radius: 16px; padding: 12px; display: flex; flex-direction: column; gap: 8px; animation: ddFadeIn .25s ease; margin-top: 10px; }
@keyframes ddFadeIn { from { opacity: 0 } to { opacity: 1 } }
.dd-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: var(--text); }
.dd-head strong { color: var(--accent-text); }
.dd-close { margin-inline-start: auto; background: none; border: none; font-size: 14px; color: var(--muted); cursor: pointer; font-family: var(--font-body); }

.sum-rows { width: 100%; display: flex; flex-direction: column; gap: 8px; }
.sum-row { display: flex; align-items: center; gap: 8px; background: var(--bg); border-radius: 12px; padding: 10px 12px; }
/* 2026-09-07 (Lea): each row's icon now sits in a colored circular badge
   (performance-tier tinted, same palette as the results header's %-badge)
   instead of a bare icon, matching her EyeFocus reference. */
.sum-row-icon {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid; box-sizing: border-box;
}
.sum-row-icon img.icon-inline { width: 16px; height: 16px; }
.sum-name { flex: 1; font-size: 13px; font-weight: 700; color: var(--text); text-align: start; }
.sum-acc { font-size: 15px; font-weight: 900; color: var(--accent-text); }

.stars { display: inline-flex; gap: 4px; direction: ltr; }
.star { color: var(--circle-bg); transition: color .3s; }
.star.on { color: var(--gold); text-shadow: 0 2px 10px rgba(232,184,0,0.35); }
.stars.lg .star { font-size: 42px; }
.stars.lg .star.on { animation: starPop .5s ease backwards; }
.stars.lg .star.on:nth-child(2) { animation-delay: .15s; }
.stars.lg .star.on:nth-child(3) { animation-delay: .3s; }
@keyframes starPop { from { transform: scale(0) rotate(-30deg); } 60% { transform: scale(1.25); } to { transform: scale(1); } }
.stars.sm .star { font-size: 13px; }

.sum-card { display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; }
.sum-day { font-size: 11px; font-weight: 900; letter-spacing: 1.5px; color: var(--muted); text-transform: uppercase; }
/* 2026-09-07 (Lea): rank-medal badge on the day-summary header, reusing
   the assessment results header's rdh-icon look (colored square, same
   accent-soft tint) — was missing entirely. */
/* 2026-09-11 (Lea: "on the results page this circle is too big"). Brought
   down to the size it is in her EyeFocus reference, where it reads as a
   small medal above the stars rather than as a second headline competing
   with the score. */
.sum-rank-badge {
  width: 34px; height: 34px; border-radius: 10px; background: var(--accent-soft);
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.sum-rank-badge img.icon-inline { width: 20px; height: 20px; }
.sum-hero { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 0 2px; }
.sum-avg { font-family: var(--font-ui); font-size: 40px; font-weight: 900; color: var(--text); line-height: 1.1; }
.sum-avg-label { font-size: 11px; font-weight: 700; color: var(--muted); letter-spacing: 1px; }
.sum-praise { font-family: var(--font-ui); font-size: 15px; font-weight: 900; color: var(--accent-text); }
.sum-invite { font-size: 13px; color: var(--muted); line-height: 1.6; background: var(--accent-soft); border: 1px solid rgba(14,165,233,0.18); border-radius: 14px; padding: 10px 14px; width: 100%; text-align: center; }

/* Dark-session overrides for the day-grid/summary chrome (mirrors
   #training.dark-session's own rules on the reference site). */
#training.dark-session .sum-row { background: rgba(224,225,221,0.05); }
#training.dark-session .sum-name { color: #E6E8EC; }
#training.dark-session .sum-acc { color: #FBBF24; }
#training.dark-session .sum-avg { color: #F2F4F7; text-shadow: 0 2px 14px rgba(20,184,166,0.25); }
#training.dark-session .sum-avg-label,
#training.dark-session .sum-day { color: #97A0B2; }
#training.dark-session .sum-praise { color: #5EEAD4; }
#training.dark-session .sum-invite { color: #C2C8D4; }

.tr-compare-row { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 18px 0; }
.tr-compare-card { flex: 1; max-width: 130px; background: var(--white); border: 1px solid var(--border); border-radius: 16px; padding: 16px 10px; text-align: center; }
.tr-compare-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin-bottom: 6px; }
.tr-compare-value { font-family: var(--font-ui); font-weight: 900; font-size: 24px; color: var(--navy); }
.tr-compare-arrow { font-size: 20px; color: var(--muted); }

/* Exercise visuals — pacer / cyclic-sighing circle (reuses the Day-1 pacer's exact look) */
.tr-ex-wrap { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; }

/* Live pulse badge — 2026-09-08 (Lea): one identical badge for all nine
   camera-based exercises (previously there was no pulse indication at all).
   Pinned to the bottom inline-start corner: that is bottom-RIGHT in
   Hebrew/RTL, exactly where it sits in Lea's reference screenshots, and it
   stays clear of the floating action buttons (inline-end) in both
   directions. Purely decorative/non-interactive, so it never intercepts a
   touch meant for the exercise canvas. */
.tr-ex-wrap { position: relative; }
.ef-hr-badge { position: absolute; bottom: 14px; inset-inline-start: 14px; width: 104px; height: 104px; pointer-events: none; z-index: 3; }
.ef-hr-badge-canvas { width: 100%; height: 100%; display: block; }
@media (max-width: 380px) { .ef-hr-badge { width: 92px; height: 92px; bottom: 6px; inset-inline-start: 6px; } }
@media (prefers-reduced-motion: reduce) { .ef-hr-badge-canvas { opacity: .92; } }
/* 2026-10-01 (Lea): a visible mute toggle during SOS and Sleep — top-end
   corner, clear of the hr badge (bottom-start) and the page-level floating
   action buttons (fixed, bottom-end, a different stacking context). Same
   dark-glass disc language as .ef-hr-badge rather than the brand gradient —
   this is a quiet utility control, not the primary action on the screen. */
.ef-mute-btn {
  position: absolute; top: 14px; inset-inline-end: 14px; z-index: 4;
  width: 40px; height: 40px; border-radius: 50%; border: none;
  background: rgba(9,17,26,0.74); color: #E8FBF6;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0; transition: background .15s, transform .12s;
}
.ef-mute-btn:hover { background: rgba(9,17,26,0.88); }
.ef-mute-btn:active { transform: scale(0.92); }
.ef-mute-btn.is-muted { color: #FDA4AF; }
@media (max-width: 380px) { .ef-mute-btn { width: 34px; height: 34px; top: 8px; inset-inline-end: 8px; } }
/* 2026-09-30 (Lea): the shared breath-shape indicator (up/down/hold arrows
   over a pill track) for the two exercises with no canvas of their own —
   see efMountBreathSteps() in js/exercises.js. Every camera-based exercise
   draws the same component directly on its own canvas instead. */
.tr-breath-steps { width: 100%; max-width: 340px; margin: 4px 0 0; }
.tr-breath-steps canvas { display: block; width: 100%; }
.tr-pacer-circle-wrap { display: flex; align-items: center; justify-content: center; padding: 20px 0; }
.tr-pacer-circle { width: 140px; height: 140px; border-radius: 50%; background: var(--gradient-cta); box-shadow: var(--glow-primary); transform: scale(0.55); }
.tr-sigh-circle { background: var(--gradient-brand); }
.tr-pacer-label { margin-top: 16px; font-family: var(--font-ui); font-weight: 900; font-size: 18px; color: var(--navy); }
.tr-sigh-count { margin-top: 8px; font-size: 13px; font-weight: 700; color: var(--accent-text); }

/* Biofeedback exercise — canvas-gauge-style ring, live HR readout */
.tr-bio-ring-wrap { position: relative; width: 160px; height: 160px; }
.tr-bio-ring { width: 100%; height: 100%; transform: rotate(-90deg); }
.tr-bio-ring-bg { fill: none; stroke: var(--circle-bg); stroke-width: 8; }
.tr-bio-ring-fg { fill: none; stroke: var(--teal); stroke-width: 8; stroke-linecap: round; transition: stroke-dashoffset .3s linear; }
.tr-bio-hr { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-family: var(--font-ui); font-weight: 900; font-size: 26px; color: var(--navy); }
.tr-bio-error { margin-top: 14px; font-size: 12.5px; color: var(--red-text); text-align: center; max-width: 260px; }

/* Dolphin Dive exercise — box-breathing canvas scene (sea/sky + animated
   dolphin silhouette). Admin-test-mode only for now, not in the schedule
   pool. Canvas itself is sized dynamically in JS from this wrapper's rect. */
.tr-ex-dolphin { width: 100%; }
.tr-dolphin-canvas { display: block; width: 100%; max-width: 360px; border-radius: 20px; box-shadow: var(--glow-primary); }

/* Fog Forest exercise — Vagus Humming canvas scene (forest + central fog
   circle). Admin-test-mode only for now, not in the schedule pool. */
.tr-ex-forest { width: 100%; }
.tr-forest-canvas { display: block; width: 100%; max-width: 360px; border-radius: 20px; box-shadow: var(--glow-accent); }

/* Slow-breathing exercise — Lea's neon teardrop contour fills the whole
   canvas, with a light particle running its four phases; deliberately no
   label element (see js/exercises.js's efRunFlame comment — her spec calls
   for zero on-screen text during active practice). Portrait, matching the
   artwork's own 532x690 proportions: a square box would leave the teardrop
   floating in empty bands. Admin-test-mode only, not in the schedule pool. */
.tr-ex-flame { width: 100%; }
.tr-flame-canvas { display: block; width: 100%; max-width: 340px; aspect-ratio: 532 / 690; border-radius: 20px; box-shadow: var(--glow-primary); }

/* Panoramic Starfield exercise — a night-sky canvas scene (central "Light
   Node" + peripheral star field) fills the whole canvas; the countdown and
   the phase word are drawn into the dark core of the spiral, so there is
   still no label element (see js/exercises.js's efRunStarfield comment).
   Taller than wide from 2026-09-11: the exercise is about carrying the eye
   out to the periphery, and a square frame gives the dispersal less room to
   travel than her portrait artwork has. Admin-test-mode only, not in the
   schedule pool. */
.tr-ex-starfield { width: 100%; }
.tr-starfield-canvas { display: block; width: 100%; max-width: 360px; aspect-ratio: 5 / 6; border-radius: 20px; box-shadow: var(--glow-primary); background: #030712; }

/* Resonance Ripple exercise — a top-down still-pool canvas scene (central
   water source + expanding ripple rings) fills the whole canvas;
   deliberately no label element, same minimalist choice as Inner Flame/
   Starfield above (see js/exercises.js's efRunRipple comment).
   Admin-test-mode only, not in the schedule pool. */
.tr-ex-ripple { width: 100%; }
/* 2026-09-28 (Lea): "square frame, not round" — every other exercise's canvas
   uses the shared rounded-rectangle card treatment, but this one is a
   circular pool/bubble scene, so a round frame reads as the same shape as
   what's drawn inside it. Ripple-only exception, not a system change. */
.tr-ripple-canvas { display: block; width: 100%; max-width: 360px; aspect-ratio: 1 / 1; border-radius: 50%; box-shadow: var(--glow-accent); background: #050C16; }

/* Exhale-extension exercise — Lea's neon capsule fills the whole canvas
   with a light running the loop clockwise: the lit top is the inhale, the
   long way round is the exhale. Portrait, matching the artwork's own
   480x740; the landscape box this used to have was cut for a horizon and a
   balloon. The countdown and the phase word are drawn into the middle of
   the capsule, so there is still no label element (see js/exercises.js's
   efRunThermal comment). Admin-test-mode only, not in the schedule pool. */
.tr-ex-thermal { width: 100%; }
.tr-thermal-canvas { display: block; width: 100%; max-width: 300px; aspect-ratio: 480 / 740; border-radius: 20px; box-shadow: var(--glow-primary); background: #080A14; }

/* "Aura" (relief-sigh SOS) exercise — a single centered glowing orb, so
   square like Starfield/Ripple above rather than landscape; her spec's
   own fixed background #050811 is painted, so no light-glow box-shadow
   from the design system's normal card treatment (would fight the
   deliberately dark, unlit viewport). Deliberately no label element, same
   minimalist choice as Inner Flame/Starfield/Ripple/Thermal above (see
   js/exercises.js's efRunAura comment). Admin-test-mode only, not in the
   schedule pool. */
.tr-ex-aura { width: 100%; }
.tr-aura-canvas { display: block; width: 100%; max-width: 360px; aspect-ratio: 1 / 1.14; border-radius: 20px; background: #050811; }

/* "Night Flow" (4-7-8 pre-sleep) exercise — square-ish canvas like
   Starfield/Ripple/Aura for a centered sphere; her spec's own fixed deep-
   indigo background #080B18 is painted, matching Aura's approach for a
   deliberately dark, unlit viewport. Deliberately no label element, same
   minimalist choice as every dark-canvas exercise above (see
   js/exercises.js's efRunNightFlow comment). Admin-test-mode only, not in
   the schedule pool. */
.tr-ex-nightflow { width: 100%; }
.tr-nightflow-canvas { display: block; width: 100%; max-width: 360px; aspect-ratio: 1 / 1; border-radius: 20px; background: #080B18; }

/* App-wide dim scrim used by efRunNightFlow to simulate her spec's "lower
   system screen brightness to ~10%" request — see the big comment above
   efRunNightFlow in js/exercises.js for why this is a simulated overlay
   (fixed over the whole app, not just this exercise's own canvas) rather
   than a real hardware-brightness call, which no web API exposes.
   pointer-events: none so it never blocks touch on whatever's underneath;
   a smooth opacity transition in on session start and back out on exit.

   2026-09-11 (Lea: "you darkened the screen so much there is nothing to
   see"). It was 90% black over EVERYTHING, the exercise's own canvas
   included, which took the whole picture down to about a tenth of its
   brightness — measured at 25 of 255 at its brightest point. Her spec asked
   for a dim SCREEN, meaning the room the exercise sits in, not a dimmed
   exercise. So the scrim is gentler now and the exercise's own view rises
   above it: the app around it recedes, the orb and its countdown stay
   readable, and the deepening still happens — through the in-canvas
   dissolve, which has its own floor. */
.tr-nightflow-dim-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.55);
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  transition: opacity 900ms ease;
}
.tr-ex-nightflow { position: relative; z-index: 10000; }

/* Dark in-session theme — 2026-08-20 correction: matched exactly against
   MoveFocus's real, live css/styles.css (fetched directly from
   movefocus.net, not from notes) after Lea flagged that this round's work
   diverged from the reference. Real MoveFocus applies .dark-session to the
   OUTER #training screen itself (not just the live exercise view) and
   HIDES the topbar entirely while it's active:
     #training.dark-session { background: #070F18; }
     #training.dark-session .user-topbar { display: none; }
   Previously EaseFocus scoped this to #trSession only and kept the topbar
   visible-but-light — a different, invented approach that wasn't what the
   reference actually does. Toggled on the outer #training screen by
   efShowTrView() in js/training.js. */
#training.dark-session { background: #070F18; }
#training.dark-session .user-topbar-slot,
#training.dark-session .user-topbar { display: none; }
.dark-session .tr-game-id { color: #F2F4F7; }
/* 2026-09-28 (Lea): "no logo next to the game name — a white circle shows
   instead." The exercise icons (assets/icons/training/exercise-*.png) are
   full-color branded artwork, not black silhouettes — brightness(0)
   invert(1) crushes every one of them to solid white, exactly the reported
   circle. Same conclusion as the segment icons just below: already
   full-color, no filter needed on a dark background. */
.dark-session .tr-game-id img.icon-inline { background: rgba(255,255,255,.12); }
.dark-session .tr-seg-bar { background: rgba(255,255,255,.14); }
.dark-session .tr-seg-label { color: rgba(255,255,255,.55); }
/* segment icons (walking/lightning/trophy, per Lea's own assets) are
   already full-color and read fine on the dark background as-is — no
   filter override needed here (see the base .tr-seg-label rules above,
   which already dim via opacity only, never grayscale). */
.dark-session .tr-timeline-seg.tr-seg-active .tr-seg-label { color: var(--teal); }
.dark-session .tr-instruction { color: #5EEAD4; }
.dark-session .tr-instruction img { filter: brightness(0) invert(1); }
.dark-session .tr-hud { background: rgba(20,184,166,.18); color: #5EEAD4; }
.dark-session .tr-pacer-label { color: #fff; }
.dark-session .tr-sigh-count { color: #5EEAD4; }
.dark-session .tr-bio-ring-bg { stroke: rgba(255,255,255,.15); }
.dark-session .tr-bio-hr { color: #fff; }
.dark-session .tr-bio-error { color: #FDA4AF; }
/* MoveFocus's dark-session also covers dashboards/rest/summary while it's
   active — the .lock-card-equivalent chrome needs its own dark overrides
   too, since it's the sprint/maintenance dashboard markup reused for the
   pre/post-session screens. EaseFocus's dashboards use .tr-dash-wrap and
   the day-grid below, not .lock-card, so the equivalent selectors here. */
#training.dark-session .tr-dash-wrap,
#training.dark-session .bl-intro-wrap,
#training.dark-session .bl-results-wrap { background: rgba(255,255,255,0.03); border-color: rgba(224,225,221,0.12); }
#training.dark-session .tr-card { background: rgba(255,255,255,0.04); border-color: rgba(224,225,221,0.12); box-shadow: none; }
#training.dark-session .bl-h2,
#training.dark-session .tr-day-badge { color: #F2F4F7; }
#training.dark-session .tr-phase-label,
#training.dark-session .bl-note,
#training.dark-session .bl-body { color: #C2C8D4; }



/* Standalone SOS / Sleep sessions — 2026-09-11 (Lea). Offered from the
   assessment entry screen and both training dashboards, as sessions in their
   own right rather than as halves of a training day. Styled as the quiet
   secondary bubble of the design system, deliberately NOT as a second
   primary: each screen keeps exactly one gradient call-to-action, and on
   these screens that is "start today's session" or "start the assessment".
   These sit under it as an alternative, not a rival. */
.solo-sessions { margin-top: 18px; }
/* ...except when it IS the card, where the card's own padding is the spacing */
.tr-card.solo-sessions { margin-top: 0; }
.solo-sessions-title {
  font-family: var(--font-ui);
  font-size: 11px; font-weight: 700; letter-spacing: .8px;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 8px; text-align: center;
}
.solo-row { display: flex; gap: 10px; }
.solo-btn {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 12px 8px;
  background: var(--accent-soft);
  border: 1px solid rgba(14,165,233,0.22);
  border-radius: 16px;
  color: var(--accent-text);
  font-family: var(--font-ui);
  cursor: pointer;
  transition: transform .12s, filter .15s;
}
.solo-btn:hover { filter: brightness(0.97); }
.solo-btn:active { transform: scale(0.97); }
.solo-btn .icon-inline { width: 1.5em; height: 1.5em; vertical-align: middle; }
.solo-btn-name { font-size: 13px; font-weight: 700; line-height: 1.25; text-align: center; }
.solo-btn-len { font-size: 11px; font-weight: 600; color: var(--muted); }
/* On the dark in-session theme the quiet bubble would vanish into the
   background, so it gets its own pair of values there. */
.dark-session .solo-btn { background: rgba(148,197,255,0.10); border-color: rgba(148,197,255,0.22); color: #CFE6FF; }
.dark-session .solo-btn-len, .dark-session .solo-sessions-title { color: #93A9C4; }


/* Open-beta notice on the login screen — 2026-09-11 (Lea), matching her
   EyeFocus reference. The quiet secondary bubble of the design system, in
   the accent's own soft tint, with the accessible -text variant for the
   label: the raw accent fails AA as text on a light ground. */
.auth-beta-pill {
  display: inline-block;
  margin: 10px auto 0;
  padding: 7px 16px;
  border-radius: 999px;
  background: var(--accent-soft);
  border: 1px solid rgba(14,165,233,0.22);
  color: var(--accent-text);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 700;
  text-align: center;
}

/* ---------- Payment gate (js/paywall.js, 2026-09-21) ----------
   One primary action — the gradient "subscribe" bubble — and everything else
   quiet, per the design system's one-primary-per-screen rule. The buy control
   is an <a> (it opens the checkout in a new tab), so it needs the block/centre
   rules a <button> gets for free. */
.tr-locked { text-align: center; }
.tr-locked-icon { font-size: 34px; line-height: 1; margin-bottom: 6px; }
.tr-locked-price { font-family: var(--font-ui); font-weight: 900; font-size: 17px; color: var(--accent-text); margin: 4px 0 12px; }
a.tr-locked-buy { display: block; width: 100%; box-sizing: border-box; text-align: center; text-decoration: none; margin-bottom: 10px; }
.tr-locked-note { margin-top: 10px; }
.tr-locked .home-link { margin-top: 6px; }

/* The ecosystem note inside the "my code" modal. */
.eco-note { margin-top: 12px; padding: 10px 12px; border-radius: 12px; background: var(--accent-soft);
  border: 1px solid rgba(14,165,233,0.18); font-size: 13px; line-height: 1.6; color: var(--text); text-align: start; }
.eco-note-links { margin-top: 6px; font-weight: 700; }
.eco-note-links a { color: var(--accent-text); }

/* 2026-10-06 (Lea): the three measurement steps (pulse, breath-hold, breathing
   rate) used to start the moment they appeared, leaving no time to read the
   instructions. Not a new screen: the existing screen is shown exactly as it
   was, with a white-filled "Tap to start" pill laid on the CENTRE of the
   step's own animation (positioned by blPlaceTapGate() in js/baseline.js) —
   the same treatment as the training exercises' gate. Until it is touched
   nothing runs (no clock, no hold, no tap counting). On the pulse step,
   touching the camera lens with a fingertip starts it too, as in training. */
.bl-tap-gate {
  position: absolute; inset: 0; z-index: 4; width: 100%; display: block;
  padding: 0; border: 0; border-radius: 18px; cursor: pointer;
  background: transparent;
  -webkit-tap-highlight-color: transparent;
}
.bl-view:not(.bl-await) .bl-tap-gate { display: none; }
.bl-tap-gate-group {
  position: absolute; left: var(--gx, 50%); top: var(--gy, 50%);
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  width: max-content; max-width: 280px; pointer-events: none;
}
.bl-tap-gate-btn {
  max-width: 230px; text-align: center; padding: 12px 22px; border-radius: 999px;
  border: 2px solid var(--accent); background: #fff;   /* white pill (Lea, 2026-10-06, after trying it see-through) */
  color: var(--navy); font-family: var(--font-ui); font-weight: 900; font-size: 15px;
  text-shadow: 0 0 8px #fff, 0 0 3px #fff;
  box-shadow: 0 0 18px rgba(14,165,233,0.28), inset 0 0 14px rgba(14,165,233,0.10);
  animation: blGatePulse 2.4s ease-in-out infinite;   /* 0.42Hz, under the 3Hz floor */
}
.bl-tap-gate-alt { position: absolute; top: calc(50% + 74px); left: 50%; transform: translateX(-50%); width: 240px; text-align: center; font-size: 12px; font-weight: 700; line-height: 1.4; color: var(--muted); text-shadow: 0 0 6px #fff, 0 0 3px #fff; }
.bl-tap-gate.is-detecting .bl-tap-gate-btn { border-color: var(--green); box-shadow: 0 0 22px rgba(20,184,166,0.5), inset 0 0 14px rgba(20,184,166,0.2); }
@keyframes blGatePulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.04); } }
.bl-tap-gate:focus-visible { outline: 3px solid rgba(14,165,233,0.45); outline-offset: -3px; }
@media (prefers-reduced-motion: reduce) { .bl-tap-gate-btn { animation: none; } }
/* The finger-on-camera chip was drawn for the dark training screens (pale mint
   text). On the light assessment card it needs the app's accessible dark-teal
   text on a soft teal tint instead. */
.bl-card .tr-cam-chip { background: rgba(20,184,166,0.10); border-color: rgba(20,184,166,0.45); color: var(--green-text); margin: 4px 0 2px; }

/* While the gate is up, the animation's own caption steps aside so the pill's
   words are the only thing at its centre (hold-button label, ring read-out). */
.bl-view.bl-await .bl-hold-btn { color: transparent; }
.bl-view.bl-await .bl-ring-center, .bl-view.bl-await .bl-ppg-status { visibility: hidden; }
