body {
  position: relative;
  display: flex; min-height: 100vh; margin: 0;
}
.onboard-center {
  position: relative; z-index: 1;
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 40px 24px;
}
.onboard-wordmark {
  display: flex; align-items: center; gap: 9px; font-family: var(--font-display);
  font-weight: 700; font-size: 19px; letter-spacing: -0.01em; text-decoration: none;
  color: var(--fg); justify-content: center; margin-bottom: 26px;
}
.onboard-wordmark svg { width: 26px; height: 26px; flex-shrink: 0; }
.card {
  max-width: 460px; width: 100%; background: var(--bg-raise); border: 1px solid var(--line);
  border-radius: 14px; padding: 36px; box-shadow: 0 30px 60px -20px rgba(0,0,0,0.5);
}
.card.wide { max-width: 920px; }
.card h1, .app-main h1 { font-family: var(--font-display); font-weight: 600; font-size: 1.4rem; margin: 0 0 8px; color: var(--fg); }
.card p.sub, .app-main p.sub { color: var(--fg-dim); font-size: 0.92rem; margin: 0 0 22px; line-height: 1.5; }
.home-sync-label {
  font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-dim); margin: -14px 0 22px;
}
label {
  display: block; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--fg-dim); margin: 18px 0 7px;
}
input, select {
  width: 100%; box-sizing: border-box; background: var(--bg-sink); border: 1px solid var(--line);
  border-radius: 6px; color: var(--fg); padding: 11px 13px; font-size: 0.95rem;
  font-family: var(--font-body);
}
input:focus, select:focus { outline: none; border-color: var(--signal); }
input:read-only { opacity: 0.55; cursor: not-allowed; }
/* Native select option dropdowns render with the browser's own colors regardless of the
   select element's own styling above (a separate, OS-drawn popup, not the same box) - dark
   background/text here so they don't flash white against this otherwise all-dark form. */
select option { background: var(--bg-sink); color: var(--fg); }
button, .btn {
  margin-top: 26px; width: 100%; background: var(--signal); color: var(--signal-ink); border: none;
  border-radius: 6px; padding: 13px; font-family: var(--font-mono); font-size: 13.5px;
  letter-spacing: 0.02em; font-weight: 600; cursor: pointer; transition: background .15s ease;
  text-align: center; text-decoration: none; display: block; box-sizing: border-box;
}
/* Every :hover rule in this file sits in @media (hover: hover): on a touch screen a tap leaves
   :hover stuck on the tapped element, and its hover colors then hurt the text's readability. */
/* Hover darkens the blue (white text keeps its contrast) and pins the text color: most .btn
   are <a>, and theme.css's generic a:hover (0,1,1) would otherwise turn the label blue on a
   blue button. */
@media (hover: hover) {
  button:hover, .btn:hover { background: color-mix(in srgb, var(--signal) 86%, black); }
  .btn:hover { color: var(--signal-ink); }
}
.btn.secondary { background: transparent; border: 1px solid var(--line); color: var(--fg); }
@media (hover: hover) { .btn.secondary:hover { background: var(--bg-sink); color: var(--fg); } }
button.is-loading { opacity: 0.75; cursor: wait; position: relative; padding-left: 40px; }
button.is-loading::before {
  content: ""; position: absolute; left: 16px; top: 50%; width: 15px; height: 15px;
  margin-top: -8px; border: 2px solid rgba(255,255,255,0.3); border-top-color: var(--signal-ink);
  border-radius: 50%; animation: onboard-spin 0.7s linear infinite;
}
@keyframes onboard-spin { to { transform: rotate(360deg); } }
.error {
  background: color-mix(in srgb, var(--warn) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--line));
  color: var(--warn); border-radius: 6px; padding: 11px 13px; font-size: 0.86rem; margin-bottom: 6px;
}
.success-title { color: var(--go); }
.success {
  background: color-mix(in srgb, var(--go) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--go) 40%, var(--line));
  color: var(--go); border-radius: 6px; padding: 11px 13px; font-size: 0.86rem; margin-bottom: 6px;
}
.check-badge {
  width: 48px; height: 48px; border-radius: 50%; background: color-mix(in srgb, var(--go) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--go) 45%, var(--line)); display: flex; align-items: center;
  justify-content: center; margin: 0 auto 20px;
}
.note { color: var(--fg-dim); font-size: 0.8rem; margin-top: 22px; line-height: 1.5; }
.consent { display: flex; align-items: flex-start; gap: 10px; margin-top: 20px; }
.consent input[type="checkbox"] {
  width: auto; margin-top: 3px; accent-color: var(--signal); flex-shrink: 0;
}
.consent label {
  display: inline; text-transform: none; letter-spacing: normal; margin: 0; font-weight: 400;
  font-family: var(--font-body); font-size: 0.85rem;
  color: var(--fg-dim); line-height: 1.45;
}
.consent label a { color: var(--signal); }
.consent.locked { opacity: 0.55; pointer-events: none; }
.keybox {
  font-family: var(--font-mono); font-size: 0.82rem; background: var(--bg-sink);
  border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; word-break: break-all;
  color: var(--fg); margin: 8px 0 4px;
}
.keybox-row { display: flex; align-items: stretch; gap: 8px; margin: 8px 0 4px; }
.keybox-row .keybox { margin: 0; flex: 1; }
.copy-btn {
  flex-shrink: 0; margin: 0; width: auto; font-family: var(--font-mono); font-size: 11px;
  background: var(--bg-sink); border: 1px solid var(--line); color: var(--fg);
  border-radius: 8px; padding: 0 14px; cursor: pointer; font-weight: 500;
}
@media (hover: hover) { .copy-btn:hover { background: var(--bg); border-color: var(--signal); color: var(--signal); } }
.status-pill {
  display: inline-block; font-family: var(--font-mono); font-size: 0.78rem;
  padding: 3px 10px; border-radius: 20px; margin-bottom: 4px;
}
.status-pill.active { background: color-mix(in srgb, var(--go) 18%, transparent); color: var(--go); }
.status-pill.needs_reauth, .status-pill.pending_garmin { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }
.status-pill.disabled, .status-pill.soon, .status-pill.off { background: var(--bg-sink); color: var(--fg-dim); }
.foot-links { margin-top: 18px; text-align: center; font-size: 0.85rem; color: var(--fg-dim); }
.foot-links a { color: var(--signal); }
/* "Continuer avec Google" (routes_auth._google_button_html) and the "ou avec ton email" rule
   between it and the password form. */
.btn-google { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 22px; font-family: var(--font-body); font-weight: 600; }
.auth-or { display: flex; align-items: center; gap: 12px; margin: 20px 0 0; font-size: 0.8rem; color: var(--fg-dim); }
.auth-or::before, .auth-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* Source-connector diagram (link-garmin) */
.connector { display: flex; align-items: center; justify-content: center; margin-bottom: 24px; }
.node {
  width: 46px; height: 46px; border-radius: 11px; display: flex; align-items: center;
  justify-content: center; flex-shrink: 0; font-family: var(--font-mono); font-size: 9px; font-weight: 600;
}
.node.source { background: var(--bg-sink); border: 1px solid var(--line); color: var(--fg-dim); }
.node.athlyze { background: var(--signal); color: var(--signal-ink); }
.link-line {
  width: 60px; height: 1px; background: repeating-linear-gradient(90deg, var(--line) 0 6px, transparent 6px 11px);
  position: relative; margin: 0 4px;
}
.link-dot {
  position: absolute; top: 50%; left: 0; width: 6px; height: 6px; border-radius: 50%;
  background: var(--go); transform: translate(-50%, -50%); box-shadow: 0 0 8px var(--go);
  animation: link-flow 1.8s ease-in-out infinite;
}
@keyframes link-flow {
  0% { left: -2px; opacity: 0; }
  15% { opacity: 1; }
  85% { opacity: 1; }
  100% { left: calc(100% + 2px); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .link-dot { animation: none; left: 50%; opacity: 1; }
}

/* Source choice (link-account) */
.options { display: flex; flex-direction: column; gap: 12px; }
.option {
  display: flex; align-items: center; gap: 14px; padding: 16px 18px; background: var(--bg-sink);
  border: 1px solid var(--line); border-radius: 10px; text-decoration: none;
}
@media (hover: hover) { a.option:hover { border-color: var(--signal); } }
.option.disabled { opacity: 0.55; }
.badge {
  width: 42px; height: 42px; border-radius: 9px; background: var(--bg); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  font-family: var(--font-mono); font-size: 9px; font-weight: 600; color: var(--fg-dim);
}
.option-body { flex: 1; }
.option-body h3 { font-family: var(--font-display); font-size: 15px; font-weight: 600; margin: 0; color: var(--fg); }
.option-body p { font-size: 12.5px; color: var(--fg-dim); margin: 3px 0 0; }
.chev { color: var(--fg-dim); font-family: var(--font-mono); font-size: 16px; }
.soon-tag {
  font-family: var(--font-mono); font-size: 9.5px; color: var(--fg-dim); border: 1px solid var(--line);
  border-radius: 12px; padding: 2px 8px; flex-shrink: 0;
}

/* Dashboard source cards */
.sources-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 24px 0; }
.activities-title-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.activities-title-row h1 { margin: 0; }
.activities-title-block { display: flex; flex-direction: column; gap: 2px; }
.activities-title-block .sub { margin: 0; }
.activities-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.activities-sync-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
.activities-sync-buttons form { margin: 0; }
/* Compact "chip" style - a sync button is a secondary utility action, not the primary CTA
   .btn/.btn.secondary is normally sized for, so it gets its own smaller footprint here
   rather than the default full padding/font. */
.btn.secondary.activities-sync-btn {
  width: auto; margin-top: 0; padding: 7px 13px; font-size: 12px; border-radius: 8px;
  display: inline-flex; align-items: center; gap: 6px; color: var(--fg-dim);
}
@media (hover: hover) { .btn.secondary.activities-sync-btn:hover { color: var(--fg); } }
.activities-filter-btn {
  width: auto; margin-top: 0; padding: 7px 14px; font-size: 12px; border-radius: 8px;
  display: none; align-items: center; gap: 6px;
}
.page-ai-analysis-card {
  background: color-mix(in srgb, var(--fg) 6%, var(--bg)); border: 1px solid var(--line);
  border-radius: 14px; padding: 16px 20px; margin: 4px 0 20px;
}
.page-ai-analysis-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-dim);
}
.page-ai-analysis-btn[hidden] { display: none; }
#page-ai-analysis-text p { margin: 0 0 10px; color: var(--fg); font-size: 14px; line-height: 1.6; }
#page-ai-analysis-text p:last-child { margin-bottom: 0; }
.page-ai-analysis-text.collapsed {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.page-ai-analysis-toggle {
  display: block; margin-top: 8px; background: none; border: none; padding: 0; cursor: pointer;
  font-family: var(--font-mono); font-size: 12px; color: var(--signal);
}
/* Without this, the generic button:hover rule (background: signal-tinted near-white) still
   wins on specificity ties broken by source order against a plain type+pseudo selector,
   painting a bright blue background under this button's own blue text - unreadable. Keep the
   plain-text look on hover, just underlined for affordance instead. */
@media (hover: hover) { .page-ai-analysis-toggle:hover { background: none; text-decoration: underline; } }
.page-ai-analysis-toggle[hidden] { display: none; }

/* Accueil (home) hub */
.home-status-card.warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
.home-flag-list { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
/* Per-zone summary at the top of the pain card (routes_home._pain_zones_html): recurrent
   zones in the warning color, improving ones in go, one-offs neutral. */
.home-pain-zones-title {
  margin: 14px 0 6px; font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--fg-dim);
}
.home-pain-zones { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.home-pain-zone {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px;
  padding: 8px 12px; border-radius: 8px; border-left: 3px solid var(--line); background: var(--bg-sink);
}
.home-pain-zone.recurrent { border-left-color: var(--warn); }
.home-pain-zone.improving { border-left-color: var(--go); }
.home-pain-zone-name { color: var(--fg); font-weight: 600; font-size: 0.92rem; }
.home-pain-zone-meta { color: var(--fg-dim); font-size: 0.78rem; font-family: var(--font-mono); }
.home-flag-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; background: var(--bg-raise); border: 1px solid var(--line);
  border-radius: 10px; text-decoration: none;
}
/* One card now mixes both sentiments (see routes_home._home_recaps_card_html) - the accent
   is per-row, not per-card, matching each row's own ⚠️/✅ icon. */
@media (hover: hover) { .home-flag-item.negative:hover { border-color: var(--warn); } }
@media (hover: hover) { .home-flag-item.positive:hover { border-color: var(--go); } }
.home-flag-item-body { display: flex; flex-direction: column; gap: 3px; }
.home-flag-item-name { color: var(--fg); font-size: 14px; font-weight: 600; }
.home-flag-item-date { color: var(--fg-dim); font-size: 12px; font-family: var(--font-mono); }
.home-flag-item-excerpt { color: var(--fg-dim); font-size: 13px; font-style: italic; line-height: 1.4; }
.home-glance-card .detail-stats-grid { margin-top: 16px; padding-top: 0; border-top: none; }
.home-glance-chat-link { width: auto; display: inline-block; margin-top: 18px; }
.home-glance-booster { color: var(--fg); font-size: 13.5px; margin: 18px 0 0; line-height: 1.5; }
/* auto-fit (not a fixed repeat(2,...)) so a lone card - digest not generated yet, or no
   glance data yet - fills the full row instead of leaving an empty second column. */
.home-summary-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; margin-top: 20px; align-items: start; }
.home-summary-row .content-card { margin-top: 0; }
.home-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 24px; }
.home-card {
  display: flex; align-items: center; gap: 14px; padding: 20px; background: var(--bg-raise);
  border: 1px solid var(--line); border-radius: 14px; text-decoration: none;
}
@media (hover: hover) { a.home-card:hover { border-color: var(--signal); } }
.home-card.disabled { opacity: 0.55; }
.home-card-body { flex: 1; }
.home-card-body h3 { font-family: var(--font-display); font-size: 15.5px; font-weight: 600; margin: 0; color: var(--fg); }
.home-card-body p { font-size: 12.5px; color: var(--fg-dim); margin: 5px 0 0; line-height: 1.45; }
@media (max-width: 640px) {
  .home-cards { grid-template-columns: 1fr; }
}

/* Chat IA */
/* Capped rather than stretching full-bleed on wide screens - narrow=False (see
   dashboard_chat_conversation) otherwise leaves a fixed 260px sidebar dwarfed by a huge,
   sparse chat pane on anything wider than a laptop. */
.chat-layout { display: flex; gap: 0; height: 100%; max-width: 1000px; }
/* Solid fill (no border, no heavy card look) rather than fully transparent - on top of the
   app's animated grid backdrop (see __athlyzeInitGridHover), a transparent sidebar let the
   grid lines show straight through behind the conversation list, which read as messy/unfinished
   rather than airy. */
.chat-sidebar {
  width: 230px; flex-shrink: 0; display: flex; flex-direction: column; gap: 2px;
  background: var(--bg-sink); border-radius: 20px 0 0 20px; padding: 14px 10px;
  border-right: 1px solid var(--line-soft);
}
/* .btn.secondary's own border/background (specificity 0,2,0) beats a plain .chat-new-btn
   override (0,1,0) regardless of source order - same cascade trap as
   .btn.secondary.activity-back-btn elsewhere in this file - so this targets the full combined
   class list actually on the button. */
.btn.secondary.chat-new-btn {
  margin-top: 0; margin-bottom: 6px; padding: 8px 6px; font-size: 13px; width: auto; align-self: flex-start;
  background: transparent; border: none; color: var(--signal);
}
@media (hover: hover) { .btn.secondary.chat-new-btn:hover { background: transparent; color: color-mix(in srgb, var(--signal) 82%, white); } }
.chat-conv-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.chat-empty-hint { color: var(--fg-dim); font-size: 13px; padding: 8px 4px; }
.chat-conv-item { position: relative; border-radius: 10px; }
.chat-conv-item a {
  display: flex; flex-direction: column; gap: 3px; overflow: hidden;
  padding: 10px 40px 10px 12px; border-radius: 10px; text-decoration: none; background: transparent;
}
.chat-conv-title {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden;
  color: var(--fg-dim); font-size: 13px; line-height: 1.4;
}
.chat-conv-date { color: var(--fg-dim); opacity: .65; font-size: 11px; }
@media (hover: hover) { .chat-conv-item a:hover { background: var(--bg-raise); } }
@media (hover: hover) { .chat-conv-item a:hover .chat-conv-title { color: var(--fg); } }
.chat-conv-item.active a { background: color-mix(in srgb, var(--signal) 10%, transparent); }
.chat-conv-item.active .chat-conv-title { color: var(--fg); font-weight: 500; }
.chat-conv-item form { margin: 0; }
/* Rename/delete icons grouped in the top-right corner, hidden until hover/focus - keeps the
   resting list focused on titles rather than every row carrying visible action buttons. */
.chat-conv-actions { position: absolute; top: 6px; right: 6px; display: flex; gap: 1px; opacity: 0; transition: opacity .12s ease; }
.chat-conv-item:hover .chat-conv-actions, .chat-conv-actions:focus-within { opacity: 1; }
/* Touch screens have no hover to reveal these, so they stay visible there. */
@media (hover: none) { .chat-conv-actions { opacity: 1; } }
.chat-conv-rename, .chat-conv-delete {
  width: 20px; height: 20px; margin: 0; padding: 0; background: transparent; border: none;
  color: var(--fg-dim); font-size: 12px; line-height: 1; border-radius: 5px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.chat-conv-delete { font-size: 14px; }
@media (hover: hover) { .chat-conv-rename:hover { background: var(--bg-raise); color: var(--signal); } }
@media (hover: hover) { .chat-conv-delete:hover { background: var(--bg-raise); color: var(--warn); } }
.chat-main {
  flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--bg-sink);
  border-radius: 0 22px 22px 0; padding: 22px 26px;
}
/* Identity header for the full-page thread only (the floating widget has its own header) -
   built from var(--bg), an absolute constant, rather than bg-raise/bg-sink (whose visual role
   flips depending on nesting depth) so the avatar tint stays correct wherever this is used. */
.chat-head { display: flex; align-items: center; gap: 10px; padding-bottom: 16px; margin-bottom: 6px; border-bottom: 1px solid var(--line-soft); flex-shrink: 0; }
.chat-head-avatar {
  width: 32px; height: 32px; border-radius: 50%; background: color-mix(in srgb, var(--signal) 20%, var(--bg-raise));
  color: var(--signal); display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.chat-head-name { font-family: var(--font-display); font-size: 14px; font-weight: 600; color: var(--fg); }
.chat-thread { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; padding-right: 4px; }
/* The widget toggles this element's [hidden] to swap in its conversation-history list (see
   .chat-widget-list below) - same [hidden]-vs-author-rule trap as .chat-widget-panel further
   down: an unconditional display:flex above always beats the UA [hidden]{display:none} rule. */
.chat-thread[hidden] { display: none; }
.chat-bubble {
  max-width: 75%; padding: 11px 14px; border-radius: 12px; font-size: 14px; line-height: 1.55;
  word-break: break-word;
}
/* Both mixed from var(--bg) - an absolute constant - rather than a contextual bg-raise/bg-sink,
   so the soft tint stays correct whether this bubble sits in .chat-main (bg-sink) or the
   floating widget panel (bg-raise) - see the .chat-widget comment below. */
.chat-bubble.user {
  align-self: flex-end; background: color-mix(in srgb, var(--signal) 26%, var(--bg)); color: var(--fg);
  white-space: pre-wrap; border-radius: 18px 18px 4px 18px;
}
.chat-bubble.model {
  align-self: flex-start; max-width: 92%; background: color-mix(in srgb, var(--fg) 9%, var(--bg)); color: var(--fg);
  border: none; border-radius: 18px 18px 18px 4px;
}
.chat-bubble.pending {
  opacity: 0.85; display: flex; align-items: center; gap: 8px; color: var(--fg-dim); font-size: 13px;
}
.chat-typing-dots { display: inline-flex; gap: 3px; align-items: center; }
.chat-typing-dots span {
  width: 5px; height: 5px; border-radius: 50%; background: var(--fg-dim);
  animation: chat-typing-bounce 1.2s infinite ease-in-out;
}
.chat-typing-dots span:nth-child(2) { animation-delay: 0.15s; }
.chat-typing-dots span:nth-child(3) { animation-delay: 0.3s; }
@keyframes chat-typing-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
  30% { transform: translateY(-3px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .chat-typing-dots span { animation: none; opacity: 0.7; }
}
.chat-bubble.error {
  align-self: center; background: transparent; border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--line));
  color: var(--warn); white-space: pre-wrap;
}
/* Rendered markdown inside a model reply - see window.athlyzeRenderMarkdown in _MARKDOWN_JS. Compact spacing
   (chat bubbles, not a document) and a contained heading style rather than real h1-h6 sizes,
   which would look oversized in a narrow bubble. */
.chat-bubble.model > *:first-child { margin-top: 0; }
.chat-bubble.model > *:last-child { margin-bottom: 0; }
/* Was inherited from the landing's own chat mock in theme.css - kept so replies don't pick up
   the global p rule (dimmer, 15px). */
.chat-bubble p { font-size: 14px; color: var(--fg); line-height: 1.65; }
.chat-bubble.model p { margin: 8px 0; }
.chat-bubble.model ul { margin: 8px 0; padding-left: 20px; }
.chat-bubble.model li { margin: 3px 0; }
/* Charts in coach replies (static/chat-chart.js). --cc-0..3: the categorical palette validated
   (lightness, CVD separation) against the model bubble in each theme - light-mode slots 2-4
   sit under 3:1 there, which is why every chart also has a legend/read-out and a data table. */
:root { --cc-0: #3987e5; --cc-1: #d95926; --cc-2: #199e70; --cc-3: #c98500; }
:root[data-theme="light"] { --cc-0: #2a78d6; --cc-1: #eb6834; --cc-2: #1baf7a; --cc-3: #eda100; }
.chat-bubble.model:has(.chat-chart) { width: 92%; }
.chat-chart { margin: 10px 0; max-width: 520px; background: var(--bg-sink); border: 1px solid var(--line-soft); border-radius: 10px; padding: 14px; }
.chat-chart svg { display: block; width: 100%; height: auto; overflow: visible; touch-action: pan-y; }
.cc-title { font-weight: 600; font-size: 13px; margin-bottom: 6px; }
.cc-title span { color: var(--fg-dim); font-weight: 400; }
.cc-grid { stroke: color-mix(in srgb, var(--fg) 10%, transparent); stroke-width: 1; }
.cc-base { stroke: color-mix(in srgb, var(--fg) 30%, transparent); stroke-width: 1; }
.cc-axis { fill: var(--fg-dim); font-family: var(--font-mono); font-size: 9.5px; }
.cc-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.cc-dot { stroke: color-mix(in srgb, var(--fg) 9%, var(--bg)); stroke-width: 2; }
.cc-cross { stroke: var(--fg-dim); stroke-width: 1; stroke-dasharray: 3 3; }
.cc-hit { fill: transparent; }
.cc-s0 { --cc: var(--cc-0); } .cc-s1 { --cc: var(--cc-1); } .cc-s2 { --cc: var(--cc-2); } .cc-s3 { --cc: var(--cc-3); }
.cc-line.cc-s0, .cc-line.cc-s1, .cc-line.cc-s2, .cc-line.cc-s3 { stroke: var(--cc); }
.cc-bar, .cc-dot, .cc-key { fill: var(--cc); background: var(--cc); }
.cc-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 6px; font-size: 12px; color: var(--fg-dim); }
.cc-legend span { display: inline-flex; align-items: center; gap: 6px; }
.cc-key { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.cc-data { margin-top: 6px; font-size: 12px; color: var(--fg-dim); }
.cc-data summary { cursor: pointer; }
.cc-data[open] { max-height: 240px; overflow: auto; }
.cc-data table { margin-top: 6px; border-collapse: collapse; font-family: var(--font-mono); font-size: 11px; }
.cc-data th, .cc-data td { padding: 2px 10px 2px 0; text-align: right; }
.cc-data th:first-child, .cc-data td:first-child { text-align: left; }
.chat-bubble.model strong { color: var(--fg); font-weight: 700; }
.chat-bubble.model a.chat-link { color: var(--signal); text-decoration: underline; }
@media (hover: hover) { .chat-bubble.model a.chat-link:hover { color: color-mix(in srgb, var(--signal) 85%, white); } }
.chat-bubble.model hr { border: none; border-top: 1px solid var(--line); margin: 12px 0; }
.chat-bubble.model code {
  font-family: var(--font-mono); font-size: 12.5px; background: var(--bg); border-radius: 4px; padding: 1px 5px;
}
.chat-bubble.model pre {
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px;
  overflow-x: auto; margin: 8px 0;
}
.chat-bubble.model pre code { background: none; padding: 0; white-space: pre; }
.chat-md-heading { font-family: var(--font-display); font-weight: 700; font-size: 14.5px; margin: 12px 0 4px; color: var(--fg); }
.chat-md-heading:first-child { margin-top: 0; }
.chat-not-configured { margin: 10px 0 0; }
.chat-input-row {
  display: flex; gap: 8px; margin-top: 14px; align-items: center; flex-shrink: 0;
  background: var(--bg-raise); border-radius: 999px; padding: 6px 6px 6px 18px;
}
.chat-input-row textarea {
  flex: 1; resize: none; background: transparent; border: none;
  color: var(--fg); padding: 8px 0; font-size: 14px; font-family: var(--font-body); max-height: 120px;
}
.chat-input-row textarea:focus { outline: none; }
.chat-send-btn {
  width: 38px; height: 38px; margin: 0; padding: 0; flex-shrink: 0; border-radius: 50%;
  background: var(--signal); color: var(--signal-ink); display: flex; align-items: center; justify-content: center;
}
.chat-send-btn:disabled { opacity: 0.5; cursor: default; }
.chat-mobile-icon-btn { display: none; }
.chat-sidebar-head { display: none; }
/* Mobile: a real messaging-app layout - the conversation list and the open thread are two
   full-screen panes, never both visible at once (unlike desktop's permanent side-by-side
   rail). .chat-layout.show-list (toggled by static/chat.js) swaps which one is showing;
   the thread is the default view since this page always has one open, same as tapping a
   contact in any chat app lands you in the conversation, not the contact list. Genuinely
   full-screen (edge to edge, no rounded card, .app-main's own padding zeroed via
   .mobile-full-bleed - see dashboard_chat_conversation's _dashboard_shell call) rather than
   a card floating in the page, and the floating "Coach IA" bubble (.chat-widget, otherwise
   present on every other page) is hidden here - you're already in the full chat, a launcher
   for the SAME thing sitting on top of it (and overlapping the input on a full-bleed layout)
   is pure redundant clutter. */
@media (max-width: 720px) {
  .app-main.mobile-full-bleed { padding: 0; }
  body:has(.app-main.mobile-full-bleed) .chat-widget { display: none; }
  .chat-layout { position: relative; height: calc(100vh - 64px - var(--tabbar-h)); min-height: 420px; }
  .chat-sidebar {
    position: absolute; inset: 0; z-index: 5; width: 100%; height: 100%;
    border-radius: 0; border-right: none; display: none;
  }
  .chat-layout.show-list .chat-sidebar { display: flex; }
  .chat-layout.show-list .chat-main { display: none; }
  .chat-main { border-radius: 0; height: 100%; padding: 16px; }
  .chat-mobile-icon-btn {
    display: flex; width: 32px; height: 32px; align-items: center; justify-content: center;
    background: transparent; border: none; color: var(--fg); cursor: pointer; border-radius: 50%;
    margin: 0; padding: 0; flex-shrink: 0;
  }
  @media (hover: hover) { .chat-mobile-icon-btn:hover { background: var(--bg-raise); } }
  .chat-sidebar-head { display: flex; align-items: center; gap: 8px; padding: 0 4px 12px; }
  .chat-sidebar-title { font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--fg); }
}

/* Chat confirm/rename/alert modal - see showModal() in _CHAT_JS. Replaces native confirm()/
   prompt()/alert() so the dialog matches the app's own look instead of the browser chrome. */
.chat-modal-overlay {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.6); display: flex; align-items: center;
  justify-content: center; z-index: 100; padding: 20px;
}
.chat-modal {
  width: 100%; max-width: 380px; border: 1px solid var(--line); background: var(--bg-raise);
  border-radius: 14px; padding: 22px; box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.5);
}
.chat-modal h3 { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--fg); margin: 0; }
.chat-modal-message { color: var(--fg-dim); font-size: 13.5px; line-height: 1.5; margin: 10px 0 0; }
.chat-modal-input {
  width: 100%; box-sizing: border-box; background: var(--bg-sink); border: 1px solid var(--line);
  border-radius: 6px; color: var(--fg); padding: 10px 12px; font-size: 14px; font-family: var(--font-body);
  margin-top: 14px;
}
.chat-modal-input:focus { outline: none; border-color: var(--signal); }
.chat-modal-actions { display: flex; gap: 10px; margin-top: 18px; }
/* .btn.danger/.btn.secondary also match at (0,2,0) specificity and are defined later in the
   file (.btn.danger's own margin-top:20px, meant for the standalone account-deletion button,
   was winning the tie via source order) - .danger/.secondary bumps this to (0,3,0) so it
   always wins regardless of where those rules sit, keeping both modal buttons the same
   height under the container's default align-items:stretch. */
.chat-modal-actions .btn, .chat-modal-actions .btn.danger, .chat-modal-actions .btn.secondary {
  margin-top: 0; width: auto; flex: 1; padding: 10px;
}
/* Browser-default focus ring is blue regardless of button color - clashes on the orange
   danger button. currentColor picks up each button's own accent (orange for danger, the
   signal blue otherwise) instead. */
.chat-modal-actions .btn:focus-visible {
  outline: 2px solid color-mix(in srgb, currentColor 70%, transparent);
  outline-offset: 2px;
}

/* Floating chat widget - present on every dashboard page for an active tenant, see the
   markup/JS in _dashboard_shell and _CHAT_WIDGET_JS. Reuses .chat-thread/.chat-bubble from
   the full Chat IA page's own styles above, so a message looks identical in both places. */
.chat-widget { position: fixed; right: 24px; bottom: 24px; z-index: 90; }
/* margin/padding explicitly zeroed - the global `button, .btn` rule (margin-top:26px,
   padding:13px, width:100%) applies to any raw <button> that doesn't override a given
   property itself; width/height/display are already set below, but margin/padding weren't,
   so they leaked through and threw off the button's size and position. */
.chat-widget-toggle {
  width: 56px; height: 56px; margin: 0; padding: 0; border-radius: 50%; border: none; background: var(--signal);
  color: var(--signal-ink); cursor: pointer; box-shadow: 0 12px 32px -10px rgba(0, 0, 0, 0.55);
  display: flex; align-items: center; justify-content: center; transition: transform .14s ease, background .14s ease;
}
@media (hover: hover) { .chat-widget-toggle:hover { transform: scale(1.06); } }
.chat-widget-toggle.open { background: var(--bg-raise); color: var(--fg); border: 1px solid var(--line); }
/* Same [hidden]-vs-author-rule trap as .chat-widget-panel below - display:block here would
   otherwise beat the UA [hidden] rule and the two icons would always render stacked. */
.chat-widget-toggle-icon { display: block; }
.chat-widget-toggle-icon[hidden] { display: none; }
.chat-widget-panel {
  position: absolute; right: 0; bottom: 72px; width: 400px; max-width: calc(100vw - 48px);
  height: 580px; max-height: calc(100vh - 130px); background: var(--bg-raise); border: 1px solid var(--line);
  border-radius: 20px; box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.6); display: flex; flex-direction: column;
  overflow: hidden;
}
/* display:flex above applies unconditionally to the class - without this, it beats the
   browser's default `[hidden] { display: none }` UA rule (an author rule always wins over a
   UA rule of equal specificity, regardless of source order), so toggling panel.hidden in JS
   had no visual effect at all and the panel could never actually close. */
.chat-widget-panel[hidden] { display: none; }
.chat-widget-panel:not([hidden]) { animation: chat-widget-in .16s ease; }
@keyframes chat-widget-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.chat-widget-header {
  display: flex; align-items: center; gap: 10px; padding: 14px 14px 14px 16px;
  border-bottom: 1px solid var(--line); flex-shrink: 0; background: var(--bg-sink);
}
.chat-widget-avatar {
  width: 30px; height: 30px; border-radius: 9px; background: color-mix(in srgb, var(--signal) 16%, transparent);
  color: var(--signal); display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.chat-widget-heading { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.chat-widget-title { font-family: var(--font-display); font-weight: 600; font-size: 13.5px; color: var(--fg); line-height: 1.3; }
.chat-widget-subtitle { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-dim); }
.chat-widget-icon-btn {
  width: 28px; height: 28px; margin: 0; padding: 0; display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; color: var(--fg-dim); text-decoration: none; border: none; background: transparent;
  border-radius: 7px; cursor: pointer;
}
@media (hover: hover) { .chat-widget-icon-btn:hover { background: var(--bg-raise); color: var(--fg); } }
.chat-widget-thread { padding: 16px; }
.chat-widget-loading { color: var(--fg-dim); font-size: 12.5px; text-align: center; padding: 20px 0; }
/* Conversation-history switcher, swapped in over .chat-widget-thread (see the "history" icon
   button in _CHAT_WIDGET_JS) rather than a separate panel - the widget stays one fixed-size box. */
.chat-widget-list { flex: 1; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.chat-widget-list[hidden] { display: none; }
.chat-widget-list-item {
  display: block; margin: 0; padding: 10px 12px; border-radius: 10px; color: var(--fg-dim); text-decoration: none;
  font-size: 13px; line-height: 1.4; background: transparent; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; cursor: pointer; border: none; width: 100%; text-align: left; font-family: var(--font-body);
}
@media (hover: hover) { .chat-widget-list-item:hover { background: var(--bg-raise); color: var(--fg); } }
.chat-widget-list-item.active { background: color-mix(in srgb, var(--signal) 10%, transparent); color: var(--fg); font-weight: 500; }
.chat-widget-form { display: flex; gap: 8px; padding: 12px; border-top: 1px solid var(--line); flex-shrink: 0; margin: 0; align-items: flex-end; }
.chat-widget-form textarea {
  flex: 1; resize: none; background: var(--bg-sink); border: 1px solid var(--line); border-radius: 10px;
  color: var(--fg); padding: 10px 12px; font-size: 13.5px; font-family: var(--font-body); max-height: 100px;
}
.chat-widget-form textarea:focus { outline: none; border-color: var(--signal); }
.chat-widget-send {
  width: 38px; height: 38px; flex-shrink: 0; border-radius: 10px; border: none; background: var(--signal);
  color: var(--signal-ink); display: flex; align-items: center; justify-content: center; cursor: pointer;
  margin: 0; padding: 0; transition: opacity .1s ease;
}
@media (hover: hover) { .chat-widget-send:hover { opacity: 0.9; } }
.chat-widget-send:disabled { opacity: 0.5; cursor: default; }
@media (max-width: 480px) {
  .chat-widget { right: 14px; bottom: 14px; }
  .chat-widget-panel { width: calc(100vw - 28px); height: calc(100vh - 120px); }
}

.profile-card h2, .section-title { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--fg); margin: 0; }
/* Prénom / Nom / Sexe / Date de naissance: the names get a bit more room, but the date keeps
   enough for "jj/mm/aaaa" + its calendar icon (a fixed 90px - sized for the old 2-digit age
   field - cut it off). Wraps to two per row below 900px rather than squeezing. */
.profile-form-row { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.2fr) minmax(140px, 1fr) minmax(160px, 1fr); gap: 16px; margin-top: 16px; align-items: end; }
.profile-form-row label { white-space: nowrap; }
@media (max-width: 900px) { .profile-form-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.profile-save-btn { width: auto; margin-top: 14px; }

/* Compte tab: theme picker + danger zone */
.theme-form { margin-top: 16px; }
.theme-options { display: flex; flex-wrap: wrap; gap: 14px; }
.theme-option {
  display: flex; align-items: center; gap: 10px; flex: 1; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px; padding: 12px 16px;
  font-size: 13.5px; color: var(--fg-dim); text-transform: none; letter-spacing: normal;
  font-family: var(--font-body); margin: 0;
}
.theme-option.selected { border-color: var(--signal); color: var(--fg); }
.theme-option input[type="radio"] { width: auto; margin: 0; accent-color: var(--signal); }
.theme-swatch { width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--line); flex-shrink: 0; }
.theme-swatch-dark { background: oklch(19% 0.01 260); }
.theme-swatch-light { background: oklch(97% 0.004 260); }
.danger-zone { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
.btn.danger {
  width: auto; background: transparent; border: 1px solid color-mix(in srgb, var(--warn) 55%, var(--line));
  color: var(--warn); margin-top: 20px;
}
@media (hover: hover) { .btn.danger:hover { background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn); } }
.connectors-faq, .details-block {
  margin-top: 8px; background: var(--bg-sink); border: 1px solid var(--line);
  border-radius: 12px; padding: 4px 20px 12px;
}
.connectors-faq h2 { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--fg); margin: 20px 0 4px; }
.connectors-faq details, .details-block details { border-top: 1px solid var(--line-soft); padding: 14px 0; }
.connectors-faq details:first-of-type, .details-block details:first-of-type { border-top: none; }
.connectors-faq summary, .details-block summary {
  cursor: pointer; font-family: var(--font-display); font-weight: 600; font-size: 14px; color: var(--fg);
  list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.connectors-faq summary::-webkit-details-marker, .details-block summary::-webkit-details-marker { display: none; }
.connectors-faq summary::after, .details-block summary::after { content: '+'; color: var(--fg-dim); font-family: var(--font-mono); font-size: 16px; flex-shrink: 0; }
.connectors-faq details[open] summary::after, .details-block details[open] summary::after { content: '\2212'; }
.connectors-faq details p, .details-block details p { color: var(--fg-dim); font-size: 13px; line-height: 1.6; margin: 10px 0 0; }
.details-block details label { margin-top: 14px; }
.details-block details label:first-of-type { margin-top: 10px; }
.source-card { background: var(--bg-sink); border: 1px solid var(--line); border-radius: 10px; padding: 20px; }
/* Same light-theme lift as .content-card (see its own comment). */
:where(:root[data-theme="light"]) .source-card {
  background: var(--bg-raise);
  box-shadow: 0 1px 2px oklch(20% 0.02 260 / 0.06), 0 4px 14px oklch(20% 0.02 260 / 0.05);
}
.content-card {
  background: var(--bg-raise); border: 1px solid var(--card-line); border-radius: 18px;
  padding: 28px; max-width: 100%; margin-top: 20px;
}
.content-card p.sub:first-child { margin-top: 0; }
/* Light theme: --bg-sink (a recessed tone - right for dark mode, where cards sit darker than
   the page) made every card a flat grey slab on a light-grey page. Raised white cards with a
   soft shadow read as clean surfaces instead; inner --bg-sink elements (inputs, zone rows,
   stat tiles) then contrast against white like they should. */
:where(:root[data-theme="light"]) .content-card { box-shadow: none; }
/* Less horizontal padding than the base .content-card (not more) - this is the primary
   view (activities list/detail), so width goes to the content grid/stats/charts, not to
   decorative side margins. Vertical padding stays generous for visual weight. */
/* .content-card.content-card-lg (0,2,0) needed to beat the base .content-card's own
   margin-top:20px (0,1,0) - the usual cascade trap in this file (see .btn.secondary.*). */
.content-card.content-card-lg { padding: 32px 18px; border-radius: 16px; margin-top: 0; }
@media (max-width: 640px) {
  .content-card-lg { padding: 20px 14px; }
}

/* Activities list page */
.activity-filter { margin-bottom: 0; }
.activity-filter label {
  font-family: var(--font-body); font-size: 12.5px; font-weight: 600; letter-spacing: 0;
  text-transform: none; color: var(--fg-dim); margin: 16px 0 6px;
}
.activity-filter label:first-child { margin-top: 0; }
.activity-filter select, .activity-filter input[type="search"] {
  width: 100%; box-sizing: border-box; background: var(--bg); border: 1px solid var(--line);
  color: var(--fg); border-radius: 10px; padding: 10px 12px; font-family: var(--font-body); font-size: 13px;
}
.activity-filter input[type="search"]:focus { outline: none; border-color: var(--signal); }
.activities-layout { display: flex; gap: 22px; align-items: flex-start; }
.activities-list { flex: 1; min-width: 0; }
/* Right column: type filter + the year/month timeline stacked together, in its own card so it
   reads as a companion panel to the bordered activity cards rather than loose floating fields. */
.activities-sidebar {
  width: 240px; flex-shrink: 0; display: flex; flex-direction: column; gap: 20px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 16px; padding: 18px;
}
.activities-sidebar-head { display: none; }
.activities-grid { display: flex; flex-direction: column; gap: 14px; }
.activities-empty {
  flex: 1; min-height: 220px; display: flex; align-items: center; justify-content: center;
  text-align: center; color: var(--fg-dim); font-size: 0.92rem;
}
/* Column now, not row: .activity-card-top (icon + heading) is its own row, and
   .activity-card-stats is a full-width sibling below it - spanning the ENTIRE card width
   (including the space under the icon), not indented to just the heading column. */
.activity-card {
  display: flex; flex-direction: column; gap: 14px; background: var(--bg); border: 1px solid var(--line);
  border-radius: 16px; padding: 20px; transition: border-color .15s, background-color .15s, transform .15s;
}
@media (hover: hover) { .activity-card:hover { border-color: color-mix(in srgb, var(--signal) 30%, var(--line)); transform: translateY(-1px); } }
.activity-card-top { display: flex; align-items: flex-start; gap: 18px; }
.activity-card-icon {
  width: 64px; height: 64px; flex-shrink: 0; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-sink); border: 1px solid var(--line-soft);
}
.activity-card-icon svg { width: 38px; height: 38px; display: block; }
.activity-card-icon polyline { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.activity-card-heading { flex: 1; min-width: 0; }
/* Date directly above the name, own line - the badge rides along on the same small meta
   line (it's secondary info too, same visual weight as the date) rather than competing with
   the name for space the way it used to. */
.activity-card-eyebrow { display: flex; align-items: center; gap: 6px 10px; flex-wrap: wrap; }
.activity-card-date { font-family: var(--font-mono); font-size: 12px; color: var(--fg-dim); }
.activity-card-badge {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; padding: 4px 10px; border-radius: 6px; flex-shrink: 0;
}
.activity-card-name {
  font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--fg);
  margin: 6px 0 0; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.activity-card-stats {
  display: flex; flex-wrap: wrap; gap: 12px 36px; padding-top: 14px;
  border-top: 1px solid var(--line-soft);
}
.activity-card-stats .k { display: block; font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-dim); text-transform: uppercase; letter-spacing: .05em; }
.activity-card-stats .v { display: block; font-family: var(--font-mono); font-size: 16px; color: var(--fg); font-weight: 500; margin-top: 4px; }
@media (max-width: 640px) {
  .activity-card { gap: 10px; padding: 14px; border-radius: 14px; }
  .activity-card-top { gap: 12px; }
  .activity-card-icon { width: 46px; height: 46px; border-radius: 11px; }
  .activity-card-icon svg { width: 26px; height: 26px; }
  .activity-card-name { font-size: 16px; margin-top: 6px; }
  .activity-card-stats { gap: 8px 22px; padding-top: 12px; }
  .activity-card-stats .v { font-size: 14px; }
}
/* Scrollable year/month rail - independent scroll from the card grid, so you can browse
   the whole history without losing your place in the list. */
.activities-timeline {
  max-height: 640px; overflow-y: auto; position: sticky; top: 0;
  padding-right: 4px; scrollbar-width: thin; scrollbar-color: var(--line) transparent;
}
.timeline-year { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--fg); margin: 14px 0 4px; }
.timeline-year:first-child { margin-top: 0; }
.timeline-month {
  display: block; font-family: var(--font-mono); font-size: 12px; color: var(--fg-dim);
  padding: 6px 9px; border-radius: 8px; text-decoration: none;
}
@media (hover: hover) { .timeline-month:hover { background: var(--bg-raise); color: var(--fg); } }
.timeline-month.active { background: color-mix(in srgb, var(--signal) 16%, transparent); color: var(--signal); font-weight: 600; }
.pagination { display: flex; align-items: center; justify-content: space-between; margin-top: 20px; }
.page-link { font-family: var(--font-mono); font-size: 12px; color: var(--signal); }
.page-link.disabled { color: var(--fg-dim); pointer-events: none; opacity: .5; }
.page-info { font-family: var(--font-mono); font-size: 11px; color: var(--fg-dim); }
/* Mobile: the filter panel (search/type/sort + the year/month timeline) becomes a drawer
   sliding in from the RIGHT (the nav drawer slides from the left - see sidebar-menu.js -
   opposite sides so the two are never visually confused), opened by the "Filtres" button
   (see static/activities-filter.js) instead of sitting permanently below the whole activity
   list where reaching it meant scrolling past every card first. */
@media (max-width: 720px) {
  .activities-layout { position: relative; }
  /* Desktop's 16px title-row gap is a horizontal gap between title-block and actions
     sitting side by side; wrapped on mobile it reads as vertical space between the
     count and the buttons below it, so it's pulled in here and pushed back out as
     margin-bottom instead, to separate the buttons from the card underneath them. */
  .activities-title-row { gap: 6px; }
  .activities-actions { width: 100%; justify-content: flex-start; margin-bottom: 14px; }
  .activities-filter-btn { display: inline-flex; }
  .activities-sidebar {
    position: fixed; top: 0; right: 0; bottom: 0; width: min(300px, 86vw); height: 100vh;
    margin: 0; border-radius: 0; border: none; border-left: 1px solid var(--line);
    box-shadow: 0 0 40px rgba(0, 0, 0, .4);
    transform: translateX(100%); transition: transform .22s ease; z-index: 2001;
    overflow-y: auto;
  }
  .activities-sidebar.open { transform: translateX(0); }
  .activities-sidebar-head { display: flex; align-items: center; justify-content: space-between; }
  .activities-sidebar-title { font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--fg); }
  .activities-timeline { max-height: none; position: static; }
}

/* Activity detail page */
.activity-card, a.activity-card { text-decoration: none; color: inherit; cursor: pointer; }
.activity-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.activity-chat-btn { width: auto; margin-top: 0; white-space: nowrap; }
/* .btn.secondary alone would win the background tie via higher specificity ((0,2,0) vs this
   rule's (0,1,0)) regardless of source order - see the identical chat-modal button bug
   earlier - so this targets the actual combined class list directly. */
.btn.secondary.activity-back-btn { width: auto; display: inline-block; background: var(--bg-raise); margin-bottom: 15px }
@media (hover: hover) { .btn.secondary.activity-back-btn:hover { background: color-mix(in srgb, var(--signal) 12%, var(--bg-raise)); } }
.activity-detail-meta { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.activity-detail-location { color: var(--fg-dim); font-size: 13px; margin: 6px 0 0; }
.activity-detail-description { color: var(--fg-dim); font-size: 13px; margin: 12px 0 0; line-height: 1.5; white-space: pre-line; }

/* Training plan */
/* No plan yet - just the page's own <h1> above this, then the quickstart field vertically
   centered in the rest of the page (see dashboard_plan's early-return for the empty-sessions
   case). calc() leaves room for .app-main's own padding, the h1, and the mobile top nav bar's
   height so the card doesn't sit lower than center. */
.plan-empty-page { min-height: calc(100vh - 280px); display: flex; align-items: center; justify-content: center; }
.plan-quickstart { display: flex; flex-direction: column; gap: 14px; width: 100%; max-width: 560px; }
.plan-quickstart textarea {
  width: 100%; box-sizing: border-box; font-size: 16px; padding: 16px 18px;
  border-radius: 12px; resize: none; background: var(--bg-sink); border: 1px solid var(--line);
  color: var(--fg); font-family: var(--font-body); line-height: 1.5;
}
.plan-quickstart textarea:focus { outline: none; border-color: var(--signal); }
/* .btn.secondary alone is transparent (see its own rule) - it would blend straight into the
   page background out here with no content-card behind it. Combining the full class list
   bumps specificity high enough to win regardless of source order (same fix as
   .btn.secondary.activity-back-btn above). */
.btn.secondary.plan-quickstart-btn { width: 100%; margin: 0; padding: 13px; background: var(--bg-raise); }
@media (hover: hover) { .btn.secondary.plan-quickstart-btn:hover { background: color-mix(in srgb, var(--signal) 12%, var(--bg-raise)); } }
.plan-overview-card { padding: 20px; }
.plan-overview-duration {
  font-family: var(--font-mono); font-size: 12px; color: var(--fg-dim); text-transform: uppercase;
  letter-spacing: .04em; margin-bottom: 14px;
}
.plan-overview-chart { margin-bottom: 0; }
.plan-progress { margin-bottom: 16px; }
.plan-progress-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 7px; }
.plan-progress-head span:first-child { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--fg); }
.plan-progress-sub { font-size: 12px; color: var(--fg-dim); }
.plan-totals { display: flex; flex-wrap: wrap; gap: 22px; margin-bottom: 16px; }
.plan-total { display: flex; flex-direction: column; gap: 3px; }
.plan-total .k { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-dim); }
.plan-total .v { font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--fg); }
/* One chart tab visible at a time (see _PLAN_OVERVIEW_TABS_JS) rather than the three weekly
   charts stacked full-size, which read as too heavy for what's meant to be a quick glance. */
.plan-chart-tabs { display: flex; gap: 6px; margin-bottom: 12px; }
.plan-chart-tab {
  width: auto; margin: 0; padding: 6px 13px; font-family: var(--font-mono); font-size: 12px;
  background: var(--bg-raise); border: 1px solid var(--line); color: var(--fg-dim); border-radius: 20px;
}
@media (hover: hover) { .plan-chart-tab:hover { color: var(--fg); } }
.plan-chart-tab.active { background: color-mix(in srgb, var(--signal) 16%, transparent); border-color: transparent; color: var(--signal); font-weight: 600; }
/* Segmented phase timeline, replacing a plain list - each segment is positioned/sized from
   its own block's date range (see _plan_timeline_html), not assumed contiguous with siblings. */
.plan-timeline { margin-bottom: 16px; }
.plan-timeline-track { position: relative; height: 34px; background: var(--bg-raise); border-radius: 8px; }
.plan-timeline-seg {
  position: absolute; top: 0; bottom: 0; border-radius: 8px; opacity: .6;
  display: flex; align-items: center; padding: 0 10px; overflow: hidden; box-sizing: border-box;
}
.plan-timeline-seg.plan-timeline-current { opacity: 1; box-shadow: inset 0 0 0 2px var(--fg); }
.plan-timeline-label {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--fg); white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0,0,0,.4); overflow: hidden; text-overflow: ellipsis;
  /* A short phase (or a narrow viewport) can size its segment below what its own name needs -
     this ellipsizes instead of the previous hard mid-word clip. The segment's own data-tip
     (see _plan_timeline_html) already surfaces the full name + date range on tap via the
     shared [data-tip] tooltip wired in health-charts.js, so the truncation loses nothing. */
}
.plan-timeline-today {
  position: absolute; top: -4px; bottom: -4px; width: 2px; background: var(--fg);
}
.plan-timeline-dates { display: flex; justify-content: space-between; margin-top: 6px; font-family: var(--font-mono); font-size: 11px; color: var(--fg-dim); }
.plan-list-card { padding: 20px; }
.plan-days { display: flex; flex-direction: column; gap: 22px; }
/* No box here on purpose - .plan-session cards (styled like Activités' .activity-card) are
   already a card each; a day-level card around a group of session-cards, inside the page's
   own outer .content-card, was three levels of nested borders for no real information. */
.plan-day-label {
  font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--fg-dim); margin-bottom: 10px;
}
.plan-day-today .plan-day-label { color: var(--signal); }
.plan-day-sessions { display: flex; flex-direction: column; gap: 10px; }
/* Same visual language as .activity-card on the Activités page (bordered card, badge+title
   head, stats row on a hairline) - deliberately reusing .activity-card-stats (.k/.v) for the
   stats row itself rather than a parallel copy. No icon tile here (unlike Activités) - plan
   sessions have no real GPS trace, and a generic per-discipline glyph didn't earn its space. */
.plan-session {
  background: var(--bg); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px;
}
.plan-session.plan-status-done { opacity: 0.6; }
.plan-session.plan-status-done .plan-session-title { text-decoration: line-through; }
.plan-session.plan-status-skipped { opacity: 0.5; }
.plan-session-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.plan-session-title { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--fg); margin: 0; }
.plan-session-stats.activity-card-stats { margin-top: 10px; padding-top: 10px; gap: 6px 20px; }
.plan-session-notes { font-size: 12.5px; color: var(--fg-dim); margin: 10px 0 0; line-height: 1.6; }
/* Weekly review cards (views/plan.html, weekly_review.py). */
.plan-reviews { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: 14px; margin-top: 18px; }
.plan-review { margin: 0; padding: 18px 20px; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--card-line); display: flex; flex-direction: column; }
.plan-review.past { border-color: color-mix(in srgb, var(--signal) 40%, var(--card-line)); }
.plan-review-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.plan-review-label { font-size: 12.5px; font-weight: 700; color: var(--fg-dim); }
.plan-review-headline { margin: 8px 0 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.plan-review-facts { margin: 8px 0 0; padding-left: 18px; font-size: 13px; color: var(--fg-dim); line-height: 1.6; flex: 1; }
.plan-review-facts:empty { display: none; }
.plan-review-btn { margin-top: 14px; width: auto; padding: 10px 16px; border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
/* "Réalisé" under a session plan_matching ticked (routes_plan._plan_actual_html). */
.plan-actual { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin-top: 10px; padding: 8px 10px; border-radius: 10px; background: var(--go-bg); font-size: 12.5px; }
.plan-actual-tag { font-weight: 700; color: var(--go); }
.plan-actual a { color: var(--fg); font-weight: 600; }
.plan-actual span:last-child { color: var(--fg-dim); }
.plan-actual small { color: var(--fg-dim); }
ul.plan-session-notes { padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
ul.plan-session-notes li::marker { color: var(--line); }
.plan-discipline-badge {
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  padding: 3px 8px; border-radius: 5px; flex-shrink: 0;
}
.plan-discipline-course { background: color-mix(in srgb, var(--signal) 16%, transparent); color: var(--signal); }
.plan-discipline-velo { background: color-mix(in srgb, var(--go) 16%, transparent); color: var(--go); }
.plan-discipline-natation { background: color-mix(in srgb, var(--teal) 16%, transparent); color: var(--teal); }
.plan-discipline-renfo { background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn); }
.plan-discipline-repos { background: color-mix(in srgb, var(--fg-dim) 20%, transparent); color: var(--fg-dim); }
.plan-discipline-autre { background: color-mix(in srgb, var(--fg-dim) 20%, transparent); color: var(--fg-dim); }
.plan-session-actions { display: flex; gap: 6px; margin-top: 10px; }
.plan-inline-form { margin: 0; }
.plan-action-btn {
  width: auto; margin: 0; padding: 5px 11px; font-size: 10.5px; font-family: var(--font-mono);
  background: var(--bg-raise); border: 1px solid var(--line); color: var(--fg-dim); border-radius: 5px; cursor: pointer;
}
@media (hover: hover) { .plan-action-btn:hover { background: color-mix(in srgb, var(--signal) 12%, var(--bg-raise)); color: var(--fg); } }
/* Distinct from the plain Fait/Sauter toggles - this one reaches an external service, not
   just a local status flip, so it gets its own accent color and sits apart (margin-left:auto
   pushes it to the far end of the actions row). Turns --go once actually pushed. */
.plan-garmin-push-btn {
  display: flex; align-items: center; gap: 6px; margin-left: auto;
  color: var(--signal); background: color-mix(in srgb, var(--signal) 12%, var(--bg-raise));
  border-color: color-mix(in srgb, var(--signal) 35%, var(--line));
}
.plan-garmin-push-btn svg { width: 13px; height: 13px; flex-shrink: 0; }
@media (hover: hover) { .plan-garmin-push-btn:hover { background: color-mix(in srgb, var(--signal) 20%, var(--bg-raise)); color: var(--signal); } }
.plan-garmin-push-btn.plan-garmin-pushed {
  color: var(--go); background: color-mix(in srgb, var(--go) 12%, var(--bg-raise));
  border-color: color-mix(in srgb, var(--go) 35%, var(--line));
}
.plan-garmin-push-btn:disabled { cursor: default; opacity: .85; }
/* One goal line for the whole plan (single flat session list under the hood, see
   plan_store.PlanStore.get_goal/set_goal, set by the coach itself via manage_training_plan) -
   the page's cue that these sessions belong to one cohesive plan, not just a bag of unrelated
   to-dos. Plain text, not an editable field - only the coach writes here. */
.plan-goal-title { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--fg); margin: 14px 0 20px; }
/* Calendar view - complete Monday-Sunday weeks, see _plan_calendar_html. Every day cell is a
   fixed size (not min-height) so a busy day and an empty day look identical in the grid -
   overflow sessions collapse into a "+N" chip instead of stretching the row. */
/* Month/week navigation row above the grid - a separate <a>-based prev/next/today cluster
   (not a <button>, so none of the global button margin/padding/width rules apply here) plus
   the existing .period-btn toggle pattern reused for the Semaine/Mois switch. */
.plan-cal-nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.plan-cal-nav-left { display: flex; align-items: center; gap: 10px; }
.plan-cal-nav-arrow {
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; background: var(--bg-raise); border: 1px solid var(--line); color: var(--fg-dim);
  text-decoration: none; flex-shrink: 0;
}
@media (hover: hover) { .plan-cal-nav-arrow:hover { color: var(--fg); border-color: color-mix(in srgb, var(--signal) 40%, var(--line)); } }
.plan-cal-nav-label { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--fg); min-width: 150px; text-align: center; }
.plan-cal-nav-today { font-family: var(--font-mono); font-size: 12px; color: var(--signal); }
.plan-calendar-card { padding: 20px; }
.plan-calendar { display: flex; flex-direction: column; gap: 6px; }
.plan-cal-week { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.plan-cal-header { margin-bottom: 2px; }
.plan-cal-weekday {
  font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--fg-dim); text-align: center; padding-bottom: 4px;
}
.plan-cal-day {
  background: var(--bg-raise); border: 1px solid var(--line); border-radius: 8px; padding: 6px;
  height: 92px; display: flex; flex-direction: column; gap: 4px; overflow: hidden;
}
.plan-cal-day.plan-cal-outside { opacity: 0.4; }
.plan-cal-day.plan-cal-today { border-color: var(--signal); }
.plan-cal-daynum { font-family: var(--font-mono); font-size: 11px; color: var(--fg-dim); flex-shrink: 0; }
.plan-cal-today .plan-cal-daynum { color: var(--signal); font-weight: 600; }
.plan-cal-chips { display: flex; flex-direction: column; gap: 3px; min-height: 0; overflow: hidden; }
.plan-cal-chip {
  font-size: 10px; padding: 2px 5px; border-radius: 4px; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; cursor: default; flex-shrink: 0;
}
.plan-cal-chip.plan-status-done { opacity: 0.55; text-decoration: line-through; }
.plan-cal-chip.plan-status-skipped { opacity: 0.4; text-decoration: line-through; }
.plan-cal-chip.plan-cal-more { background: var(--bg-sink); color: var(--fg-dim); text-align: center; }
/* Week view: 7 columns instead of ~35, so each day cell can afford to be much taller and show
   every session (see _plan_calendar_html's week_mode raising _MAX_CHIPS) instead of the
   month view's cramped 3-then-"+N" truncation. */
.plan-calendar-week-mode .plan-cal-day { height: 220px; }
.plan-calendar-week-mode .plan-cal-chip { font-size: 11.5px; padding: 4px 7px; white-space: normal; }
@media (max-width: 780px) {
  .plan-calendar-card { padding: 14px; }
  .plan-cal-weekday { font-size: 9px; }
  .plan-cal-day { height: 60px; padding: 4px; }
  .plan-cal-chip { font-size: 0; padding: 3px; border-radius: 50%; width: 8px; height: 8px; }
  /* Month view crams up to ~35 day cells across a phone screen - no room for readable text,
     so a session collapses to a plain colored dot above. Week view only ever has 7 columns
     even on mobile, so it keeps real (smaller) text instead - this needs its own explicit
     width/height/border-radius/font-size here rather than just relying on the desktop
     .plan-calendar-week-mode rule's higher specificity, since that rule never touches
     width/height/border-radius at all and would otherwise leave chips dot-shaped with
     text overflowing a circle. */
  .plan-calendar-week-mode .plan-cal-day { height: 180px; }
  .plan-calendar-week-mode .plan-cal-chip {
    width: auto; height: auto; border-radius: 4px; font-size: 9.5px; padding: 2px 4px; white-space: normal;
  }
}
.detail-stats-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 18px 24px;
  margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--line-soft);
}
.detail-stats-grid .k { display: block; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-dim); }
.detail-stats-grid .v { display: block; font-family: var(--font-mono); font-size: 17px; color: var(--fg); margin-top: 5px; }
/* Activity detail page's main stats banner (see routes_activities._detail_stats_groups_html)
   - themed sections laid out as an even grid (fills the card's width instead of an organic
   flex-wrap that could leave a ragged last row), each a subtly-tinted titled tile so the
   theme reads at a glance without a heavy colored border. Each tile's mean (primary=True)
   is colored and rendered larger, a sibling like max staying small/neutral next to it. */
.detail-stat-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--line-soft); }
.detail-stat-group { display: flex; flex-direction: column; gap: 12px; background: var(--bg-sink); border-radius: 10px; padding: 14px 16px; }
.detail-stat-group-label { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-dim); }
.detail-stat-group.accent-pace .detail-stat-group-label { color: color-mix(in srgb, var(--signal) 70%, var(--fg-dim)); }
.detail-stat-group.accent-hr .detail-stat-group-label { color: color-mix(in srgb, var(--warn) 70%, var(--fg-dim)); }
.detail-stat-group.accent-load .detail-stat-group-label { color: color-mix(in srgb, var(--teal) 70%, var(--fg-dim)); }
.detail-stat-group-row { display: flex; flex-wrap: wrap; gap: 16px; }
.detail-stat .k { display: block; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-dim); }
.detail-stat .v { display: block; font-family: var(--font-mono); font-size: 16px; color: var(--fg); margin-top: 4px; }
.detail-stat.primary .v { font-size: 23px; font-weight: 600; }
.detail-stat-group.accent-pace .detail-stat.primary .v { color: var(--signal); }
.detail-stat-group.accent-hr .detail-stat.primary .v { color: var(--warn); }
.detail-stat-group.accent-load .detail-stat.primary .v { color: var(--teal); }
.chart-title { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-dim); margin-bottom: 10px; }
.hr-zone-chart { margin-top: 28px; }
.hr-zone-rows { display: flex; flex-direction: column; gap: 8px; }
.hr-zone-row {
  display: grid; grid-template-columns: 22px 1fr 44px 34px; align-items: center; gap: 10px;
  font-family: var(--font-mono); font-size: 11px;
}
.hr-zone-row-label { font-weight: 600; }
.hr-zone-row-track { height: 10px; border-radius: 5px; background: var(--bg-raise); overflow: hidden; }
.hr-zone-row-fill { height: 100%; border-radius: 5px; min-width: 2px; }
.hr-zone-row-value { color: var(--fg); text-align: right; }
.hr-zone-row-pct { color: var(--fg-dim); text-align: right; }
.detail-map-card { margin-top: 28px; }
.detail-map-card-photos-only { display: flex; }
/* Overlaid on the map's bottom-left corner - the basemap switcher (top-right, see below)
   already owns that corner, so this deliberately sits opposite it. Falls back to a plain
   inline button (see detail-map-card-photos-only) when there's no map to sit on at all. */
.map-photos-vignette {
  position: absolute; bottom: 10px; left: 10px; z-index: 1000; margin-top: 0;
  width: 64px; height: 64px; padding: 0; border-radius: 10px; overflow: hidden; cursor: pointer;
  border: 2px solid color-mix(in srgb, var(--bg) 60%, transparent);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.detail-map-card-photos-only .map-photos-vignette { position: static; box-shadow: none; }
.map-photos-vignette img { width: 100%; height: 100%; object-fit: cover; display: block; }
.map-photos-vignette-count {
  position: absolute; bottom: 3px; right: 3px; background: rgba(0, 0, 0, 0.65); color: #fff;
  font-family: var(--font-mono); font-size: 10px; font-weight: 600; padding: 1px 5px; border-radius: 5px;
}
/* [hidden] must win over the explicit `display: flex` below (an author-stylesheet class
   selector otherwise beats the browser's own [hidden]{display:none} UA rule, regardless of
   specificity, since author styles always outrank UA ones) - toggled via el.hidden in JS. */
.photo-lightbox[hidden] { display: none; }
.photo-lightbox {
  position: fixed; inset: 0; z-index: 2000; background: rgba(5, 8, 14, 0.92);
  display: flex; align-items: center; justify-content: center; padding: 40px;
}
.photo-lightbox-img { max-width: 100%; max-height: 100%; border-radius: 8px; object-fit: contain; }
.photo-lightbox-prev[hidden], .photo-lightbox-next[hidden] { display: none; }
.photo-lightbox-close, .photo-lightbox-prev, .photo-lightbox-next {
  position: absolute; width: auto; margin-top: 0; background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2); color: #fff; border-radius: 50%;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.photo-lightbox-close { top: 20px; right: 20px; width: 36px; height: 36px; font-size: 22px; line-height: 1; }
.photo-lightbox-prev, .photo-lightbox-next { top: 50%; transform: translateY(-50%); width: 44px; height: 44px; font-size: 18px; }
.photo-lightbox-prev { left: 16px; }
.photo-lightbox-next { right: 16px; }
@media (hover: hover) { .photo-lightbox-close:hover, .photo-lightbox-prev:hover, .photo-lightbox-next:hover { background: rgba(255, 255, 255, 0.18); } }
.photo-lightbox-counter {
  position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
  font-family: var(--font-mono); font-size: 12px; color: rgba(255, 255, 255, 0.7);
}
/* position + z-index together (not just position:relative) deliberately establishes a NEW
   local stacking context here - Leaflet's own internal panes plus .map-photos-vignette/
   .map-basemap-switcher (z-index up to 1000, see below) would otherwise compete directly in
   whatever stacking context contains THIS card, which has no z-index of its own either -
   meaning that 1000 could paint over things far outside the map, like the sticky mobile
   topbar (z-index:10) or the floating chat widget (z-index:90), the moment the map scrolls
   to overlap them. Contained here, none of that can ever leak past this card's own box. */
.detail-map-stack { position: relative; z-index: 0; }
.detail-map, .detail-map-3d {
  width: 100%; height: 420px; border-radius: 10px; overflow: hidden; border: 1px solid var(--line); background: var(--bg);
}
.detail-map-3d { display: none; }
.map-basemap-switcher {
  position: absolute; top: 10px; right: 10px; z-index: 1000; display: flex; gap: 3px;
  background: color-mix(in srgb, var(--bg) 80%, transparent); backdrop-filter: blur(6px);
  padding: 4px; border-radius: 8px; border: 1px solid var(--line);
}
.map-basemap-btn {
  width: auto; margin-top: 0; flex-shrink: 0;
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .03em;
  color: var(--fg-dim); background: transparent; border: none; border-radius: 5px;
  padding: 5px 9px; cursor: pointer; transition: background-color .15s, color .15s;
}
@media (hover: hover) { .map-basemap-btn:hover { color: var(--fg); background: var(--bg-sink); } }
.map-basemap-btn.active { color: var(--signal-ink); background: var(--signal); }
.detail-charts { display: flex; flex-direction: column; gap: 18px; margin-top: 28px; }
.laps-card { margin-top: 28px; }
.laps-table-wrap { overflow-x: auto; }
.laps-table { width: 100%; border-collapse: collapse; margin-top: 10px; }
.laps-table th {
  text-align: left; font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--fg-dim); padding: 8px 12px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.laps-table td {
  padding: 9px 12px; border-bottom: 1px solid var(--line-soft); color: var(--fg);
  font-family: var(--font-mono); font-size: 12.5px; white-space: nowrap;
}
.laps-table tbody tr:nth-child(even) { background: var(--bg-sink); }
@media (hover: hover) { .laps-table tbody tr:hover { background: color-mix(in srgb, var(--signal) 10%, var(--bg-sink)); } }
.capture-recap-flag {
  background: color-mix(in srgb, var(--warn) 14%, var(--bg-sink)); border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--line));
  color: var(--fg); border-radius: 10px; padding: 10px 14px; font-size: 13px; line-height: 1.5; margin-bottom: 14px;
}
/* Recap header: title + small "Détacher" text button on the same line (see
   routes_activities._activity_recap_html); .chart-title keeps its own margin. */
.capture-recap-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.capture-recap-head form { margin: 0; flex-shrink: 0; }
/* margin/width reset: the global button rule makes every button a full-width primary CTA. */
.capture-recap-detach {
  margin: 0; width: auto; display: inline; background: none; border: none; padding: 0; cursor: pointer;
  color: var(--fg-dim); font-family: var(--font-mono); font-size: 11.5px; font-weight: 400; text-decoration: underline;
}
@media (hover: hover) { .capture-recap-detach:hover { background: none; color: var(--fg); } }
/* "Rattacher une séance Capture" (routes_activities._capture_link_picker_html): each session
   is a whole-card submit button - same global button reset as above. */
.capture-link-list { display: flex; flex-direction: column; gap: 8px; margin: 0; }
.capture-link-row {
  margin: 0; width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--bg-sink); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px;
  color: var(--fg); text-align: left; font-family: var(--font-body); font-weight: 400; font-size: 14px;
}
@media (hover: hover) {
  .capture-link-row:hover { background: color-mix(in srgb, var(--signal) 8%, var(--bg-sink)); border-color: color-mix(in srgb, var(--signal) 45%, var(--line)); }
}
.capture-link-row.suggested { border-color: color-mix(in srgb, var(--signal) 60%, var(--line)); background: color-mix(in srgb, var(--signal) 6%, var(--bg-sink)); }
.capture-link-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.capture-link-badge {
  align-self: flex-start; font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--signal); font-weight: 700;
}
.capture-link-name { font-weight: 600; overflow-wrap: anywhere; }
.capture-link-meta { font-family: var(--font-mono); font-size: 12px; color: var(--fg-dim); }
.capture-link-note { font-size: 12px; color: var(--fg-dim); font-style: italic; }
.capture-link-plus {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  border: 1px solid var(--line); font-family: var(--font-mono); font-size: 16px; color: var(--fg-dim);
}
.capture-link-row.suggested .capture-link-plus { background: var(--signal); border-color: var(--signal); color: var(--signal-ink); }
.capture-link-more { margin-top: 2px; }
.capture-link-more summary {
  cursor: pointer; list-style: none; text-align: center; font-family: var(--font-mono); font-size: 12px;
  color: var(--fg-dim); padding: 6px 0;
}
.capture-link-more summary::-webkit-details-marker { display: none; }
.capture-link-more[open] summary { margin-bottom: 8px; }
.capture-link-more .capture-link-row + .capture-link-row { margin-top: 8px; }
.capture-recap-block { border-left: 3px solid var(--block-color, var(--line)); padding: 6px 0 10px 14px; margin-top: 22px; }
.capture-recap-block-name {
  font-family: var(--font-mono); font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--fg); display: flex; align-items: center; gap: 8px;
}
.capture-recap-block-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--block-color, var(--fg-dim)); flex-shrink: 0; }
.capture-recap-block-comment { color: var(--fg-dim); font-size: 13px; margin: 8px 0 0; line-height: 1.5; white-space: pre-line; }
.capture-recap-sequence {
  margin-top: 14px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
  background: var(--bg-sink);
}
.capture-recap-sequence-head {
  font-family: var(--font-mono); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--seq-color, var(--fg-dim)); background: color-mix(in srgb, var(--seq-color, var(--fg-dim)) 16%, transparent);
  padding: 9px 14px; border-bottom: 1px solid var(--line);
}
.capture-recap-sequence-body { padding: 12px 14px 4px; }
.capture-recap-exercise { margin-bottom: 12px; }
.capture-recap-exercise-name { font-weight: 700; font-size: 14px; color: var(--fg); margin-bottom: 6px; }
.capture-recap-sets { display: flex; flex-direction: column; gap: 5px; }
.capture-recap-set-row {
  display: flex; align-items: center; gap: 10px; font-family: var(--font-mono); font-size: 12.5px; color: var(--fg);
  background: var(--bg); border: 1px solid var(--line-soft); border-radius: 6px; padding: 6px 10px;
}
.capture-recap-set-num {
  color: var(--fg-dim); min-width: 18px; text-align: center; font-weight: 600;
}
.health-period-toggle { display: flex; gap: 4px; margin: 20px 0 24px; }
/* Dashboard-style mosaic, not one big card: each metric gets its own panel, sized to what it
   needs (a gauge is small/square, a heatmap strip is wide/short, a stacked-bar chart is
   taller) - dense packing fills gaps instead of forcing every row into matched-height,
   evenly-aligned tiles. */
.health-dashboard { display: grid; grid-template-columns: repeat(12, 1fr); grid-auto-flow: dense; gap: 16px; }
.health-panel { position: relative; background: var(--bg-sink); border: 1px solid var(--line); border-radius: 12px; padding: 22px; grid-column: span 4; }
/* "Agrandir" (expand) button - see _health_panel_html and the expand-panel wiring in
   _HEALTH_CHARTS_SYNC_JS. Hidden until hover, same convention as the chat conversation
   list's rename/delete icons. */
.health-panel-expand {
  position: absolute; top: 10px; right: 10px; width: 26px; height: 26px; padding: 0; margin: 0;
  background: transparent; border: none; color: var(--fg-dim); font-size: 14px; border-radius: 6px;
  cursor: pointer; opacity: 0; transition: opacity .12s ease; z-index: 2; line-height: 1;
}
.health-panel:hover .health-panel-expand, .health-panel-expand:focus-visible { opacity: 1; }
@media (hover: none) { .health-panel-expand { opacity: 1; } }
@media (hover: hover) { .health-panel-expand:hover { background: var(--bg-raise); color: var(--signal); } }
/* The expanded modal reuses .chat-modal-overlay/.chat-modal (global rules, not scoped to the
   chat page) for a consistent look, sized up for chart/gauge content instead of a small
   confirm dialog. */
.health-panel-expand-box {
  max-width: min(1100px, 92vw); width: 100%; max-height: 88vh; overflow-y: auto; position: relative;
  /* Extra top clearance - the panel content's own top-right label (e.g. a chart's date
     range) sits flush with .chat-modal's normal 22px padding, which collides with the close
     button occupying that same corner. */
  padding-top: 46px;
}
.health-panel-expand-close {
  position: absolute; top: 14px; right: 14px; width: 30px; height: 30px; padding: 0; margin: 0;
  background: var(--bg-sink); border: 1px solid var(--line); color: var(--fg); font-size: 16px;
  border-radius: 7px; cursor: pointer; z-index: 2;
}
@media (hover: hover) { .health-panel-expand-close:hover { background: color-mix(in srgb, var(--signal) 14%, var(--bg-sink)); } }
/* These are fixed px/max-width constraints in their normal mosaic-tile context (see their
   own rules) - overridden here, scoped under the expand box, so the same chart/gauge markup
   actually looks bigger once moved there instead of just sitting in more empty whitespace. */
.health-panel-expand-box .detail-chart-svg-wrap { height: 320px; }
.health-panel-expand-box .health-gauge-dial-wrap { max-width: 420px; }
.health-panel-expand-box .health-bars-wrap { height: 260px; }
.health-panel-expand-explain {
  margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--line);
  color: var(--fg-dim); font-size: 0.87rem; line-height: 1.55;
}
/* Entrance animation, staggered per card so the dashboard builds itself in rather than
   popping in all at once - backwards fill-mode holds the "from" state during each card's
   delay instead of flashing at full opacity first. */
@keyframes health-panel-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
.health-panel { animation: health-panel-in .45s cubic-bezier(.2, .7, .3, 1) backwards; }
.health-panel:nth-child(1) { animation-delay: .02s; }
.health-panel:nth-child(2) { animation-delay: .07s; }
.health-panel:nth-child(3) { animation-delay: .12s; }
.health-panel:nth-child(4) { animation-delay: .17s; }
.health-panel:nth-child(5) { animation-delay: .22s; }
.health-panel:nth-child(6) { animation-delay: .27s; }
.health-panel:nth-child(7) { animation-delay: .32s; }
.health-panel:nth-child(8) { animation-delay: .37s; }
.health-panel:nth-child(n+9) { animation-delay: .4s; }
@media (prefers-reduced-motion: reduce) {
  .health-panel { animation: none; }
}
.health-panel.span-3 { grid-column: span 3; }
.health-panel.span-4 { grid-column: span 4; }
.health-panel.span-5 { grid-column: span 5; }
.health-panel.span-6 { grid-column: span 6; }
.health-panel.span-7 { grid-column: span 7; }
.health-panel.span-8 { grid-column: span 8; }
.health-panel.span-12 { grid-column: span 12; }
@media (max-width: 980px) {
  .health-dashboard { grid-template-columns: repeat(6, 1fr); }
  .health-panel, .health-panel.span-3, .health-panel.span-4 { grid-column: span 3; }
  .health-panel.span-5, .health-panel.span-6, .health-panel.span-7 { grid-column: span 6; }
  .health-panel.span-8, .health-panel.span-12 { grid-column: span 6; }
}
@media (max-width: 640px) {
  .health-dashboard { grid-template-columns: 1fr; gap: 14px; }
  .health-panel { grid-column: 1 !important; padding: 18px; }
}
.period-btn {
  font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .03em;
  color: var(--fg-dim); background: transparent; border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 16px; text-decoration: none; transition: background-color .15s, color .15s, border-color .15s;
}
@media (hover: hover) { .period-btn:hover { color: var(--fg); border-color: color-mix(in srgb, var(--signal) 40%, var(--line)); } }
.period-btn.active { color: var(--signal-ink); background: var(--signal); border-color: var(--signal); }
/* Radial dial gauge: latest value vs personal range for this period, not a trend line - the
   point is "is today high/low/normal for me", which a sparkline doesn't answer at a glance.
   Modeled on the Grafana dashboard's speedometer-style dials. */
.health-gauge {}
.health-gauge-dial-wrap { max-width: 220px; margin: 4px auto 0; text-align: center; }
.health-gauge-dial { width: 100%; display: block; }
.health-gauge-value {
  /* Normal flow below the dial, not overlaid on it - the needle's pivot dot sits right at the
     bottom edge of the semicircle, so absolutely-positioned text there collided with it. */
  display: flex; align-items: baseline; justify-content: center; gap: 5px; margin-top: -6px;
}
.health-gauge-num { font-family: var(--font-display); font-size: 30px; font-weight: 700; color: var(--fg); }
.health-gauge-unit { font-family: var(--font-mono); font-size: 12px; color: var(--fg-dim); }
.health-gauge-status {
  display: block; width: fit-content; margin: 6px auto 0; font-family: var(--font-mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .04em; padding: 4px 10px; border-radius: 12px;
}
.health-gauge-status.low { background: color-mix(in srgb, #4f83cc 20%, transparent); color: #7fb0ec; }
.health-gauge-status.mid { background: color-mix(in srgb, #4caf7d 20%, transparent); color: #7fd6ab; }
.health-gauge-status.high { background: color-mix(in srgb, #e08541 20%, transparent); color: #f3ac74; }
.health-gauge-status.bad { background: color-mix(in srgb, #e0524a 20%, transparent); color: #f28b85; }
/* Sitting-time index: dial beside the per-day bars, stacked on narrow screens. */
.sedentary-row { display: flex; gap: 24px; align-items: center; }
.sedentary-gauge { flex: 0 0 260px; }
.sedentary-bars { flex: 1; min-width: 0; }
.sedentary-bars .health-bars-wrap { height: 160px; }
.health-panel-expand-box .sedentary-bars .health-bars-wrap { height: 260px; }
.health-stack-bar.partial { opacity: 0.45; }
.compensation-summary, .sit-map-stats { font-size: 12.5px; color: var(--fg-dim); margin: 2px 0 10px; line-height: 1.5; }
.compensation-num { font-family: var(--font-display); font-size: 18px; font-weight: 700; color: var(--fg); margin-right: 4px; }
/* Dashed goal line across a bar chart (e.g. the 75-min compensation target). */
.target-wrap { position: relative; }
.target-line { position: absolute; left: 8px; right: 8px; border-top: 1px dashed var(--fg-dim); pointer-events: none; }
.target-line span { position: absolute; right: 0; top: -15px; font-family: var(--font-mono); font-size: 9.5px; color: var(--fg-dim); }
/* Hour x day sitting map: one row per day, one cell per hour. */
.sit-map { display: grid; gap: 2px; align-items: center; }
.sit-map-hour { font-family: var(--font-mono); font-size: 9px; color: var(--fg-dim); text-align: center; }
.sit-map-day { font-family: var(--font-mono); font-size: 9.5px; color: var(--fg-dim); }
.sit-map-day.partial { opacity: 0.5; }
.sit-map-cell { height: 11px; border-radius: 2px; }
.sit-map-cell.empty { background: var(--line-soft); }
@media (hover: hover) { .sit-map-cell:hover { outline: 1px solid var(--fg); } }
@media (max-width: 720px) { .sit-map-hour:nth-child(even) { visibility: hidden; } }
@media (max-width: 720px) {
  .sedentary-row { flex-direction: column; align-items: stretch; }
  .sedentary-gauge { flex-basis: auto; }
}
.health-gauge-delta { margin-top: 10px; text-align: center; font-family: var(--font-mono); font-size: 12px; color: var(--fg-dim); }
.gauge-legend {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 12px; margin-top: 14px;
  padding-top: 12px; border-top: 1px solid var(--line-soft);
}
.gauge-legend-item {
  display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-dim);
}
.gauge-legend-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.gauge-legend-range { color: var(--fg); }
/* Donut: average composition (e.g. sleep-stage split) - proportion-of-whole is the point,
   which a bar/line doesn't show as directly. */
.health-donut-card {}
.health-donut-row { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; margin-top: 6px; }
.health-donut-wrap { position: relative; width: 130px; height: 130px; flex-shrink: 0; }
.health-donut { width: 100%; height: 100%; display: block; }
.health-donut-center {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.health-donut-num { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--fg); }
.health-donut-sub { font-family: var(--font-mono); font-size: 10px; color: var(--fg-dim); }
.health-donut-legend { display: flex; flex-direction: column; gap: 8px; margin-top: 0; }
/* Heatmap strip: color-intensity per day (à la GitHub contributions) - reads "which days were
   high/low" faster than scanning a line chart's exact values. */
.heatmap-strip { display: flex; gap: 3px; height: 40px; }
.heatmap-cell { flex: 1; border-radius: 3px; }
.heatmap-cell.empty { background: var(--line-soft); }
[data-tip] { cursor: default; }
.hover-tip {
  position: fixed; z-index: 2000; transform: translate(-50%, -100%);
  background: var(--bg-raise); border: 1px solid var(--line); color: var(--fg);
  font-family: var(--font-mono); font-size: 11px; line-height: 1.45; padding: 5px 9px; border-radius: 6px;
  /* Short tips stay on one line; a long one wraps into a narrower, taller box. */
  width: max-content; max-width: 230px; white-space: normal; text-align: left; pointer-events: none;
}
.donut-seg { cursor: default; transition: opacity .1s; }
@media (hover: hover) { .donut-seg:hover { opacity: 0.8; } }
/* Bar chart: daily totals (calories) read more naturally as discrete bars than a connected
   trend line. */
.health-bars-wrap { height: 110px; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 10px 8px 0; box-sizing: border-box; }
.health-bars { display: flex; align-items: flex-end; gap: 3px; height: 100%; }
.health-bar { flex: 1; background: var(--signal); border-radius: 2px 2px 0 0; min-height: 2px; transition: opacity .1s; }
.health-bar.empty { background: var(--line-soft); }
.health-bar.partial { opacity: 0.45; } /* current week, still in progress (see routes_performance._weekly_volume) */
@media (hover: hover) { .health-bar:hover, .sleep-seg:hover, .heatmap-cell:hover { opacity: 0.75; } }
/* Stacked sleep-stage bars - each bar's own height is total sleep vs the period max, and the
   4 segments inside are flex-proportioned by each stage's share, like the Grafana dashboard's
   nightly sleep-stage panel. */
.health-bars.health-stack { align-items: flex-end; }
.health-stack-bar { flex: 1; display: flex; flex-direction: column-reverse; border-radius: 2px 2px 0 0; overflow: hidden; min-height: 2px; }
.sleep-seg { width: 100%; }
.sleep-seg.deep { background: #3b5bdb; }
.sleep-seg.light { background: #4dabf7; }
.sleep-seg.rem { background: #9775fa; }
.sleep-seg.awake { background: #495057; }
.sleep-legend { display: flex; gap: 16px; margin-top: 10px; flex-wrap: wrap; }
.sleep-legend-item { display: flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-dim); }
.sleep-legend-dot { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
.sleep-legend-dot.deep { background: #3b5bdb; }
.sleep-legend-dot.light { background: #4dabf7; }
.sleep-legend-dot.rem { background: #9775fa; }
.sleep-legend-dot.awake { background: #495057; }
.detail-chart-head { display: flex; align-items: center; gap: 10px; font-family: var(--font-mono); font-size: 11px; color: var(--fg-dim); margin-bottom: 6px; }
.detail-chart-head span:first-child { text-transform: uppercase; letter-spacing: .04em; }
.detail-chart-range { margin-left: auto; }
.chart-smooth-btn {
  width: auto; flex-shrink: 0; margin-top: 0;
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .03em;
  color: var(--fg-dim); background: transparent; border: 1px solid var(--line); border-radius: 12px;
  padding: 3px 10px; cursor: pointer; transition: background-color .15s, color .15s, border-color .15s;
}
@media (hover: hover) { .chart-smooth-btn:hover { color: var(--fg); border-color: color-mix(in srgb, var(--signal) 40%, var(--line)); } }
.chart-smooth-btn.active { color: var(--signal-ink); background: var(--signal); border-color: var(--signal); }
.detail-chart-body { display: flex; gap: 8px; align-items: stretch; }
.detail-chart-yaxis {
  display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end;
  width: 34px; flex-shrink: 0; padding: 6px 0; box-sizing: border-box;
  font-family: var(--font-mono); font-size: 9.5px; color: var(--fg-dim);
}
@media (max-width: 640px) {
  /* No fixed width on mobile - let it shrink to whatever the label digits actually need
     (flex's own min-content sizing), so the SVG chart area next to it (flex:1) gets back
     whatever room a fixed 34px was reserving even when the real labels are narrower. */
  .detail-chart-yaxis { width: auto; }
}
.detail-chart-xaxis {
  display: flex; justify-content: space-between; margin-top: 4px; padding: 0 2px;
  font-family: var(--font-mono); font-size: 9.5px; color: var(--fg-dim);
}
.detail-chart-svg-wrap { position: relative; flex: 1; min-width: 0; height: 70px; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 6px; box-sizing: border-box; cursor: crosshair; }
/* More vertical room when a target-pace overlay is drawn (see routes_activities._detail_
   chart_block's has-target class) - two crossing lines need more height to stay legible
   than one line ever did. */
.detail-chart.has-target .detail-chart-svg-wrap { height: 110px; }
/* overflow:hidden explicit, not relied on as an SVG UA-stylesheet default - a point outside
   a fixed axis_bounds (see routes_activities._pace_axis_bounds/_svg_sparkline) draws past
   the 0-100 viewBox on purpose and must actually clip here, not spill into the chart's own
   padding/border. */
.detail-chart-svg-wrap svg { width: 100%; height: 100%; display: block; overflow: hidden; }
.detail-chart-svg-wrap polyline {
  fill: none; stroke: var(--signal); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  /* Without this, preserveAspectRatio="none" stretches the viewBox non-uniformly, so the
     stroke itself gets stretched into a fat, uneven line on steep sections instead of
     staying a constant, thin pixel width along the whole path. */
  vector-effect: non-scaling-stroke;
}
/* display:none by default, NOT the `hidden` attribute - it isn't reliably reflected as
   display:none on raw SVG shape elements (no HTML [hidden] UA-stylesheet rule / IDL property
   for them in every engine), so it silently failed to hide this line at all. */
.detail-chart-svg-wrap polyline.alt { stroke: #ffb454; stroke-width: 1.75; stroke-dasharray: 3 2.5; display: none; }
.detail-chart-svg-wrap polyline.alt.visible { display: inline; }
/* Prescribed target pace (see connectors/capture.target_pace_series) - always visible when
   present, unlike .alt above which is behind its own toggle. Green reads as "the plan/goal"
   next to .actual below, distinct from .alt's orange smoothing overlay. Deliberately heavy
   (2.5 vs the primary line's 1.5, full opacity, wide dashes) - two same-weight crossing
   lines were unreadable; the target now reads as a clearly different object. */
.detail-chart-svg-wrap polyline.target { stroke: var(--go); stroke-width: 2.5; stroke-dasharray: 6 4; opacity: 1; }
/* Real pace achieved per prescription segment (see routes_activities._actual_pace_by_
   segments) - always visible, paired against .target above as "plan vs reality". Orange
   dashed (same hue as .alt's smoothing overlay, but a tighter dash so the two are still
   distinguishable at a glance) and the same weight as .target, so the two read as equally
   important; the primary raw/noisy line steps back instead (see .dimmed and the :not()
   rule below). */
.detail-chart-svg-wrap polyline.actual { stroke: #ffb454; stroke-width: 2.5; stroke-dasharray: 4 3; opacity: 1; }
/* Thins the primary line only on a chart with a target/actual overlay (see the .has-target
   rule above) - .dimmed (applied server-side via dim_primary, not just the JS toggle)
   already fades it; this just keeps its stroke from competing on width too. .target/.actual
   are excluded - both stay at full weight, they're the ones meant to draw the eye here.
   Everywhere else (no overlay), every chart's line keeps its normal weight untouched. */
.detail-chart.has-target .detail-chart-svg-wrap polyline:not(.target):not(.actual) { stroke-width: 1; }
.detail-chart-target-legend { display: inline-flex; align-items: center; gap: 5px; color: var(--go); }
.detail-chart-target-legend::before { content: ""; width: 14px; height: 0; border-top: 2.5px dashed var(--go); }
.detail-chart-actual-legend { display: inline-flex; align-items: center; gap: 5px; color: #ffb454; }
.detail-chart-actual-legend::before { content: ""; width: 14px; height: 0; border-top: 2.5px dashed #ffb454; }
.detail-chart-svg-wrap polyline.vo2-line-cycling { stroke: #ffb454; }
.detail-chart-svg-wrap polyline.dimmed { opacity: 0.35; transition: opacity .15s; }
/* Every chart on the activity detail page (Altitude/FC/Allure-Vitesse/Cadence, see
   _detail_chart_block's fill=True call sites) - a translucent fill under the line down to
   the chart's own baseline, drawn behind the polyline. */
.detail-chart-svg-wrap polygon.area { fill: var(--signal); opacity: 0.14; }
.detail-chart-cursor-line {
  position: absolute; top: 6px; bottom: 6px; width: 1px;
  background: color-mix(in srgb, var(--fg) 35%, transparent); pointer-events: none;
}
.detail-chart-cursor-dot {
  position: absolute; width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: 50%;
  background: var(--signal); box-shadow: 0 0 0 2px var(--bg); pointer-events: none;
}
.detail-chart-tooltip {
  position: absolute; top: 2px; transform: translate(-50%, -100%);
  background: var(--bg-raise); border: 1px solid var(--line); color: var(--fg);
  font-family: var(--font-mono); font-size: 11px; padding: 3px 7px; border-radius: 5px;
  white-space: nowrap; pointer-events: none;
}
@media (max-width: 640px) {
  .detail-map, .detail-map-3d { height: 280px; }
  .map-basemap-btn { padding: 5px 7px; }
  /* Force exactly 2 columns instead of auto-fit's minmax(170px, 1fr), which collapses to
     a single column on most phones (170px * 2 + gap doesn't fit) - condensed padding/gaps/
     font sizes so a tile still reads cleanly at half the card's width. */
  .detail-stat-groups { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  /* Which tile spans the full row (the headline distance/durée tile, and a trailing one
     left without a partner to pair with) is computed in Python - see
     _detail_stats_groups_html/_detail_stat_group's span_full param and docstring for why
     this isn't a :nth-child guess (it can't know which groups a given activity actually
     rendered - a group missing from the MIDDLE, e.g. no "Allure" tile for strength
     training, throws off any position-based guess for everything after it). */
  .detail-stat-groups .detail-stat-group.span-full { grid-column: 1 / -1; }
  .detail-stat-group { padding: 10px 12px; gap: 8px; }
  .detail-stat-group-row { gap: 10px; }
  .detail-stat .v { font-size: 14px; }
  .detail-stat.primary .v { font-size: 19px; }
}

.source-card.warn { border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); }
.source-head { display: flex; align-items: center; justify-content: space-between; }
.source-name { display: flex; align-items: center; gap: 10px; font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--fg); }
.source-card p { color: var(--fg-dim); font-size: 12.5px; margin: 10px 0 0; }
.source-card .action { margin-top: 12px; display: inline-block; font-family: var(--font-mono); font-size: 11.5px; color: var(--signal); border: 1px solid var(--line); border-radius: 6px; padding: 7px 12px; }
.progress-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.progress-bar { flex: 1; height: 5px; border-radius: 3px; background: var(--line); overflow: hidden; }
.progress-pct { font-family: var(--font-mono); font-size: 11px; color: var(--fg-dim); flex-shrink: 0; min-width: 32px; text-align: right; }
.progress-fill { height: 100%; background: var(--signal); border-radius: 3px; transition: width .4s ease; }
.backfill-activity {
  margin-top: 10px; font-family: var(--font-mono); font-size: 11px; color: var(--fg-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: opacity .25s ease;
}
.backfill-activity .activity-date { color: var(--signal); margin-right: 7px; }

/* Logged-in app shell (sidebar + main) - used by /dashboard, distinct from the centered-card
   .onboard-center system above (auth screens/admin still use that one). width:100% because
   body (shared with the centered-card auth pages) is itself display:flex - without it
   .app-shell only shrinks to fit its content as a flex item of body, instead of filling the
   viewport (the sidebar no longer being a flex child of .app-shell doesn't change this). */
/* position:relative (not just static) so this stays a normal-flow "positioned" element that
   paints in DOM order relative to the grid-hover canvas (also position:absolute, prepended
   as body's first child) - without this, .app-shell being position:static would put it in a
   lower stacking layer than any positioned sibling regardless of DOM order, so the canvas'
   color-highlight cells would paint OVER the dashboard's cards instead of behind them (this
   is exactly what .onboard-center's own position:relative already prevents on the auth
   pages that share this same canvas overlay). */
.app-shell { width: 100%; min-height: 100vh; position: relative; }
/* position:fixed + a vh-based height, so the sidebar stays pinned to the viewport and never
   scrolls away, no matter how tall the main content gets (the Activities grid especially).
   .app-main below gets a matching margin-left instead of relying on flex layout for the gap. */
.sidebar {
  position: fixed; top: 16px; left: 16px; bottom: 16px; width: 220px;
  height: calc(100vh - 32px); border-radius: 20px;
  background: var(--bg-raise); border: none;
  display: flex; flex-direction: column; padding: 24px 16px;
}
.sidebar-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 28px; }
.sidebar-logo { padding: 0 8px; }
/* Desktop: fold the sidebar away (#sidebar-collapse) and bring it back (#sidebar-expand,
   floating top-left) - html.sidebar-collapsed, remembered per device by sidebar-menu.js. The
   content then takes the freed width. Phones never show either button (drawer instead). */
.sidebar-fold {
  width: 34px; height: 34px; margin: 0; padding: 0; display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 10px; color: var(--fg-dim); flex-shrink: 0;
}
.sidebar-fold svg { stroke: currentColor; stroke-width: 1.8; fill: none; stroke-linecap: round; stroke-linejoin: round; }
@media (hover: hover) { .sidebar-fold:hover { background: var(--bg-sink); color: var(--fg); } }
.sidebar-expand { display: none; position: fixed; top: 16px; left: 16px; z-index: 50; background: var(--bg-raise); }
@media (min-width: 721px) {
  .sidebar, .app-main, .install-banner { transition: transform .22s ease, margin-left .22s ease, left .22s ease; }
  .sidebar-collapsed .sidebar { transform: translateX(calc(-100% - 24px)); }
  .sidebar-collapsed .sidebar-expand { display: inline-flex; }
  .sidebar-collapsed .app-main { margin-left: 50px; }
  .sidebar-collapsed .install-banner { left: 24px; }
  /* Peek: the mouse at the screen's left edge slides it back over the content (not pushing
     it), until the mouse leaves it - see sidebar-menu.js. */
  .sidebar-collapsed.sidebar-peek .sidebar { transform: none; z-index: 60; box-shadow: 0 16px 48px rgba(0, 0, 0, .35); }
}
@media (max-width: 720px) { .sidebar-fold { display: none; } }
.sidebar-nav { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.sidebar-link {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 14px; border-radius: 999px; font-family: var(--font-body); font-size: 14px;
  font-weight: 600; color: var(--fg-dim); text-decoration: none;
}
@media (hover: hover) { .sidebar-link:hover { background: var(--bg-sink); color: var(--fg); } }
.sidebar-link.active { background: var(--signal); color: var(--signal-ink); font-weight: 700; }
.sidebar-link.disabled { cursor: default; }
@media (hover: hover) { .sidebar-link.disabled:hover { background: none; color: var(--fg-dim); } }
.sidebar-group-label {
  font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--fg-dim); padding: 28px 12px 6px; opacity: 0.7;
}
.sidebar-footer {
  margin-top: auto; display: flex; flex-direction: column; gap: 4px;
  border-top: 1px solid var(--line-soft); padding-top: 12px;
}
.sidebar-account {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-radius: 7px;
  color: var(--fg-dim); text-decoration: none; font-size: 13.5px;
}
@media (hover: hover) { .sidebar-account:hover { background: var(--bg-sink); color: var(--fg); } }
.sidebar-account.active { color: var(--fg); }
.sidebar-account-avatar {
  width: 26px; height: 26px; border-radius: 50%; background: color-mix(in srgb, var(--signal) 18%, var(--bg-sink));
  color: var(--signal); font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.sidebar-account-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-logout { padding: 10px 12px; }
.app-main { margin-left: 260px; padding: 44px 40px; }
.app-main.narrow { max-width: 780px; }
/* Activities page only: the page itself never scrolls (sidebar, header, filter all stay put)
   - only .activities-list scrolls internally, independently from the timeline rail beside it. */
.app-main.scroll-lock { height: 100vh; box-sizing: border-box; overflow: hidden; display: flex; flex-direction: column; }
.app-main.scroll-lock .content-card { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.app-main.scroll-lock .activities-layout { flex: 1; min-height: 0; align-items: stretch; }
.app-main.scroll-lock .activities-list {
  min-height: 0; height: 100%; overflow-y: auto; padding-right: 4px;
  display: flex; flex-direction: column;
}
/* Grows to fill the list even when there are too few cards to scroll, so .pagination
   stays pinned to the card's bottom edge instead of floating right under the last card. */
.app-main.scroll-lock .activities-list .activities-grid { flex: 1; }
.app-main.scroll-lock .activities-sidebar { height: 100%; }
.app-main.scroll-lock .activities-timeline { flex: 1; min-height: 0; max-height: none; }
/* Chat IA: same scroll-lock idea as Activities above - only .chat-thread scrolls, the
   conversation rail and the page chrome around it stay put. */
.app-main.scroll-lock .chat-layout { flex: 1; min-height: 0; }
.app-main.scroll-lock .chat-sidebar { height: 100%; }
.app-main.scroll-lock .chat-main { min-height: 0; }
/* Mobile nav: a slim top bar (logo + hamburger) that opens the SAME .sidebar as an
   off-canvas drawer, instead of squeezing it into a horizontal scrolling strip - a drawer
   keeps every link readable and one tap away, rather than a strip you have to scroll to
   find "Sources" in. Hidden on desktop; see _dashboard_shell for the markup and
   static/sidebar-menu.js for the open/close behavior. */
.mobile-topbar { display: none; }
.sidebar-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, .55); z-index: 2000; }
.sidebar-backdrop[hidden] { display: none; }
@media (max-width: 720px) {
  .app-main.scroll-lock { height: auto; overflow: visible; display: block; }
  .app-main.scroll-lock .content-card { display: block; }
  .app-main.scroll-lock .activities-list { height: auto; overflow-y: visible; display: block; padding-right: 0px }
  .app-main.scroll-lock .activities-list .activities-grid { flex: none; }
  .app-main.scroll-lock .activities-sidebar { height: auto; }
  /* Same specificity as the desktop-only rule above (0,2,0) so source order decides - this
     block comes later, so it correctly wins back the mobile collapsed-rail sizing. */
  .app-main.scroll-lock .activities-timeline { flex: none; height: auto; max-height: 160px; }
  .mobile-topbar {
    display: flex; align-items: center; gap: 12px; padding: 14px 20px;
    border-bottom: 1px solid var(--line-soft); position: sticky; top: 0; z-index: 10;
    background: var(--bg);
  }
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; width: min(260px, 82vw); height: 100vh;
    margin: 0; border-radius: 0; border: none; border-right: 1px solid var(--line);
    box-shadow: 0 0 40px rgba(0, 0, 0, .4);
    transform: translateX(-100%); transition: transform .22s ease; z-index: 2001;
    background: var(--bg); overflow-y: auto;
  }
  .sidebar.open { transform: translateX(0); }
  .app-main { margin-left: 0; padding: 28px 20px; }
}

/* Admin tenant table */
.admin-table { width: 100%; border-collapse: collapse; margin-top: 24px; }
.admin-table th {
  text-align: left; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--fg-dim); padding: 10px 12px; border-bottom: 1px solid var(--line);
}
.admin-table td {
  padding: 12px; border-bottom: 1px solid var(--line-soft); color: var(--fg);
  font-family: var(--font-mono); font-size: 12.5px;
}
.admin-table-wrap { overflow-x: auto; }
.admin-delete-form { margin: 0; }
.btn.secondary.admin-delete-btn {
  width: auto; margin-top: 0; padding: 6px 12px; font-size: 11px; white-space: nowrap;
  color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, var(--line));
}
@media (hover: hover) { .btn.secondary.admin-delete-btn:hover { background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn); } }

@media (max-width: 560px) {
  .onboard-center { padding: 28px 16px; }
  .card { padding: 24px; }
  .card.wide { padding: 24px 18px; }
  .sources-grid { grid-template-columns: 1fr; }
  .connector { transform: scale(0.9); }
}

/* Nutrition (/dashboard/nutrition) */
.nutrition-totals { margin-top: 20px; }
.nutrition-totals .k { font-size: 11px; }
.nutrition-totals .v { font-size: 24px; font-weight: 600; }
/* Weekly balance card - deliberately louder than the plain .content-card cards around it
   (accent left border + a big headline number) since it's the one figure meant to guide the
   athlete at a glance, not just another stat tile. */
.nutrition-balance-card {
  border-left: 3px solid var(--signal); background: color-mix(in srgb, var(--signal) 6%, var(--bg-sink));
}
.nutrition-balance-window {
  margin: 0; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--fg-dim);
}
.nutrition-balance-headline { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-top: 10px; }
.nutrition-balance-label { font-family: var(--font-display); font-size: 1.3rem; font-weight: 700; color: var(--fg); }
.nutrition-balance-value {
  font-family: var(--font-mono); font-size: 2.1rem; font-weight: 700; color: var(--signal); line-height: 1;
}
.nutrition-balance-value small { font-size: 0.9rem; font-weight: 500; color: var(--fg-dim); }
.nutrition-balance-detail { margin: 12px 0 0; color: var(--fg-dim); font-size: 0.82rem; }
.nutrition-balance-detail strong { color: var(--fg); font-weight: 600; }

.nutrition-meals-grid { display: grid; grid-template-columns: 1fr; gap: 16px; margin-top: 16px; }
.nutrition-meal-card { margin-top: 0; }
/* flex-start, not center: the totals badge under the title makes this block taller than the
   "+ Ajouter" button - centering would sink the button below the title instead of lining up
   with it. */
/* Title + "+ Ajouter" share one line only (both flex-shrink:0/nowrap) - the totals badge
   moved OUT of this row (own line below, full card width) after it was found wrapping onto
   2 lines on mobile: squeezed into a narrow column alongside the button, its long "kcal ·
   P.. · G.. · L.." text had nowhere near enough room. Full width fixes that outright. */
.nutrition-meal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.nutrition-meal-head h3 {
  margin: 0; min-width: 0; overflow-wrap: break-word; font-family: var(--font-display);
  font-size: 1.1rem; font-weight: 600; color: var(--fg); line-height: 1.3;
}
.nutrition-meal-totals {
  display: inline-block; width: fit-content; max-width: 100%; box-sizing: border-box;
  background: var(--bg-raise); border: 1px solid var(--line); border-radius: 20px; padding: 4px 10px;
  color: var(--fg-dim); font-size: 0.78rem; font-family: var(--font-mono); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; margin-top: 10px;
}
.nutrition-meal-totals.nutrition-meal-empty { font-family: var(--font-body); opacity: 0.75; }

@media (min-width: 880px) {
  .nutrition-meals-grid { grid-template-columns: repeat(2, 1fr); }
}
/* Mobile: the four meals become a horizontal swipe carousel (one meal per screen, native
   scroll-snap), with a tab strip above to jump straight to one and show which is in view.
   On wider screens the tab strip stays hidden and the grid above applies. */
.nutrition-meal-tabs { display: none; }
.nutrition-recipes-link { margin-top: 24px; }
@media (max-width: 640px) {
  .nutrition-meal-tabs {
    display: flex; gap: 6px; margin-top: 16px; overflow-x: auto; scrollbar-width: none;
  }
  .nutrition-meal-tabs::-webkit-scrollbar { display: none; }
  /* margin/width reset: these are <button>s, and the global button rule would make each one a
     full-width CTA with a 26px top margin (one tab visible, a big gap above the meals). */
  .nutrition-meal-tab {
    margin: 0; width: auto;
    flex: 1 0 auto; padding: 8px 12px; border-radius: 20px; border: 1px solid var(--line);
    background: var(--bg-raise); color: var(--fg-dim); font: inherit; font-size: 0.82rem;
    white-space: nowrap; cursor: pointer;
  }
  .nutrition-meal-tab.active { background: var(--signal); border-color: var(--signal); color: var(--signal-ink); font-weight: 600; }
  /* Bleeds past .app-main's 20px mobile side padding so a card slides off the screen edge
     instead of being clipped at the padding; the same 20px goes back as inner padding +
     scroll-padding so a snapped card still lines up with the rest of the page. */
  .nutrition-meals-grid {
    display: flex; align-items: flex-start; gap: 12px; margin: 12px -20px 0; padding: 0 20px;
    scroll-padding-inline: 20px;
    overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .nutrition-meals-grid::-webkit-scrollbar { display: none; }
  .nutrition-meals-grid > .nutrition-meal-card { flex: 0 0 100%; scroll-snap-align: start; scroll-snap-stop: always; }
}
.nutrition-log-entry {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 0; border-top: 1px solid var(--line-soft);
}
.nutrition-log-entry-main { flex: 1; min-width: 0; }
.nutrition-log-entry-name { color: var(--fg); font-size: 0.93rem; font-weight: 500; overflow-wrap: break-word; }
.nutrition-log-entry-macros { color: var(--fg-dim); font-size: 0.78rem; font-family: var(--font-mono); margin-top: 4px; }
.nutrition-inline-form { margin: 0; }

/* Quantity is secondary info: a badge + pencil icon by default (see _log_entry_html) -
   <details>/<summary> so it works with no JS (clicking it just opens the stepper form
   below); nutrition-stepper.js layers instant +/- on top once it's open. */
.nutrition-qty-toggle { flex-shrink: 0; }
.nutrition-qty-summary {
  display: flex; align-items: center; gap: 6px; cursor: pointer; list-style: none;
  background: var(--bg-raise); border: 1px solid var(--line); border-radius: 20px;
  padding: 5px 10px; color: var(--fg-dim); font-family: var(--font-mono); font-size: 0.78rem;
}
.nutrition-qty-summary::-webkit-details-marker { display: none; }
@media (hover: hover) { .nutrition-qty-summary:hover { color: var(--fg); border-color: color-mix(in srgb, var(--fg-dim) 40%, var(--line)); } }
.nutrition-qty-pencil { flex-shrink: 0; }
.nutrition-qty-toggle[open] .nutrition-qty-summary { display: none; }
.nutrition-stepper-form { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.nutrition-stepper { display: flex; align-items: center; gap: 4px; background: var(--bg-raise); border: 1px solid var(--line); border-radius: 8px; padding: 3px; }
.nutrition-step-btn {
  margin: 0; width: 30px; height: 30px; border-radius: 6px; border: none; background: transparent;
  color: var(--fg); font-size: 15px; line-height: 1; cursor: pointer; flex-shrink: 0;
}
@media (hover: hover) { .nutrition-step-btn:hover { background: var(--bg-sink); } }
.nutrition-stepper-input {
  width: 60px; margin: 0; padding: 6px 4px; text-align: center; border: none; background: transparent;
  font-family: var(--font-mono); font-size: 12.5px;
}
.nutrition-edit-confirm {
  margin: 0; width: auto; flex-shrink: 0; background: transparent; color: var(--go); border: 1px solid var(--line);
  border-radius: 6px; padding: 6px 9px; font-size: 14px; line-height: 1;
}
@media (hover: hover) { .nutrition-edit-confirm:hover { background: var(--bg-sink); } }

.nutrition-delete-btn {
  margin: 0; width: auto; background: transparent; color: var(--fg-dim); opacity: 0.65; border: none;
  padding: 6px 8px; font-size: 15px; line-height: 1; flex-shrink: 0;
}
@media (hover: hover) { .nutrition-delete-btn:hover { color: var(--warn); opacity: 1; background: transparent; } }

@media (max-width: 480px) {
  /* Name+macros keep the full first line, quantity/delete share the second - avoids three
     columns fighting for space on a phone-width row. */
  .nutrition-log-entry { flex-wrap: wrap; row-gap: 8px; }
  .nutrition-log-entry-main { flex-basis: 100%; }
  .nutrition-qty-toggle { flex: 1; }
  /* Same visual size as the meal's .nutrition-meal-totals pill (it used to be a 40px-tall
     bar stretched across the row); the comfortable tap target is an invisible ::before
     extending around it instead of the visible pill itself. */
  .nutrition-qty-summary { position: relative; width: fit-content; padding: 4px 10px; }
  .nutrition-qty-summary::before { content: ""; position: absolute; inset: -10px -8px; }
  .nutrition-step-btn,
  .nutrition-edit-confirm { min-height: 40px; }
}
.nutrition-btn-sm { margin-top: 0; width: auto; padding: 7px 12px; font-size: 11.5px; flex-shrink: 0; white-space: nowrap; }
/* The select's content ("portion (25 g)") needs more room than a 1-4 digit quantity - a
   flex-2/flex-1 split starved it on narrow screens, clipping the text (real bug, confirmed
   headless-mobile screenshot: "portion (25" cut off). A fixed input width leaves the select
   the rest of the row regardless of viewport width. */
.nutrition-quantity-row { display: flex; gap: 8px; }
.nutrition-quantity-row input { flex: 0 0 90px; }
.nutrition-quantity-row select { flex: 1; min-width: 0; }
.nutrition-per100 { color: var(--fg-dim); font-weight: normal; }
.nutrition-macro-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.nutrition-camera-frame { position: relative; width: 100%; max-width: 420px; margin: 14px auto 0; }
.nutrition-camera-video {
  display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: 8px; background: #000;
}
/* An author `display` rule of the same specificity beats the UA [hidden]{display:none}
   regardless of source order (author origin always wins) - without this, toggling the
   `hidden` attribute (nutrition-photo.js's open/close, nutrition-scan.js's camera-failed
   fallback) silently stopped hiding the video. */
.nutrition-camera-video[hidden] { display: none; }
/* Horizontal band guide (barcodes read wider than tall) - the huge box-shadow spread dims
   everything outside it, a common scanner-app cue for where to hold the code. Decorative
   only (aria-hidden), never intercepts taps meant for the video/torch button beneath it. */
.nutrition-scan-guide {
  position: absolute; inset: 24% 8%; border: 2px solid var(--signal); border-radius: 10px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.35); pointer-events: none;
}
.nutrition-torch-btn {
  position: absolute; top: 10px; right: 10px; width: 38px; height: 38px; border-radius: 50%;
  border: none; background: rgba(0, 0, 0, 0.55); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
@media (hover: hover) { .nutrition-torch-btn:hover { background: rgba(0, 0, 0, 0.7); } }
.nutrition-torch-btn.active { background: var(--signal); color: var(--signal-ink); }
.nutrition-food-result {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 0; border-top: 1px solid var(--line-soft); text-decoration: none;
}
.nutrition-food-result:first-child { border-top: none; }
.nutrition-food-result-name { flex: 1; min-width: 0; color: var(--fg); font-size: 0.92rem; overflow-wrap: break-word; }
.nutrition-food-result-macros { color: var(--fg-dim); font-size: 0.8rem; font-family: var(--font-mono); white-space: nowrap; flex-shrink: 0; }
.nutrition-recipe-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; text-decoration: none; margin-top: 12px; }
.nutrition-recipe-row-name { flex: 1; min-width: 0; overflow-wrap: break-word; }
.nutrition-recipe-row .sub { flex-shrink: 0; }
.nutrition-photo-form button { margin-top: 0; }

@media (max-width: 560px) {
  .nutrition-macro-grid { grid-template-columns: 1fr; }
}

/* Nutrition "Ajouter" modal (routes_nutrition.py's _modal_shell) - a real full navigation to
   /dashboard/nutrition/add, styled as an overlay so it reads as a modal on top of the diary
   rather than a plain page swap. Same visual language as .chat-modal-overlay/.chat-modal. */
.nutrition-modal-overlay {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.6); display: flex; align-items: flex-start;
  justify-content: center; z-index: 100; padding: 20px; overflow-y: auto;
}
.nutrition-modal {
  width: 100%; max-width: 480px; border: 1px solid var(--line); background: var(--bg-raise);
  border-radius: 14px; padding: 22px; box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.5);
  margin: auto 0;
}
.nutrition-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.nutrition-modal-head h2 { font-family: var(--font-display); font-size: 17px; font-weight: 600; color: var(--fg); margin: 0; min-width: 0; overflow-wrap: break-word; }
.nutrition-modal-close {
  color: var(--fg-dim); font-size: 22px; line-height: 1; text-decoration: none; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  margin: -6px -6px 0 0; border-radius: 8px;
}
@media (hover: hover) { .nutrition-modal-close:hover { color: var(--fg); background: var(--bg-sink); } }
/* Sections inside the modal reuse the existing .content-card helpers as-is (quantity form,
   search, manual-add...) - flattened to plain divider-separated blocks here instead of
   nested cards-in-a-card. */
.nutrition-modal .content-card {
  background: transparent; border: none; border-top: 1px solid var(--line-soft);
  border-radius: 0; padding: 18px 0 0; margin-top: 18px; box-shadow: none;
}
.nutrition-modal .content-card:first-child { border-top: none; margin-top: 0; padding-top: 0; }

.nutrition-scan-primary { text-align: center; margin-top: 10px; }
.nutrition-scan-hint { color: var(--fg-dim); font-size: 0.82rem; margin: 10px 0 14px; }
.nutrition-barcode-fallback { display: flex; gap: 8px; }
.nutrition-barcode-fallback input[type="text"] { flex: 1; margin: 0; }
.nutrition-barcode-fallback button { margin: 0; width: auto; padding: 11px 16px; }
/* Scan / create are separate views of the add modal (see dashboard_nutrition_add), reached
   from the home view and linking back through .nutrition-view-back. */
.nutrition-view-back {
  display: inline-block; margin-top: 12px; color: var(--fg-dim); font-size: 0.85rem; text-decoration: none;
}
@media (hover: hover) { .nutrition-view-back:hover { color: var(--fg); } }
.nutrition-modal .nutrition-view-back + .content-card,
.nutrition-modal .nutrition-method-tabs + .content-card { border-top: none; margin-top: 16px; padding-top: 0; }
/* Create view: photo (left) / manual entry (right) as a two-way segmented switch. */
.nutrition-method-tabs {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-top: 14px; padding: 4px;
  background: var(--bg-sink); border: 1px solid var(--line); border-radius: 10px;
}
.nutrition-method-tab {
  text-align: center; padding: 9px 8px; border-radius: 7px; text-decoration: none;
  color: var(--fg-dim); font-size: 0.88rem; font-weight: 500;
}
@media (hover: hover) { .nutrition-method-tab:hover { color: var(--fg); } }
.nutrition-method-tab.active { background: var(--bg-raise); color: var(--fg); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); }
.nutrition-estimate-keep { display: flex; align-items: center; gap: 8px; color: var(--fg-dim); font-size: 0.85rem; }
.nutrition-estimate-keep input { width: auto; margin: 0; }

@media (max-width: 560px) {
  .nutrition-modal-overlay { padding: 0; align-items: stretch; }
  .nutrition-modal { max-width: none; min-height: 100%; border-radius: 0; border-left: none; border-right: none; margin: 0; }
  /* The close '×' stays reachable while scrolling a long modal (search results, manual-add
     form) instead of only being available at the very top. */
  .nutrition-modal-head {
    position: sticky; top: 0; background: var(--bg-raise); z-index: 1;
    margin: -22px -22px 0; padding: 16px 22px; border-bottom: 1px solid var(--line-soft);
  }
  .nutrition-barcode-fallback { flex-wrap: wrap; }
  .nutrition-barcode-fallback input[type="text"] { min-width: 0; flex-basis: 100%; }
  .nutrition-barcode-fallback button { flex: 1; }
}

/* Add modal home view (_home_view_html): one search/describe field with the barcode scanner
   inside it, then result/recents/recipes lists as flat rows with a one-tap "+" on the right. */
.nutrition-omnibox {
  display: flex; align-items: center; margin-top: 16px; background: var(--bg-sink);
  border: 1px solid var(--line); border-radius: 12px; padding: 4px 4px 4px 14px;
}
.nutrition-omnibox:focus-within { border-color: var(--signal); }
.nutrition-omnibox input[type="search"] {
  flex: 1; min-width: 0; margin: 0; padding: 10px 0; border: none; background: transparent;
  color: var(--fg); font-size: 16px; outline: none; box-shadow: none;
}
.nutrition-omnibox-scan {
  flex-shrink: 0; width: 42px; height: 42px; border-radius: 9px; color: var(--signal);
  display: flex; align-items: center; justify-content: center;
}
@media (hover: hover) { .nutrition-omnibox-scan:hover { background: var(--bg-raise); } }
.nutrition-add-section { margin-top: 22px; }
.nutrition-add-section h4 {
  margin: 0 0 4px; font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  text-transform: uppercase; letter-spacing: .06em; color: var(--fg-dim);
}
.nutrition-quick-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line-soft); }
.nutrition-add-section h4 + .nutrition-quick-row,
.nutrition-add-section h4 + .nutrition-food-result { border-top: none; }
.nutrition-quick-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; text-decoration: none; }
.nutrition-quick-name { color: var(--fg); font-size: 0.92rem; overflow-wrap: break-word; }
.nutrition-quick-meta { color: var(--fg-dim); font-size: 0.78rem; font-family: var(--font-mono); }
.nutrition-quick-add {
  margin: 0; width: 36px; height: 36px; flex-shrink: 0; border-radius: 50%; padding: 0;
  border: 1px solid var(--line); background: transparent; color: var(--signal);
  font-size: 20px; line-height: 1; cursor: pointer;
}
@media (hover: hover) { .nutrition-quick-add:hover { background: color-mix(in srgb, var(--signal) 14%, transparent); border-color: var(--signal); } }
.nutrition-estimate-row {
  display: flex; align-items: center; gap: 12px; width: 100%; margin: 16px 0 0; padding: 12px 14px;
  text-align: left; cursor: pointer; border-radius: 10px; color: var(--signal);
  border: 1px dashed color-mix(in srgb, var(--signal) 55%, var(--line));
  background: color-mix(in srgb, var(--signal) 7%, transparent);
}
@media (hover: hover) { .nutrition-estimate-row:hover { background: color-mix(in srgb, var(--signal) 13%, transparent); } }
.nutrition-estimate-row svg { flex-shrink: 0; }
.nutrition-estimate-row .nutrition-quick-name { font-weight: 600; }
.nutrition-add-empty { margin-top: 20px; text-align: center; }
.nutrition-add-footer { margin: 22px 0 0; text-align: center; color: var(--fg-dim); font-size: 0.85rem; }
.nutrition-add-footer a { color: var(--signal); text-decoration: none; }

/* Goal targets (/dashboard/nutrition/goals + the diary's totals): "1850 / 2400" with a thin
   progress bar under the day's value, amber once clearly past the target. */
.nutrition-target { font-size: 0.55em; font-weight: 500; color: var(--fg-dim); }
.nutrition-progress { display: block; height: 4px; margin-top: 8px; border-radius: 2px; background: var(--line); overflow: hidden; }
.nutrition-progress span { display: block; height: 100%; background: var(--signal); border-radius: 2px; }
.nutrition-progress.over span { background: #ffb454; }
.nutrition-target-line { margin: 8px 0 0; color: var(--fg); }
.nutrition-goal-options { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 14px 0; }
.nutrition-goal-option {
  display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px; background: var(--bg-sink);
}
.nutrition-goal-option:has(input:checked), .nutrition-goal-option.active { border-color: var(--signal); background: color-mix(in srgb, var(--signal) 8%, var(--bg-sink)); }
.nutrition-goal-option input { position: absolute; opacity: 0; pointer-events: none; }
/* The options are <label>s, so reset the global form-label look (mono, uppercase). */
.nutrition-goal-option { position: relative; margin: 0; font-family: var(--font-body); text-transform: none; letter-spacing: normal; transition: border-color .15s, background .15s; }
@media (hover: hover) { .nutrition-goal-option:hover { border-color: color-mix(in srgb, var(--signal) 50%, var(--line)); } }
.nutrition-goal-option:has(input:focus-visible) { outline: 2px solid var(--signal); outline-offset: 2px; }
.nutrition-goal-option:has(input:checked)::after {
  content: "✓"; position: absolute; top: 10px; right: 12px; font-size: 13px; font-weight: 700; color: var(--signal);
}
.nutrition-goal-name { color: var(--fg); font-family: var(--font-display); font-weight: 600; font-size: 1rem; padding-right: 20px; }
.nutrition-goal-hint { color: var(--fg-dim); font-size: 0.82rem; line-height: 1.45; }
.nutrition-goal-options { margin-bottom: 0; }
/* Goals page: Objectif and Cibles side by side on wide screens (each option / tile then
   stacks in its own column), one column below that. With no goal set the Cibles card is
   absent, so the Objectif card takes the full row. */
.nutri-goal-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: stretch; }
.nutri-goal-row:has(> :nth-child(2)) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.nutri-goal-row > .content-card { margin: 0; min-width: 0; }
.nutri-goal-row + .content-card { margin-top: 20px; }
.nutri-goal-row:has(> :nth-child(2)) .nutrition-goal-options,
.nutri-goal-row:has(> :nth-child(2)) .nutri-goal-tiles { grid-template-columns: 1fr; }
@media (max-width: 900px) {
  .nutri-goal-row:has(> :nth-child(2)) { grid-template-columns: minmax(0, 1fr); }
}
/* Goals page: target tiles, each with the arithmetic behind its number. */
.nutri-goal-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 14px; }
.nutri-goal-tiles > div { padding: 12px 14px; border-radius: 10px; background: var(--bg-sink); border: 1px solid var(--line-soft); min-width: 0; }
.nutri-goal-tiles .k, .nutri-weight-now .k {
  display: block; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-dim);
}
.nutri-goal-tiles .v, .nutri-weight-now .v { display: block; font-family: var(--font-mono); font-size: 22px; color: var(--fg); margin-top: 6px; }
.nutri-goal-tiles .v small, .nutri-weight-now .v small { font-size: 12px; color: var(--fg-dim); }
.nutri-goal-calc { display: block; margin-top: 4px; font-size: 0.78rem; color: var(--fg-dim); line-height: 1.4; }
.nutri-goal-calc strong { color: var(--fg); font-weight: 600; }
.app-main p.sub.nutri-goal-note { margin: 14px 0 0; font-size: 0.82rem; }
.nutri-weight-table td.nutri-weight-delta { color: var(--fg-dim); }
.nutri-weight-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.nutri-weight-now { text-align: right; }
.nutri-weight-now .v { margin-top: 0; }
.nutri-weight-history { margin-top: 16px; border-top: 1px solid var(--line-soft); }
.nutri-weight-history summary {
  display: flex; align-items: center; gap: 8px; padding: 14px 0 2px; cursor: pointer; list-style: none;
  font-size: 0.9rem; color: var(--fg); user-select: none;
}
.nutri-weight-history summary::-webkit-details-marker { display: none; }
.nutri-weight-history summary::before {
  content: "›"; display: inline-block; width: 12px; color: var(--fg-dim); font-size: 1.1rem; line-height: 1; transition: transform .15s;
}
.nutri-weight-history[open] summary::before { transform: rotate(90deg); }
.nutri-weight-history summary small { color: var(--fg-dim); font-size: 0.78rem; }
@media (hover: hover) { .nutri-weight-history summary:hover { color: var(--signal); } }
.nutri-weight-table td:last-child, .nutri-weight-table th:last-child { width: 1%; padding-right: 0; }
.nutri-weight-table .nutrition-inline-form { display: flex; justify-content: flex-end; }
.nutrition-weight-form { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-top: 4px; }
.nutrition-weight-form label { flex: 1; min-width: 130px; }
.nutrition-weight-form button { width: auto; margin: 0 0 2px; }
@media (max-width: 560px) {
  .nutrition-goal-options { grid-template-columns: 1fr; }
  .nutri-goal-tiles { grid-template-columns: 1fr; }
}

/* Diary top strip (_goal_strip_html): goal + weight always visible, plus an inline
   "poids du jour" field on today's page until the athlete has weighed in. */
/* Day totals + goal/weight strip (.nutrition-summary wraps both). Laid out with container
   queries on the wrapper's own width, not the viewport's - the sidebar eats 260px from 721px
   up, so a viewport breakpoint put the side-by-side layout exactly where it didn't fit (the
   strip overlapped the totals around 768px) and stacked totals one per line elsewhere.
   - narrow (<520px): totals 2x2, strip below (goal | weight, weigh-in field full width)
   - medium: totals in one row of 4, strip below in one row
   - wide (>=900px): totals left, strip as a 300px column on the right */
.nutrition-summary {
  container-type: inline-size;
  margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--line-soft);
}
.nutrition-totals-row { display: grid; gap: 18px; }
.nutrition-totals-row .nutrition-totals {
  grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 20px;
  margin-top: 0; padding-top: 0; border-top: none;
}
.nutrition-goal-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.nutrition-strip-weigh { grid-column: 1 / -1; }
@container (min-width: 520px) {
  .nutrition-totals-row .nutrition-totals { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .nutrition-goal-strip { display: flex; flex-wrap: wrap; }
  .nutrition-goal-strip .nutrition-strip-goal { flex: 1 1 150px; }
  .nutrition-strip-weigh { flex: 2 1 260px; }
}
@container (min-width: 900px) {
  .nutrition-totals-row { grid-template-columns: minmax(0, 1fr) 300px; align-items: start; gap: 28px; }
  .nutrition-goal-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.nutrition-strip-goal {
  display: flex; flex-direction: column; gap: 3px; padding: 10px 14px; min-width: 0;
  border: 1px solid var(--line); border-radius: 10px; background: var(--bg-raise); text-decoration: none;
}
@media (hover: hover) { .nutrition-strip-goal:hover { border-color: color-mix(in srgb, var(--signal) 50%, var(--line)); } }
.nutrition-strip-k { font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-dim); }
.nutrition-strip-v { color: var(--fg); font-weight: 600; font-size: 0.98rem; }
.nutrition-strip-v small { display: block; margin-top: 2px; color: var(--fg-dim); font-weight: 500; font-family: var(--font-mono); font-size: 0.75rem; white-space: nowrap; }
.nutrition-strip-cta { border-style: dashed; border-color: color-mix(in srgb, var(--signal) 55%, var(--line)); }
.nutrition-strip-cta .nutrition-strip-v { color: var(--signal); }
.nutrition-strip-weigh { display: flex; align-items: center; gap: 8px; margin: 0; min-width: 0; }
.nutrition-strip-weigh input { flex: 1; margin: 0; min-width: 0; }
.nutrition-strip-weigh button { margin: 0; }

/* Nutrition Jour / Semaine / Mois switch (routes_nutrition._period_tabs_html). */
/* Sits on the right of the date/period selector row (.plan-cal-nav, already a wrapping
   space-between flex row) - wraps under it on narrow screens. */
.nutrition-nav-right { display: flex; align-items: center; gap: 14px; margin-left: auto; }
.nutrition-period-tabs {
  display: inline-grid; grid-template-columns: repeat(3, auto); gap: 4px; margin: 0 0 0 auto; padding: 3px;
  background: var(--bg-sink); border: 1px solid var(--line); border-radius: 10px;
}
.nutrition-period-tab {
  padding: 5px 14px; border-radius: 7px; text-decoration: none; text-align: center;
  color: var(--fg-dim); font-size: 0.88rem; font-weight: 500;
}
@media (hover: hover) { .nutrition-period-tab:hover { color: var(--fg); } }
@media (max-width: 560px) {
  /* Wrapped under the selector: full-width, three equal segments instead of floating right. */
  .plan-cal-nav > .nutrition-period-tabs, .nutrition-nav-right { width: 100%; }
  .nutrition-nav-right .nutrition-period-tabs { flex: 1; }
  .nutrition-period-tabs { grid-template-columns: repeat(3, 1fr); }
}
.nutrition-period-tab.active { background: var(--bg-raise); color: var(--fg); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); }
/* 2 columns on a narrow summary (the split tile then spans both), auto-fill once there's room. */
.nutri-period-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 20px; margin-top: 0; padding-top: 0; border-top: none; }
.nutri-period-tiles .nutri-tile-wide { grid-column: 1 / -1; }
@container (min-width: 560px) {
  .nutri-period-tiles { grid-template-columns: repeat(auto-fill, minmax(175px, 1fr)); }
  .nutri-period-tiles .nutri-tile-wide { grid-column: auto; }
}
.nutri-split { font-size: 14px !important; padding-top: 7px; white-space: nowrap; }

/* Week/month chart (_period_chart_html): HTML bars (legible labels at any width) + an SVG
   expenditure line stretched over the same plot. Intake = --signal bars; expenditure = a
   neutral 2px line, so the two series differ by mark AND color, and a legend names both. */
.nutri-chart-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.nutri-chart-head h3 { margin: 0; }
.nutri-chart-head h3 small { color: var(--fg-dim); font-weight: 400; font-size: 0.75rem; margin-left: 4px; }
.nutri-legend { display: flex; gap: 14px; color: var(--fg-dim); font-size: 0.8rem; }
.nutri-legend span { display: inline-flex; align-items: center; gap: 6px; }
/* Expenditure is the neutral reference the intake is read against, not a second series
   competing for attention - hence a grey next to the signal-coloured intake. */
.nutri-chart-card { --nutri-out: color-mix(in srgb, var(--fg-dim) 55%, var(--bg-raise)); }
.nutri-key { width: 10px; height: 10px; border-radius: 2px; }
.nutri-key.in { background: var(--signal); }
.nutri-key.out { background: var(--nutri-out); }
.nutri-chart { display: flex; gap: 8px; margin-top: 16px; }
.nutri-yaxis { position: relative; width: 36px; flex-shrink: 0; height: 200px; margin-bottom: 22px; }
.nutri-yaxis span {
  position: absolute; right: 0; transform: translateY(50%);
  font-family: var(--font-mono); font-size: 10px; color: var(--fg-dim);
}
.nutri-plot { position: relative; flex: 1; min-width: 0; height: 200px; margin-bottom: 22px; border-bottom: 1px solid var(--line); }
.nutri-grid { position: absolute; left: 0; right: 0; height: 0; border-top: 1px dashed var(--line-soft); }
.nutri-cols { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(var(--days), minmax(0, 1fr)); gap: 2px; }
.nutri-col { position: relative; display: flex; align-items: flex-end; justify-content: center; text-decoration: none; }
@media (hover: hover) { .nutri-col:hover { background: color-mix(in srgb, var(--fg) 5%, transparent); border-radius: 4px 4px 0 0; } }
.nutri-pair { display: flex; align-items: flex-end; justify-content: center; gap: 2px; width: min(84%, 44px); height: 100%; }
.nutri-bar { display: block; flex: 1; min-width: 0; max-width: 20px; border-radius: 4px 4px 0 0; }
.nutri-bar.in { background: var(--signal); }
.nutri-bar.out { background: var(--nutri-out); }
.nutri-bar.partial { opacity: 0.45; }
.nutri-bar-missing { display: block; flex: 1; max-width: 20px; height: 2px; background: var(--line); }
.nutri-col-label {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 6px;
  font-family: var(--font-mono); font-size: 10px; color: var(--fg-dim); white-space: nowrap;
}
.nutri-col[data-tip]:hover::after {
  content: attr(data-tip); position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  z-index: 3; white-space: nowrap; pointer-events: none;
  background: var(--bg-raise); color: var(--fg); border: 1px solid var(--line); border-radius: 6px;
  padding: 5px 8px; font-size: 11.5px; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
}
/* Balance strip: bars grow up (surplus) or down (deficit) from a centred zero line; the
   value sits on the opposite side of zero so it never collides with its own bar. */
.nutri-bal-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-top: 4px; font-size: 0.8rem; color: var(--fg-dim);
}
.nutri-key.on { background: var(--go); }
.nutri-key.off { background: var(--warn); }
.nutri-bal-head small { font-size: 0.72rem; margin-left: 4px; }
.nutri-bal-chart { margin-top: 8px; }
.nutri-bal-chart .nutri-yaxis, .nutri-bal-plot { height: 90px; margin-bottom: 0; }
.nutri-bal-plot { border-bottom: none; }
.nutri-zero { position: absolute; left: 0; right: 0; top: 50%; border-top: 1px solid var(--line); }
.nutri-bal-col { position: relative; }
.nutri-bal-bar { position: absolute; left: 50%; transform: translateX(-50%); width: min(42%, 20px); background: var(--fg-dim); }
.nutri-bal-bar.up { bottom: 50%; border-radius: 4px 4px 0 0; }
.nutri-bal-bar.down { top: 50%; border-radius: 0 0 4px 4px; }
.nutri-bal-bar.on { background: var(--go); }
.nutri-bal-bar.off { background: var(--warn); }
.nutri-bal-val {
  position: absolute; left: 50%; transform: translateX(-50%);
  font-family: var(--font-mono); font-size: 10px; color: var(--fg-dim); white-space: nowrap;
}
.nutri-bal-val.up { top: calc(50% + 3px); }
.nutri-bal-val.down { bottom: calc(50% + 3px); }

.nutri-table-wrap { overflow-x: auto; margin-top: 10px; }
.nutri-table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 12.5px; }
.nutri-table th {
  text-align: right; font-size: 10.5px; font-weight: 500; text-transform: uppercase; letter-spacing: .04em;
  color: var(--fg-dim); padding: 8px 10px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.nutri-table td { text-align: right; padding: 8px 10px; border-bottom: 1px solid var(--line-soft); color: var(--fg); white-space: nowrap; }
.nutri-table th:first-child, .nutri-table td:first-child { text-align: left; }
.nutri-table td a { color: var(--fg); text-decoration: none; }
@media (hover: hover) { .nutri-table td a:hover { color: var(--signal); } }
.nutri-table td.muted { color: var(--fg-dim); text-align: left; font-style: italic; }
.nutri-table tr.gap td:first-child { color: var(--fg-dim); }
@media (max-width: 560px) {
  .nutri-yaxis, .nutri-plot { height: 160px; }
  .nutri-bal-chart .nutri-yaxis, .nutri-bal-plot { height: 80px; }
}

/* Notifications card (/dashboard/account, static/push.js). */
.push-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.push-actions .btn { width: auto; margin-top: 0; }
.push-prefs { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.push-pref { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.push-pref input { width: auto; margin: 3px 0 0; }
.push-pref strong { display: block; color: var(--fg); font-weight: 600; font-size: 0.92rem; }
.push-pref small { display: block; color: var(--fg-dim); font-size: 0.82rem; margin-top: 2px; }

/* Pull-to-refresh indicator for the installed PWA - see static/pull-refresh.js. Parked just
   above the viewport; the script slides it down with the finger and reloads past the
   threshold. */
.ptr-indicator {
  position: fixed; top: 0; left: 50%; z-index: 3000; width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center; border-radius: 50%;
  background: var(--bg); border: 1px solid var(--line); color: var(--fg-dim);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .25); opacity: 0; pointer-events: none;
  transform: translate(-50%, -50px);
  margin-top: env(safe-area-inset-top, 0px);
}
.ptr-indicator.ready { color: var(--signal); }
.ptr-indicator.spinning svg { animation: onboard-spin .7s linear infinite; }

/* Mobile bottom tab bar - see templates._mobile_tabbar_html. Replaces the topbar hamburger
   ("Plus" opens the same drawer) and the floating chat bubble (Coach is a tab). Body gets
   bottom padding so the last content isn't hidden under the fixed bar. */
:root { --tabbar-h: 0px; }
.mobile-tabbar { display: none; }
@media (max-width: 720px) {
  :root { --tabbar-h: calc(60px + env(safe-area-inset-bottom, 0px)); }
  body { padding-bottom: var(--tabbar-h); }
  .chat-widget { display: none; }
  .mobile-tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 1000;
    height: var(--tabbar-h); padding-bottom: env(safe-area-inset-bottom, 0px); box-sizing: border-box;
    /* Opaque, no backdrop-filter blur: during the cross-document view transition (see
       @view-transition below) the old page is shown as a captured snapshot, which drops the
       blur until the new page paints - the bar visibly flickered on every tab change. */
    background: var(--bg);
    border-top: 1px solid var(--line-soft);
  }
  .mobile-tab {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    width: auto; margin: 0; padding: 0; background: none; border: none; border-radius: 0;
    color: var(--fg-dim); text-decoration: none; font-family: var(--font-body); font-size: 10.5px;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
  }
  .mobile-tab svg { stroke: currentColor; stroke-width: 1.9; fill: none; stroke-linecap: round; stroke-linejoin: round; }
  .mobile-tab.active { color: var(--signal); font-weight: 600; }
  /* Coach: the one filled pill, so the AI coach reads as the app's main action. */
  .mobile-tab.coach svg {
    width: 44px; height: 30px; padding: 5px 11px; box-sizing: border-box; border-radius: 15px;
    background: color-mix(in srgb, var(--signal) 16%, transparent); color: var(--signal);
  }
  .mobile-tab.coach.active svg { background: var(--signal); stroke: var(--signal-ink); }
  .mobile-tab { transition: color .2s ease, transform .15s ease; }
  .mobile-tab svg { transition: background-color .25s ease, stroke .25s ease; }
  .mobile-tab:active { transform: scale(.88); }
  /* Sliding indicator: a short signal-colored bar on the tab bar's top edge, under the active
     tab (--tab-i, set server side and moved on tap by static/mobile-tabbar.js, which waits for
     this slide to finish before navigating). Overshooting easing for a slight spring. */
  .mobile-tab-indicator {
    position: absolute; top: -1px; width: 28px; height: 3px; border-radius: 0 0 3px 3px;
    left: calc(100% / 5 * var(--tab-i) + (100% / 5 - 28px) / 2);
    background: var(--signal); box-shadow: 0 0 10px color-mix(in srgb, var(--signal) 60%, transparent);
    transition: left .26s cubic-bezier(.34, 1.4, .64, 1);
  }
  .mobile-tab.pop svg { animation: tab-pop .26s cubic-bezier(.34, 1.56, .64, 1); }
}
@keyframes tab-pop {
  0% { transform: scale(.8); }
  55% { transform: scale(1.18) translateY(-2px); }
  100% { transform: scale(1); }
}
/* Page transitions, mobile only: a cross-document view transition keeps the old page painted
   until the new one is ready, then slides the content like a native app - forward (new page
   in from the right) when drilling down or moving to a tab further right, back when going up
   or left, a plain crossfade otherwise. The direction is picked per navigation by
   PAGE_TRANSITION_SCRIPT (templates.py) as a view-transition type. The top bar and tab bar
   get their own transition names with no animation, so they stay perfectly still while the
   content moves. Unsupported browsers just do a normal page load. */
@media (max-width: 720px) and (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  .mobile-tabbar { view-transition-name: tabbar; }
  .mobile-topbar { view-transition-name: topbar; }
}
::view-transition-group(tabbar), ::view-transition-group(topbar),
::view-transition-old(tabbar), ::view-transition-new(tabbar),
::view-transition-old(topbar), ::view-transition-new(topbar) { animation: none; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .2s; }
html:active-view-transition-type(forward)::view-transition-old(root) { animation: page-out-left .3s cubic-bezier(.4, 0, .2, 1) both; }
html:active-view-transition-type(forward)::view-transition-new(root) { animation: page-in-right .3s cubic-bezier(.2, .8, .2, 1) both; }
html:active-view-transition-type(back)::view-transition-old(root) { animation: page-out-right .3s cubic-bezier(.4, 0, .2, 1) both; }
html:active-view-transition-type(back)::view-transition-new(root) { animation: page-in-left .3s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes page-out-left { to { transform: translateX(-18%); opacity: 0; } }
@keyframes page-in-right { from { transform: translateX(28%); opacity: 0; } }
@keyframes page-out-right { to { transform: translateX(18%); opacity: 0; } }
@keyframes page-in-left { from { transform: translateX(-28%); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .mobile-tab, .mobile-tab svg, .mobile-tab-indicator { transition: none; }
  .mobile-tab.pop svg { animation: none; }
}

/* Habit tracker (/dashboard/habits, routes_habits.py + habits.js): one row per habit, one
   round check per day, current streak on the right. Today's column is tinted. */
.habit-summary { margin: 0 0 14px; }
.habit-summary strong { color: var(--fg); font-family: var(--font-mono); }
.habit-this-week { font-size: 0.85rem; }
.habit-grid-wrap { overflow-x: auto; }
.habit-grid { width: 100%; border-collapse: separate; border-spacing: 0; }
.habit-grid th, .habit-grid td { padding: 6px 2px; text-align: center; border-bottom: 1px solid var(--line-soft); }
.habit-grid tbody tr:last-child th, .habit-grid tbody tr:last-child td { border-bottom: none; }
.habit-grid thead th {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; text-transform: uppercase;
  letter-spacing: .04em; color: var(--fg-dim); padding-bottom: 10px;
}
.habit-grid thead th span { display: block; font-size: 13px; color: var(--fg); margin-top: 2px; text-transform: none; }
.habit-grid th.today, .habit-grid td.today { background: color-mix(in srgb, var(--signal) 7%, transparent); }
.habit-grid thead th.today { border-radius: 8px 8px 0 0; }
.habit-grid thead th.today span { color: var(--signal); }
.habit-grid .habit-name {
  text-align: left; padding-right: 12px; font-weight: 500; font-size: 0.92rem; color: var(--fg);
  max-width: 220px; overflow-wrap: anywhere;
}
.habit-grid .habit-streak { font-family: var(--font-mono); font-size: 12px; color: var(--fg-dim); padding-left: 10px; white-space: nowrap; text-align: right; }
.habit-toggle { margin: 0; display: flex; justify-content: center; }
button.habit-cell {
  margin: 0; width: 30px; height: 30px; padding: 0; border-radius: 50%; display: inline-grid; place-items: center;
  background: transparent; border: 1.5px solid var(--line); color: var(--signal-ink); cursor: pointer;
  transition: background .12s, border-color .12s, transform .12s;
}
@media (hover: hover) { button.habit-cell:hover { background: color-mix(in srgb, var(--signal) 12%, transparent); border-color: var(--signal); } }
button.habit-cell:active { transform: scale(0.9); }
button.habit-cell.done { background: var(--signal); border-color: var(--signal); }
button.habit-cell.done::after { content: "✓"; font-size: 15px; font-weight: 700; line-height: 1; }
/* Partway to a daily target > 1: a ring filled to count/target (--p), the count inside. */
button.habit-cell.partial {
  border-color: var(--signal); color: var(--fg); font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  background: conic-gradient(color-mix(in srgb, var(--signal) 45%, transparent) calc(var(--p) * 360deg), transparent 0);
}
.habit-grid .habit-target { display: block; font-family: var(--font-mono); font-size: 10.5px; font-weight: 400; color: var(--fg-dim); margin-top: 2px; }
button.habit-cell.future { opacity: 0.3; cursor: default; border-style: dashed; }
@media (hover: hover) { button.habit-cell.future:hover { background: transparent; border-color: var(--line); } }
.habit-add-form, .habit-edit-form { display: flex; gap: 8px; align-items: center; }
.habit-add-form { margin-top: 14px; }
.habit-add-form input, .habit-edit-form input { flex: 1; min-width: 0; }
.habit-add-form select, .habit-edit-form select { width: auto; flex-shrink: 0; }
.habit-add-form .btn, .habit-edit-form .btn { margin: 0; width: auto; padding: 11px 16px; flex-shrink: 0; }
.habit-edit-form input, .habit-edit-form select { padding: 8px 10px; font-size: 0.9rem; }
.habit-edit-form .btn { padding: 8px 12px; font-size: 12px; }
.habit-manage-panel { margin-top: 20px; }
.habit-manage-panel > summary { display: inline-block; width: auto; margin: 0; padding: 10px 16px; list-style: none; cursor: pointer; }
.habit-manage-panel > summary::-webkit-details-marker { display: none; }
.habit-manage-panel > summary::before { content: "+ "; }
.habit-manage-panel[open] > summary::before { content: "− "; }
.habit-manage-panel > .content-card { margin-top: 12px; }
.habit-manage { list-style: none; margin: 16px 0 0; padding: 0; border-top: 1px solid var(--line-soft); }
.habit-manage li { padding: 8px 0; border-bottom: 1px solid var(--line-soft); }
.habit-manage li:last-child { border-bottom: none; }
/* Phone: no room for a name column beside seven cells, so each habit becomes a block - name
   and streak on top, the week's seven cells full width underneath, lined up under the day
   header. Same table markup, re-laid out as a grid per row. */
@media (max-width: 560px) {
  .habit-grid, .habit-grid thead, .habit-grid tbody { display: block; }
  .habit-grid tr { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); align-items: center; }
  .habit-grid thead .habit-name, .habit-grid thead .habit-streak { display: none; }
  .habit-grid thead tr { position: sticky; top: 0; z-index: 1; background: var(--bg-sink); }
  .habit-grid th, .habit-grid td { border-bottom: none; padding: 4px 0; }
  .habit-grid tbody tr { padding: 12px 0 10px; border-bottom: 1px solid var(--line-soft); }
  .habit-grid tbody tr:last-child { border-bottom: none; }
  .habit-grid tbody .habit-name { grid-row: 1; grid-column: 1 / 6; max-width: none; padding: 0 0 8px; font-size: 0.95rem; }
  .habit-grid tbody .habit-streak { grid-row: 1; grid-column: 6 / 8; padding: 0 0 8px; color: var(--fg); }
  /* The "Série" column header is hidden on phone, so each block labels its own streak. */
  .habit-grid tbody .habit-streak::before {
    content: "Série "; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
    letter-spacing: .04em; color: var(--fg-dim);
  }
  .habit-grid .habit-target { display: inline; margin: 0 0 0 6px; }
  /* The tinted column would read as stripes across stacked blocks - mark today's own cell
     instead (the day header number is already blue). */
  .habit-grid td.today { background: none; }
  .habit-grid thead th.today { background: none; }
  .habit-grid td.today button.habit-cell:not(.done):not(.partial) { border-color: color-mix(in srgb, var(--signal) 70%, var(--line)); border-width: 2px; }
  .habit-manage-panel > summary { display: block; text-align: center; }
  button.habit-cell { width: 36px; height: 36px; }
  button.habit-cell.done::after { font-size: 16px; }
  .habit-add-form, .habit-edit-form { flex-wrap: wrap; }
  .habit-add-form input, .habit-edit-form input { flex-basis: 100%; }
}

/* "Installe l'app Athlyze" popin (templates._INSTALL_BANNER_HTML, driven by
   static/install-prompt.js): position fixed so it floats over the page instead of pushing it
   down - above the mobile tab bar on phones, bottom-left next to the sidebar on desktop (away
   from the chat bubble, bottom-right). Every [hidden] rule here is explicit: the display:flex
   below would otherwise beat the UA [hidden]{display:none} rule (same trap as the chat
   widget), and both buttons need the global full-width button rule reset. */
.install-banner {
  position: fixed; z-index: 95; left: 260px; bottom: 24px; width: 360px; box-sizing: border-box;
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 12px; padding: 14px;
  background: color-mix(in srgb, var(--signal) 8%, var(--bg-raise));
  border: 1px solid color-mix(in srgb, var(--signal) 40%, var(--line)); border-radius: 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
  animation: install-banner-in .25s ease-out;
}
@keyframes install-banner-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .install-banner { animation: none; } }
@media (max-width: 720px) {
  .install-banner { left: 12px; right: 12px; width: auto; bottom: calc(var(--tabbar-h) + 12px); }
}
.install-banner[hidden], .install-banner [hidden] { display: none; }
.install-banner-icon { flex-shrink: 0; }
.install-banner-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 0; font-size: 13px; line-height: 1.45; color: var(--fg-dim); }
.install-banner-text strong { color: var(--fg); font-size: 14px; }
.install-banner-share { vertical-align: -2px; color: var(--signal); }
/* Always on its own full-width row under the text. */
.install-banner-btn { order: 3; margin: 0; width: 100%; padding: 10px 14px; font-size: 13px; }
.install-banner-close {
  margin: -4px -4px 0 0; width: 30px; height: 30px; flex-shrink: 0; padding: 0; display: grid; place-items: center;
  background: none; color: var(--fg-dim); border-radius: 50%;
}
@media (hover: hover) { .install-banner-close:hover { background: var(--bg-sink); color: var(--fg); } }


/* ---- "Énergie" design (views/components.html, views/home.html) ------------------------ */

/* Ring logo (components.html's logo macro): signal-blue square in the app chrome, inverted
   on top of the blue band. */
.logo-app .logo-sq { fill: var(--signal); }
.logo-app .logo-track { stroke: #ffffff; stroke-opacity: 0.35; }
.logo-app .logo-ring { stroke: #ffffff; }
.logo-app .logo-dot { fill: #ffffff; }
.logo-band .logo-sq { fill: #ffffff; }
.logo-band .logo-track { stroke: var(--band); stroke-opacity: 0.25; }
.logo-band .logo-ring { stroke: var(--band); }
.logo-band .logo-dot { fill: var(--band); }

/* Pages that open on the band (body.has-band): the mobile top bar takes the band's color so
   the two read as one block. */
@media (max-width: 720px) {
  body.has-band .mobile-topbar { background: var(--band); color: var(--band-ink); border-bottom: none; }
  body.has-band .mobile-topbar .wordmark { color: var(--band-ink); }
}

.e-band {
  background: var(--band); color: var(--band-ink); border-radius: 22px;
  padding: 30px 32px 70px; display: flex; justify-content: space-between; align-items: flex-start; gap: 20px;
}
.app-main .e-band h1 { color: var(--band-ink); font-size: 34px; font-weight: 700; letter-spacing: -0.015em; margin: 0; }
.e-band-text { margin: 8px 0 0; font-size: 14.5px; line-height: 1.45; color: var(--band-dim); max-width: 620px; }
.e-band-meta { margin: 6px 0 0; font-size: 12.5px; color: var(--band-dim); opacity: 0.9; }
.e-band-chip {
  flex-shrink: 0; padding: 6px 14px; border-radius: 999px; background: var(--hero);
  font-size: 13px; font-weight: 700; white-space: nowrap;
}
.e-band-chip.go { color: var(--go); }
.e-band-chip.warn { color: var(--warn); }
/* No hero card under the band (no data yet): no room to leave for the overlap. */
.e-band.flat { padding-bottom: 30px; }

/* The hero card overlapping the band's bottom edge. */
.e-hero {
  position: relative; margin: -56px 24px 0; padding: 18px; border-radius: 18px;
  background: var(--hero); box-shadow: var(--hero-shadow); border: 1px solid var(--card-line);
}
.e-hero-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 14px; }
.e-hero-head h2 { margin: 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; color: var(--fg); }
.e-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.e-tile {
  display: flex; flex-direction: column; gap: 2px; padding: 14px 16px; border-radius: 14px;
  background: var(--bg-raise); min-width: 0;
}
:where(:root:not([data-theme="light"])) .e-tile { background: var(--bg-sink); }
.e-tile-label { font-size: 12.5px; font-weight: 600; color: var(--fg-dim); }
.e-tile-value { font-family: var(--font-display); font-size: 28px; font-weight: 700; color: var(--fg); letter-spacing: -0.01em; }
.e-tile-unit { font-size: 13px; font-weight: 500; color: var(--fg-dim); }
.e-tile-status { font-size: 12px; font-weight: 700; }
.e-tile-status.go { color: var(--go); }
.e-tile-status.warn { color: var(--warn); }
.e-tile-status.neutral { color: var(--fg-dim); }
.e-hero-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.e-hero-actions .btn { margin: 0; width: auto; display: inline-flex; align-items: center; padding: 12px 18px; border-radius: 12px; font-family: var(--font-body); font-size: 14px; font-weight: 700; }

.e-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; margin-top: 18px; align-items: start; }
.e-grid > .content-card { margin-top: 0; padding: 22px; }
.e-card-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.app-main .e-card-head h2, .e-card-head h2 { margin: 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; color: var(--fg); }
.e-card-meta { font-size: 12px; color: var(--fg-dim); white-space: nowrap; }
.e-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 12px; margin-top: 14px; }
.e-stat-label { display: block; font-size: 12px; font-weight: 600; color: var(--fg-dim); }
.e-stat-value { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--fg); }
.e-delta { font-size: 12px; font-weight: 700; margin-left: 4px; }
.e-delta.go { color: var(--go); }
.e-delta.warn { color: var(--warn); }
.e-delta.flat { color: var(--fg-dim); }
.e-pill { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 700; white-space: nowrap; }
.e-pill.go { background: var(--go-bg); color: var(--go); }
.e-pill.warn { background: var(--warn-bg); color: var(--warn); }
.e-pill.accent { background: var(--signal-soft); color: var(--signal-text); }
.e-pill.neutral { background: var(--bg-sink); color: var(--fg-dim); }
.e-list { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.e-list-item {
  display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 14px;
  border-radius: 12px; background: var(--bg-sink); color: var(--fg); text-decoration: none;
}
:where(:root[data-theme="light"]) .e-list-item { background: #ffffff; }
.e-list-item-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.e-list-item-title { font-size: 14px; font-weight: 700; }
.e-list-item-meta { font-size: 12.5px; color: var(--fg-dim); }
.e-list-item-quote { font-size: 12.5px; color: var(--fg-dim); font-style: italic; }
.e-shortcuts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 18px; }
.e-shortcut {
  display: flex; flex-direction: column; gap: 4px; padding: 16px 18px; border-radius: 16px;
  background: var(--bg-raise); border: 1px solid var(--card-line); color: var(--fg); text-decoration: none;
}
@media (hover: hover) {
  a.e-shortcut:hover { background: color-mix(in srgb, var(--signal) 10%, var(--bg-raise)); color: var(--fg); }
  a.e-list-item:hover { background: color-mix(in srgb, var(--signal) 8%, var(--bg-sink)); color: var(--fg); }
}
.e-shortcut.disabled { opacity: 0.5; }
.e-shortcut-title { font-family: var(--font-display); font-size: 15px; font-weight: 700; }
.e-shortcut-desc { font-size: 12.5px; color: var(--fg-dim); line-height: 1.4; }

@media (max-width: 720px) {
  /* Full-bleed band under the (band-colored) mobile top bar - cancels .app-main's padding. */
  .e-band { margin: -28px -20px 0; border-radius: 0; padding: 18px 20px 64px; flex-direction: column; gap: 10px; }
  .app-main .e-band h1 { font-size: 28px; }
  .e-band-chip { align-self: flex-start; }
  .e-hero { margin: -48px -4px 0; padding: 16px; }
  .e-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .e-tile { padding: 12px; }
  .e-tile-value { font-size: 24px; }
  .e-shortcuts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- Nutrition, "Énergie" design (views/nutrition.html, nutrition_period.html) ---------- */
/* Band: date line + title left, date selector + Jour/Semaine/Mois right; the cards below
   overlap its bottom edge like the home page's hero (.nutri-layout / .nutri-hero margins). */
.nutri-band { align-items: flex-start; padding-bottom: 78px; }
.nutri-band-main { min-width: 0; }
.nutri-band-nav { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; flex-shrink: 0; }
.nutri-band-date { display: flex; align-items: center; gap: 8px; }
.nutri-band-arrow {
  display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.16); color: var(--band-ink); text-decoration: none; font-size: 15px;
}
.nutri-band-arrow.disabled { opacity: 0.35; }
@media (hover: hover) { a.nutri-band-arrow:hover { background: rgba(255, 255, 255, 0.28); color: var(--band-ink); } }
.nutri-band-label { min-width: 150px; text-align: center; font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--band-ink); }
/* White on the band in both themes (the band itself is blue in both). */
.nutri-band-today {
  padding: 4px 11px; border-radius: 999px; background: #ffffff; color: var(--band);
  font-size: 12px; font-weight: 700; text-decoration: none;
}
@media (hover: hover) { .nutri-band-today:hover { color: var(--band); background: var(--band-dim); } }
.nutri-band .nutrition-period-tabs { margin: 0; background: rgba(255, 255, 255, 0.14); border: none; border-radius: 999px; }
.nutri-band .nutrition-period-tab { color: var(--band-dim); border-radius: 999px; font-weight: 600; padding: 5px 16px; }
@media (hover: hover) { .nutri-band .nutrition-period-tab:hover { color: var(--band-ink); } }
.nutri-band .nutrition-period-tab.active { background: #ffffff; color: var(--band); }

/* Desktop: summary column + meals column, like the mock-up. */
/* Only the "Bilan du jour" card overlaps the band (like the home page's hero); the two
   columns start below it. */
.nutri-day-card {
  position: relative; margin: -56px 24px 0; padding: 20px 22px; border-radius: 18px;
  background: var(--hero); box-shadow: var(--hero-shadow); border: 1px solid var(--card-line);
}
.nutri-day-body { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 32px; align-items: end; }
.nutri-day-body .nutri-macro-cols { margin-top: 0; }
.nutri-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); gap: 20px; margin-top: 24px; align-items: start; }
.nutri-side { display: flex; flex-direction: column; gap: 20px; }
.nutri-side > .content-card { margin-top: 0; padding: 22px; }
.nutri-day-title { margin: 0 0 6px; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--fg); }
.nutri-hero-top { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.nutri-kcal-value { font-family: var(--font-display); font-size: 36px; font-weight: 700; color: var(--fg); letter-spacing: -0.02em; }
.nutri-kcal-target { font-size: 13.5px; color: var(--fg-dim); }
.nutri-goal-link { text-decoration: none; }
.nutri-day-kcal > .nutrition-progress { height: 8px; border-radius: 4px; margin-top: 10px; }
.nutri-day-kcal > .nutrition-progress span { border-radius: 4px; }
.nutrition-progress { background: var(--signal-soft); }
.nutrition-progress.over span { background: var(--warn); }
.nutri-macro-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 14px; }
.nutri-macro-col { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.nutri-macro-value { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--fg); }
.nutri-macro-value .nutrition-target { font-size: 12.5px; }
.nutri-macro-note { font-size: 11.5px; font-weight: 600; }
.nutri-macro-note.go { color: var(--go); }
.nutri-macro-note.neutral { color: var(--fg-dim); }

.nutri-weight-line { margin: 8px 0 0; display: flex; align-items: baseline; gap: 10px; }
.nutri-weight-value { font-family: var(--font-display); font-size: 28px; font-weight: 700; color: var(--fg); }
.nutri-weight-bars { display: flex; align-items: flex-end; gap: 3px; height: 60px; margin-top: 12px; }
.nutri-weight-bars span { flex: 1; border-radius: 2px; background: var(--signal-soft); }
:where(:root[data-theme="light"]) .nutri-weight-bars span { background: color-mix(in srgb, var(--signal) 35%, white); }
.nutri-weight-bars span.last { background: var(--signal); }
.nutri-weight-trend { margin: 8px 0 0; font-size: 12.5px; color: var(--fg-dim); }
.nutri-weight-card .nutrition-strip-weigh { margin-top: 12px; }
.nutri-weight-card .health-chart { margin-top: 14px; }
.nutri-weight-card a.e-card-meta { text-decoration: none; }

.nutrition-balance-card { border-left: none; background: var(--bg-raise); }
.nutrition-balance-card .nutrition-balance-headline { margin: 10px 0 0; }
.nutri-bal-rows { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.nutri-bal-row { display: grid; grid-template-columns: 112px minmax(0, 1fr) auto; align-items: center; gap: 10px; font-size: 12.5px; }
.nutri-bal-k { color: var(--fg-dim); font-weight: 600; }
.nutri-bal-track { height: 8px; border-radius: 4px; background: var(--signal-soft); overflow: hidden; }
.nutri-bal-track span { display: block; height: 100%; border-radius: 4px; }
.nutri-bal-track .in { background: var(--signal); }
.nutri-bal-track .out { background: var(--fg-dim); opacity: 0.55; }
.nutri-bal-v { color: var(--fg-dim); white-space: nowrap; }
.nutri-bal-v strong { color: var(--fg); font-family: var(--font-display); font-size: 14px; }
.nutri-bal-line { display: flex; justify-content: space-between; gap: 12px; margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--line-soft); font-size: 12.5px; color: var(--fg-dim); }
.nutri-bal-line + .nutri-bal-line { margin-top: 0; }
.nutri-bal-line strong { color: var(--fg); }
.nutrition-balance-value { font-family: var(--font-display); color: var(--fg); }

/* Meals: one list card on desktop, one card per meal on a phone (below). */
.nutri-meals { background: var(--bg-raise); border: 1px solid var(--card-line); border-radius: 18px; padding: 6px 22px 14px; }
.nutri-meal { padding: 14px 0; border-bottom: 1px solid var(--line-soft); }
.nutri-meal-head { display: flex; align-items: baseline; gap: 10px; }
.nutri-meal-head h3 { margin: 0; flex: 1; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--fg); }
.nutri-meal-kcal { font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--fg); }
.nutri-meal-kcal small { font-size: 11.5px; font-weight: 500; color: var(--fg-dim); }
.nutri-meal-add {
  align-self: center; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%;
  background: var(--signal); color: var(--signal-ink); font-size: 18px; font-weight: 700; line-height: 1; text-decoration: none;
}
@media (hover: hover) { .nutri-meal-add:hover { color: var(--signal-ink); background: color-mix(in srgb, var(--signal) 86%, black); } }
/* Adding to a meal: on desktop a discreet "+ Ajouter un aliment" row closing each meal's list;
   on a phone the round "+" in the meal header instead. */
.nutri-meal-head .nutri-meal-add { display: none; }
.nutri-meal-add-row {
  display: block; margin-top: 6px; padding: 7px 10px; border: 1px dashed var(--line); border-radius: 10px;
  color: var(--fg-dim); font-size: 13px; font-weight: 600; text-decoration: none;
}
@media (hover: hover) { .nutri-meal-add-row:hover { color: var(--signal-text); border-color: var(--signal); background: var(--signal-soft); } }
/* Mouse screens: the row only appears while its meal is hovered (or focused from the keyboard).
   Its space stays reserved (opacity, not display) so the list never jumps under the pointer. */
@media (hover: hover) {
  .nutri-meal-add-row { opacity: 0; transition: opacity .15s ease; }
  .nutri-meal:hover .nutri-meal-add-row, .nutri-meal-add-row:focus-visible { opacity: 1; }
}
}
.nutri-meal-empty { margin: 6px 0 0; font-size: 13px; color: var(--fg-dim); }
.nutri-items { margin-top: 4px; }
/* One row per item: "name · quantity" growing on the left, kcal + delete pinned right - at
   every width (these out-rank the older phone rules that wrapped quantity/delete under the
   name). The quantity reads as plain secondary text; opened, it takes the full row. */
.nutri-items .nutrition-log-entry { padding: 6px 0; border-top: none; align-items: flex-start; flex-wrap: nowrap; row-gap: 0; }
.nutri-items .nutrition-log-entry-main { flex: 1 1 auto; flex-basis: auto; }
.nutri-items .nutrition-qty-toggle { flex: 0 1 auto; }
.nutri-items .nutrition-qty-toggle[open] { flex-basis: 100%; }
.nutri-items .nutrition-qty-summary {
  background: none; border: none; padding: 0; gap: 4px;
  font-family: var(--font-body); font-size: 12.5px; color: var(--fg-dim);
}
@media (hover: hover) { .nutri-items .nutrition-qty-summary:hover { color: var(--fg); } }
.nutri-items .nutrition-qty-pencil { opacity: 0.6; }
.nutri-items .nutrition-delete-btn { margin: 0; padding: 0 2px; }
.nutrition-log-entry-main { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; }
.nutrition-log-entry-name { font-size: 13.5px; color: var(--fg); }
.nutrition-log-entry-kcal { font-family: var(--font-display); font-size: 13.5px; font-weight: 600; color: var(--fg-dim); padding-top: 2px; }
.nutri-items .nutrition-qty-badge { font-size: 12.5px; color: inherit; }
.nutri-items .nutrition-log-entry-macros { width: 100%; font-size: 11.5px; color: var(--fg-dim); }
.nutri-meals-col > .nutrition-recipes-link { margin: 12px 0 0; font-size: 13px; }

/* Week/month view: averages in a hero card overlapping the band. */
.nutri-macros { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.nutri-macro { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; border-radius: 14px; background: var(--bg-raise); min-width: 0; }
:where(:root:not([data-theme="light"])) .nutri-macro { background: var(--bg-sink); }
.nutri-tile-wide .nutri-macro-value { font-size: 16px; }
.nutri-hero + .nutri-chart-card { margin-top: 20px; }

@media (max-width: 720px) {
  .nutri-band { flex-direction: column; align-items: stretch; gap: 12px; padding-bottom: 64px; }
  .nutri-band-nav { align-items: stretch; }
  .nutri-band-date { justify-content: space-between; }
  .nutri-band-label { min-width: 0; flex: 1; }
  .nutri-band .nutrition-period-tabs { width: 100%; grid-template-columns: repeat(3, 1fr); }
  /* One column, mock-up order: day card (overlapping the band), meals, weight, balance. */
  .nutri-layout { display: flex; flex-direction: column; align-items: stretch; gap: 14px; margin-top: 16px; }
  .nutri-day-title { display: none; }
  .nutri-side { display: contents; }
  .nutri-day-card { margin: -48px -4px 0; padding: 16px; }
  .nutri-day-body { grid-template-columns: 1fr; gap: 14px; }
  /* Meals: badge strip + one meal per swipe (scroll-snap; nutrition-meal-swipe.js keeps the
     badges in sync). Bleeds past .app-main's 20px side padding so a card slides off the edge. */
  .nutri-meals-col { order: 1; min-width: 0; }
  .nutri-meal-tabs { display: flex; gap: 6px; margin: 0 0 10px; overflow-x: auto; scrollbar-width: none; }
  .nutri-meal-tabs::-webkit-scrollbar { display: none; }
  .nutri-meal-tabs .nutrition-meal-tab {
    margin: 0; width: auto; flex: 0 0 auto; padding: 7px 13px; border-radius: 999px; border: 1px solid var(--line);
    background: var(--bg-raise); color: var(--fg-dim); font: inherit; font-size: 13px; font-weight: 600; white-space: nowrap;
  }
  .nutri-meal-tabs .nutrition-meal-tab small { font-weight: 500; opacity: 0.75; }
  .nutri-meal-tabs .nutrition-meal-tab.active { background: var(--signal); border-color: var(--signal); color: var(--signal-ink); }
  .nutri-meals {
    /* stretch: every meal card takes the carousel's height (the longest meal's) instead of a
       short card floating over an empty gap. */
    display: flex; align-items: stretch; gap: 12px; margin: 0 -20px; padding: 0 20px; scroll-padding-inline: 20px;
    overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; scrollbar-width: none;
    background: none; border: none; border-radius: 0; box-shadow: none;
  }
  .nutri-meals::-webkit-scrollbar { display: none; }
  .nutri-meal {
    flex: 0 0 100%; scroll-snap-align: start; scroll-snap-stop: always; box-sizing: border-box;
    background: var(--bg-raise); border: 1px solid var(--card-line); border-radius: 16px; padding: 13px 14px; border-bottom: none;
  }
  .nutrition-balance-card { order: 2; }
  .nutri-weight-card { order: 3; }
  .nutri-meal-head .nutri-meal-add { display: grid; }
  .nutri-meal-add-row { display: none; }
  .nutri-kcal-value { font-size: 32px; }
  .nutri-meals-col > .nutrition-recipes-link { margin: 10px 0 0; }
}

.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---- Activities list, "Énergie" design (views/activities.html) -------------------------- */
.acts-band { align-items: flex-end; flex-wrap: wrap; }
.acts-sync { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.acts-sync form { margin: 0; }
.acts-sync-btn {
  margin: 0; width: auto; display: inline-flex; align-items: center; gap: 6px; padding: 7px 13px;
  border-radius: 999px; border: none; background: rgba(255, 255, 255, 0.16); color: var(--band-ink);
  font-family: var(--font-body); font-size: 12.5px; font-weight: 700;
}
@media (hover: hover) { .acts-sync-btn:hover { background: rgba(255, 255, 255, 0.28); color: var(--band-ink); } }
.acts-week-hero { padding: 16px 22px; }
.acts-week-hero h2 { margin: 0 0 10px; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--fg); }
.acts-week-stats { flex: 1; }

.acts-toolbar { display: none; }
.acts-chip {
  flex-shrink: 0; padding: 7px 14px; border-radius: 999px; border: 1px solid var(--line);
  color: var(--fg); font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap;
}
@media (hover: hover) { .acts-chip:hover { color: var(--fg); border-color: var(--signal); } }
.acts-chip.active { background: var(--signal); border-color: var(--signal); color: var(--signal-ink); }
.acts-filter-btn { display: none; }

.acts-layout { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 20px; margin-top: 20px; align-items: start; }
.acts-list { background: var(--bg-raise); border: 1px solid var(--card-line); border-radius: 18px; overflow: hidden; }
.acts-head, .acts-row {
  display: grid; grid-template-columns: 44px minmax(0, 2.4fr) minmax(0, 0.9fr) minmax(0, 0.8fr) minmax(0, 0.8fr) minmax(0, 0.7fr);
  gap: 12px; align-items: center; padding: 10px 18px;
}
.acts-head { font-size: 11.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-dim); border-bottom: 1px solid var(--line-soft); }
.acts-head span:last-child, .acts-load { text-align: right; }
.acts-group { margin: 0; padding: 12px 18px 4px; font-size: 11.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim); }
.acts-row { color: var(--fg); text-decoration: none; border-bottom: 1px solid var(--line-soft); font-size: 14px; }
@media (hover: hover) { a.acts-row:hover { color: var(--fg); background: color-mix(in srgb, var(--signal) 6%, transparent); } }
.acts-icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: var(--signal-soft); color: var(--signal-text); }
.acts-icon svg { width: 22px; height: 22px; }
.acts-icon polyline { fill: none; stroke: currentColor; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
.acts-icon svg[viewBox="0 0 100 40"] { width: 34px; height: 20px; }
.acts-icon.lift { background: var(--warn-bg); color: var(--warn); }
.acts-icon.trail { background: var(--go-bg); color: var(--go); }
.acts-icon.bike { background: color-mix(in srgb, var(--teal) 18%, transparent); color: var(--teal); }
.acts-icon.other { background: var(--bg-sink); color: var(--fg-dim); }
.acts-name-cell { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
.acts-name { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.acts-meta { display: none; }
.acts-date { color: var(--fg-dim); }
.acts-num { font-family: var(--font-display); font-weight: 600; }
.acts-load strong { font-family: var(--font-display); font-weight: 700; }
.acts-load small { display: none; }
.acts-main .pagination { margin-top: 14px; }

/* .activities-sidebar is kept for the drawer JS hooks - its older panel look is reset here. */
.acts-side.activities-sidebar { display: flex; flex-direction: column; gap: 14px; background: none; border: none; padding: 0; box-shadow: none; height: auto; }
.acts-side > .content-card { margin-top: 0; padding: 18px 20px; }
.acts-side h2 { margin: 0 0 10px; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--fg); }
.acts-stats { display: grid; grid-template-columns: auto auto auto; justify-content: space-between; gap: 8px; }
.acts-stats span, .acts-month-row span { display: block; font-size: 12px; color: var(--fg-dim); }
.acts-stats strong { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--fg); white-space: nowrap; }
.acts-month-row { display: flex; justify-content: space-between; margin: 0; padding: 7px 0; border-top: 1px solid var(--line-soft); font-size: 13.5px; }
.acts-month-row span { display: inline; font-size: 13.5px; color: var(--fg); }
.acts-month-row strong { font-family: var(--font-display); }
/* Search + sort, first card of the right column (and of the phone filter drawer). */
.acts-side > .acts-drawer-search { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px; }
.acts-drawer-search label { margin: 0; font-family: var(--font-body); font-size: 12px; font-weight: 600; letter-spacing: 0; text-transform: none; }
.acts-drawer-search input, .acts-drawer-search select { margin: 0 0 4px; padding: 9px 12px; border-radius: 12px; font-size: 13.5px; }
.acts-side .activities-sidebar-head { display: none; }
.acts-timeline { max-height: 320px; overflow-y: auto; }
.acts-timeline .timeline-month { display: block; padding: 6px 10px; border-radius: 999px; color: var(--fg-dim); font-family: var(--font-body); font-size: 13.5px; text-decoration: none; }
.acts-timeline .timeline-month.active { background: var(--signal); color: var(--signal-ink); font-weight: 700; }
.acts-timeline .timeline-year { padding: 10px 10px 4px; font-family: var(--font-body); font-size: 11.5px; font-weight: 700; color: var(--fg-dim); }

@media (max-width: 720px) {
  .acts-band { align-items: stretch; }
  .acts-week-hero { padding: 14px 16px; }
  .acts-week-hero h2 { margin-bottom: 8px; }
  .acts-week-stats.act-groups { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
  .acts-week-stats .act-group-value { font-size: 18px; }
  .acts-week-stats .act-group:not(:first-child) { border-left: 1px solid var(--line); padding-left: 10px; }
  .acts-toolbar { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin: 14px 0 0; }
  .acts-filter-btn {
    display: inline-flex; align-items: center; gap: 6px; margin: 0; width: auto; flex-shrink: 0; padding: 7px 12px;
    border-radius: 999px; border: 1px solid var(--line); background: var(--bg-raise); color: var(--fg);
    font-family: var(--font-body); font-size: 13px; font-weight: 600;
  }
  .acts-layout { display: block; margin-top: 12px; }
  .acts-list { background: none; border: none; border-radius: 0; overflow: visible; display: flex; flex-direction: column; gap: 8px; }
  .acts-head { display: none; }
  .acts-group { padding: 8px 2px 0; }
  .acts-row { display: flex; gap: 12px; padding: 12px 14px; border: 1px solid var(--card-line); border-radius: 16px; background: var(--bg-raise); }
  .acts-name-cell { flex: 1; flex-direction: column; align-items: flex-start; gap: 3px; }
  .acts-meta { display: block; font-size: 12px; color: var(--fg-dim); }
  .acts-date, .acts-num { display: none; }
  .acts-load { flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; }
  .acts-load strong { font-size: 17px; }
  .acts-load small { display: block; font-size: 11px; color: var(--fg-dim); }
  /* Right column -> filter drawer (activities-filter.js toggles .open). */
  .acts-side.activities-sidebar {
    position: fixed; top: 0; right: 0; bottom: 0; left: auto; width: min(320px, 88vw); height: 100vh; z-index: 2001; overflow-y: auto;
    padding: 18px 16px; background: var(--bg); transform: translateX(100%); transition: transform .22s ease;
  }
  .acts-side.activities-sidebar.open { transform: translateX(0); }
  .acts-side .activities-sidebar-head { display: flex; justify-content: space-between; align-items: center; }
  .acts-timeline { max-height: none; }
}

/* ---- Activity detail, "Énergie" design (views/activity.html) ---------------------------- */
/* Stretched so the side column can push the headline stats down level with the name. */
.act-band { align-items: stretch; }
.act-band-main { min-width: 0; }
.act-back {
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 14px; padding: 6px 13px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.16); color: var(--band-ink); font-size: 13px; font-weight: 700; text-decoration: none;
}
@media (hover: hover) { .act-back:hover { background: rgba(255, 255, 255, 0.28); color: var(--band-ink); } }
.act-band .e-band-meta { margin: 0 0 4px; }
.app-main .act-band h1 { overflow-wrap: anywhere; }
.act-band-side { display: flex; flex-direction: column; align-items: flex-end; justify-content: space-between; gap: 14px; flex-shrink: 0; }
.act-headline { display: flex; gap: 26px; }
.act-headline div { display: flex; flex-direction: column; align-items: flex-end; }
.act-headline strong { font-family: var(--font-display); font-size: 30px; font-weight: 700; line-height: 1.05; color: var(--band-ink); white-space: nowrap; }
.act-headline span { font-size: 12px; color: var(--band-dim); }
.act-band-side form { margin: 0; }
.act-chat-btn {
  margin: 0; width: auto; padding: 9px 16px; border: none; border-radius: 999px;
  background: var(--hero); color: var(--signal-text); font-family: var(--font-body); font-size: 13.5px; font-weight: 700; cursor: pointer;
}
@media (hover: hover) { .act-chat-btn:hover { background: var(--hero); color: var(--signal-text); filter: brightness(0.95); } }

.act-tiles-card {
  position: relative; margin: -56px 24px 0; padding: 16px 18px; border-radius: 18px;
  background: var(--hero); box-shadow: var(--hero-shadow); border: 1px solid var(--card-line);
}
.act-groups { display: flex; }
.act-group { flex: 1 1 0; display: flex; flex-direction: column; gap: 4px; min-width: 0; padding: 4px 18px; border-left: 1px solid var(--line); }
.act-group.effects { flex-grow: 1.6; }
.act-group:first-child { border-left: none; padding-left: 4px; }
.act-group-label { font-size: 12px; font-weight: 600; color: var(--fg-dim); }
.act-group-value { font-family: var(--font-display); font-size: 24px; font-weight: 700; line-height: 1.15; color: var(--fg); white-space: nowrap; }
.act-group-value small { font-family: var(--font-body); font-size: 12.5px; font-weight: 600; color: var(--fg-dim); }
.act-group-sub { font-size: 12.5px; color: var(--fg-dim); }
.act-effect { display: flex; flex-direction: column; gap: 4px; }
.act-effect + .act-effect { margin-top: 4px; }
.act-effect-head { display: flex; align-items: baseline; gap: 6px; font-size: 12.5px; color: var(--fg-dim); }
.act-effect-head strong { font-family: var(--font-display); font-size: 15px; color: var(--fg); }
.act-effect-head em { margin-left: auto; font-style: normal; font-weight: 600; color: var(--signal-text); white-space: nowrap; }
.act-effect-bar { height: 5px; border-radius: 999px; background: var(--line); overflow: hidden; }
.act-effect-bar span { display: block; height: 100%; border-radius: inherit; background: var(--signal); }

.act-layout { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 20px; margin-top: 20px; align-items: start; }
.act-main, .act-side { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
/* The widgets keep their own markup from the old page, which spaced them with margin-top. */
.act-block .detail-map-card, .act-block .detail-charts, .act-block .laps-card, .act-block .hr-zone-chart { margin-top: 0; }
.act-map .detail-map, .act-map .detail-map-3d { border-radius: 18px; border-color: var(--card-line); }
.act-map .chart-title { display: none; }
.act-desc h2 { margin: 0 0 8px; font-family: var(--font-display); font-size: 15px; font-weight: 700; }
.act-desc p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--fg); white-space: pre-line; }

@media (max-width: 960px) {
  .act-layout { grid-template-columns: minmax(0, 1fr); }
  /* One column: map, charts, Capture feedback then its sets, zones, comment, laps last. */
  .act-main, .act-side { display: contents; }
  .act-map { order: 1; } .act-charts { order: 2; } .act-recap { order: 3; } .act-sets { order: 4; }
  .act-zones { order: 5; } .act-desc { order: 6; } .act-laps { order: 7; }
}
@media (max-width: 720px) {
  .act-band { padding-bottom: 64px; }
  .act-band-side { align-items: stretch; width: 100%; }
  .act-band-side form { order: 1; }
  .act-headline { gap: 0; justify-content: space-between; }
  .act-headline div { align-items: flex-start; }
  .act-headline strong { font-size: 24px; }
  .act-chat-btn { width: 100%; padding: 11px 16px; }
  .act-tiles-card { margin: -48px -4px 0; padding: 14px; }
  .act-groups { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 18px; }
  .act-group, .act-group:first-child { border-left: none; padding: 0 4px; }
  /* Its bars need the room: full width, under the others. */
  .act-group.effects { grid-column: 1 / -1; order: 1; padding-top: 14px; border-top: 1px solid var(--line); }
  .act-group-value { font-size: 20px; }
  .act-layout { gap: 14px; margin-top: 14px; }
  .act-map .detail-map, .act-map .detail-map-3d { height: 300px; }
}
.act-layout .content-card { margin-top: 0; padding: 22px; }
@media (max-width: 720px) { .act-layout .content-card { padding: 16px; } }

/* ---- Performance + Santé, "Énergie" design (views/metrics.html) ------------------------- */
.m-band { align-items: flex-start; }
.m-band-side { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; flex-shrink: 0; }
.m-analyze-btn {
  display: inline-flex; align-items: center; gap: 8px; margin: 0; width: auto; padding: 9px 16px; border: none; border-radius: 999px;
  background: var(--hero); color: var(--signal-text); font-family: var(--font-body); font-size: 13.5px; font-weight: 700; cursor: pointer;
}
@media (hover: hover) { .m-analyze-btn:hover { background: var(--hero); color: var(--signal-text); filter: brightness(0.95); } }
.m-analyze-btn:disabled { opacity: 0.75; cursor: progress; }
.m-analyze-btn[hidden], .page-ai-analysis-card[hidden] { display: none; }
.m-band .nutrition-period-tabs { grid-template-columns: repeat(auto-fit, minmax(0, auto)); grid-auto-flow: column; margin: 0; background: rgba(255, 255, 255, 0.14); border: none; border-radius: 999px; }
.m-band .nutrition-period-tab { color: var(--band-dim); border-radius: 999px; font-weight: 600; padding: 5px 16px; }
@media (hover: hover) { .m-band .nutrition-period-tab:hover { color: var(--band-ink); } }
.m-band .nutrition-period-tab.active { background: #ffffff; color: var(--band); box-shadow: none; }

.m-hero h2 { margin: 0 0 14px; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--fg); }
.m-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.m-stat { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 2px 20px; border-left: 1px solid var(--line); }
.m-stat:first-child { border-left: none; padding-left: 2px; }
.m-stat-label { font-size: 12px; font-weight: 600; color: var(--fg-dim); }
.m-stat-value { font-family: var(--font-display); font-size: 30px; font-weight: 700; line-height: 1.1; color: var(--fg); white-space: nowrap; }
.m-stat-value small { font-family: var(--font-body); font-size: 12.5px; font-weight: 600; color: var(--fg-dim); }
.m-pill {
  align-self: flex-start; padding: 3px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 700; white-space: nowrap;
  color: var(--pill); background: color-mix(in srgb, var(--pill) 16%, transparent);
}
.m-meter { position: relative; margin: 4px 0 2px; }
.m-meter-track { display: flex; gap: 2px; height: 8px; }
.m-meter-track span { display: block; height: 100%; }
.m-meter-track span:first-child { border-radius: 4px 0 0 4px; }
.m-meter-track span:last-child { border-radius: 0 4px 4px 0; }
.m-meter-mark {
  position: absolute; top: -4px; width: 4px; height: 16px; margin-left: -2px; border-radius: 2px;
  background: var(--fg); box-shadow: 0 0 0 2px var(--hero);
}
.m-stat-sub { font-size: 12.5px; color: var(--fg-dim); }

.m-body { margin-top: 20px; }
/* The Coach IA analysis, in the band in place of the subtitle (templates._page_ai_analysis). */
.m-band-main { min-width: 0; max-width: 720px; }
.m-band-main:has(.page-ai-analysis-card:not([hidden])) .e-band-text { display: none; }
.m-band .page-ai-analysis-card { margin: 12px 0 0; padding: 0; background: none; border: none; border-radius: 0; }
.m-band .page-ai-analysis-head { margin-bottom: 6px; color: var(--band-dim); font-family: var(--font-body); font-size: 12px; font-weight: 700; letter-spacing: 0.04em; }
.m-band .page-ai-analysis-head .chat-widget-avatar { background: rgba(255, 255, 255, 0.18); color: var(--band-ink); }
.m-band #page-ai-analysis-text p { color: var(--band-ink); font-size: 14.5px; line-height: 1.55; }
.m-band .page-ai-analysis-toggle { width: auto; text-align: left; margin-top: 6px; color: var(--band-ink); font-family: var(--font-body); font-size: 13px; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
@media (hover: hover) { .m-band .page-ai-analysis-toggle:hover { color: var(--band-ink); opacity: 0.85; } }
.m-body .health-panel { background: var(--bg-raise); border-color: var(--card-line); border-radius: 18px; }
/* Panel titles and key/value lists in the page's own type, not the old mono caps. */
.m-body .detail-chart-head { font-family: var(--font-body); font-size: 12.5px; }
.m-body .detail-chart-head span:first-child { font-family: var(--font-display); font-size: 15px; font-weight: 700; text-transform: none; letter-spacing: 0; color: var(--fg); }
.m-body .detail-stats-grid { display: flex; flex-direction: column; gap: 0; margin-top: 6px; padding-top: 0; border-top: none; }
.m-body .detail-stats-grid > div { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 9px 0; border-top: 1px solid var(--line-soft); }
.m-body .detail-stats-grid .k { font-family: var(--font-body); font-size: 13.5px; text-transform: none; letter-spacing: 0; color: var(--fg); }
.m-body .detail-stats-grid .v { margin: 0; font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--fg); white-space: nowrap; }

@media (max-width: 720px) {
  .m-band-side { width: 100%; align-items: stretch; }
  .m-band .nutrition-period-tabs { align-self: flex-start; }
  .m-analyze-btn { justify-content: center; padding: 11px 16px; }
  .m-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 0; }
  .m-stat, .m-stat:first-child { border-left: none; padding: 0 8px; }
  .m-stat:nth-child(even) { border-left: 1px solid var(--line); padding-left: 14px; }
  .m-stat-value { font-size: 24px; }
  .m-body { margin-top: 14px; }
}

/* Performance page only (views/performance.html): ACWR + weekly volume overlapping the band,
   then the VO2max cards (with their trend line) and the race predictions. */
.perf-top { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 16px; margin: -56px 24px 0; }
.perf-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: 20px; }
.perf-card { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 20px; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.perf-hero { background: var(--hero); box-shadow: var(--hero-shadow); }
.perf-card h2 { margin: 0; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--fg); }
.perf-card .m-stat-value { font-size: 40px; }
.perf-card-head { display: flex; justify-content: space-between; align-items: center; gap: 8px 12px; flex-wrap: wrap; }
.perf-card-head span { font-size: 12px; color: var(--fg-dim); }
.m-meter-ticks { position: relative; height: 14px; font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-dim); }
.m-meter-ticks span { position: absolute; transform: translateX(-50%); }
.m-meter-ticks span:first-child { transform: none; }
.m-meter-ticks span:last-child { transform: translateX(-100%); }
.m-meter-ticks.inner span, .m-meter-ticks.inner span:first-child, .m-meter-ticks.inner span:last-child { transform: translateX(-50%); }
/* Grows to fill the card (as tall as the ACWR card next to it), never under 130px. */
.perf-bars { flex: 1 1 130px; min-height: 130px; display: flex; align-items: flex-end; gap: clamp(2px, 0.6vw, 8px); margin-top: 12px; border-bottom: 1px solid var(--line); }
/* Each bar stacks its sports bottom-up (column-reverse keeps "Course" at the base). */
.perf-bar { flex: 1; min-height: 2px; display: flex; flex-direction: column-reverse; gap: 1px; border-radius: 6px 6px 0 0; overflow: hidden; }
.perf-bar i { display: block; width: 100%; }
.perf-bar.partial { opacity: 0.45; }
.perf-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 4px; font-size: 12.5px; color: var(--fg-dim); }
.perf-legend span { display: inline-flex; align-items: center; gap: 6px; }
.perf-legend i, .perf-level-label i { display: inline-block; width: 9px; height: 9px; border-radius: 3px; }
.perf-legend strong { color: var(--fg); }
.perf-legend-title { font-weight: 600; color: var(--fg); }
.perf-sub-title { margin-top: 10px; font-size: 12px; font-weight: 600; color: var(--fg-dim); }
.perf-spark-axis { margin-top: 2px; }
.perf-row-2 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.perf-levels { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 10px; }
.perf-levels > div { display: flex; flex-direction: column; gap: 2px; }
.perf-levels strong { font-family: var(--font-display); font-size: 26px; font-weight: 700; color: var(--fg); }
.perf-level-label { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--fg); }
.perf-level-label small { font-weight: 500; color: var(--fg-dim); }
/* One 100 % column per week/month, "Facile" at the base (column-reverse). */
.perf-int-cols { display: flex; align-items: stretch; gap: clamp(2px, 0.5vw, 6px); height: 74px; margin-top: 14px; }
.perf-int-col { flex: 1; display: flex; flex-direction: column-reverse; gap: 1px; border-radius: 4px; overflow: hidden; background: var(--line); cursor: crosshair; }
.perf-int-col i { display: block; width: 100%; }
.perf-int-col.partial { opacity: 0.5; }
.perf-int-cols:has(.perf-int-col.is-hover) .perf-int-col:not(.is-hover) { opacity: 0.4; }
.perf-records a { text-decoration: none; color: var(--signal-text); }
.perf-axis { display: flex; justify-content: space-between; gap: 8px; font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-dim); }
/* Room on the right for the min/max labels, so they never sit on the line. */
.perf-spark { position: relative; height: 64px; margin-top: 8px; padding-right: 26px; }
.perf-spark svg { width: 100%; height: 100%; display: block; overflow: visible; }
.perf-vo2 .perf-axis { padding-right: 26px; }
.perf-vo2 .m-stat-sub strong { color: var(--fg); font-weight: 700; }
.perf-spark polygon { fill: color-mix(in srgb, var(--signal) 14%, transparent); stroke: none; }
.perf-spark polygon.zoned { fill-opacity: 0.16; }
.perf-spark-band { fill: color-mix(in srgb, var(--go) 16%, transparent); }
.perf-spark polyline { fill: none; stroke: var(--signal); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.perf-spark-max, .perf-spark-min { position: absolute; right: 0; font-family: var(--font-mono); font-size: 10px; color: var(--fg-dim); }
.perf-spark-max { top: -2px; } .perf-spark-min { bottom: 0; }
.perf-preds h2 { margin-bottom: 4px; }
.perf-pred { display: flex; justify-content: space-between; align-items: baseline; margin: 0; padding: 8px 0; border-top: 1px solid var(--line-soft); font-size: 13.5px; }
.perf-pred strong { font-family: var(--font-display); font-size: 15px; }

@media (max-width: 960px) {
  .perf-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .perf-preds, .perf-intensity { grid-column: 1 / -1; }
}
@media (max-width: 720px) {
  .perf-top { grid-template-columns: minmax(0, 1fr); gap: 14px; margin: -48px -4px 0; }
  .perf-row { gap: 12px; margin-top: 14px; }
  .perf-card { padding: 16px; }
  .perf-card .m-stat-value { font-size: 32px; }
  .perf-vo2 .m-stat-value { font-size: 28px; }
  .perf-vo2 .m-stat-value small { display: block; margin-top: 2px; }
  .perf-bars { flex: none; height: 110px; min-height: 0; gap: 2px; }
  .perf-spark { height: 44px; }
  .perf-levels strong { font-size: 21px; }
  .perf-int-cols { height: 60px; gap: 2px; }
}

/* Hover on the Performance charts (perf-charts.js; the bars' read-out is the shared .hover-tip). */
.perf-bar, .perf-int-col, .perf-spark { cursor: crosshair; touch-action: pan-y; }
.perf-bars:has(.perf-bar.is-hover) .perf-bar:not(.is-hover) { opacity: 0.4; }
.perf-spark-cursor { position: absolute; top: 0; bottom: 0; width: 1px; margin-left: -0.5px; background: var(--fg-dim); pointer-events: none; }
.perf-spark-dot {
  position: absolute; width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; border-radius: 50%; pointer-events: none;
  background: var(--signal); box-shadow: 0 0 0 2px var(--bg-raise);
}
.perf-hero .perf-spark-dot { box-shadow: 0 0 0 2px var(--hero); }
.perf-spark-cursor[hidden], .perf-spark-dot[hidden] { display: none; }

/* Santé (views/health.html): trend line under each key figure, the Sommeil and Ta journée cards. */
.m-stat-trend { margin-top: 4px; }
.m-stat-trend .perf-spark { height: 44px; }
.m-hero .perf-spark-dot { box-shadow: 0 0 0 2px var(--hero); }
.health-row { grid-template-columns: minmax(0, 1fr); }
.health-row.two { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
/* Aujourd'hui: "Dernière nuit" keeps its own height next to the taller "Ta journée". */
.health-row.fit { align-items: start; }
.health-sleep-top { display: flex; align-items: flex-end; gap: 28px; flex-wrap: wrap; margin-top: 6px; }
.health-sleep-top > div { display: flex; flex-direction: column; gap: 2px; }
.health-sleep-top .m-pill { align-self: flex-end; margin-bottom: 6px; }
.health-stage-bar { display: flex; gap: 2px; height: 12px; margin-top: 12px; border-radius: 6px; overflow: hidden; }
.health-stage-bar i { display: block; height: 100%; }
.health-sleep-bars { flex: none; height: 120px; min-height: 0; margin-top: 14px; }
.health-hour-bars { flex: none; height: 120px; min-height: 0; margin-top: 14px; }
.health-hour-bars .perf-bar { background: var(--line); }
.health-hour-bars .perf-bar.moving { background: #4caf7d; }
.health-hour-bars .perf-bar.sitting { background: #e08541; }
@media (max-width: 960px) { .health-row.two { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 720px) {
  .health-sleep-top { gap: 18px; }
  .health-sleep-bars, .health-hour-bars { height: 90px; }
}
.health-alerts { margin-top: 14px; padding: 10px 14px; border-radius: 12px; background: var(--warn-bg); }
.health-alerts p { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--warn); }
.health-alerts p + p { margin-top: 4px; }
.health-alerts-ok { margin: 14px 0 0; font-size: 12.5px; color: var(--fg-dim); }
.health-extras { display: flex; flex-direction: column; margin-top: 10px; }
.health-extras p { display: flex; justify-content: space-between; margin: 0; padding: 7px 0; border-top: 1px solid var(--line-soft); font-size: 13.5px; }
.health-extras strong { font-family: var(--font-display); }
.health-goal { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.health-goal p { display: flex; justify-content: space-between; margin: 0; font-size: 13.5px; }
.health-goal strong { font-family: var(--font-display); }
.health-goal-bar { height: 10px; border-radius: 5px; background: var(--line); overflow: hidden; }
.health-goal-bar i { display: block; height: 100%; border-radius: inherit; background: var(--go); }
.perf-bar.steps { background: var(--signal); }

.health-split { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.health-split p { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; }
.health-split-sit { font-size: 12.5px; color: var(--fg-dim); display: inline-flex; align-items: center; gap: 6px; }
.health-split .health-stage-bar { margin-top: 8px; }

/* Nutrition day view: the 90-day weight line (same spark as Performance / Santé). */
.nutri-weight-trend-chart { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; }
.nutri-weight-trend-chart .perf-spark { height: 110px; }
.nutri-weight-trend-chart .perf-spark-max, .nutri-weight-trend-chart .perf-spark-min { background: none; }

/* ---- Habits, "Énergie" design (views/habits.html) --------------------------------------- */
.habit-card .habit-card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px 24px; flex-wrap: wrap; margin-bottom: 12px; }
.habit-card .nutri-day-title { margin: 0; }
.habit-progress { display: flex; flex-direction: column; gap: 6px; min-width: 240px; }
.habit-card .habit-summary { margin: 0; font-size: 13px; }
.habit-card .habit-summary strong { font-family: var(--font-display); font-size: 15px; }
.habit-progress-bar { height: 8px; border-radius: 4px; background: var(--line); overflow: hidden; }
.habit-progress-bar i { display: block; height: 100%; border-radius: inherit; background: var(--signal); transition: width .2s; }
.habit-card .habit-grid thead th { font-family: var(--font-body); font-size: 11.5px; font-weight: 700; letter-spacing: 0.03em; }
.habit-card .habit-grid thead th span { font-family: var(--font-display); font-size: 15px; font-weight: 700; }
.habit-card .habit-grid th.today, .habit-card .habit-grid td.today { background: var(--signal-soft); }
.habit-card .habit-grid .habit-name { font-weight: 700; font-size: 14px; }
.habit-card .habit-grid .habit-streak { font-family: var(--font-display); font-size: 13px; font-weight: 700; color: var(--fg); }
.habit-card button.habit-cell { width: 34px; height: 34px; }
.habit-manage-panel > summary.habit-manage-toggle {
  display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--bg-raise); color: var(--fg); font-size: 13.5px; font-weight: 700;
}
@media (hover: hover) { .habit-manage-panel > summary.habit-manage-toggle:hover { border-color: var(--signal); color: var(--fg); } }
.habit-manage-panel > summary.habit-manage-toggle::before { content: "+"; }
.habit-manage-panel[open] > summary.habit-manage-toggle::before { content: "−"; }
.habit-manage-panel > .content-card { margin-top: 12px; padding: 22px; }
.habit-manage-panel h3 { margin: 0; font-family: var(--font-display); font-size: 16px; font-weight: 700; }
@media (max-width: 720px) {
  .habit-progress { min-width: 0; width: 100%; }
  .habit-card button.habit-cell { width: 30px; height: 30px; }
  .habit-manage-panel > .content-card { padding: 16px; }
}
.habit-band .nutri-band-nav { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
.habit-band .nutrition-period-tabs { grid-template-columns: repeat(2, 1fr); }
/* Month view: one Monday-first calendar per habit, the day's number inside each cell. */
.habit-months { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.habit-month { padding: 14px; border-radius: 14px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.habit-month-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.habit-month-head .habit-name { font-weight: 700; font-size: 14px; color: var(--fg); overflow-wrap: anywhere; }
.habit-month-head .habit-target { display: inline; margin-left: 6px; font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-dim); }
.habit-month-stats { flex-shrink: 0; font-size: 12px; color: var(--fg-dim); white-space: nowrap; }
.habit-month-stats .habit-streak { font-family: var(--font-display); font-weight: 700; color: var(--fg); }
.habit-month-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; justify-items: center; }
.habit-month-dow { font-size: 10.5px; font-weight: 700; color: var(--fg-dim); padding-bottom: 2px; }
.habit-month-day .habit-toggle { display: flex; }
.habit-month-day button.habit-cell { width: 30px; height: 30px; font-family: var(--font-mono); font-size: 11px; color: var(--fg-dim); }
.habit-month-day button.habit-cell.done { color: var(--signal-ink); }
.habit-month-day button.habit-cell.partial { color: var(--fg); }
.habit-month-day.today button.habit-cell:not(.done):not(.partial) { border-color: var(--signal); border-width: 2px; color: var(--signal-text); font-weight: 700; }
@media (max-width: 720px) {
  .habit-band .nutri-band-nav { align-items: stretch; }
  .habit-months { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .habit-month-day button.habit-cell { width: 34px; height: 34px; }
}

/* ---- Sources, "Énergie" design (views/sources.html) ------------------------------------- */
.src-grid { position: relative; margin: -56px 24px 0; align-items: stretch; }
.src-page .source-card {
  display: flex; flex-direction: column; padding: 20px; border-radius: 18px;
  background: var(--hero); border: 1px solid var(--card-line); box-shadow: var(--hero-shadow);
}
.src-page .source-card.warn { border-color: color-mix(in srgb, var(--warn) 50%, var(--card-line)); }
.src-page .source-head { gap: 10px; }
.src-page .source-name { font-size: 17px; font-weight: 700; }
.src-page .source-name::before {
  content: ""; width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0; overflow: hidden;
  background: center / cover no-repeat;
}
/* The apps' own marks (grid order: Garmin, Strava, Capture), inlined so there's no extra asset
   to serve: Garmin's delta as on the Garmin Connect icon, Strava's chevrons, Capture's tile
   (capture-app.fr/logo.svg). */
.src-page .source-card:nth-child(1) .source-name::before { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23000%22/%3E%3Csvg x=%224%22 y=%224%22 width=%2216%22 height=%2216%22 viewBox=%2219.35 8.2 3.4 3.4%22%3E%3Cpath fill=%22%2311a9ed%22 d=%22M6.265 12.024a.289.289 0 0 0-.236-.146h-.182a.289.289 0 0 0-.234.146l-1.449 3.025c-.041.079.004.138.094.138h.335c.132 0 .193-.061.228-.134.037-.073.116-.234.13-.266.02-.045.083-.071.175-.071h1.559c.089 0 .148.016.175.071.018.035.098.179.136.256a.24.24 0 0 0 .234.142h.486c.089 0 .13-.069.098-.132-.034-.061-1.549-3.029-1.549-3.029zm-.914 2.224c-.089 0-.132-.067-.094-.148l.571-1.222c.039-.081.1-.081.136 0l.555 1.222c.037.081-.006.148-.096.148H5.351zm12.105-2.201v3.001c0 .083.073.138.163.138h.396c.089 0 .163-.057.163-.146v-2.998c0-.089-.059-.163-.148-.163h-.411c-.09-.001-.163.054-.163.168zm-6.631 1.88c-.051-.073-.022-.154.063-.181 0 0 .342-.102.506-.25.165-.146.246-.36.246-.636a1 1 0 0 0-.096-.457.787.787 0 0 0-.27-.303 1.276 1.276 0 0 0-.423-.171c-.165-.035-.386-.047-.386-.047a8.81 8.81 0 0 0-.325-.008H8.495a.164.164 0 0 0-.163.163v2.998c0 .089.073.146.163.146h.388c.089 0 .163-.057.163-.146v-1.193s.002 0 .002-.002l.738-.002c.089 0 .205.061.258.134l.766 1.077c.071.096.138.132.228.132h.508c.089 0 .104-.085.073-.128-.032-.038-.794-1.126-.794-1.126zm-.311-.61a1.57 1.57 0 0 1-.213.028 8.807 8.807 0 0 1-.325.006h-.763a.164.164 0 0 1-.163-.163v-.608c0-.089.073-.163.163-.163h.762c.089 0 .236.004.325.006 0 0 .114.004.213.028a.629.629 0 0 1 .24.098.358.358 0 0 1 .126.148.473.473 0 0 1 0 .374.352.352 0 0 1-.126.148.617.617 0 0 1-.239.098zm11.803-1.439c-.089 0-.163.059-.163.146v1.919c0 .089-.051.11-.114.047l-1.921-1.992a.376.376 0 0 0-.276-.118h-.362c-.114 0-.163.061-.163.122v3.068c0 .061.059.12.148.12h.362c.089 0 .152-.049.152-.132l.002-2.021c0-.089.051-.11.114-.045l2.004 2.082a.36.36 0 0 0 .279.116h.272a.164.164 0 0 0 .163-.163v-2.986a.164.164 0 0 0-.163-.163h-.334zm-7.835 1.87c-.043.079-.116.077-.159 0l-.939-1.724a.262.262 0 0 0-.236-.146h-.51a.164.164 0 0 0-.163.163v2.996c0 .089.059.15.163.15h.317c.089 0 .154-.057.154-.142 0-.041.002-2.179.004-2.179.004 0 1.173 2.177 1.173 2.177a.105.105 0 0 0 .189 0s1.179-2.173 1.181-2.173c.004 0 .002 2.11.002 2.173 0 .087.069.142.159.142h.364c.089 0 .163-.045.163-.163V12.04a.164.164 0 0 0-.163-.163h-.488a.265.265 0 0 0-.244.142l-.967 1.729zM0 13.529c0 1.616 1.653 1.697 1.984 1.697 1.098 0 1.561-.297 1.58-.309a.29.29 0 0 0 .152-.264v-1.116a.186.186 0 0 0-.187-.187H2.151c-.104 0-.171.083-.171.187v.116c0 .104.067.187.171.187h.797a.14.14 0 0 1 .14.14v.52c-.157.065-.874.274-1.451.136-.836-.199-.901-.89-.901-1.096 0-.173.053-1.043 1.079-1.13.831-.071 1.378.264 1.384.268.098.051.199.014.254-.089l.104-.209c.043-.085.028-.175-.077-.246-.006-.004-.59-.319-1.494-.319C.055 11.813 0 13.354 0 13.529zm22.134-2.478h-2.165c-.079 0-.148-.039-.187-.108s-.039-.146 0-.215l1.084-1.874a.21.21 0 0 1 .187-.108.21.21 0 0 1 .187.108l1.084 1.874a.203.203 0 0 1 0 .215.22.22 0 0 1-.19.108zm1.488 3.447c.207 0 .378.169.378.378a.379.379 0 0 1-.378.378.379.379 0 0 1-.378-.378.38.38 0 0 1 .378-.378zm.002.7c.173 0 .305-.14.305-.321s-.13-.321-.305-.321-.307.14-.307.321c0 .18.13.321.307.321zm-.146-.543h.169c.102 0 .152.041.152.124 0 .071-.045.122-.114.122l.126.195h-.077l-.124-.195h-.061v.195h-.073v-.441h.002zm.073.189h.085c.055 0 .091-.012.091-.069 0-.051-.045-.065-.091-.065h-.085v.134z%22/%3E%3C/svg%3E%3C/svg%3E"); }
.src-page .source-card:nth-child(2) .source-name::before { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23fc4c02%22/%3E%3Cg transform=%22translate(4.2 4) scale(0.66)%22%3E%3Cpath fill=%22%23fff%22 d=%22M15.387 17.944l-2.089-4.116h-3.065L15.387 24l5.15-10.172h-3.066m-7.008-5.599l2.836 5.598h4.172L10.463 0l-7 13.828h4.169%22/%3E%3C/g%3E%3C/svg%3E"); }
.src-page .source-card:nth-child(3) .source-name::before { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 133.00 134.00%22%3E%3Cdefs/%3E%3Cpath fill=%22%23000000%22 stroke=%22%23000000%22 fill-opacity=%221%22 stroke-width=%221%22 stroke-opacity=%221%22 title=%22Rectangle 2%22 d=%22M1.0027 1.0044C1.0027 1.0044 1.0027 1.0044 1.0027 1.0044H132.0027C132.0027 1.0044 132.0027 1.0044 132.0027 1.0044V133.0044C132.0027 133.0044 132.0027 133.0044 132.0027 133.0044H1.0027C1.0027 133.0044 1.0027 133.0044 1.0027 133.0044Z%22 id=%22tSvg88daaa8262%22/%3E%3Cpath fill=%22%23c8f135%22 stroke=%22%23c8f135%22 fill-opacity=%221%22 stroke-width=%221%22 stroke-opacity=%221%22 title=%22Path 4%22 d=%22M82.7322 96.25C82.7322 96.25 92.2411 86.25 92.2411 86.25C92.2411 86.25 92.2411 78.7422 92.2411 78.7422C92.2411 78.7422 106.7833 78.7422 106.7833 78.7422C106.7833 78.7422 106.7833 92.7257 106.7833 92.7257C106.7833 92.7257 89.25 110.2589 89.25 110.2589C89.25 110.2589 68.25 110.2589 68.25 110.2589C68.25 110.2589 68.25 96.25 68.25 96.25C68.25 96.25 82.7322 96.25 82.7322 96.25ZM44.4653 72.25C44.4653 72.25 44.4653 63.0663 44.4653 63.0663C44.4653 63.0663 50.2974 57.2341 50.2974 57.2341C50.2974 57.2341 50.2974 91.75 50.2974 91.75C50.2974 91.75 39.7299 91.75 39.7299 91.75C39.7299 91.75 39.7299 96.2429 39.7299 96.2429C39.7299 96.2429 64.3048 96.2429 64.3048 96.2429C64.3048 96.2429 64.3048 110.25 64.3048 110.25C64.3048 110.25 43.75 110.25 43.75 110.25C43.75 110.25 25.25 91.75 25.25 91.75C25.25 91.75 25.25 72.25 25.25 72.25C25.25 72.25 44.4653 72.25 44.4653 72.25ZM70.25 24.25C70.25 24.25 70.25 38.25 70.25 38.25C70.25 38.25 62.25 38.25 62.25 38.25C62.25 38.25 40.4641 60.0359 40.4641 60.0359C40.4641 60.0359 40.4641 65.8038 40.4641 65.8038C40.4641 65.8038 25.2206 65.8038 25.2206 65.8038C25.2206 65.8038 25.2206 54.6447 25.2206 54.6447C25.2206 54.6447 56.0232 24.25 56.0232 24.25C56.0232 24.25 70.25 24.25 70.25 24.25ZM74.25 23.75C74.25 23.75 106.7846 23.75 106.7846 23.75C106.7846 23.75 106.7846 54.765 106.7846 54.765C106.7846 54.765 92.1151 54.765 92.1151 54.765C92.1151 54.765 92.1151 38.2494 92.1151 38.2494C92.1151 38.2494 74.25 38.2494 74.25 38.2494C74.25 38.2494 74.25 23.75 74.25 23.75Z%22 id=%22tSvgc06d8e8417%22/%3E%3C/svg%3E"); }
.src-page .status-pill { padding: 3px 10px; border-radius: 999px; font-family: var(--font-body); font-size: 11px; font-weight: 700; letter-spacing: 0.02em; }
.src-page .source-card p { font-size: 13.5px; line-height: 1.5; margin: 12px 0 0; }
.src-page .source-card p.error { color: var(--warn); }
/* The card's action sits at its foot whatever the text length above it. */
.src-page .source-card > .action, .src-page .source-card > form, .src-page .source-card > div[style*="display:flex"] { margin-top: auto !important; padding-top: 16px; }
.src-page .source-card .action {
  display: inline-flex; align-self: flex-start; padding: 9px 16px; border: none; border-radius: 999px;
  background: var(--signal); color: var(--signal-ink); font-family: var(--font-body); font-size: 13.5px; font-weight: 700; text-decoration: none;
}
@media (hover: hover) { .src-page .source-card .action:hover { background: var(--signal); color: var(--signal-ink); filter: brightness(1.08); } }
.src-page .source-card .btn.secondary { margin: 0; width: auto; padding: 8px 14px; border-radius: 999px; font-size: 13px; }
.src-page .progress-bar { border-radius: 999px; }
.src-success { margin: 16px 0 0; padding: 10px 14px; border-radius: 12px; background: var(--go-bg); color: var(--go); font-weight: 600; }
.src-faq { margin-top: 20px; }
.src-faq .connectors-faq { margin: 0; padding: 0; background: none; border: none; }
.src-faq .connectors-faq h2 { margin-top: 0; font-size: 17px; font-weight: 700; }
.src-faq .connectors-faq summary { font-family: var(--font-body); font-size: 14px; font-weight: 600; color: var(--fg); text-transform: none; letter-spacing: 0; }
.src-faq .connectors-faq details p { font-size: 13.5px; }
@media (max-width: 960px) { .src-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 720px) {
  .src-grid { margin: -48px -4px 0; gap: 12px; }
  .src-page .source-card { padding: 16px; }
}
.src-band .e-band-chip { color: var(--fg); }
.src-band .e-band-chip.go { color: var(--go); }
.src-page .source-card .btn.secondary { font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }

/* "Bientôt disponible" cards: same look, muted, no action; their own marks, inlined. */
.src-soon-title { margin: 28px 0 12px; font-family: var(--font-display); font-size: 17px; font-weight: 700; color: var(--fg); }
.src-soon { margin: 0; }
.src-page .src-soon .source-card { background: var(--bg-raise); box-shadow: none; }
.src-page .src-soon .source-card p { color: var(--fg-dim); }
.src-page .src-soon .source-card.src-apple .source-name::before, .onb-source-logo.apple { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23000%22/%3E%3Cg transform=%22translate(5 4.6) scale(0.58)%22%3E%3Cpath fill=%22%23fff%22 d=%22M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701%22/%3E%3C/g%3E%3C/svg%3E"); }
.src-page .src-soon .source-card.src-suunto .source-name::before, .onb-source-logo.suunto { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23000%22/%3E%3Csvg x=%223%22 y=%223%22 width=%2218%22 height=%2218%22 viewBox=%2260 60 140 140%22%3E%3Cpath fill=%22%23fff%22 d=%22M99.9 125.7c-16 22.9-29.2 42.4-29.3 43.2-.1 1.4 6.1 1.6 59.4 1.6 53.5 0 59.5-.2 59.4-1.6C189.3 167 131.2 84 130 84c-.5 0-14 18.8-30.1 41.7z%22/%3E%3C/svg%3E%3C/svg%3E"); }
.src-page .src-soon .source-card.src-coros .source-name::before, .onb-source-logo.coros { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23000%22/%3E%3Csvg x=%223%22 y=%223%22 width=%2218%22 height=%2218%22 viewBox=%220 0 1024 1024%22%3E%3Cpath fill=%22%23F8273B%22 d=%22M611.28637781 226.3848448l313.2594324 182.00737337L925.07539342 786.3244288 612.34554539 967.44210091l-52.8312832-28.51279417 245.1761334-182.36749028L804.22436181 437.85826304 562.20454798 254.81290525l49.08182983-28.42806045zM171.15984213 335.14018133l34.86779961 304.15059058 275.38359524 158.95988452 279.04831715-118.71151332v56.85612089l-313.7678336 181.11767325L120.10795918 728.9599067V366.78811193l51.03069867-31.62674745zM569.19505465 56.55789909l312.72984804 181.11767211 1.80058566 60.13954162-280.04393414-121.80428345-274.9175626 159.76485205-37.02850219 301.75687111-49.06064668-28.42806044 0.50840121-363.12504548L569.19505465 56.55789909z%22 p-id=%224590%22%3E%3C/path%3E%3C/svg%3E%3C/svg%3E"); }
.src-sync-note { margin-top: 4px; font-size: 13px; }
.src-page .source-card p.source-what { color: var(--fg); font-weight: 500; }
.src-page .source-card div[style*="display:flex"] { flex-wrap: wrap; }
.src-band-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; flex-shrink: 0; }
.src-last-sync { font-size: 12.5px; font-weight: 600; color: var(--band-dim); }
@media (max-width: 720px) { .src-band-side { align-items: flex-start; } }

/* ---- MCP, "Énergie" design (views/mcp.html) --------------------------------------------- */
.mcp-band .e-band-chip { color: var(--fg); }
.mcp-band .e-band-chip.go { color: var(--go); }
.mcp-card { display: flex; flex-direction: column; gap: 10px; }
.mcp-card .nutri-day-title { margin: 0; }
.mcp-text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--fg-dim); }
.mcp-card .keybox { margin: 4px 0 0; padding: 12px 14px; border-radius: 12px; background: var(--bg-sink); border: 1px solid var(--line); font-family: var(--font-mono); font-size: 13px; overflow-wrap: anywhere; }
.mcp-actions { display: flex; align-items: center; gap: 12px 16px; flex-wrap: wrap; }
.mcp-actions form { margin: 0; }
.mcp-actions .note { margin: 0; font-size: 12.5px; color: var(--fg-dim); }
.mcp-btn { margin: 0; width: auto; padding: 10px 18px; border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
.mcp-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 20px; }
.mcp-grid .content-card { margin: 0; padding: 22px; }
.mcp-grid h2 { margin: 0 0 12px; font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.mcp-steps ol { list-style: none; counter-reset: step; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.mcp-steps li { counter-increment: step; display: grid; grid-template-columns: 28px 1fr; column-gap: 12px; }
.mcp-steps li::before {
  content: counter(step); grid-row: span 2; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%;
  background: var(--signal); color: var(--signal-ink); font-family: var(--font-display); font-weight: 700; font-size: 14px;
}
.mcp-steps li strong { font-size: 14px; color: var(--fg); }
.mcp-steps li span { font-size: 13px; line-height: 1.5; color: var(--fg-dim); }
.mcp-can ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.mcp-can li { font-size: 13.5px; line-height: 1.5; color: var(--fg-dim); }
.mcp-can li span { display: inline-block; min-width: 54px; margin-right: 8px; padding: 2px 8px; border-radius: 999px; background: var(--signal-soft); color: var(--signal-text); font-size: 11.5px; font-weight: 700; text-align: center; }
.mcp-can li:last-child span { background: var(--go-bg); color: var(--go); }
.mcp-alt { margin-top: 20px; }
.mcp-alt .details-block { margin: 0; background: var(--bg-raise); border-color: var(--card-line); border-radius: 18px; padding: 6px 22px 10px; }
.mcp-alt .details-block summary { font-family: var(--font-body); font-weight: 700; }
@media (max-width: 860px) { .mcp-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 720px) { .mcp-grid { gap: 12px; margin-top: 14px; } .mcp-grid .content-card { padding: 16px; } }
@media (max-width: 720px) { .mcp-card .nutri-day-title, .habit-card .nutri-day-title { display: block; } }

/* ---- Abonnement, "Énergie" design (views/billing.html) ---------------------------------- */
.bill-band .e-band-chip { color: var(--fg); }
.bill-band .e-band-chip.go { color: var(--go); }
.bill-band .e-band-chip.warn { color: var(--warn); }
.bill-card { display: flex; flex-direction: column; gap: 12px; }
.bill-card .nutri-day-title { margin: 0; }
.bill-card form { margin: 0; }
.bill-card .note { margin: 0; font-size: 12.5px; color: var(--fg-dim); }
.bill-notice { margin: 0; padding: 10px 14px; border-radius: 12px; font-size: 13.5px; font-weight: 600; background: var(--bg-sink); }
.bill-notice.go { color: var(--go); background: var(--go-bg); }
.bill-notice.warn { color: var(--warn); }
.bill-plans { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.bill-plan { display: flex; flex-direction: column; gap: 6px; padding: 18px; border-radius: 16px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.bill-plan-name { font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--fg); }
.bill-plan-name em { margin-left: 6px; padding: 2px 8px; border-radius: 999px; background: var(--signal-soft); color: var(--signal-text); font-size: 11.5px; font-style: normal; }
.bill-plan-price { font-family: var(--font-display); font-size: 26px; font-weight: 700; color: var(--fg); }
.bill-plan-price small { font-size: 13px; font-weight: 600; color: var(--fg-dim); }
.bill-plan-sub { flex: 1; font-size: 13px; line-height: 1.5; color: var(--fg-dim); }
.bill-plan .mcp-btn { align-self: flex-start; margin-top: 6px; }
@media (max-width: 720px) { .bill-plans { grid-template-columns: minmax(0, 1fr); } }

/* ---- Chat IA, "Énergie" design (views/chat.html) ---------------------------------------- */
.e-chat { max-width: none; gap: 16px; }
.e-chat .chat-sidebar { width: 260px; padding: 16px; gap: 4px; border-radius: 18px; border-right: none; background: var(--bg-raise); border: 1px solid var(--card-line); }
.e-chat .chat-sidebar form { margin: 0; }
.e-chat-new {
  display: block; width: 100%; margin: 0 0 8px; padding: 11px; border: none; border-radius: 12px;
  background: var(--signal); color: var(--signal-ink); font-family: var(--font-body); font-size: 13.5px; font-weight: 700; cursor: pointer;
}
@media (hover: hover) { .e-chat-new:hover { background: var(--signal); color: var(--signal-ink); filter: brightness(1.08); } }
.e-chat .chat-conv-group { margin: 10px 4px 2px; font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim); }
.e-chat .chat-conv-group:first-child { margin-top: 2px; }
.e-chat .chat-conv-item a { padding: 10px 44px 10px 12px; border-radius: 999px; }
.e-chat .chat-conv-title { font-size: 13.5px; color: var(--fg); }
.e-chat .chat-conv-item.active a { background: var(--signal); }
.e-chat .chat-conv-item.active .chat-conv-title { color: var(--signal-ink); font-weight: 700; }
.e-chat .chat-conv-item.active .chat-conv-rename, .e-chat .chat-conv-item.active .chat-conv-delete { color: var(--signal-ink); }
.e-chat .chat-conv-actions { top: 50%; transform: translateY(-50%); right: 8px; }
.e-chat .chat-main { position: relative; padding: 0; overflow: hidden; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.e-chat .chat-head { height: 64px; padding: 0 20px; margin: 0; gap: 12px; border-bottom: none; background: var(--band); color: var(--band-ink); }
.e-chat .chat-head-avatar { width: 36px; height: 36px; background: #fff; color: var(--band); }
.e-chat .chat-head-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.e-chat .chat-head-name { font-size: 16px; font-weight: 700; color: var(--band-ink); }
.e-chat .chat-head-sub { font-size: 12px; color: var(--band-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.e-chat .chat-thread { padding: 24px 28px 12px; gap: 14px; }
.e-chat .chat-thread > * { max-width: 760px; }
.e-chat .chat-bubble { font-size: 14.5px; }
.e-chat .chat-bubble.user { max-width: 70%; padding: 12px 16px; background: var(--signal); color: var(--signal-ink); }
.e-chat .chat-bubble.model { max-width: 86%; padding: 16px 18px; background: var(--bg); line-height: 1.6; }
.e-chat .chat-bubble.model strong { color: inherit; }
.e-chat .chat-start { display: flex; flex-direction: column; gap: 12px; margin: auto 0; }
.e-chat .chat-start .chat-empty-hint { margin: 0; padding: 0; font-size: 14px; }
.chat-suggest { display: flex; flex-wrap: wrap; gap: 8px; }
.chat-suggest-chip {
  margin: 0; width: auto; padding: 7px 13px; border-radius: 999px; border: 1px solid var(--line); background: var(--bg);
  color: var(--fg); font-family: var(--font-body); font-size: 13px; font-weight: 600; cursor: pointer; text-align: left;
}
@media (hover: hover) { .chat-suggest-chip:hover { border-color: var(--signal); background: var(--bg); color: var(--fg); } }
.e-chat .chat-not-configured { margin: 0 20px 8px; }
.e-chat .chat-input-row { margin: 0 20px 20px; padding: 6px 6px 6px 18px; background: var(--bg); border: 1px solid var(--line); }
.e-chat .chat-send-btn { width: 40px; height: 40px; }
@media (max-width: 720px) {
  .e-chat { gap: 0; }
  .e-chat .chat-sidebar { width: 100%; border-radius: 0; border: none; background: var(--bg); padding: 16px; }
  .e-chat .chat-main { border-radius: 0; border: none; height: 100%; padding: 0; background: var(--bg); }
  .e-chat .chat-head { padding: 0 16px; }
  .e-chat #chat-show-list { color: var(--band-ink); margin-left: auto; }
  .e-chat .chat-thread { padding: 16px 16px 8px; }
  .e-chat .chat-bubble.user { max-width: 82%; padding: 11px 14px; font-size: 14px; }
  .e-chat .chat-bubble.model { max-width: 92%; padding: 14px 15px; font-size: 14px; background: var(--bg-raise); }
  .e-chat .chat-input-row { margin: 0 12px 12px; background: var(--bg-raise); }
}
body:has(.e-chat) .chat-widget { display: none; }

/* ---- Programme, "Énergie" design (views/plan.html) -------------------------------------- */
.plan-band-side { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; flex-shrink: 0; }
.plan-band-progress { display: flex; flex-direction: column; align-items: flex-end; }
.plan-band-progress strong { font-family: var(--font-display); font-size: 32px; font-weight: 700; line-height: 1; color: var(--band-ink); }
.plan-band-progress span { font-size: 12.5px; color: var(--band-dim); }
.plan-band .nutrition-period-tabs, .plan-section-head .nutrition-period-tabs { grid-template-columns: repeat(2, auto); }
.plan-band .nutrition-period-tabs { margin: 0; background: rgba(255, 255, 255, 0.14); border: none; border-radius: 999px; }
.plan-band .nutrition-period-tab { color: var(--band-dim); border-radius: 999px; font-weight: 600; padding: 5px 16px; }
@media (hover: hover) { .plan-band .nutrition-period-tab:hover { color: var(--band-ink); } }
.plan-band .nutrition-period-tab.active { background: #fff; color: var(--band); box-shadow: none; }
.plan-quick-card .plan-quickstart { max-width: none; }
.plan-quick-card .plan-quickstart-btn { align-self: flex-start; margin: 0; width: auto; padding: 10px 18px; border-radius: 999px; }

.plan-overview-wrap { position: relative; margin: -56px 24px 0; }
.plan-overview-wrap .plan-overview-card { margin: 0; padding: 20px 22px; border-radius: 18px; background: var(--hero); box-shadow: var(--hero-shadow); border: 1px solid var(--card-line); }
.plan-overview-wrap .plan-overview-duration { font-family: var(--font-body); font-size: 12.5px; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--fg-dim); }
.plan-overview-wrap .plan-total .k { font-family: var(--font-body); font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; }
.plan-overview-wrap .plan-total .v { font-size: 22px; font-weight: 700; }
.plan-overview-wrap .progress-bar { height: 8px; border-radius: 999px; }
.plan-overview-wrap .plan-timeline-track { background: var(--bg-raise); border-radius: 10px; overflow: hidden; }
.plan-overview-wrap .plan-timeline-label { font-family: var(--font-body); font-weight: 700; }
.plan-overview-wrap .plan-chart-tab { border-radius: 999px; font-family: var(--font-body); font-weight: 600; text-transform: none; letter-spacing: 0; }
.plan-overview-wrap .plan-chart-tab.active { background: var(--signal); color: var(--signal-ink); }
.plan-overview-wrap .detail-chart-head span:first-child { font-family: var(--font-display); font-size: 15px; font-weight: 700; text-transform: none; letter-spacing: 0; color: var(--fg); }
.plan-overview-wrap .health-bars-wrap { background: none; border: none; padding: 0; }
.plan-overview-wrap .health-bar { border-radius: 6px 6px 0 0; }

.plan-section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 26px 0 14px; }
.plan-section-nav { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.plan-section-nav h2 { margin: 0; font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--fg); }
.plan-nav-arrow {
  display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: var(--bg-raise);
  border: 1px solid var(--card-line); color: var(--fg); text-decoration: none;
}
@media (hover: hover) { .plan-nav-arrow:hover { border-color: var(--signal); color: var(--fg); } }
.plan-nav-today { font-size: 13px; font-weight: 700; color: var(--signal-text); text-decoration: none; }
.plan-section-head .nutrition-period-tabs { margin: 0; }

/* Week view (views/plan.html, routes_plan._plan_week_days): a column per day - a header, then
   one card per session. The column itself has no box, so a rest day or a one-session day
   doesn't stretch into a tall empty card next to a busy one. */
.plan-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 10px; align-items: start; }
.plan-wday { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.plan-wday-head { display: flex; justify-content: space-between; align-items: baseline; padding: 4px 6px 2px; border-bottom: 2px solid transparent; }
.plan-wday.today .plan-wday-head { border-bottom-color: var(--signal); }
.plan-wday-head span { font-size: 12px; font-weight: 700; color: var(--fg-dim); }
.plan-wday-head strong { font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--fg); }
.plan-wday.today .plan-wday-head strong { color: var(--signal-text); }
.plan-wday-empty { margin: 0; padding: 12px 14px; border-radius: 14px; border: 1px dashed var(--card-line); font-size: 12.5px; color: var(--fg-dim); }
.plan-wsession { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: 14px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.plan-wday.today .plan-wsession { border-color: color-mix(in srgb, var(--signal) 55%, var(--card-line)); }
.plan-wsession-pills { display: flex; flex-wrap: wrap; gap: 4px; }
.plan-wsession .plan-discipline-badge { border-radius: 999px; font-family: var(--font-body); font-size: 10.5px; font-weight: 700; text-transform: none; letter-spacing: 0; padding: 2px 8px; }
.plan-wstatus { padding: 2px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 700; }
.plan-wstatus.go { background: var(--go-bg); color: var(--go); }
.plan-wstatus.warn { background: var(--warn-bg); color: var(--warn); }
.plan-wstatus.accent { background: var(--signal); color: var(--signal-ink); }
.plan-wstatus.neutral { background: var(--bg-sink); color: var(--fg-dim); }
.plan-wsession-title { font-family: var(--font-display); font-size: 14.5px; font-weight: 700; line-height: 1.3; color: var(--fg); overflow-wrap: break-word; hyphens: auto; }
.plan-wsession.plan-status-skipped .plan-wsession-title { text-decoration: line-through; color: var(--fg-dim); }
.plan-wsession-stats { font-size: 12px; font-weight: 600; color: var(--fg); }
.plan-wsession-detail { font-size: 12px; line-height: 1.45; color: var(--fg-dim); }

/* Month grid and list, restyled. */
.plan-page .plan-calendar-card, .plan-page .plan-list-card { margin: 0; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.plan-page .plan-cal-weekday { font-family: var(--font-body); font-size: 11.5px; font-weight: 700; letter-spacing: 0.03em; }
.plan-page .plan-cal-day { border-radius: 12px; }
.plan-page .plan-cal-chip { border-radius: 8px; font-family: var(--font-body); font-weight: 600; }
.plan-page .plan-list-card { margin-top: 20px; }
.plan-page .plan-day-label { font-family: var(--font-display); font-size: 14px; font-weight: 700; text-transform: none; letter-spacing: 0; color: var(--fg); }
.plan-page .plan-session { border-radius: 16px; background: var(--bg); border: 1px solid var(--card-line); }
.plan-page .plan-session-title { font-size: 16px; font-weight: 700; }
.plan-page .plan-discipline-badge { border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
.plan-page .plan-action-btn { border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; padding: 6px 12px; }
.plan-page .activity-card-stats .k { font-family: var(--font-body); text-transform: none; letter-spacing: 0; font-weight: 600; }
.plan-page .activity-card-stats .v { font-family: var(--font-display); font-weight: 700; }

@media (max-width: 960px) { .plan-week { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) {
  .plan-band-side { align-items: stretch; width: 100%; }
  .plan-band-progress { flex-direction: row; align-items: baseline; gap: 8px; }
  .plan-band-progress strong { font-size: 24px; }
  .plan-overview-wrap { margin: -48px -4px 0; }
  .plan-overview-wrap .plan-overview-card { padding: 16px; }
  .plan-week { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .plan-wday.rest { flex-direction: row; align-items: center; }
  .plan-wday-head { justify-content: flex-start; gap: 8px; }
  .plan-wday.rest .plan-wday-head { flex-shrink: 0; }
  .plan-wday.rest .plan-wday-empty { flex: 1; padding: 8px 12px; }
  .plan-section-head { margin: 18px 0 12px; }
  .plan-section-nav h2 { font-size: 17px; }
}
/* The program's progress is in the band (views/plan.html) - not repeated in the overview card. */
.plan-overview-wrap .plan-progress { display: none; }
.plan-wsession-detail { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
/* Plan calendar session detail (plan-calendar.js). */
.plan-week [data-session], .plan-calendar [data-session] { cursor: pointer; }
@media (hover: hover) {
  .plan-week [data-session]:hover { border-color: color-mix(in srgb, var(--signal) 70%, var(--card-line)); }
  .plan-calendar [data-session]:hover { filter: brightness(0.95); }
}
.plan-pop {
  position: fixed; z-index: 2500; width: min(360px, calc(100vw - 24px)); max-height: min(70vh, 560px); overflow-y: auto;
  padding: 18px; border-radius: 18px; background: var(--hero); border: 1px solid var(--card-line);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.28);
}
.plan-pop[hidden] { display: none; }
.plan-detail { display: flex; flex-direction: column; gap: 10px; }
.plan-detail-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.plan-detail-date { font-size: 12.5px; font-weight: 700; color: var(--fg-dim); }
.plan-detail-close { margin: 0; width: 28px; height: 28px; padding: 0; border: none; border-radius: 50%; background: var(--bg-raise); color: var(--fg); font-size: 18px; line-height: 1; cursor: pointer; }
.plan-pop:not(.pinned) .plan-detail-close { visibility: hidden; }
.plan-detail .plan-discipline-badge { border-radius: 999px; font-family: var(--font-body); font-size: 11px; font-weight: 700; text-transform: none; letter-spacing: 0; }
.plan-detail .plan-wstatus { font-size: 11px; }
.plan-detail-title { margin: 0; font-family: var(--font-display); font-size: 18px; font-weight: 700; color: var(--fg); }
.plan-detail-stats { display: flex; gap: 20px; }
.plan-detail-stats div { display: flex; flex-direction: column; gap: 2px; }
.plan-detail-stats span { font-size: 11.5px; font-weight: 600; color: var(--fg-dim); }
.plan-detail-stats strong { font-family: var(--font-display); font-size: 17px; color: var(--fg); }
.plan-detail-notes .plan-session-notes { margin: 0; font-size: 13px; line-height: 1.55; color: var(--fg-dim); }
.plan-detail-notes ul.plan-session-notes { padding-left: 18px; }
.plan-detail-actions { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 4px; }
.plan-detail-actions .plan-garmin-push-btn { margin-left: auto; }
.plan-detail-actions .plan-action-btn { border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; padding: 7px 14px; }
/* No detail popover on a phone (plan-calendar.js) - nothing to point at there either. */
@media (max-width: 720px) { .plan-week [data-session], .plan-calendar [data-session] { cursor: default; } }

/* ---- Objectif & poids, "Énergie" design (views/goals.html) ------------------------------ */
.goals-band { align-items: flex-end; }
.goals-band-weight { display: flex; flex-direction: column; align-items: flex-end; flex-shrink: 0; }
.goals-band-weight strong { font-family: var(--font-display); font-size: 34px; font-weight: 700; line-height: 1; color: var(--band-ink); }
.goals-band-weight strong small { font-size: 15px; color: var(--band-dim); }
.goals-band-weight span { margin-top: 4px; font-size: 12.5px; color: var(--band-dim); }
.goals-hero .nutri-day-title { margin: 0; }
.goals-hero .nutrition-goal-options { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); margin: 12px 0 0; }
.goals-hero .nutrition-goal-option { border-radius: 14px; background: var(--bg-raise); }
.goals-hero .nutrition-goal-option:has(input:checked), .goals-hero .nutrition-goal-option.active { background: var(--signal-soft); }
.goals-hero .nutrition-goal-name { font-weight: 700; }
.goals-targets { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line-soft); }
.goals-targets .content-card { margin: 0; padding: 0; background: none; border: none; box-shadow: none; }
.goals-targets h3 { margin: 0; font-family: var(--font-display); font-size: 16px; font-weight: 700; }
.goals-targets .nutri-goal-tiles > div { border-radius: 14px; background: var(--bg-raise); border-color: var(--card-line); }
.goals-targets .nutri-goal-tiles .k { font-family: var(--font-body); font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; }
.goals-targets .nutri-goal-tiles .v { font-family: var(--font-display); font-weight: 700; font-size: 24px; }
.goals-targets .nutri-goal-note { margin: 12px 0 0; font-size: 12.5px; }
.goals-weight { margin-top: 20px; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--card-line); padding: 22px; }
.goals-weight .e-card-head h2 { margin: 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.goals-weight .perf-spark { height: 130px; margin-top: 10px; }
.goals-weight-form { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.goals-weight-form label { display: flex; flex-direction: column; gap: 4px; margin: 0; font-family: var(--font-body); font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--fg-dim); }
.goals-weight-form input { margin: 0; border-radius: 12px; }
.goals-weight-form .btn { margin: 0; width: auto; padding: 10px 18px; border-radius: 999px; }
.goals-weight .nutri-weight-history { margin-top: 14px; }
.goals-weight .nutri-weight-history summary { font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
@media (max-width: 720px) {
  .goals-band { align-items: stretch; }
  .goals-band-weight { align-items: flex-start; }
  .goals-band-weight strong { font-size: 28px; }
  .goals-targets .nutri-goal-tiles { grid-template-columns: minmax(0, 1fr); }
  .goals-weight { padding: 16px; margin-top: 14px; }
  .goals-weight .perf-spark { height: 100px; }
}
.goals-weight-form .btn { font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
@media (max-width: 720px) { .goals-hero .nutri-day-title { display: block; } }

/* ---- Compte, "Énergie" design (views/account.html) -------------------------------------- */
.acc-who { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.acc-avatar { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; background: #fff; color: var(--band); font-family: var(--font-display); font-weight: 700; font-size: 16px; }
.acc-who > span:last-child { display: flex; flex-direction: column; }
.acc-who strong { font-size: 15px; color: var(--band-ink); }
.acc-who small { font-size: 12.5px; color: var(--band-dim); }
.acc-profile .nutri-day-title { margin: 0 0 12px; }
.acc-profile .profile-form label, .acc-danger label { font-family: var(--font-body); font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--fg-dim); }
.acc-profile input, .acc-profile select, .acc-danger input { border-radius: 12px; }
.acc-note { margin: 10px 0 0; font-size: 12.5px; }
.acc-btn { margin: 14px 0 0; width: auto; padding: 10px 18px; border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
.acc-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 20px; align-items: start; }
.acc-grid > .content-card, .acc-danger { margin: 0; padding: 22px; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.acc-grid:not(:has(#push-card)) { grid-template-columns: minmax(0, 1fr); }
.acc-danger { margin-top: 20px; }
.acc-grid .section-title, .acc-danger .section-title { margin: 0 0 12px; font-family: var(--font-display); font-size: 17px; font-weight: 700; text-transform: none; letter-spacing: 0; color: var(--fg); }
.acc-grid .theme-option { border-radius: 14px; }
.acc-grid #push-card .btn { margin-top: 0; width: auto; padding: 9px 16px; border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
.acc-grid .acc-tabs { grid-column: 1 / -1; }
.tabs-form-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.tabs-form-row label { font-family: var(--font-body); font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--fg-dim); }
.tabs-form-actions { display: flex; gap: 10px; flex-wrap: wrap; }
@media (max-width: 1100px) { .tabs-form-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px) { .acc-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 720px) {
  .acc-who { align-self: flex-start; }
  .acc-profile .nutri-day-title { display: block; }
  .acc-grid { gap: 12px; margin-top: 14px; }
  .acc-grid > .content-card, .acc-danger { padding: 16px; }
}
/* Nouvelle clé MCP (views/mcp_key.html). */
.mcp-keyrow { display: flex; gap: 8px; align-items: stretch; margin: 4px 0 0; }
.mcp-keyrow .keybox { flex: 1; min-width: 0; margin: 0; }
.mcp-copy { margin: 0; width: auto; padding: 0 18px; border: none; border-radius: 12px; background: var(--signal); color: var(--signal-ink); font-family: var(--font-body); font-weight: 700; cursor: pointer; }
@media (hover: hover) { .mcp-copy:hover { background: var(--signal); color: var(--signal-ink); filter: brightness(1.08); } }
.mcp-back { align-self: flex-start; margin-top: 6px; text-decoration: none; }
.mcp-alt .keybox-row { display: flex; gap: 8px; }
.mcp-alt .keybox { flex: 1; min-width: 0; border-radius: 12px; font-family: var(--font-mono); font-size: 12.5px; overflow-wrap: anywhere; }
.mcp-alt .copy-btn { margin: 0; width: auto; border-radius: 12px; }
@media (max-width: 720px) { .mcp-keyrow { flex-direction: column; } .mcp-copy { padding: 11px 18px; } }

/* ---- Signed-out pages (templates._page: login, signup, Garmin linking), "Énergie" design --
   Desktop: the blue pitch panel on the left, the form card on the right. Phone: the panel is
   the band across the top and the card overlaps its bottom edge, like the app's pages.
   On desktop the layout is pinned to the viewport and only the card itself scrolls. */
.auth { flex: 1; display: grid; grid-template-columns: minmax(360px, 5fr) 6fr; height: 100vh; height: 100dvh; padding: 16px; gap: 16px; position: relative; z-index: 1; }
.auth-band {
  display: flex; flex-direction: column; justify-content: space-between; gap: 32px;
  padding: 36px 40px; border-radius: 24px; background: var(--band); color: var(--band-ink);
  min-height: 0; overflow-y: auto;
}
.auth-logo { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-display); font-weight: 700; font-size: 20px; color: var(--band-ink); text-decoration: none; color: #fff; }
.auth-logo svg { width: 30px; height: 30px; color: var(--band); }
@media (hover: hover) { .auth-logo:hover { color: #fff; } }
.auth-pitch h2 { margin: 0 0 26px; max-width: 420px; font-family: var(--font-display); font-size: 34px; font-weight: 700; line-height: 1.12; letter-spacing: -0.015em; color: var(--band-ink); }
.auth-pitch ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 16px; max-width: 420px; }
.auth-pitch li { display: flex; flex-direction: column; gap: 3px; padding-left: 18px; border-left: 2px solid rgba(255, 255, 255, 0.35); }
.auth-pitch li strong { font-size: 15px; color: var(--band-ink); }
.auth-pitch li span { font-size: 13.5px; line-height: 1.45; color: var(--band-dim); }
.auth-main { display: flex; min-height: 0; padding: 24px; }
.auth-main > div { margin: auto; max-height: 100%; overflow-y: auto; overscroll-behavior: contain; }
.auth-main .card { border-radius: 22px; border: 1px solid var(--card-line); background: var(--hero); box-shadow: var(--hero-shadow); padding: 34px; }
.auth-main .card h1 { font-size: 26px; font-weight: 700; letter-spacing: -0.01em; }
.auth-main .card label { font-family: var(--font-body); font-size: 12.5px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--fg-dim); }
.auth-main .card input:not([type="checkbox"]) { border-radius: 12px; }
.auth-main .card button[type="submit"] { border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
@media (max-width: 860px) {
  .auth { display: block; height: auto; padding: 0; }
  .auth-band { gap: 18px; padding: 22px 20px 72px; border-radius: 0; overflow: visible; }
  .auth-pitch h2 { margin: 0; font-size: 24px; }
  .auth-pitch ul { display: none; }
  .auth-main { display: block; padding: 0 12px 28px; margin-top: -52px; }
  .auth-main > div { max-height: none; overflow: visible; }
  .auth-main .card { max-width: none; padding: 22px 18px; }
}
/* Signup invite code as 8 boxes (invite-code.js). */
.invite-boxes { display: flex; align-items: center; gap: 6px; margin: 4px 0 0; }
.invite-box {
  width: 0; flex: 1 1 0; min-width: 0; max-width: 46px; height: 50px; margin: 0 !important; padding: 0 !important; text-align: center;
  border-radius: 12px !important; font-family: var(--font-mono); font-size: 20px; font-weight: 600; text-transform: uppercase;
}
.invite-dash { color: var(--fg-dim); font-weight: 700; }
.invite-boxes.valid .invite-box { border-color: var(--go); background: var(--go-bg); }
.invite-boxes.invalid .invite-box { border-color: var(--warn); background: var(--warn-bg); }
.invite-status { min-height: 18px; margin: 6px 0 12px; font-size: 12.5px; font-weight: 600; color: var(--fg-dim); }
.invite-status.ok { color: var(--go); }
.invite-status.bad { color: var(--warn); }
/* Signup live field checks (signup-form.js). */
.field-error { margin: 4px 0 10px; font-size: 12.5px; font-weight: 600; color: var(--warn); }
.field-error[hidden] { display: none; }
.auth-main .card input.field-invalid { border-color: var(--warn); }

/* ---- Onboarding (routes_onboarding.py, views/onboarding*.html) --------------------------- */
.onb-pitch h2 { margin-bottom: 8px; }
.onb-intro { margin: 0 0 22px; font-size: 14px; color: var(--band-dim); }
.onb-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; max-width: 420px; }
/* Not the login pitch's bordered list items (.auth-pitch li) - the numbered dots say it all. */
.auth-pitch .onb-steps li { padding-left: 0; border-left: none; }
.onb-steps a { display: flex; align-items: center; gap: 12px; padding: 9px 12px; border-radius: 14px; color: var(--band-ink); text-decoration: none; }
@media (hover: hover) { .onb-steps a:hover { background: rgba(255, 255, 255, 0.1); color: var(--band-ink); } }
.onb-steps li.current a { background: rgba(255, 255, 255, 0.16); }
.onb-num { display: grid; place-items: center; flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.45); font-family: var(--font-display); font-weight: 700; font-size: 13.5px; }
.onb-steps li.current .onb-num { background: #fff; border-color: #fff; color: var(--band); }
.onb-steps li.done .onb-num { background: rgba(255, 255, 255, 0.22); border-color: transparent; }
.onb-steps strong { display: block; font-size: 14.5px; }
.onb-steps small { display: block; font-size: 12.5px; color: var(--band-dim); }
.auth-main .card.onboard-card { max-width: 520px; }
.onb-count { margin: 0 0 6px; font-size: 12px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-dim); }
.onb-bar { height: 6px; margin-bottom: 22px; border-radius: 3px; background: var(--line); overflow: hidden; }
.onb-bar i { display: block; height: 100%; border-radius: inherit; background: var(--signal); }
.onb-form { display: flex; flex-direction: column; }
.onb-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
.onb-row > div { display: flex; flex-direction: column; }
.onb-actions { display: flex; align-items: center; gap: 16px; margin-top: 18px; flex-wrap: wrap; }
.onb-actions button, .onb-primary {
  margin: 0; width: auto; padding: 12px 22px; border: none; border-radius: 999px; background: var(--signal); color: var(--signal-ink);
  font-family: var(--font-body); font-size: 14.5px; font-weight: 700; text-decoration: none; text-transform: none; letter-spacing: 0; cursor: pointer;
}
@media (hover: hover) { .onb-primary:hover, .onb-actions button:hover { background: var(--signal); color: var(--signal-ink); filter: brightness(1.08); } }
/* Desktop: the card scrolls inside the pinned layout (.auth-main > div), so its buttons stick
   to its bottom edge - always reachable - with a fade above them while there's more below
   (.onb-more, toggled by onboarding.js). */
@media (min-width: 861px) {
  /* bottom/padding/margin of -34px/34px: the card's own bottom padding, so the bar covers it too. */
  .onboard-card .onb-actions { position: sticky; bottom: -34px; z-index: 2; padding: 14px 0 34px; margin-bottom: -34px; background: var(--hero); }
  .onboard-card .onb-actions::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 32px; background: linear-gradient(to bottom, transparent, var(--hero)); pointer-events: none; opacity: 0; transition: opacity .15s; }
  .onboard-card.onb-more .onb-actions::before { opacity: 1; }
}
.onb-skip { font-size: 13.5px; font-weight: 600; color: var(--fg-dim); text-decoration: none; }
@media (hover: hover) { .onb-skip:hover { color: var(--fg); } }
.onb-ok { margin: 4px 0 0; padding: 10px 14px; border-radius: 12px; background: var(--go-bg); color: var(--go); font-weight: 600; font-size: 13.5px; }
.onb-ok[hidden], .onb-install [hidden] { display: none; }
.onb-note { margin: 16px 0 0; font-size: 12.5px; }
.onb-sources { display: flex; flex-direction: column; gap: 10px; }
.onb-source { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.onb-source > span:nth-child(2) { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.onb-source strong { font-size: 14.5px; color: var(--fg); }
.onb-source small { font-size: 12.5px; color: var(--fg-dim); }
.onb-source.soon { background: transparent; border-style: dashed; }
.onb-source.soon .onb-source-logo { opacity: .55; filter: grayscale(.4); }
.onb-soon { flex-shrink: 0; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; padding: 4px 10px; border-radius: 999px; background: var(--bg-sink); color: var(--fg-dim); }
.onb-source-logo { width: 34px; height: 34px; flex-shrink: 0; border-radius: 9px; background: center / cover no-repeat; }
.onb-link { margin: 0; width: auto; flex-shrink: 0; padding: 8px 14px; border-radius: 999px; border: 1px solid var(--signal); background: transparent; color: var(--signal-text); font-family: var(--font-body); font-size: 13px; font-weight: 700; text-decoration: none; cursor: pointer; }
@media (hover: hover) { .onb-link:hover { background: var(--signal); color: var(--signal-ink); } }
.onb-linked { flex-shrink: 0; font-size: 13px; font-weight: 700; color: var(--go); }
.onb-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 4px; }
.onb-chip { margin: 0; width: auto; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--line); background: var(--bg-raise); color: var(--fg); font-family: var(--font-body); font-size: 12.5px; font-weight: 600; text-transform: none; letter-spacing: 0; cursor: pointer; }
@media (hover: hover) { .onb-chip:hover { border-color: var(--signal); background: var(--bg-raise); color: var(--fg); } }
.onb-label-top { margin-top: 16px; }
.onb-goals { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.onb-goal { position: relative; display: flex; align-items: center; margin: 0; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--line); background: var(--bg-raise); cursor: pointer; text-transform: none; letter-spacing: 0; }
.onb-goal input { position: absolute; opacity: 0; pointer-events: none; }
.onb-goal strong { font-size: 13.5px; color: var(--fg); }
.onb-goal.active, .onb-goal:has(input:checked) { border-color: var(--signal); background: var(--signal-soft); }
.onb-goal:has(input:focus-visible) { outline: 2px solid var(--signal); outline-offset: 2px; }
.onb-install { display: flex; flex-direction: column; gap: 8px; }
.onb-install-hint { margin: 0; padding: 12px 14px; border-radius: 12px; background: var(--bg-raise); font-size: 13.5px; line-height: 1.5; color: var(--fg); }
.onb-push { margin-top: 14px; }
.onb-push .content-card { margin: 0; padding: 14px; border-radius: 14px; background: var(--bg-raise); border: 1px solid var(--card-line); box-shadow: none; }
.onb-push .btn { margin-top: 0; width: auto; border-radius: 999px; }
/* Phone: the step list becomes a horizontal timeline across the band - numbered dots joined
   by a line, each step's name under its dot, done ones checked, the current one white. */
@media (max-width: 860px) {
  .onb-pitch h2 { font-size: 22px; }
  .onb-intro { margin: 0 0 16px; }
  .onb-steps { flex-direction: row; gap: 0; max-width: none; }
  .auth-pitch .onb-steps li { position: relative; flex: 1 1 0; min-width: 0; padding: 0; border-left: none; }
  .onb-steps li + li::before {
    content: ""; position: absolute; top: 15px; right: 50%; width: 100%; height: 2px;
    background: rgba(255, 255, 255, 0.3); z-index: 0;
  }
  .onb-steps li.done + li::before, .onb-steps li.done + li.current::before { background: rgba(255, 255, 255, 0.75); }
  .onb-steps a { position: relative; z-index: 1; flex-direction: column; gap: 6px; padding: 0 2px; border-radius: 0; text-align: center; }
  .onb-steps li.current a { background: none; }
  .onb-num { width: 32px; height: 32px; background: var(--band); }
  .onb-steps li.done .onb-num { background: color-mix(in srgb, #fff 30%, var(--band)); }
  .auth-pitch .onb-steps li strong { font-size: 11px; font-weight: 600; line-height: 1.25; color: var(--band-dim); }
  .auth-pitch .onb-steps li.current strong { font-weight: 700; color: var(--band-ink); }
  .onb-steps small { display: none; }
}
/* Home: "Termine ta configuration" (views/home.html). */
.home-onb { margin-top: 20px; padding: 20px 22px; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--signal); }
.home-onb-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.home-onb h2 { margin: 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.home-onb-actions { display: flex; align-items: center; gap: 10px; }
.home-onb-actions form { margin: 0; }
.home-onb-actions .btn { margin: 0; width: auto; padding: 9px 18px; border-radius: 999px; }
.home-onb-hide { margin: 0; width: auto; padding: 0; border: none; background: none; color: var(--fg-dim); font-family: var(--font-body); font-size: 13px; font-weight: 600; cursor: pointer; }
@media (hover: hover) { .home-onb-hide:hover { background: none; color: var(--fg); } }
.home-onb-bar { height: 6px; margin: 14px 0 12px; border-radius: 3px; background: var(--line); overflow: hidden; }
.home-onb-bar i { display: block; height: 100%; background: var(--signal); }
.home-onb-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.home-onb-steps a { display: inline-block; padding: 6px 12px; border-radius: 999px; background: var(--bg); border: 1px solid var(--line); color: var(--fg); font-size: 12.5px; font-weight: 600; text-decoration: none; }
.home-onb-steps li.done a { background: var(--go-bg); border-color: transparent; color: var(--go); }
.onb-source-logo.strava { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23fc4c02%22/%3E%3Cg transform=%22translate(4.2 4) scale(0.66)%22%3E%3Cpath fill=%22%23fff%22 d=%22M15.387 17.944l-2.089-4.116h-3.065L15.387 24l5.15-10.172h-3.066m-7.008-5.599l2.836 5.598h4.172L10.463 0l-7 13.828h4.169%22/%3E%3C/g%3E%3C/svg%3E"); }
.onb-source-logo.capture { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 133.00 134.00%22%3E%3Cdefs/%3E%3Cpath fill=%22%23000000%22 stroke=%22%23000000%22 fill-opacity=%221%22 stroke-width=%221%22 stroke-opacity=%221%22 title=%22Rectangle 2%22 d=%22M1.0027 1.0044C1.0027 1.0044 1.0027 1.0044 1.0027 1.0044H132.0027C132.0027 1.0044 132.0027 1.0044 132.0027 1.0044V133.0044C132.0027 133.0044 132.0027 133.0044 132.0027 133.0044H1.0027C1.0027 133.0044 1.0027 133.0044 1.0027 133.0044Z%22 id=%22tSvg88daaa8262%22/%3E%3Cpath fill=%22%23c8f135%22 stroke=%22%23c8f135%22 fill-opacity=%221%22 stroke-width=%221%22 stroke-opacity=%221%22 title=%22Path 4%22 d=%22M82.7322 96.25C82.7322 96.25 92.2411 86.25 92.2411 86.25C92.2411 86.25 92.2411 78.7422 92.2411 78.7422C92.2411 78.7422 106.7833 78.7422 106.7833 78.7422C106.7833 78.7422 106.7833 92.7257 106.7833 92.7257C106.7833 92.7257 89.25 110.2589 89.25 110.2589C89.25 110.2589 68.25 110.2589 68.25 110.2589C68.25 110.2589 68.25 96.25 68.25 96.25C68.25 96.25 82.7322 96.25 82.7322 96.25ZM44.4653 72.25C44.4653 72.25 44.4653 63.0663 44.4653 63.0663C44.4653 63.0663 50.2974 57.2341 50.2974 57.2341C50.2974 57.2341 50.2974 91.75 50.2974 91.75C50.2974 91.75 39.7299 91.75 39.7299 91.75C39.7299 91.75 39.7299 96.2429 39.7299 96.2429C39.7299 96.2429 64.3048 96.2429 64.3048 96.2429C64.3048 96.2429 64.3048 110.25 64.3048 110.25C64.3048 110.25 43.75 110.25 43.75 110.25C43.75 110.25 25.25 91.75 25.25 91.75C25.25 91.75 25.25 72.25 25.25 72.25C25.25 72.25 44.4653 72.25 44.4653 72.25ZM70.25 24.25C70.25 24.25 70.25 38.25 70.25 38.25C70.25 38.25 62.25 38.25 62.25 38.25C62.25 38.25 40.4641 60.0359 40.4641 60.0359C40.4641 60.0359 40.4641 65.8038 40.4641 65.8038C40.4641 65.8038 25.2206 65.8038 25.2206 65.8038C25.2206 65.8038 25.2206 54.6447 25.2206 54.6447C25.2206 54.6447 56.0232 24.25 56.0232 24.25C56.0232 24.25 70.25 24.25 70.25 24.25ZM74.25 23.75C74.25 23.75 106.7846 23.75 106.7846 23.75C106.7846 23.75 106.7846 54.765 106.7846 54.765C106.7846 54.765 92.1151 54.765 92.1151 54.765C92.1151 54.765 92.1151 38.2494 92.1151 38.2494C92.1151 38.2494 74.25 38.2494 74.25 38.2494C74.25 38.2494 74.25 23.75 74.25 23.75Z%22 id=%22tSvgc06d8e8417%22/%3E%3C/svg%3E"); }
.onb-form textarea {
  width: 100%; box-sizing: border-box; margin: 4px 0 0; padding: 12px 14px; border-radius: 12px; resize: vertical;
  background: var(--bg-sink); border: 1px solid var(--line); color: var(--fg); font-family: var(--font-body); font-size: 14px; line-height: 1.5;
}
.onb-form textarea:focus { outline: none; border-color: var(--signal); }
.onb-form textarea::placeholder { color: var(--fg-dim); }
.home-onb-actions .btn { font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }

/* The apps' own marks on the linking pages (the Garmin / Capture connector diagram, the
   legacy "Connecte tes données" options) - same inlined images as the Sources page. */
.brand-logo { background: center / cover no-repeat; color: transparent !important; font-size: 0 !important; border: none !important; overflow: hidden; }
.brand-logo.brand-garmin { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23000%22/%3E%3Csvg x=%224%22 y=%224%22 width=%2216%22 height=%2216%22 viewBox=%2219.35 8.2 3.4 3.4%22%3E%3Cpath fill=%22%2311a9ed%22 d=%22M6.265 12.024a.289.289 0 0 0-.236-.146h-.182a.289.289 0 0 0-.234.146l-1.449 3.025c-.041.079.004.138.094.138h.335c.132 0 .193-.061.228-.134.037-.073.116-.234.13-.266.02-.045.083-.071.175-.071h1.559c.089 0 .148.016.175.071.018.035.098.179.136.256a.24.24 0 0 0 .234.142h.486c.089 0 .13-.069.098-.132-.034-.061-1.549-3.029-1.549-3.029zm-.914 2.224c-.089 0-.132-.067-.094-.148l.571-1.222c.039-.081.1-.081.136 0l.555 1.222c.037.081-.006.148-.096.148H5.351zm12.105-2.201v3.001c0 .083.073.138.163.138h.396c.089 0 .163-.057.163-.146v-2.998c0-.089-.059-.163-.148-.163h-.411c-.09-.001-.163.054-.163.168zm-6.631 1.88c-.051-.073-.022-.154.063-.181 0 0 .342-.102.506-.25.165-.146.246-.36.246-.636a1 1 0 0 0-.096-.457.787.787 0 0 0-.27-.303 1.276 1.276 0 0 0-.423-.171c-.165-.035-.386-.047-.386-.047a8.81 8.81 0 0 0-.325-.008H8.495a.164.164 0 0 0-.163.163v2.998c0 .089.073.146.163.146h.388c.089 0 .163-.057.163-.146v-1.193s.002 0 .002-.002l.738-.002c.089 0 .205.061.258.134l.766 1.077c.071.096.138.132.228.132h.508c.089 0 .104-.085.073-.128-.032-.038-.794-1.126-.794-1.126zm-.311-.61a1.57 1.57 0 0 1-.213.028 8.807 8.807 0 0 1-.325.006h-.763a.164.164 0 0 1-.163-.163v-.608c0-.089.073-.163.163-.163h.762c.089 0 .236.004.325.006 0 0 .114.004.213.028a.629.629 0 0 1 .24.098.358.358 0 0 1 .126.148.473.473 0 0 1 0 .374.352.352 0 0 1-.126.148.617.617 0 0 1-.239.098zm11.803-1.439c-.089 0-.163.059-.163.146v1.919c0 .089-.051.11-.114.047l-1.921-1.992a.376.376 0 0 0-.276-.118h-.362c-.114 0-.163.061-.163.122v3.068c0 .061.059.12.148.12h.362c.089 0 .152-.049.152-.132l.002-2.021c0-.089.051-.11.114-.045l2.004 2.082a.36.36 0 0 0 .279.116h.272a.164.164 0 0 0 .163-.163v-2.986a.164.164 0 0 0-.163-.163h-.334zm-7.835 1.87c-.043.079-.116.077-.159 0l-.939-1.724a.262.262 0 0 0-.236-.146h-.51a.164.164 0 0 0-.163.163v2.996c0 .089.059.15.163.15h.317c.089 0 .154-.057.154-.142 0-.041.002-2.179.004-2.179.004 0 1.173 2.177 1.173 2.177a.105.105 0 0 0 .189 0s1.179-2.173 1.181-2.173c.004 0 .002 2.11.002 2.173 0 .087.069.142.159.142h.364c.089 0 .163-.045.163-.163V12.04a.164.164 0 0 0-.163-.163h-.488a.265.265 0 0 0-.244.142l-.967 1.729zM0 13.529c0 1.616 1.653 1.697 1.984 1.697 1.098 0 1.561-.297 1.58-.309a.29.29 0 0 0 .152-.264v-1.116a.186.186 0 0 0-.187-.187H2.151c-.104 0-.171.083-.171.187v.116c0 .104.067.187.171.187h.797a.14.14 0 0 1 .14.14v.52c-.157.065-.874.274-1.451.136-.836-.199-.901-.89-.901-1.096 0-.173.053-1.043 1.079-1.13.831-.071 1.378.264 1.384.268.098.051.199.014.254-.089l.104-.209c.043-.085.028-.175-.077-.246-.006-.004-.59-.319-1.494-.319C.055 11.813 0 13.354 0 13.529zm22.134-2.478h-2.165c-.079 0-.148-.039-.187-.108s-.039-.146 0-.215l1.084-1.874a.21.21 0 0 1 .187-.108.21.21 0 0 1 .187.108l1.084 1.874a.203.203 0 0 1 0 .215.22.22 0 0 1-.19.108zm1.488 3.447c.207 0 .378.169.378.378a.379.379 0 0 1-.378.378.379.379 0 0 1-.378-.378.38.38 0 0 1 .378-.378zm.002.7c.173 0 .305-.14.305-.321s-.13-.321-.305-.321-.307.14-.307.321c0 .18.13.321.307.321zm-.146-.543h.169c.102 0 .152.041.152.124 0 .071-.045.122-.114.122l.126.195h-.077l-.124-.195h-.061v.195h-.073v-.441h.002zm.073.189h.085c.055 0 .091-.012.091-.069 0-.051-.045-.065-.091-.065h-.085v.134z%22/%3E%3C/svg%3E%3C/svg%3E"); }
.brand-logo.brand-strava { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect width=%2224%22 height=%2224%22 rx=%225%22 fill=%22%23fc4c02%22/%3E%3Cg transform=%22translate(4.2 4) scale(0.66)%22%3E%3Cpath fill=%22%23fff%22 d=%22M15.387 17.944l-2.089-4.116h-3.065L15.387 24l5.15-10.172h-3.066m-7.008-5.599l2.836 5.598h4.172L10.463 0l-7 13.828h4.169%22/%3E%3C/g%3E%3C/svg%3E"); }
.brand-logo.brand-capture { background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 133.00 134.00%22%3E%3Cdefs/%3E%3Cpath fill=%22%23000000%22 stroke=%22%23000000%22 fill-opacity=%221%22 stroke-width=%221%22 stroke-opacity=%221%22 title=%22Rectangle 2%22 d=%22M1.0027 1.0044C1.0027 1.0044 1.0027 1.0044 1.0027 1.0044H132.0027C132.0027 1.0044 132.0027 1.0044 132.0027 1.0044V133.0044C132.0027 133.0044 132.0027 133.0044 132.0027 133.0044H1.0027C1.0027 133.0044 1.0027 133.0044 1.0027 133.0044Z%22 id=%22tSvg88daaa8262%22/%3E%3Cpath fill=%22%23c8f135%22 stroke=%22%23c8f135%22 fill-opacity=%221%22 stroke-width=%221%22 stroke-opacity=%221%22 title=%22Path 4%22 d=%22M82.7322 96.25C82.7322 96.25 92.2411 86.25 92.2411 86.25C92.2411 86.25 92.2411 78.7422 92.2411 78.7422C92.2411 78.7422 106.7833 78.7422 106.7833 78.7422C106.7833 78.7422 106.7833 92.7257 106.7833 92.7257C106.7833 92.7257 89.25 110.2589 89.25 110.2589C89.25 110.2589 68.25 110.2589 68.25 110.2589C68.25 110.2589 68.25 96.25 68.25 96.25C68.25 96.25 82.7322 96.25 82.7322 96.25ZM44.4653 72.25C44.4653 72.25 44.4653 63.0663 44.4653 63.0663C44.4653 63.0663 50.2974 57.2341 50.2974 57.2341C50.2974 57.2341 50.2974 91.75 50.2974 91.75C50.2974 91.75 39.7299 91.75 39.7299 91.75C39.7299 91.75 39.7299 96.2429 39.7299 96.2429C39.7299 96.2429 64.3048 96.2429 64.3048 96.2429C64.3048 96.2429 64.3048 110.25 64.3048 110.25C64.3048 110.25 43.75 110.25 43.75 110.25C43.75 110.25 25.25 91.75 25.25 91.75C25.25 91.75 25.25 72.25 25.25 72.25C25.25 72.25 44.4653 72.25 44.4653 72.25ZM70.25 24.25C70.25 24.25 70.25 38.25 70.25 38.25C70.25 38.25 62.25 38.25 62.25 38.25C62.25 38.25 40.4641 60.0359 40.4641 60.0359C40.4641 60.0359 40.4641 65.8038 40.4641 65.8038C40.4641 65.8038 25.2206 65.8038 25.2206 65.8038C25.2206 65.8038 25.2206 54.6447 25.2206 54.6447C25.2206 54.6447 56.0232 24.25 56.0232 24.25C56.0232 24.25 70.25 24.25 70.25 24.25ZM74.25 23.75C74.25 23.75 106.7846 23.75 106.7846 23.75C106.7846 23.75 106.7846 54.765 106.7846 54.765C106.7846 54.765 92.1151 54.765 92.1151 54.765C92.1151 54.765 92.1151 38.2494 92.1151 38.2494C92.1151 38.2494 74.25 38.2494 74.25 38.2494C74.25 38.2494 74.25 23.75 74.25 23.75Z%22 id=%22tSvgc06d8e8417%22/%3E%3C/svg%3E"); }

/* ---- Home "Programme" card (views/home_plan.html) ------------------------------------- */
.home-plan-card a.e-card-meta { font-weight: 700; color: var(--signal-text); text-decoration: none; }
.home-plan-goal { margin: 4px 0 0; font-size: 12.5px; color: var(--fg-dim); }
.home-plan-empty { margin: 10px 0 14px; }
.home-plan-next { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin-top: 14px; padding: 14px 16px; border-radius: 14px; background: var(--bg-raise); border: 1px solid var(--card-line); color: inherit; text-decoration: none; }
.home-plan-next.today { border-color: color-mix(in srgb, var(--signal) 55%, var(--card-line)); }
@media (hover: hover) { .home-plan-next:hover { border-color: var(--signal); } }
.home-plan-when { font-size: 12px; font-weight: 700; color: var(--fg-dim); }
.home-plan-next.today .home-plan-when { color: var(--signal-text); }
.home-plan-next .plan-discipline-badge { border-radius: 999px; font-family: var(--font-body); font-size: 10.5px; font-weight: 700; text-transform: none; letter-spacing: 0; padding: 2px 8px; }
.home-plan-title { font-family: var(--font-display); font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--fg); }
.home-plan-stats { font-size: 12.5px; font-weight: 600; color: var(--fg); }
.home-plan-detail { font-size: 12.5px; line-height: 1.45; color: var(--fg-dim); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }

/* ---- Selects: the native arrow sits flush against the right edge - replaced by a drawn
   chevron inset like the text. Last in the file, and only background-image/position/size
   (never the background shorthand), so it wins over each page's own select rule while
   keeping that rule's background color and padding. */
select:not([multiple]) {
  -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%239aa3b5' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; background-size: 12px 8px;
  padding-right: 38px; text-overflow: ellipsis;
  /* Without the native look, a select's line box is tighter than a text input's (42px vs
     45px side by side) - this evens them out. */
  line-height: 1.366;
}
/* Same for the date input, a couple px taller than its neighbours because of the padding
   Chrome/Safari put around its date text. */
input[type="date"]::-webkit-datetime-edit, input[type="date"]::-webkit-datetime-edit-fields-wrapper { padding: 0; }
:root[data-theme="light"] select:not([multiple]) {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23667085' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ---- Spacing scale, app-wide --------------------------------------------------------
   One rhythm for every dashboard page, measured across all of them: 20px between blocks
   (vertically and side by side) on desktop, 14px on a phone, 16px of padding inside a card
   on a phone. Last in the file so it settles the per-page rules above that had drifted
   (16px here, 18px there, 12px for the home shortcuts). */
.e-grid, .e-shortcuts, .perf-row, .mcp-grid, .acc-grid { gap: 20px; margin-top: 20px; }
.perf-top { gap: 20px; }
.sources-grid { gap: 20px; }
.src-grid { gap: 20px; }
.src-faq { padding: 22px; }
.e-grid > .content-card { padding: 22px; }
.nutri-day-card + .nutri-layout { margin-top: 20px; }
/* Sources: a card's button never touches the text above it once the cards stack (its
   margin-top: auto only adds room when a taller neighbour stretches the row). */
.src-page .source-card > p:has(+ .action) { margin-bottom: 16px; }
/* Habits: the title lines up with the first line of the summary next to it, not with the
   middle of that two-line block. */
.habit-card .habit-card-head { align-items: flex-start; }
.habit-card .habit-summary { margin: 0; }
/* Nutrition's weigh-in button, the pill every other form on the app uses. */
.nutrition-strip-weigh button { padding: 10px 16px; border-radius: 999px; font-family: var(--font-body); font-size: 13px; font-weight: 700; text-transform: none; letter-spacing: 0; }
@media (max-width: 720px) {
  /* The card overlapping the band used to stick out 4px past the cards below it (16px from
     the screen edge vs 20px) - now the same column as everything else. */
  .e-hero, .nutri-day-card, .act-tiles-card, .perf-top, .src-grid, .plan-overview-wrap { margin-left: 0; margin-right: 0; }
  .e-grid, .e-shortcuts, .perf-row, .mcp-grid, .acc-grid, .sources-grid, .src-grid, .perf-top { gap: 14px; }
  .e-grid, .e-shortcuts, .perf-row, .mcp-grid, .acc-grid, .nutri-day-card + .nutri-layout, .acc-danger, .plan-page .plan-list-card { margin-top: 14px; }
  .e-grid > .content-card, .acc-grid > .content-card, .mcp-grid .content-card, .src-faq { padding: 16px; }
}

/* Admin dashboard (views/admin.html, routes_admin.admin_page) - its own page, not the athlete
   shell: a top bar with section anchors, then cards. */
.adm-body { display: block; background: var(--bg); color: var(--fg); margin: 0; font-family: var(--font-body); }
.adm-main section { padding: 0; border: none; }
.adm-top {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
  padding: 14px 32px; background: var(--bg); border-bottom: 1px solid var(--line-soft);
}
.adm-top .wordmark { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-display); font-weight: 700; font-size: 18px; color: var(--fg); text-decoration: none; }
.adm-tag { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--signal-text); background: var(--signal-soft); padding: 2px 8px; border-radius: 999px; }
.adm-nav { display: flex; gap: 4px; flex: 1; flex-wrap: wrap; }
.adm-nav a, .adm-logout { color: var(--fg-dim); text-decoration: none; font-size: 13.5px; font-weight: 600; padding: 6px 10px; border-radius: 8px; }
@media (hover: hover) { .adm-nav a:hover, .adm-logout:hover { background: var(--bg-sink); color: var(--fg); } }
.adm-main { max-width: 1240px; margin: 0 auto; padding: 8px 32px 64px; }
.adm-main section { scroll-margin-top: 72px; }
.adm-h { display: flex; align-items: center; gap: 10px; margin: 36px 0 14px; font-family: var(--font-display); font-size: 21px; font-weight: 700; }
.adm-h small { font-family: var(--font-body); font-size: 13px; font-weight: 500; color: var(--fg-dim); }
.adm-count { font-family: var(--font-mono); font-size: 12px; font-weight: 600; color: var(--fg-dim); background: var(--bg-sink); padding: 2px 8px; border-radius: 999px; }
.adm-flash { margin: 20px 0 0; padding: 10px 14px; border-radius: 10px; font-size: 14px; }
.adm-flash.ok { background: var(--go-bg); color: var(--go); }
.adm-flash.err { background: var(--warn-bg); color: var(--warn); }
.adm-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.adm-tiles .e-tile { background: var(--bg-raise); border: 1px solid var(--card-line); border-radius: 16px; padding: 16px 18px; }
.adm-charts, .adm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: 14px; margin-top: 14px; align-items: start; }
.adm-card { background: var(--bg-raise); border: 1px solid var(--card-line); border-radius: 16px; padding: 18px 20px; }
.adm-card h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 14.5px; font-weight: 700; }
.adm-card .chat-chart { margin: 0; max-width: none; padding: 0; background: none; border: none; }
.adm-grid .adm-card { min-height: 100%; box-sizing: border-box; }
.adm-empty { color: var(--fg-dim); font-size: 13.5px; margin: 0; }
.adm-muted { color: var(--fg-dim); }
.adm-services { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: 10px 24px; }
.adm-services li { display: grid; grid-template-columns: 10px 1fr auto; align-items: center; gap: 2px 10px; font-size: 13.5px; }
.adm-services small { grid-column: 2 / -1; color: var(--fg-dim); font-size: 12px; }
.adm-dot { width: 9px; height: 9px; border-radius: 50%; }
.adm-dot.ok { background: var(--go); }
.adm-dot.ko { background: var(--warn); box-shadow: 0 0 0 4px var(--warn-bg); }
.adm-state { font-size: 12px; font-weight: 700; color: var(--fg-dim); }
.adm-issues { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.adm-issues li { display: flex; flex-direction: column; gap: 2px; font-size: 13.5px; }
.adm-issues small { color: var(--fg-dim); font-size: 12px; }
.adm-issues code { font-size: 11px; color: var(--fg-dim); background: var(--bg-sink); padding: 4px 6px; border-radius: 6px; white-space: pre-wrap; word-break: break-word; max-height: 60px; overflow: auto; }
.adm-filters { display: flex; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.adm-filters input, .adm-filters select { margin: 0; width: auto; flex: 1; min-width: 200px; max-width: 360px; }
.adm-filters select { flex: 0 1 220px; min-width: 160px; }
.adm-table-card { padding: 0; overflow-x: auto; }
.adm-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.adm-table th { text-align: left; font-size: 11.5px; font-weight: 700; color: var(--fg-dim); padding: 12px 14px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.adm-table th.sortable { cursor: pointer; user-select: none; }
.adm-table th.asc::after { content: " ↑"; } .adm-table th.desc::after { content: " ↓"; }
.adm-table td { padding: 11px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.adm-table tr:last-child td { border-bottom: none; }
.adm-table td small { display: block; color: var(--fg-dim); font-size: 12px; }
.adm-table tr[hidden] { display: none; }
.adm-src { display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 7px; margin: 1px 4px 1px 0; border-radius: 6px; background: var(--bg-sink); }
.adm-menu { position: relative; }
.adm-menu summary { list-style: none; cursor: pointer; padding: 4px 10px; border-radius: 8px; color: var(--fg-dim); letter-spacing: 2px; }
.adm-menu summary::-webkit-details-marker { display: none; }
@media (hover: hover) { .adm-menu summary:hover { background: var(--bg-sink); color: var(--fg); } }
/* position: fixed, placed by views/admin.html's script when opened: the table card scrolls
   horizontally (overflow-x), which would otherwise clip an absolutely positioned menu. */
.adm-menu-pop {
  position: fixed; z-index: 30; min-width: 210px; padding: 6px;
  background: var(--bg-raise); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 12px 32px rgba(0, 0, 0, .35);
}
.adm-menu-pop form { margin: 0; }
.adm-menu-pop button, .adm-link-btn {
  margin: 0; width: 100%; text-align: left; background: none; color: var(--fg); padding: 8px 10px; border-radius: 8px;
  font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: 0;
}
.adm-menu-pop button.danger, .adm-link-btn { color: var(--warn); }
.adm-link-btn { width: auto; padding: 4px 8px; }
@media (hover: hover) { .adm-menu-pop button:hover, .adm-link-btn:hover { background: var(--bg-sink); } }
.adm-usage { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.adm-usage li { display: grid; grid-template-columns: minmax(180px, 1.3fr) 2fr minmax(200px, 1.2fr); align-items: center; gap: 14px; font-size: 13.5px; }
.adm-usage-bar { height: 8px; border-radius: 999px; background: var(--bg-sink); overflow: hidden; }
.adm-usage-bar i { display: block; height: 100%; border-radius: 999px; background: var(--signal); }
.adm-usage-n { color: var(--fg-dim); font-size: 12.5px; }
.adm-usage-n strong { color: var(--fg); }
.adm-invite-form { display: flex; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.adm-invite-form input { margin: 0; flex: 1; min-width: 220px; }
.adm-invite-form button { margin: 0; width: auto; padding: 10px 18px; }
@media (max-width: 860px) {
  .adm-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .adm-usage li { grid-template-columns: 1fr; gap: 4px; }
}
@media (max-width: 560px) {
  .adm-top, .adm-main { padding-left: 16px; padding-right: 16px; }
  .adm-nav { order: 3; flex-basis: 100%; overflow-x: auto; flex-wrap: nowrap; }
}

/* "Forme basse ce matin" (components.adapt_card, routes_plan.today_adaptation). */
.adapt-card { margin: 18px 0 0; padding: 18px 20px; border-radius: 18px; background: var(--bg-raise); border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--card-line)); }
.adapt-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.adapt-head h2 { margin: 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.adapt-text { margin: 10px 0 0; font-size: 14px; color: var(--fg-dim); }
.adapt-text strong { color: var(--fg); }
.adapt-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.adapt-actions form { margin: 0; }
.adapt-btn { margin: 0; width: auto; padding: 9px 16px; border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }

.home-plan-race { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 6px 0 0; font-size: 13.5px; color: var(--fg-dim); }
.home-plan-race strong { color: var(--signal-text); font-family: var(--font-display); font-size: 16px; }
/* Target race card (views/plan.html, routes_plan.race_view, race_goal.py). */
.plan-race { margin: 18px 0 0; padding: 18px 20px; border-radius: 18px; background: var(--bg-raise); border: 1px solid var(--card-line); }
.plan-race-main { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.plan-race-count { display: flex; flex-direction: column; align-items: center; justify-content: center; min-width: 92px; padding: 12px 14px; border-radius: 16px; background: var(--signal); color: var(--signal-ink); }
.plan-race-count strong { font-family: var(--font-display); font-size: 28px; line-height: 1; }
.plan-race-count span { font-size: 12px; font-weight: 600; opacity: .85; margin-top: 4px; }
.plan-race-info { flex: 1; min-width: 200px; }
.plan-race-label { font-size: 12px; font-weight: 700; color: var(--fg-dim); }
.plan-race-info h2 { margin: 2px 0 0; font-family: var(--font-display); font-size: 20px; font-weight: 700; }
.plan-race-info p { margin: 4px 0 0; font-size: 13.5px; color: var(--fg-dim); }
.plan-race-pills { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.plan-race-note { font-size: 12.5px; color: var(--fg-dim); }
.plan-race-times { display: flex; gap: 18px; }
.plan-race-times div { display: flex; flex-direction: column; }
.plan-race-times span { font-size: 12px; font-weight: 600; color: var(--fg-dim); }
.plan-race-times strong { font-family: var(--font-display); font-size: 22px; }
.plan-race-edit { margin-top: 14px; }
.plan-race-main + .plan-race-edit { border-top: 1px solid var(--line-soft); padding-top: 12px; }
.plan-race-edit summary { cursor: pointer; font-size: 13.5px; font-weight: 700; color: var(--signal-text); }
.plan-race-edit .sub { margin: 8px 0 0; }
.plan-race-form { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 12px; align-items: end; }
.plan-race-form label { font-family: var(--font-body); font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--fg-dim); }
.plan-race-form input, .plan-race-form select { margin: 0; }
.plan-race-form-actions { grid-column: 1 / -1; display: flex; gap: 8px; }
.plan-race-form-actions .btn { margin: 0; width: auto; padding: 10px 18px; border-radius: 999px; font-family: var(--font-body); font-weight: 700; text-transform: none; letter-spacing: 0; }
@media (max-width: 720px) { .plan-race-form { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

/* In-app launch relay (templates.SPLASH_OVERLAY): on the first page of an installed-app launch
   (html.pwa-launch), the same screen as the system splash (static/splash/*.png, manifest's
   background_color) stays over the page until it has loaded, then fades - no white flash. */
.pwa-splash { display: none; }
.pwa-launch .pwa-splash {
  display: flex; position: fixed; inset: 0; z-index: 10000; flex-direction: column; align-items: center; justify-content: center;
  background: #132238 radial-gradient(circle at 50% 44%, rgba(59, 158, 255, .2) 0, rgba(59, 158, 255, 0) 42vmin);
  transition: opacity .45s ease;
}
.pwa-splash-logo { width: 30vmin; height: 30vmin; transition: transform .45s cubic-bezier(.34, 1.4, .64, 1); }
.pwa-splash-word { margin-top: 5vmin; font-family: var(--font-display); font-weight: 700; color: #fff; font-size: 11vmin; letter-spacing: -0.02em; line-height: 1; }
.pwa-splash-tag { position: absolute; bottom: 7vh; font-family: var(--font-body); font-weight: 500; color: rgba(255, 255, 255, .55); font-size: 3.6vmin; letter-spacing: .02em; }
.pwa-launch-out .pwa-splash { opacity: 0; pointer-events: none; }
.pwa-launch-out .pwa-splash-logo { transform: scale(1.12); }
@media (prefers-reduced-motion: reduce) { .pwa-launch .pwa-splash, .pwa-splash-logo { transition: none; } }
.adm-invited { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 12px; }
.adm-mail { font-weight: 700; color: var(--go); text-decoration: underline; }
.adm-invite-btn { color: var(--signal-text); }
