/* Phone-first, dark theme (morning check-ins and evening BP happen in dim rooms). */
:root {
  --bg: #14171c;
  --panel: #1d222b;
  --border: #2c3442;
  --text: #dde3ec;
  --muted: #8b96a8;
  --accent: #4fa3ff;
  --link: #7cc0ff;
  --good: #45c98a;
  --warn: #e6b84c;
  --bad: #e2606c;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.5;
}

/* Links. There was no `a` rule at all, so every link on every page fell back to
   the UA's #0000EE / #551A8B against a dark panel — measured 1.70:1 unvisited
   and 1.45:1 visited, against WCAG AA's 4.5:1 floor. Reported from real use on
   the Workouts page: "blue on dark grey and very difficult to read."

   --link is deliberately lighter than --accent. Link text is body-sized and
   often sits in a dense list, so it targets AAA (8.24:1 on --panel, 9.27:1 on
   --bg) rather than --accent's AA-passing 6.09:1. --accent stays the fill,
   border and active-state colour, where it sits behind dark text or large
   shapes and is not doing this job.

   Kept deliberately low-specificity and placed early so every component rule
   below still wins: .tabbar a, .win-tabs a, .logout and .btn all set their own
   colour and must keep it. :visited must be restated or it reverts to purple. */
a { color: var(--link); }
a:visited { color: var(--link); }
a:hover, a:focus-visible { color: var(--text); }

header {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .6rem 1rem;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}
.brand { font-weight: 700; color: var(--accent); }
.logout { margin-left: auto; color: var(--muted); text-decoration: none; font-size: .9rem; }
.logout:hover { color: var(--text); }
main {
  max-width: 44rem;
  margin: 0 auto;
  padding: 1rem 1rem calc(4.8rem + env(safe-area-inset-bottom, 0));
}

/* Bottom tab bar (phone-native primary nav) */
.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  display: flex;
  background: var(--panel);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom, 0);
  z-index: 20;
}
.tabbar a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .1rem;
  padding: .5rem 0 .55rem;
  color: var(--muted);
  text-decoration: none;
  font-size: .7rem;
}
.app-icon { width: 1em; height: 1em; display: block; flex: 0 0 auto; }
.tabbar a .app-icon { font-size: 1.5rem; }
.tabbar a.active { color: var(--accent); }

/* Floating Coach button */
.fab {
  position: fixed;
  right: 1rem;
  bottom: calc(4.6rem + env(safe-area-inset-bottom, 0));
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: var(--accent);
  color: #06121f;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  box-shadow: 0 3px 14px rgba(0, 0, 0, .45);
  z-index: 21;
}
.fab .app-icon { font-size: 1.75rem; }
.fab:active { transform: scale(.95); }
h1 { font-size: 1.35rem; margin: .5rem 0 1rem; }
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem;
  margin-bottom: 1rem;
}
.card h2 { font-size: 1.02rem; margin: 0 0 .5rem; color: var(--muted); }
.stat { font-size: 1.6rem; font-weight: 700; }
.stat small { font-size: .9rem; font-weight: 400; color: var(--muted); }
.muted { color: var(--muted); }
.error { color: var(--bad); }
.success { color: var(--good); }
.inline-form { display: inline; }

/* Forms: big tap targets */
input[type=password], input[type=text], input[type=email], textarea, select {
  width: 100%;
  padding: .8rem;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 1rem;
}
button, .btn {
  display: inline-block;
  padding: .8rem 1.4rem;
  border-radius: 10px;
  border: none;
  background: var(--accent);
  color: #06121f;
  text-decoration: none;   /* .btn is often an <a>; the UA underline reads as broken on a filled button */
  font-size: 1.05rem;
  font-weight: 600;
  cursor: pointer;
}
button:active { transform: scale(.98); }

.consent {
  display: flex;
  gap: .6rem;
  align-items: flex-start;
  font-size: .85rem;
  color: var(--muted);
  line-height: 1.4;
}
.consent input[type=checkbox] { margin-top: .2rem; flex-shrink: 0; width: 1.1rem; height: 1.1rem; }

.token-box {
  font-family: monospace;
  font-size: .85rem;
  word-break: break-all;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .6rem;
}

.admin-actions { display: flex; flex-direction: column; gap: .4rem; align-items: flex-end; }
.admin-actions form { margin: 0; }

/* Today grid */
.grid2 { display: grid; grid-template-columns: 1fr; gap: 1rem; margin-bottom: 1rem; }
@media (min-width: 34rem) { .grid2 { grid-template-columns: 1fr 1fr; } }
.grid2 .card { margin-bottom: 0; }
.pills { display: flex; flex-wrap: wrap; gap: .4rem; }
.pill {
  background: var(--border);
  border-radius: 999px;
  padding: .15rem .7rem;
  font-size: .9rem;
}

/* Freshness */
table.freshness { width: 100%; border-collapse: collapse; }
table.freshness td { padding: .25rem 0; }
table.freshness td:last-child { text-align: right; }
.dot {
  display: inline-block;
  width: .65rem;
  height: .65rem;
  border-radius: 50%;
  margin-right: .55rem;
}
.dot.good { background: var(--good); }
.dot.warn { background: var(--warn); }
.dot.bad { background: var(--bad); }

/* Check-in sliders */
.checkin-form { display: grid; gap: 1rem; }
.slider-row label {
  display: flex;
  justify-content: space-between;
  font-weight: 600;
  margin-bottom: .2rem;
}
.slider-row output { color: var(--accent); font-weight: 700; }
input[type=range] { width: 100%; accent-color: var(--accent); height: 2rem; }
.range-ends {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: .8rem;
}

/* Trends */
.win-tabs { display: flex; gap: .4rem; align-items: center; margin-bottom: 1rem; }
.win-tabs a {
  color: var(--muted);
  text-decoration: none;
  padding: .3rem .8rem;
  border-radius: 999px;
  border: 1px solid var(--border);
}
.win-tabs a.active { color: var(--text); background: var(--border); }
.win-tabs .muted { margin-left: .5rem; font-size: .85rem; }
.chart-card { height: 300px; padding-bottom: 2.6rem; }
.chart-card canvas { max-height: 230px; }

/* Chart wrapper for cards with variable extra content (snapshot line, link) —
   card height is auto; only the chart area itself is a fixed-height box, as
   Chart.js's maintainAspectRatio:false needs a sized ancestor. */
.chart-wrap { position: relative; height: 210px; margin-top: .5rem; }

/* Whole-card tap target ("tap the card" instead of a link at the bottom).
   The stretched <a> is a DOM sibling of the card's other content — never a
   parent, since nothing inside a parent link could stay independently
   clickable. Elements that must keep their own separate destination (a
   delete button, a link to somewhere else) get position:relative so they
   paint above the overlay; everything else (title, snapshot text, the
   preview chart) intentionally falls through to the card-wide link. */
.card-tappable { position: relative; }
.card-tappable > .card-link { position: absolute; inset: 0; z-index: 1; border-radius: 12px; }
.card-tappable > .card-link:active { background: rgba(255, 255, 255, .03); }
.card-tappable .card-above { position: relative; z-index: 2; }
/* card_title()'s .tip (the ⓘ disclosure) needs the same lift as any other
   inner control, or tapping it navigates away instead of opening — but only
   the .tip itself, not its sibling <h2>. Lifting the whole .card-head
   container (title + tip together) was the first attempt and was wrong: it
   turned the title text into a dead zone that neither opened the tip nor
   fell through to the card-wide link, since a non-clickable h2 has nothing
   to catch the tap once it's floated above the overlay. */
.card-tappable .tip { position: relative; z-index: 2; }
.card-chevron { position: absolute; top: 1.1rem; right: 1rem; color: var(--muted); font-size: 1.1rem; }

/* Scroll landing targets for tappable cards that link to an anchor on
   another page (e.g. today.php's Sleep card -> vitals.php#sleep) — the
   sticky header would otherwise cover the top of the scrolled-to card, and
   nothing marks which card the eye should land on. */
[id].card { scroll-margin-top: 4rem; }
.card:target {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  animation: target-fade 1.6s ease-out forwards;
}
@keyframes target-fade {
  from { outline-color: var(--accent); }
  to { outline-color: transparent; }
}

/* The plan header on Workouts -- the card naming the current phase. Tinted so it
   reads as the page's identity rather than one more card in the stack.

   Deliberately NOT --accent: an accent border already means "today" (.day.today)
   and "proposal" (.card.proposal), and a left rule already means "changed"
   (.day.changed). Borrowing any of those would make an identity look like a
   status. The tint is --panel nudged toward the accent hue instead, which is new
   vocabulary rather than overloaded vocabulary.

   Contrast measured on #1b2532: --text 11.99:1, --muted 5.18:1 (the intent line
   is .muted, so it is the one that matters -- AA floor is 4.5:1).

   h2 goes to --text because .card h2 is --muted globally, which left the page's
   own title as the most washed-out text on it. */
.card.plan-header { background: #1b2532; border-color: #33465e; }
.card.plan-header h2 { color: var(--text); }

/* Workouts week grid. The 15rem minimum is load-bearing and measured, not taste:
   the old 8.5rem (136px) let auto-fit pack columns narrower than the content
   ever needed, at EVERY width. At 375px that gave two 167px cards wrapping 15 of
   16 exercise lines -- "DB floor press 3 x 10 @ 40 lb - 90s rest - Watch for
   pinching/sharp pain" broke into NINE lines, worst precisely where the safety
   caveat is. Desktop was worse, not better: 900px packed FOUR 161px columns,
   wrapping 16 of 16, worst 10 lines.

   At 15rem the grid only forms a column when it can afford one -- 375px: 1 col
   (5 of 16 wrapping, and 115px SHORTER than the old two-column layout, 1695 vs
   1810, because wrapping cost more height than the second column saved);
   600px: 2 cols @ 279px; 900px+: 2 cols @ 331px, 5 of 16, worst 4. The desktop
   week block grows 813 -> 848px, an accepted trade for a third of the wrapping.
   No media query needed; do not lower the minimum to fit more columns. */
.week { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
        gap: .6rem; margin-bottom: 1rem; }
.week .day { background: var(--panel); border: 1px solid var(--border);
             border-radius: 10px; padding: .6rem; }
.week .day.today { border-color: var(--accent); }
.week .day.changed { border-left: 4px solid var(--warn); }
.week .dow { color: var(--muted); font-size: .8rem; }
.week .dtitle { font-weight: 600; margin: .15rem 0; }
.workout-day-title {
  position: relative;
  display: flex;
  align-items: center;
  gap: .3rem;
}
.workout-day-title-text { min-width: 0; }
.week .type-rest .dtitle, .week .type-active .dtitle { color: var(--muted); font-weight: 400; }
.plan-exercises { margin: .45rem 0 0; padding-left: 1.1rem; font-size: .9rem; }
.plan-exercises li { margin: .25rem 0; }
.plan-prescription li { line-height: 1.35; }
.plan-target { color: var(--muted); font-size: .86rem; }
/* Per-exercise coaching note. Full --text, not --muted: it carries caveats like
   "shoulder: stop if painful", which at --muted had the same 5.34:1 weight as
   the rest timing beside it. --text measures 12.37:1 on --panel. Amber/red were
   considered and rejected -- a training caveat is not an alert. */
.plan-note { margin-top: .15rem; font-size: .84rem; color: var(--text); }
.plan-note-short {
  display: flex;
  align-items: center;
  gap: .25rem;
}
.plan-note-tip { flex: 0 0 auto; }
.plan-total { margin-top: .35rem; }
.plan-intervals {
  margin: .35rem 0 0;
  padding-left: 1.1rem;
  color: var(--muted);
  font-size: .88rem;
}
.plan-intervals li { margin: .2rem 0; line-height: 1.35; }
.btn.small { padding: .35rem .9rem; font-size: .9rem; margin-top: .4rem; }
table.sessions { width: 100%; border-collapse: collapse; }
table.sessions td { padding: .35rem .4rem .35rem 0; vertical-align: top; }
.pill.st-completed { background: #1f4635; color: var(--good); }
.pill.st-partial { background: #4a3c1c; color: var(--warn); }
.pill.st-skipped { background: #4a2328; color: var(--bad); }
.workout-state {
  display: inline-block;
  margin-top: .4rem;
  padding: .25rem .55rem;
  border-radius: 999px;
  font-size: .82rem;
  font-weight: 700;
}
.workout-state.st-completed { background: #1f4635; color: var(--good); }
.workout-state.st-in-progress { background: #4a3c1c; color: var(--warn); }
.workout-state.st-ended-early { background: #4a3c1c; color: var(--warn); }
.workout-state.st-skipped { background: #4a2328; color: var(--bad); }

/* Workout player */
.player { text-align: center; padding: 1rem 1rem 2rem; }
.player p { margin: .45rem 0; }
.player .exname { font-size: 1.6rem; margin: .3rem 0; }
.player .target { color: var(--muted); font-size: 1.1rem; }
.setgrid { display: flex; gap: .8rem; justify-content: center; margin: .65rem 0; }
.setgrid label { display: block; text-align: left; color: var(--muted); max-width: 9rem; }
.setgrid input { width: 100%; font-size: 1.4rem; text-align: center; }
.timed-set {
  display: grid;
  gap: .55rem;
  justify-items: center;
}
.timer-controls {
  display: flex;
  gap: .55rem;
  justify-content: center;
  width: 100%;
}
.timer-controls .btn { margin-top: 0; padding: .65rem 1rem; font-size: 1rem; }
button.big { width: 100%; max-width: 24rem; padding: 1rem; font-size: 1.2rem; margin-top: .35rem; }
.timer { font-size: 4.5rem; font-weight: 700; color: var(--accent); margin: 1rem 0; }
.set-timer { margin: 0; line-height: 1; }
.side-status { margin: 0; color: var(--text); font-weight: 700; }
.player input[type=range] { max-width: 24rem; }
.player-guide { margin: .7rem auto 0; max-width: 28rem; text-align: left; }
.player-guide > summary {
  color: var(--link);
  cursor: pointer;
  text-align: center;
}
.player-guide[open] > summary { margin-bottom: .4rem; }
.exercise-blurb { margin: .35rem 0; color: var(--muted); font-size: .92rem; line-height: 1.45; }
.player-links {
  border-top: 0;
  margin-top: .5rem;
  padding-top: 0;
}
/* Exercise cards */
.letter-divider {
  color: var(--accent);
  font-size: .9rem;
  letter-spacing: .08em;
  margin: 1.1rem 0 .45rem;
}
.exercise-card h3 { color: var(--text); margin: 0 0 .45rem; font-size: 1.02rem; }
.exercise-card p { margin: .45rem 0; }
.exercise-note {
  display: grid;
  grid-template-columns: 1fr 2rem;
  gap: .6rem;
  align-items: start;
  background: rgba(89, 169, 255, .09);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  margin: .75rem 0 .45rem;
  padding: .65rem .55rem .65rem .75rem;
}
.exercise-note-label {
  color: var(--muted);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin-bottom: .2rem;
}
.exercise-note-text { font-size: .92rem; line-height: 1.45; color: var(--text); }
.exercise-note-dismiss { margin: 0; }
.exercise-note-dismiss button {
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  display: grid;
  place-items: center;
  padding: 0;
}
.exercise-note-dismiss .app-icon { font-size: 1rem; }
.exercise-links {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .6rem;
  border-top: 1px solid var(--border);
  margin-top: .8rem;
  padding-top: .8rem;
}
.exercise-links.single { grid-template-columns: 1fr; }
.exercise-link {
  display: block;
  text-align: center;
  text-decoration: none;
  padding: .65rem .7rem;
  border-radius: 10px;
  border: 1px solid var(--border);
  color: var(--text);
  background: var(--bg);
}
.exercise-link:active { transform: scale(.98); }
.exercise-guide-card h1 { margin-top: 0; }
.exercise-guide-detail h2 {
  color: var(--muted);
  font-size: .95rem;
  margin: 1rem 0 .45rem;
}
.exercise-guide-detail ol,
.exercise-guide-detail ul {
  margin: .35rem 0 0;
  padding-left: 1.25rem;
}
.exercise-guide-detail li { margin: .45rem 0; }

/* Readiness */
.readiness { border-left: 4px solid var(--border); }
.readiness.tier-push { border-left-color: var(--good); }
.readiness.tier-normal { border-left-color: var(--accent); }
.readiness.tier-easy { border-left-color: var(--warn); }
.readiness.tier-rest { border-left-color: var(--bad); }
.r-head { display: flex; gap: 1.2rem; align-items: center; margin-bottom: .8rem; }
.r-score { font-size: 3rem; font-weight: 800; line-height: 1; }
.r-score small { font-size: 1rem; color: var(--muted); font-weight: 400; }
.tier-pill { text-transform: uppercase; letter-spacing: .06em; font-weight: 700; }
.tier-push .tier-pill { background: #1f4635; color: var(--good); }
.tier-normal .tier-pill { background: #1c3a5e; color: var(--accent); }
.tier-easy .tier-pill { background: #4a3c1c; color: var(--warn); }
.tier-rest .tier-pill { background: #4a2328; color: var(--bad); }
.r-advice { margin: .3rem 0 0; }
.r-parts { display: grid; gap: .35rem; }
.r-part { display: grid; grid-template-columns: 6rem 1fr 2.2rem; gap: .6rem;
          align-items: center; font-size: .9rem; }
.r-part .bar { background: var(--bg); border-radius: 999px; height: .5rem; overflow: hidden; }
.r-part .bar div { background: var(--accent); height: 100%; border-radius: 999px; }

/* Metric explanations: a one-line gloss under a stat, and a tap-to-open
   disclosure for anything that needs more than a sentence. */
.metric-note { color: var(--muted); font-size: .82rem; margin: .4rem 0 0; line-height: 1.4; }
.explain { margin-top: .7rem; font-size: .85rem; }
.explain > summary {
  color: var(--muted); cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: .3rem;
}
.explain > summary::-webkit-details-marker { display: none; }
.explain > summary::before { content: "ⓘ"; font-style: normal; }
.explain > summary:hover { color: var(--text); }
.explain[open] > summary { color: var(--text); margin-bottom: .4rem; }
.explain .explain-body { color: var(--muted); line-height: 1.5; }
.explain .explain-body dl { display: grid; grid-template-columns: auto 1fr;
  gap: .15rem .6rem; margin: .4rem 0 0; }
.explain .explain-body dt { color: var(--text); white-space: nowrap; }
.explain .explain-body dd { margin: 0; }

/* Card title row with an optional ⓘ info tip. The tip body is anchored to
   the (relative) title row and spans its full width, so it can never spill
   past the card edge on a narrow phone; it overlays rather than reflows. */
.card-head { position: relative; display: flex; align-items: center;
  gap: .4rem; margin-bottom: .5rem; }
.card-head h2 { margin: 0; }
.tip { display: inline-flex; }
.tip > summary { list-style: none; cursor: pointer; color: var(--muted);
  line-height: 1; font-size: .95rem; }
.tip > summary::-webkit-details-marker { display: none; }
.tip > summary::after { content: "ⓘ"; }
.tip[open] > summary { color: var(--accent); }
.tip-body { position: absolute; top: 100%; left: 0; right: 0; z-index: 30;
  margin-top: .35rem; background: var(--bg); border: 1px solid var(--border);
  border-radius: 10px; padding: .6rem .75rem; box-shadow: 0 6px 20px rgba(0,0,0,.5);
  color: var(--muted); font-size: .82rem; line-height: 1.5; }

/* Coach chat */
.chat #thread { display: flex; flex-direction: column; gap: .6rem;
                max-height: 55vh; overflow-y: auto; margin-bottom: .8rem; }
.msg { padding: .6rem .9rem; border-radius: 12px; max-width: 85%;
       white-space: pre-wrap; overflow-wrap: break-word; }
.msg.me { align-self: flex-end; background: #1c3a5e; }
.msg.coach { align-self: flex-start; background: var(--border); }
.msg.pending { color: var(--muted); font-style: italic; }
.msg.md { white-space: normal; }
.msg.md ul, .msg.md ol { margin: .35rem 0; padding-left: 1.35rem; }
.msg.md li { margin: .15rem 0; }
.msg.md code { padding: .1rem .25rem; border-radius: 4px; background: var(--bg); }
.msg-h { margin: .2rem 0 .35rem; font-size: 1rem; }
.composer { display: flex; gap: .6rem; }
.composer textarea { flex: 1; resize: none; }
.composer button { align-self: flex-end; }
.chat-actions { margin: .6rem 0 0; font-size: .85rem; }
.memlist { list-style: none; padding: 0; margin: 0; display: grid; gap: .5rem; }
.memlist .pill { margin-right: .4rem; }
.memlist .forget { margin-left: .4rem; font-size: .85rem; }

/* Coach plan proposal */
.card.proposal { border: 1px solid var(--accent); }
.proposal-actions { display: flex; gap: .6rem; margin: .6rem 0; flex-wrap: wrap; }
.proposal-changes { margin: .6rem 0 .3rem; }
.proposal-note { margin: .4rem 0 .6rem; }
.proposal-grid { margin-top: .6rem; }
.btn-ghost {
  background: transparent; color: var(--muted);
  border: 1px solid var(--border);
}

/* Labs */
table.labs { width: 100%; border-collapse: collapse; }
table.labs td { padding: .4rem .5rem .4rem 0; border-bottom: 1px solid var(--border); vertical-align: top; }
table.labs td:nth-child(2) { white-space: nowrap; }
.flag {
  display: inline-block; background: #4a2328; color: var(--bad);
  border-radius: 4px; padding: 0 .35rem; font-size: .8rem; font-weight: 700;
}
table.labs td.lab-flag strong { color: var(--warn); }

/* BP protocol grid */
table.bp-grid { width: 100%; border-collapse: collapse; text-align: center; }
table.bp-grid th, table.bp-grid td {
  padding: .4rem .2rem; border: 1px solid var(--border); font-size: .95rem;
}
table.bp-grid th:first-child, table.bp-grid td:first-child {
  text-align: left; color: var(--muted); width: 3rem;
}
table.bp-grid td.hit { color: var(--good); font-weight: 700; }
table.bp-grid td.miss { color: var(--border); }

/* Login */
.login-wrap { max-width: 22rem; margin: 18vh auto 0; padding: 0 1rem; }
.login-wrap h1 { text-align: center; }
.login-wrap form { display: grid; gap: .8rem; }
