/* ═══════════════════════════════════════════════════════════════════
   IRONLOG DASHBOARD — dark theme, matches the member app.
   One token set drives every screen. Change a value here, it
   propagates everywhere. Plate colours carry MEANING, never decoration:
     --p10 green  = healthy / complete
     --p15 yellow = warning / needs attention
     --p25 red    = danger / churn
     --p20 blue   = the single action accent (buttons, active nav)
   ═══════════════════════════════════════════════════════════════════ */
@import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@500;600;700&family=Inter:wght@400;500;600&display=swap');

:root{
  --bg:#15171B; --surf:#1E2127; --surf-2:#191C21; --line:#2C313A;
  --text:#F1EFE9; --dim:#8A929E; --faint:#4A515C;
  --p25:#E03A3E; --p20:#2F6FE0; --p15:#F2C230; --p10:#22A45D;
  --r:12px; --r-sm:9px;
}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--text);font-family:'Inter',system-ui,sans-serif;
  font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased}
svg{fill:none;stroke:currentColor;stroke-width:1.8}
a{color:inherit;text-decoration:none}

/* ── shell ─────────────────────────────────────────────────────── */
.shell{display:flex;min-height:100vh}

/* ── sidebar ───────────────────────────────────────────────────── */
.side{width:220px;flex-shrink:0;background:#121418;border-right:1px solid var(--line);
  display:flex;flex-direction:column;padding:22px 14px;position:sticky;top:0;height:100vh}
.brand{display:flex;align-items:center;gap:10px;padding:4px 10px 24px}
.brand-logo{flex-shrink:0;display:block;width:32px;height:32px}
.brand-logo-lg{width:48px;height:48px}
.brand-text{display:flex;flex-direction:column;gap:1px;min-width:0}
.brand-mark{width:32px;height:32px;border-radius:var(--r-sm);background:var(--p20);color:#fff;
  display:flex;align-items:center;justify-content:center;
  font-family:'Barlow Condensed',sans-serif;font-weight:700;font-size:16px}
.brand-n{font-family:'Barlow Condensed',sans-serif;font-weight:700;font-size:19px;
  text-transform:uppercase;letter-spacing:.02em;line-height:1.1}
.brand-gym{font-family:'Inter',sans-serif;font-size:11px;font-weight:500;text-transform:none;
  letter-spacing:0;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nav{display:flex;flex-direction:column;gap:2px}
.nav-i{display:flex;align-items:center;gap:11px;padding:10px 12px;border-radius:var(--r-sm);
  font-size:14px;font-weight:500;color:var(--dim);cursor:pointer}
.nav-i svg{width:18px;height:18px}
.nav-i:hover{background:var(--surf);color:var(--text)}
.nav-i.on{background:rgba(47,111,224,.14);color:#fff}
.nav-i.on svg{color:var(--p20)}
.nav-sec{font-size:10px;text-transform:uppercase;letter-spacing:.13em;font-weight:600;
  color:var(--faint);padding:18px 12px 8px}
.side-foot{margin-top:auto;display:flex;align-items:center;gap:10px;padding:10px 12px;
  border-radius:var(--r-sm);background:var(--surf)}
.coach-av{width:30px;height:30px;border-radius:50%;flex-shrink:0;background:var(--p20);color:#fff;
  display:flex;align-items:center;justify-content:center;
  font-family:'Barlow Condensed',sans-serif;font-weight:600;font-size:13px}
.side-foot-n{font-weight:600;font-size:13px}
.side-foot-r{font-size:11px;color:var(--dim)}

/* ── main ──────────────────────────────────────────────────────── */
.main{flex:1;display:flex;flex-direction:column;min-width:0}
.top{display:flex;align-items:center;justify-content:space-between;padding:22px 28px}
.top-l h1{font-family:'Barlow Condensed',sans-serif;font-size:28px;font-weight:700;
  text-transform:uppercase;letter-spacing:-.01em;line-height:1}
.top-l p{font-size:13px;color:var(--dim);margin-top:3px}
.top-r{display:flex;gap:10px;align-items:center}
.content{padding:0 28px 28px;flex:1}

/* ── controls ──────────────────────────────────────────────────── */
/* Input chrome and the search affordance are separate on purpose: reusing
   `.search` for any old text field is what put a magnifier behind the
   password boxes. Use `.inp` for a plain field, `.inp.search` to search. */
.inp{height:38px;border-radius:var(--r-sm);padding:0 14px;font-size:13px;
  font-family:inherit;width:220px;background:var(--surf);
  border:1px solid var(--line);color:var(--text)}
.inp:focus{outline:none;border-color:var(--p20)}
.inp::placeholder{color:var(--faint)}
.search{padding-left:36px;background:var(--surf) no-repeat 12px center;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%234A515C' stroke-width='2'><circle cx='7' cy='7' r='5'/><path d='M15 15l-4-4'/></svg>")}
.btn{height:38px;padding:0 16px;border-radius:var(--r-sm);font-size:13px;font-weight:600;
  cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:7px;
  border:none;background:var(--p20);color:#fff}
.btn svg{width:15px;height:15px;stroke-width:2.2;stroke-linecap:round}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--text)}
.btn.ghost:hover{background:var(--surf)}

/* ── stat cards ────────────────────────────────────────────────── */
.stats{display:flex;gap:14px;margin-bottom:20px}
.stat{flex:1;background:var(--surf);border:1px solid var(--line);border-radius:var(--r);padding:16px 18px}
.stat-l{font-size:11px;text-transform:uppercase;letter-spacing:.09em;font-weight:600;color:var(--dim)}
.stat-v{font-family:'Barlow Condensed',sans-serif;font-size:32px;font-weight:700;
  font-variant-numeric:tabular-nums;line-height:1.1;margin-top:6px}
.stat-d{font-size:11px;color:var(--faint);margin-top:2px}
.stat.warn .stat-v{color:var(--p15)}

/* ── panel + table ─────────────────────────────────────────────── */
.panel{background:var(--surf);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
table{width:100%;border-collapse:collapse}
thead th{text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.1em;font-weight:600;
  color:var(--dim);padding:12px 16px;background:var(--surf-2);border-bottom:1px solid var(--line)}
tbody td{padding:13px 16px;font-size:13px;vertical-align:middle;border-bottom:1px solid var(--line)}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:rgba(255,255,255,.02)}

.m-cell{display:flex;align-items:center;gap:11px}
.m-av{width:34px;height:34px;border-radius:50%;flex-shrink:0;background:#2C313A;color:var(--text);
  display:flex;align-items:center;justify-content:center;
  font-family:'Barlow Condensed',sans-serif;font-weight:600;font-size:14px}
.m-n{font-weight:600}
.m-sub{font-size:11px;color:var(--dim)}
.prog-pill{font-size:11px;font-weight:600;padding:3px 9px;border-radius:6px;display:inline-block;
  background:rgba(47,111,224,.14);color:#7FA9EE}

.adh{display:flex;align-items:center;gap:9px}
.adh-bar{width:64px;height:6px;border-radius:3px;overflow:hidden;background:var(--line)}
.adh-fill{height:100%;border-radius:3px}
.adh-v{font-family:'Barlow Condensed',sans-serif;font-weight:600;font-size:14px;
  font-variant-numeric:tabular-nums;width:34px}
.spark{height:22px}
/* nowrap because a figure broken across two lines ("1,500" / "EGP", "50 / 1099")
   reads as two numbers — these cells are always short by construction. */
.last{font-variant-numeric:tabular-nums;color:var(--dim);white-space:nowrap}

.dot{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:500;
  white-space:nowrap}
.dot::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.st-active{color:var(--p10)}
.st-quiet{color:var(--p15)}
.st-gone{color:var(--p25)}

/* ── empty state ───────────────────────────────────────────────── */
.empty{text-align:center;padding:64px 24px;color:var(--dim)}
.empty svg{width:40px;height:40px;color:var(--faint);margin-bottom:14px}
.empty h3{font-family:'Barlow Condensed',sans-serif;font-size:20px;font-weight:600;
  text-transform:uppercase;color:var(--text);margin-bottom:6px}

/* ── responsive: collapse sidebar to icons ─────────────────────── */
@media(max-width:960px){
  .side{width:64px;padding:22px 8px}
  .brand-text,.nav-i span,.nav-sec,.side-foot div{display:none}
  .brand{justify-content:center;padding:4px 0 24px}
  .nav-i{justify-content:center;padding:11px}
  .side-foot{justify-content:center;background:none}
}

/* ── panel header (used by members list) ───────────────────────── */
.panel-h{display:flex;align-items:center;justify-content:space-between;
  padding:14px 16px;border-bottom:1px solid var(--line)}
.panel-t{font-family:'Barlow Condensed',sans-serif;font-size:16px;font-weight:600;
  text-transform:uppercase;letter-spacing:.02em}
.panel-h .btn.ghost{height:32px;padding:0 12px;font-size:12px}

/* AI-generated program pill uses yellow — Spotter's colour, not a coach's blue */
.pill{font-size:11px;font-weight:600;padding:3px 9px;border-radius:6px;display:inline-block;
  background:rgba(47,111,224,.14);color:#7FA9EE}
.pill.ai{background:rgba(242,194,48,.14);color:#F2C230}

.empty-t{font-family:'Barlow Condensed',sans-serif;font-size:20px;font-weight:600;
  text-transform:uppercase;color:var(--text);margin-bottom:6px}

/* ── chat transcripts (platform admin) ─────────────────────────────
   A transcript is read, not skimmed, so the column is capped at a
   comfortable measure instead of stretching to a 1900px monitor. */
.chat-log{padding:14px 16px 18px;max-width:760px}
.chat-row{display:flex;margin-bottom:10px}
.chat-row.me{justify-content:flex-end}
.chat-b{max-width:78%;padding:8px 12px;border-radius:var(--r-sm);font-size:13px;line-height:1.5;
  /* pre-line, not pre-wrap: keeps the model's paragraph breaks without
     preserving the template's own indentation as dead space. */
  white-space:pre-line;background:var(--surf-2);border:1px solid var(--line);color:var(--text)}
.chat-row.me .chat-b{background:var(--p20);border-color:transparent;color:#fff}
.chat-meta{display:block;margin-top:4px;font-size:10.5px;letter-spacing:.02em;opacity:.6;
  font-variant-numeric:tabular-nums}
.chat-toggle{cursor:pointer;padding:10px 16px;font-size:12px;color:var(--dim);
  border-bottom:1px solid var(--line);user-select:none}
.chat-toggle:hover{color:var(--text)}
details[open] .chat-toggle{border-bottom-color:var(--line)}

/* ── login page ────────────────────────────────────────────────── */
.login-page{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}
.login-wrap{width:100%;max-width:420px}
.login-panel{background:var(--surf);border:1px solid var(--line);border-radius:var(--r);padding:28px 28px 24px}
.login-header{display:flex;flex-direction:column;align-items:center;gap:12px;padding-bottom:22px;
  margin-bottom:22px;border-bottom:1px solid var(--line)}
.login-logo-frame{width:96px;height:96px;border:1px solid var(--line);border-radius:var(--r);
  display:flex;align-items:center;justify-content:center;background:var(--bg)}
.login-logo{display:block;width:72px;height:72px}
.login-wordmark{font-family:'Barlow Condensed',sans-serif;font-size:30px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;line-height:1}
.login-panel h1{font-family:'Barlow Condensed',sans-serif;font-size:26px;font-weight:700;
  text-transform:uppercase;margin-bottom:6px}
.login-sub{font-size:13px;color:var(--dim);margin-bottom:20px}
.login-panel label{display:block;margin-bottom:6px;font-size:11px;text-transform:uppercase;
  letter-spacing:.08em;color:var(--dim)}
.login-panel input{width:100%;height:42px;border-radius:var(--r-sm);padding:0 14px;margin-bottom:14px;
  font-family:inherit;font-size:14px;background:var(--surf-2);border:1px solid var(--line);color:var(--text)}
.login-btn{width:100%;justify-content:center;margin-top:4px}
.login-error{color:var(--p25);font-size:13px;margin-bottom:12px}

.side-foot-out{margin-left:auto}
.side-foot-out button{height:32px;padding:0 10px;font-size:11px}

/* ── platform admin ────────────────────────────────────────────── */
.row-form{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.row-form + .row-form{margin-top:8px}
.row-form label{flex-shrink:0;min-width:96px}
.row-form .btn{height:32px;padding:0 12px;font-size:12px}
tbody td .row-form .search{margin:0}

/* Whole-row link. One stretched anchor per row rather than a link in every
   cell: same click target, one tab stop instead of six. The row is the
   containing block, so it needs position:relative. */
.tr-link{position:relative;cursor:pointer}
.tr-link:hover{background:rgba(47,111,224,.07)}
.tr-link .stretch{position:absolute;inset:0}
.tr-link:focus-within{outline:1px solid var(--p20);outline-offset:-1px}
.chev{color:var(--faint);font-size:16px;line-height:1}
.tr-link:hover .chev{color:var(--p20)}
.chev-cell{text-align:right;width:32px}

/* Panels side by side on a wide screen, stacked on a narrow one. */
.cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));
  gap:14px;margin-bottom:20px;align-items:start}
.pad{padding:16px}
.pad p{color:var(--dim)}
.mb{margin-bottom:20px}

/* Two-column key/value table inside a panel — the label column is fixed so
   several of these stacked in a grid stay aligned with each other. */
.kv td:first-child{width:44%;color:var(--dim)}
.kv td{padding:10px 16px}
/* "we don't have this" — never a zero, which would read as a real figure. */
.miss{color:var(--faint);font-style:italic}
.yes{color:var(--p10)}
.no{color:var(--faint)}

/* Volume bar — reuses the adherence bar's shape, wider measure. */
.vol-bar{width:120px;height:6px;border-radius:3px;overflow:hidden;background:var(--line)}
.vol-fill{height:100%;border-radius:3px;background:var(--p20)}

/* A token count is six or seven digits; the adherence bar's 34px number
   column was sized for "87%". */
.adh-v.wide{width:auto;min-width:58px}

/* ── bar chart (platform report) ─────────────────────────────────
   There is no JS charting library on the Django side and there isn't going
   to be one: six months of a single series is a flex row of divs, and the
   heights arrive pre-computed from platform_services._chart(). Same spirit
   as _sparkline.html, which does the line version in hand-rolled SVG. */
.bars{display:flex;align-items:flex-end;gap:10px;padding:18px 16px}
.bar{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:6px}
.bar-track{width:100%;height:96px;display:flex;align-items:flex-end;overflow:hidden;
  background:var(--surf-2);border:1px solid var(--line);border-radius:var(--r-sm)}
.bar-fill{width:100%;min-height:2px;border-radius:var(--r-sm) var(--r-sm) 0 0}
.bar-v{font-family:'Barlow Condensed',sans-serif;font-weight:600;font-size:14px;
  font-variant-numeric:tabular-nums}
.bar-x{font-size:10px;text-transform:uppercase;letter-spacing:.09em;color:var(--dim)}

/* An explanatory line inside a panel — a missing price or a caveat on a
   figure. Yellow because it's a gap in what we know, not an error. */
.note{margin:14px 16px;padding:11px 13px;border-radius:var(--r-sm);font-size:12.5px;
  background:rgba(242,194,48,.09);border:1px solid rgba(242,194,48,.32)}
.note code{font-size:12px;color:var(--p15)}
.note.quiet{background:none;border-color:var(--line);color:var(--dim)}
/* Same shape, the other two meanings. Red is "you have to fix this", green is
   "it saved" — the plate code, so a coach reads the colour before the words. */
.note.bad{background:rgba(224,58,62,.09);border-color:rgba(224,58,62,.34);color:var(--text)}
.note.ok{background:rgba(34,164,93,.09);border-color:rgba(34,164,93,.32);color:var(--text)}
.note ul{margin:2px 0 0 16px}

/* ── authoring (coach writes a program or a diet plan) ────────────
   The one place in this dashboard with a form bigger than a single row, so
   the one place needing layout beyond .row-form. Still no JavaScript: every
   control here is a plain input or a named submit button. */
.fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:12px 14px;padding:16px}
.fields.tight{grid-template-columns:repeat(auto-fit,minmax(120px,1fr))}
.field{display:flex;flex-direction:column;gap:5px;min-width:0}
.field.wide{grid-column:1/-1}
.field label{font-size:10px;text-transform:uppercase;letter-spacing:.09em;font-weight:600;
  color:var(--dim)}
.field .hint{font-size:11px;color:var(--faint)}
/* .inp is fixed at 220px for the search boxes it was written for; inside a
   grid cell the cell is already the measure. */
.field .inp,.field select,.field textarea{width:100%}
select.inp{padding:0 10px;appearance:none;
  background:var(--surf) no-repeat right 10px center;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='7' fill='none' stroke='%238A929E' stroke-width='1.6'><path d='M1 1l4 4 4-4'/></svg>")}
textarea.inp{height:auto;min-height:76px;padding:10px 13px;line-height:1.55;resize:vertical}
.act{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:14px 16px;
  border-top:1px solid var(--line)}
.act .spacer{margin-left:auto}
.btn.danger{background:transparent;border:1px solid rgba(224,58,62,.4);color:var(--p25)}
.btn.danger:hover{background:rgba(224,58,62,.1)}
.btn.sm{height:30px;padding:0 10px;font-size:11.5px}

/* Editor beside its exercise picker. Two independent columns rather than
   .cols' equal fit: the set grid needs the room and the picker is a list of
   short names. Stacks under 1100px, where 300px of picker starts to squeeze
   the weight/reps cells. */
.author{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:14px;align-items:start}
@media(max-width:1100px){.author{grid-template-columns:minmax(0,1fr)}}

/* One exercise, or one meal — same card, since both are "a heading, some
   numbers, and buttons that change the list". */
.ex{border-bottom:1px solid var(--line)}
.ex:last-child{border-bottom:none}
.ex-h{display:flex;align-items:center;gap:10px;padding:12px 16px 10px}
.ex-n{font-weight:600;font-size:13.5px}
.ex-i{font-family:'Barlow Condensed',sans-serif;font-weight:700;font-size:15px;color:var(--faint);
  font-variant-numeric:tabular-nums;width:20px;flex-shrink:0}
.ex-sub{font-size:11px;color:var(--dim)}
.ex-acts{margin-left:auto;display:flex;gap:6px;flex-shrink:0}
.ex-body{padding:0 16px 14px}
.ex.bad{background:rgba(224,58,62,.05)}

/* The set grid. Fixed columns so set 1 and set 8 line up, tabular numbers so
   the digits do too — the same reason the member app sets font-variant-numeric
   on every number it prints. */
.setg{width:100%;border-collapse:collapse}
.setg th{text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.09em;
  font-weight:600;color:var(--dim);padding:0 8px 6px 0;background:none;border:none}
.setg td{padding:0 8px 6px 0;border:none;vertical-align:middle}
.setg .n{font-family:'Barlow Condensed',sans-serif;font-weight:700;font-size:14px;
  color:var(--dim);font-variant-numeric:tabular-nums;width:22px}
.setg .inp{height:32px;padding:0 9px;font-size:12.5px;font-variant-numeric:tabular-nums}
.setg td.x{width:28px;text-align:right;padding-right:0}
.setg .x .btn{height:28px;width:28px;padding:0;justify-content:center;font-size:15px;
  line-height:1;color:var(--dim)}
.setg .x .btn:hover{color:var(--p25);border-color:rgba(224,58,62,.4)}

/* Picker rows. A whole row is the button, because "add this exercise" is the
   only thing you can do to one. */
.pick{max-height:560px;overflow-y:auto}
.pick-i{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:9px 16px;
  background:none;border:none;border-bottom:1px solid var(--line);cursor:pointer;
  font-family:inherit;color:var(--text)}
.pick-i:hover{background:rgba(47,111,224,.07)}
.pick-i:disabled{cursor:default;opacity:.45}
.pick-i:disabled:hover{background:none}
.pick-n{font-size:13px;font-weight:500}
.pick-m{font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint)}
.pick-add{margin-left:auto;color:var(--p20);font-size:17px;line-height:1;flex-shrink:0}
.pick-i:disabled .pick-add{color:var(--p10);font-size:13px}

/* Targets beside what the meals actually come to. Reported, never enforced —
   see authoring/diet.py MacroCheck, and note the label is "so far", not a
   pass/fail. */
.tot{display:flex;gap:20px;flex-wrap:wrap;padding:12px 16px;border-top:1px solid var(--line);
  background:var(--surf-2)}
.tot-i{display:flex;flex-direction:column;gap:1px}
.tot-l{font-size:10px;text-transform:uppercase;letter-spacing:.09em;font-weight:600;color:var(--dim)}
.tot-v{font-family:'Barlow Condensed',sans-serif;font-weight:700;font-size:18px;
  font-variant-numeric:tabular-nums;line-height:1.1}
.tot-v.off{color:var(--p15)}
