:root{
  --bg:#121214;
  --surface:#1B1B1F;
  --surface2:#232328;
  --surface3:#2A2A31;
  --border:#2E2E34;
  --text:#F1F0EC;
  --text-dim:#8C8B92;
  --text-faint:#5C5B62;
  --accent:#FF5A36;
  --accent-dim:#7A2D1B;
  --accent-soft:rgba(255,90,54,0.14);
  --good:#7CD992;
  --fail:#FF4368;
  --radius:14px;
}
*{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
html,body{margin:0;padding:0;}
body{
  background:var(--bg);
  color:var(--text);
  font-family:'Inter',sans-serif;
  min-height:100vh;
  overflow-x:hidden;
  /* Clears the tab bar AND the floating + above it. At 88px the last thing on a scrolled page
     sat under the FAB — most visibly the "How'd I do?" button, an orange control with the orange
     + resting on it. The FAB's own bottom is 96px and it is 58px tall, so 160px clears both. */
  padding-bottom:160px;
  max-width: 600px;
  margin: 0 auto;
  position: relative;
}
.mono{font-family:'JetBrains Mono',monospace;}
.display{font-family:'Bebas Neue',sans-serif; letter-spacing:0.03em;}

/* subtle plate-texture backdrop on header */
header.top{
  padding:22px 18px 16px;
  position:sticky; top:0; z-index:20;
  background:linear-gradient(180deg, var(--bg) 60%, rgba(18,18,20,0.85));
  backdrop-filter:blur(6px);
  border-bottom:1px solid var(--border);
  display: flex; justify-content: space-between; align-items: center;
  max-width: 600px;
  margin: 0 auto;
}
.brand{
  display:flex; align-items:center; gap:10px;
}
.plate-mark{
  width:30px; height:30px; border-radius:50%;
  border:5px solid var(--accent);
  position:relative; flex-shrink:0;
}
.plate-mark::after{
  content:''; position:absolute; inset:0; margin:auto;
  width:6px; height:6px; border-radius:50%; background:var(--accent);
  top:0;bottom:0;left:0;right:0;
}
.brand h1{
  font-family:'Bebas Neue',sans-serif;
  font-size:30px; letter-spacing:0.06em; margin:0; line-height:1;
}
.brand small{display:block; color:var(--text-dim); font-size:11px; letter-spacing:0.08em; text-transform:uppercase; margin-top:2px;}

main{padding:16px; max-width:560px; margin:0 auto;}
.hidden{display:none !important;}

/* Tabs bottom nav */
nav.tabbar{
  position:fixed; bottom:0; left:0; right:0; z-index:30;
  display:flex; background:var(--surface);
  border-top:1px solid var(--border);
  padding:8px 8px calc(8px + env(safe-area-inset-bottom));
  max-width: 600px;
  margin: 0 auto;
}
nav.tabbar button{
  flex:1; background:none; border:none; color:var(--text-faint);
  display:flex; flex-direction:column; align-items:center; gap:4px;
  padding:8px 4px; font-family:'Inter',sans-serif; font-size:11px; font-weight:600;
  letter-spacing:0.04em; text-transform:uppercase; cursor:pointer;
}
nav.tabbar button svg{width:22px; height:22px; stroke:var(--text-faint); fill:none; stroke-width:2;}
nav.tabbar button.active{color:var(--accent);}
nav.tabbar button.active svg{stroke:var(--accent);}

/* **Log is now genuinely centred, and the trick that used to fake it is gone.**

   With four tabs it could not be: the third cell's centre sits right of the bar's centre whatever the
   widths, so Log was given a bigger flex and the other three were shrunk to `flex:0 1 auto` to drag it
   leftwards — which got it within a measured 17px and left the bar visibly lopsided. Adding Settings
   made it the third of FIVE, so equal cells put its centre exactly on the bar's, and every hack above
   could be deleted rather than tuned.

   All five keep `flex:1` (basis 0), so sizing Log's type up does not move it. Below about 340px its
   glyph does push its own cell a few pixels wider than the other four — flex items have `min-width:auto`
   and the icon is a floor — but that is symmetric about the middle cell, so **the centre stays the
   centre**: measured 0px at 320, 360, 390 and 430px. Equal widths were never the requirement; a
   centred third of an odd number is. */
nav.tabbar button{font-size:9.5px; gap:3px; padding:8px 4px; letter-spacing:0.03em;}
nav.tabbar button svg{width:20px; height:20px;}
/* Still the tab you stand on in a gym, so it keeps its pill and a larger glyph — emphasis now, rather
   than emphasis standing in for position. */
/* Still the tab you stand on in a gym, so it keeps its pill and a larger glyph — emphasis now, rather
   than emphasis standing in for position.

   Sized up again on the second look: at 11px against the others' 9.5px it read as "slightly wider
   padding" rather than as the focus of the bar. **Only type and glyph grow, never the cell.** Every
   tab is `flex:1` with a basis of 0, so the five widths stay identical and Log's centre stays exactly
   on the bar's — which is the property `markup.test.js` and a 0px measurement at six widths exist to
   protect. Growing the cell instead would buy emphasis by giving the centring back. */
nav.tabbar button[data-tab="today"]{
  margin:0 2px; font-size:13px; letter-spacing:0.07em; font-weight:700;
  background:var(--surface2); border-radius:16px; padding:7px 4px 8px;
}
nav.tabbar button[data-tab="today"] svg{width:29px; height:29px; stroke-width:2.5;}
nav.tabbar button[data-tab="today"].active{background:var(--accent-soft);}
/* Below this the five labels start to touch. Dropping a point of type is cheaper than truncating
   "Exercises" or hiding a label, and the icons carry the meaning at this size anyway. */
@media (max-width:359px){
  nav.tabbar button{font-size:8.5px; padding:8px 2px; letter-spacing:0.01em;}
  nav.tabbar button[data-tab="today"]{font-size:11.5px; margin:0 1px; letter-spacing:0.04em;}
  nav.tabbar button[data-tab="today"] svg{width:26px; height:26px;}
}

/* session card */
.session-head{
  display:flex; justify-content:space-between; align-items:flex-end; margin-bottom:14px;
}
.session-head h2{font-family:'Bebas Neue',sans-serif; font-size:34px; margin:0; letter-spacing:0.02em;}
.session-head .sub{color:var(--text-dim); font-size:13px; margin-top:2px;}
.loc-btn{
  background:var(--surface2); border:1px solid var(--border); color:var(--text);
  font-family:'Inter'; font-size:14.5px; padding:10px 14px; border-radius:10px; cursor:pointer;
  transition:all 0.15s; font-weight:500;
  display:flex; align-items:center; gap:6px;
}
.loc-btn svg{width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:2;}
.loc-btn:active{background:var(--border);}
.loc-btn.active{background:var(--accent-soft); color:var(--accent); border-color:var(--accent);}
/* Full-screen modal panel. Seven of these existed as identical inline styles; the only real
   differences were stacking order and, for one, the background. Override those inline. */
.modal-overlay{
  position:fixed; inset:0; left:0; right:0;
  max-width:600px; margin:0 auto;
  padding:20px; padding-top:calc(20px + env(safe-area-inset-top));
  overflow-y:auto;
  background:var(--surface); z-index:60;
}

/* The row every modal opens with: the Bebas headline, and the close button on the right.
   Fourteen copies of one inline style existed, and the gap under them had drifted to five
   different values — 6, 8, 16, 20 and 24px — so which modal you were in changed how far the
   title sat from its own content. The six newest all used 8, so 8 is what this is. */
.modal-head{display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;}
/* A title carrying a line of explanation aligns to the top of that pair, not to its middle. */
.modal-head.has-sub{align-items:flex-start;}
.modal-title{font-family:'Bebas Neue',sans-serif; font-size:32px; margin:0; letter-spacing:0.04em;}
.modal-sub{font-size:13px; color:var(--text-dim); margin:2px 0 0;}

.manage-loc-item{
  display:flex; justify-content:space-between; align-items:center; gap:10px;
  padding:12px; border-bottom:1px solid var(--border);
}
.manage-loc-item:last-child{border-bottom:none;}
.manage-loc-item .name{font-size:15px; font-weight:600; display:flex; align-items:center; gap:8px;}
.manage-loc-item .name svg{width:18px; height:18px; stroke:var(--text-faint); fill:none; stroke-width:2;}
.manage-loc-item .name.hidden-text{text-decoration:line-through; color:var(--text-faint);}

.icon-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(60px, 1fr)); gap:12px;
}
.icon-grid button{
  background:var(--surface2); border:1px solid var(--border); border-radius:12px;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  padding:16px 0; cursor:pointer; color:var(--text); transition:all 0.15s;
}
.icon-grid button svg{width:28px; height:28px; stroke:currentColor; fill:none; stroke-width:1.5;}
.icon-grid button:active{background:var(--border);}

.row-card{
  background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius);
  padding:13px 14px; margin-bottom:10px; display:flex; justify-content:space-between; gap:10px; align-items:flex-start;
}
.row-card .ex-name{font-weight:700; font-size:14.5px; margin-bottom:3px;}
.row-card .ex-detail{font-family:'JetBrains Mono',monospace; font-size:13px; color:var(--text-dim); line-height:1.5;}
.row-card .ex-detail .fail{color:var(--fail); font-weight:700;}
.row-actions{display:flex; gap:6px; flex-shrink:0;}
/* `padding:0` because these are real <button>s now, not divs: the row edit and delete were
   unreachable by keyboard and unannounced by a screen reader, and a button's default padding
   would otherwise squeeze the glyph inside the fixed 36px box. */
.icon-btn{
  background:var(--surface2); border:1px solid var(--border); color:var(--text-dim);
  width:36px; height:36px; border-radius:8px; display:flex; align-items:center; justify-content:center; cursor:pointer;
  padding:0;
}
.icon-btn svg{width:15px; height:15px; stroke:currentColor; fill:none; stroke-width:2;}
.icon-btn.danger:active{background:var(--fail); color:#fff; border-color:var(--fail);}

.empty-state{
  text-align:center; padding:50px 20px; color:var(--text-faint);
}
.empty-state .plate-mark{margin:0 auto 14px; width:44px; height:44px; border-width:7px; opacity:0.5;}
.empty-state p{font-size:14px; line-height:1.6; max-width:280px; margin:0 auto;}

.fab{
  position:fixed; right:calc(max(20px, 50% - 280px)); bottom:96px; z-index:25;
  width:58px; height:58px; border-radius:50%; background:var(--accent); border:none;
  display:flex; align-items:center; justify-content:center; box-shadow:0 8px 22px rgba(255,90,54,0.35);
  cursor:pointer;
}
.fab svg{width:28px; height:28px; fill:none;}
/* Not on Settings. "Add a set" is a fair action from Stats, History or Exercises — they are all views
   of training — but on Settings it is unrelated to everything on screen, and it was landing on top of
   a toggle row. It used to be hidden here by accident: Settings was a sheet, and the sheet's backdrop
   covered it. Making Settings a tab took that away, so the rule is stated instead.
   `:has()` is unsupported gracefully — the FAB simply stays, which is where it was. */
body:has(#tab-settings:not(.hidden)) .fab{display:none;}

/* History */
.hist-session{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  margin-bottom:12px; overflow:hidden;
}
.hist-session-head{
  padding:14px 16px; display:flex; justify-content:space-between; align-items:center; cursor:pointer;
}
.hist-session-head .d{font-weight:700; font-size:15px;}
.hist-session-head .l{color:var(--text-dim); font-size:13.5px; margin-top:2px;}
.hist-session-head .count{font-weight:600; font-size:15px; color:var(--text);}
.hist-session-head .chev{width:16px; height:16px; stroke:var(--text-faint); fill:none; stroke-width:2;}

/* Help. One modal, one section at a time, chosen by the strip at the top — and by which tab
   you opened it from. The `?` sits in each tab's own header. */
.help-btn{
  width:26px; height:26px; flex-shrink:0; border-radius:50%; cursor:pointer;
  background:transparent; border:1px solid var(--border); color:var(--text-faint);
  font-family:'Inter',sans-serif; font-size:13px; font-weight:700; line-height:1;
  display:flex; align-items:center; justify-content:center; padding:0;
}
.help-btn:active{background:var(--accent-soft); border-color:var(--accent); color:var(--accent);}
/* The title and the section strip stay put while the section scrolls under them. A long
   section used to mean scrolling back to the top to reach the other three. The negative
   margins cancel the modal's own padding so the bar covers the full width as it sticks. */
/* **The container must have NO top padding, and that is the whole bug.** A sticky child is clamped to
   its scroll container's CONTENT box, not its border box — so with `padding-top:20px` on the modal,
   `top:0` resolved to 20px down, and the negative margin moved the element's layout position without
   moving that clamp. The result was a 20px transparent strip across the top of the screen that the
   help text slid up through: measured, the header stuck at y=20 and `elementFromPoint(x, 3)` found
   nothing painted at all. Reported as "the menu doesn't go to the top of the screen".

   So the space above the title now comes from this element's own padding instead, and the safe-area
   inset comes with it. The side margins stay negative so the bar still bleeds the full width. */
#howToModal{padding-top:0;}
.help-head{
  position:sticky; top:0; z-index:2;
  background:var(--surface);
  margin:0 -20px;
  padding:calc(20px + env(safe-area-inset-top)) 20px 0;
}
.help-head-row{
  display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;
}
.help-tabs{
  display:flex; gap:6px; flex-wrap:wrap;
  padding-bottom:12px; border-bottom:1px solid var(--border);
}
.help-tab{
  font-family:'Bebas Neue',sans-serif; font-size:17px; letter-spacing:0.04em; text-transform:uppercase;
  background:var(--surface2); border:1px solid var(--border); color:var(--text-faint);
  padding:5px 13px; border-radius:8px; cursor:pointer; line-height:1.4;
}
.help-tab.active{background:var(--accent-soft); border-color:var(--accent); color:var(--accent);}
/* One line saying what the section is, before the cards say how it works. */
.help-intro{
  font-size:14.5px; line-height:1.55; color:var(--text-dim);
  margin:18px 2px 16px; padding-left:11px; border-left:2px solid var(--accent-dim);
}
.ht-example{
  background:var(--surface); padding:12px 14px; border-radius:10px; margin-top:10px;
  border:1px solid var(--border);
  font-family:'JetBrains Mono',monospace; font-size:12.5px; line-height:1.6; white-space:pre-wrap;
}
.ht-text code{
  font-family:'JetBrains Mono',monospace; font-size:12.5px;
  background:var(--surface3); padding:1px 5px; border-radius:4px; color:var(--text);
}
/* Bold in help copy is nearly always the name of a button or a setting. Lifting it to full
   text colour is what lets you find one by skimming instead of reading. */
.ht-text strong{color:var(--text); font-weight:600;}
.ht-text p + p, .ht-text p + .ht-defs, .ht-text .ht-defs + p{margin-top:11px;}

/* Labelled rows — a setting, a tracking type — where prose was hiding a list. The spacing is
   margins rather than a flex gap: a term has to sit closer to its own definition than to the
   next term, or the pairs stop reading as pairs. */
.ht-defs{margin:0;}
.ht-defs dt{
  font-size:14px; font-weight:600; color:var(--text); line-height:1.4; margin-top:12px;
}
.ht-defs dt:first-child{margin-top:0;}
.ht-defs dd{
  margin:3px 0 0; font-size:14px; color:var(--text-dim); line-height:1.55;
  padding-left:11px; border-left:2px solid var(--border);
}

/* The sentence you would regret skimming past. */
.ht-note{
  background:var(--surface); border-left:2px solid var(--accent);
  border-radius:0 8px 8px 0; padding:10px 12px;
}
.ht-grid{
  display:flex; flex-direction:column; gap:14px; margin-bottom:24px;
}
.ht-card{
  background:var(--surface2); border:1px solid var(--border); border-radius:12px; padding:17px;
  display:flex; gap:14px; align-items:flex-start;
}
.ht-icon{
  width:42px; height:42px; background:rgba(255, 90, 54, 0.1); border-radius:10px; display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.ht-icon svg{
  width:20px; height:20px; stroke:var(--accent); fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round;
}
.ht-text{min-width:0;}
.ht-text h3{
  margin:0 0 9px; font-size:16.5px; font-weight:700; color:var(--text); letter-spacing:-0.01em;
  line-height:1.3;
}
/* 1.6 rather than 1.45: these are long sentences read one-handed, and the extra leading is
   what keeps a five-paragraph card from looking like a wall. */
.ht-text p{
  margin:0; font-size:14.5px; color:var(--text-dim); line-height:1.6;
}
.hist-session-body{display:none; padding:14px; border-top:1px solid var(--border);}
.hist-session-body.open{display:block;}

.month-header{
  font-family:'Bebas Neue', sans-serif; font-size:26px; letter-spacing:0.04em; color:var(--text);
  margin:24px 0 14px; border-bottom:1px solid var(--border); padding-bottom:6px;
  display:flex; justify-content:space-between; align-items:center; cursor:pointer;
}
.month-body{display:none;}
.month-body.open{display:block;}
.chev{transition:transform 0.2s; stroke:var(--text-faint); width:16px; height:16px; fill:none; stroke-width:2;}
.chev.open{transform:rotate(180deg);}
.session-actions-mini{display:flex; gap:8px; margin-top:6px;}
.text-link{color:var(--text-dim); font-size:12px; background:none; border:none; text-decoration:underline; cursor:pointer; padding:4px 0;}

.search-bar{
  background:var(--surface2); border:1px solid var(--border); border-radius:10px; padding:10px 14px;
  display:flex; align-items:center; gap:8px; margin-bottom:16px;
}
.search-bar svg{width:16px; height:16px; stroke:var(--text-faint); fill:none; stroke-width:2; flex-shrink:0;}
.search-bar input{background:none; border:none; color:var(--text); font-family:'Inter'; font-size:14px; width:100%;}
.search-bar input:focus{outline:none;}

.ex-list-item{
  background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:13px 15px;
  display:flex; justify-content:space-between; align-items:center; margin-bottom:9px; cursor:pointer;
}
.ex-list-item .name{font-weight:700; font-size:14.5px;}
.ex-list-item .meta{color:var(--text-faint); font-size:12px; margin-top:3px;}
.ex-list-item .arrow{stroke:var(--text-faint); width:16px; height:16px; fill:none; stroke-width:2; flex-shrink:0;}
/* Shown in the merge picker only when two candidates would otherwise draw identically, because
   the thing that differs is whitespace and HTML collapses it. Accent-tinted: it is the line that
   answers the question you opened the modal with. */
.ex-list-item .merge-exact{font-size:11px; color:var(--accent); margin-top:4px;}
.ex-list-item .merge-exact code{font-family:'JetBrains Mono',monospace; font-size:11.5px; color:var(--accent);}

.section-label{
  font-family:'Bebas Neue',sans-serif; letter-spacing:0.06em; color:var(--text-dim); font-size:15px;
  margin:22px 0 10px; text-transform:uppercase;
}

/* Bottom Sheet */
.sheet-backdrop{
  position:fixed; inset:0; background:rgba(0,0,0,0.8); z-index:40; opacity:0; pointer-events:none; transition:opacity 0.2s;
}
.sheet-backdrop.open{opacity:1; pointer-events:auto;}
.sheet{
  position:fixed; left:0; right:0; bottom:0; z-index:41; background:var(--surface);
  border-radius:22px 22px 0 0; border:1px solid var(--border); border-bottom:none;
  max-height:88vh; overflow-y:auto; transform:translateY(100%); transition:transform 0.25s cubic-bezier(.2,.9,.3,1);
  padding:10px 18px calc(24px + env(safe-area-inset-bottom));
  max-width:600px; margin:0 auto;
}
.sheet.open{transform:translateY(0);}
.sheet-handle{width:38px; height:4px; background:var(--border); border-radius:4px; margin:6px auto 14px;}
.sheet h3{font-family:'Bebas Neue'; font-size:24px; letter-spacing:0.04em; margin:0 0 16px;}
.field-label{font-size:11px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text); font-weight:600; margin-bottom:7px; display:block;}
.field{margin-bottom:16px; position:relative;}
.input-field {
  background:var(--surface2); border:1px solid var(--border); color:var(--text);
  font-family:'Inter', sans-serif; font-size:15px; padding:12px 13px; border-radius:10px; width:100%; box-sizing: border-box;
}
#exInput.input-field { border: 1px solid var(--accent-dim); }
textarea.input-field {font-family:'JetBrains Mono', monospace; font-size:13.5px; resize:vertical; min-height:44px;}
.input-field:focus {outline:none; border-color:var(--accent);}

.ghost-input{
  background:transparent !important; border:none !important; border-bottom:1px dashed var(--border) !important;
  color:var(--text) !important; font-family:'Inter', sans-serif !important; font-size:14.5px !important;
  width:100%; padding:6px 0 !important; border-radius:0 !important; outline:none; transition:all 0.2s;
}
.ghost-input::placeholder{color:var(--text-faint);}
.ghost-input:focus{border-bottom-color:var(--accent) !important; border-bottom-style:solid !important;}

.autocomplete-list{
  position:absolute; top:100%; left:0; right:0; background:var(--surface3); border:1px solid var(--border);
  border-radius:10px; margin-top:4px; max-height:180px; overflow-y:auto; z-index:5; display:none;
}
.autocomplete-list.show{display:block;}
.autocomplete-list div{padding:10px 13px; font-size:14px; cursor:pointer; border-bottom:1px solid var(--border);}
.autocomplete-list div:last-child{border-bottom:none;}
.autocomplete-list div:active{background:var(--accent-soft);}
.autocomplete-list div .freq{color:var(--text-faint); font-size:11px; margin-left:6px;}

.stepper-row{display:flex; align-items:center; gap:10px;}
.stepper-row .stepper-btn{
  width:56px; height:56px; border-radius:50%; display:flex; align-items:center; justify-content:center; cursor:pointer; flex-shrink:0; user-select:none;
}
.stepper-row .stepper-btn[data-amt^="-"] {
  background: var(--surface3); color: var(--fail); border: 1px solid var(--border); font-size: 28px;
}
.stepper-row .stepper-btn[data-amt^="-"]:active {
  background: rgba(255, 67, 104, 0.15); color: var(--fail);
}
.stepper-row .stepper-btn:not([data-amt^="-"]) {
  background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-dim); font-size: 28px; font-weight: 700;
}
.stepper-row .stepper-btn:not([data-amt^="-"]):active {
  background: var(--accent); color: #fff;
}
.stepper-row input{
  text-align:center; flex:1; font-family:'JetBrains Mono', monospace; font-weight:700; font-size:14px;
  background:var(--surface2); border:1px solid var(--border); color:var(--text); padding:8px 4px; border-radius:10px; width:100%; min-width: 0;
}
.stepper-row input:focus{outline:none; border-color:var(--accent);}

.optional-box { background:var(--surface2); border:1px dashed var(--border) !important; color:var(--text); padding:10px; border-radius:10px; width:100%; font-family:'JetBrains Mono', monospace; text-align:center; font-weight:600; font-size:14px; }
.optional-box:focus { outline:none; border-color:var(--accent) !important; }
.detail-box { background:var(--surface3); border:1px solid var(--border); color:var(--text); padding:12px; border-radius:10px; width:100%; font-family:'JetBrains Mono', monospace; font-size:14px; font-weight:600; resize:vertical; }
.detail-box:focus { outline:none; border-color:var(--accent); }

.row-2{display:flex; gap:12px;}
.row-2 .field{flex:1;}
.toggle-row{display:flex; align-items:center; justify-content:space-between; background:var(--surface2); border:1px solid var(--border); padding:11px 13px; border-radius:10px; margin-bottom:12px;}
.toggle-row span{font-size:14px; font-weight:500;}
/* A toggle whose label needs a sentence under it. Baseline-aligned to the top rather than centred,
   because a two-line explanation next to a vertically-centred switch reads as unrelated to it. */
.toggle-row:has(.toggle-text){align-items:flex-start;}
.toggle-text{min-width:0; padding-right:12px;}
.toggle-text span{display:block; line-height:1.35;}
.toggle-text em{color:var(--text-faint); font-style:normal; font-weight:400;}
.switch{width:42px; height:24px; border-radius:20px; background:var(--surface3); border:1px solid var(--border); position:relative; cursor:pointer; flex-shrink:0;}
.switch::after{content:''; position:absolute; width:18px; height:18px; border-radius:50%; background:var(--text-dim); top:2px; left:2px; transition:all 0.18s;}
.switch.on{background:var(--accent-soft); border-color:var(--accent);}
.switch.on::after{transform:translateX(18px); background:var(--accent);}

/* Rows to review, grouped by exercise. The group is the unit you fix — five identical
   "Full song" rows under one heading is one decision, not five. */
.review-group{
  background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius);
  padding:13px 14px; margin-bottom:10px;
}
.review-head{display:flex; align-items:baseline; justify-content:space-between; gap:10px;}
.review-name{font-weight:700; font-size:14.5px;}
.review-count{font-family:'JetBrains Mono',monospace; font-size:11.5px; color:var(--text-faint); flex-shrink:0;}
.review-tpl{font-size:11px; color:var(--accent); margin-top:2px;}
.review-why{font-size:12px; color:var(--text-dim); line-height:1.45; margin:8px 0 4px;}
.review-row{
  display:flex; align-items:baseline; gap:10px; cursor:pointer;
  padding:7px 0; border-top:1px solid var(--border);
}
.review-date{font-size:11px; color:var(--text-faint); font-family:'Inter',sans-serif; width:64px; flex-shrink:0;}
.review-detail{font-family:'JetBrains Mono',monospace; font-size:12.5px; color:var(--text-dim); min-width:0; overflow-wrap:anywhere;}

/* ---------- Muscle groups ---------- */
/* Chips rather than a multi-select: tagging fifty exercises has to be tapping, and the whole
   set has to be visible at once so you can see what you have not answered. */
.muscle-block{margin-bottom:16px;}
.muscle-label{font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em; font-weight:700; margin-bottom:8px;}
/* ---------- EXERCISE GUIDE ---------- */
/* The how-to card on the exercise detail view: a drawn figure doing the movement, then the three
   things worth saying about it. Only for names js/guides.js knows — no card otherwise. */
.guide-card{
  background:var(--surface2); border:1px solid var(--border); border-radius:12px;
  padding:13px 14px; margin-bottom:16px;
}
.guide-label{
  font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em;
  font-weight:700; margin-bottom:10px;
}
.guide-anim{background:var(--surface); border:1px solid var(--border); border-radius:10px; padding:4px 8px;}
.guide-anim svg{display:block; width:100%; height:auto; max-height:200px;}
/* The figure in the text colour, the load in the accent, the equipment in the border grey —
   the same palette logic as every chart in the app. */
.gd-body{stroke:var(--text); fill:none; stroke-linecap:round; stroke-linejoin:round;}
/* The far-side arm and leg: fainter and behind, which is what gives the figure a body. */
.gd-far{stroke:var(--text-faint); fill:none; stroke-linecap:round; stroke-linejoin:round;}
.gd-head{fill:var(--text); stroke:none;}
.gd-load{stroke:var(--accent); fill:none; stroke-linecap:round; stroke-linejoin:round;}
.gd-prop{stroke:var(--border); fill:none; stroke-linecap:round; stroke-linejoin:round;}
.guide-cues{margin-top:12px; display:flex; flex-direction:column; gap:10px;}
.guide-cue-label{
  font-size:10.5px; color:var(--accent); text-transform:uppercase; letter-spacing:0.06em;
  font-weight:700; margin-bottom:3px;
}
.guide-cues ul{margin:0; padding-left:17px; display:flex; flex-direction:column; gap:4px;}
.guide-cues li{font-size:13px; color:var(--text-dim); line-height:1.45;}

.muscle-chips{display:flex; flex-wrap:wrap; gap:6px;}
.muscle-chip{
  background:var(--surface2); color:var(--text-faint); border:1px solid var(--border);
  border-radius:20px; padding:6px 12px; font-family:'Inter',sans-serif; font-size:12.5px;
  font-weight:600; cursor:pointer;
}
.muscle-chip.on{background:var(--accent-soft); border-color:var(--accent); color:var(--accent);}
/* Dashed and transparent, the same "none of the above" shape the location row's + and the
   custom-rest + use, so it reads as a way to add an answer rather than as a fourteenth answer. */
.muscle-chip-add{background:transparent; border-style:dashed; color:var(--text-dim);}
.muscle-chip-add:active{background:var(--surface2); color:var(--text);}
.muscle-suggest{
  display:block; width:100%; margin-top:8px; padding:7px 12px; text-align:left;
  background:transparent; border:1px dashed var(--accent-dim); border-radius:8px;
  color:var(--accent); font-family:'Inter',sans-serif; font-size:12px; cursor:pointer;
}
.ex-list-item .ex-muscles{color:var(--accent); font-size:11.5px; margin-top:4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}

/* Weekly work by muscle group. Plain HTML bars rather than the SVG the time series use: this
   is categorical, there is no axis to scale, and twelve rows read better as elements. */
.mg-week{font-size:11px; color:var(--text-faint); margin-bottom:10px;}
.mg-bars{display:flex; flex-direction:column; gap:5px;}
.mg-row{display:flex; align-items:center; gap:8px;}
.mg-row.zero{opacity:0.45;}
.mg-name{font-size:11.5px; color:var(--text-dim); width:74px; flex-shrink:0;}
.mg-bar{flex:1; height:8px; background:var(--surface3); border-radius:4px; overflow:hidden; min-width:0;}
.mg-fill{display:block; height:100%; background:var(--accent); border-radius:4px;}
.mg-sets{font-family:'JetBrains Mono',monospace; font-size:12px; font-weight:700; color:var(--text); width:22px; text-align:right; flex-shrink:0;}
.mg-neglected{display:flex; align-items:center; flex-wrap:wrap; gap:6px; margin-top:12px; padding-top:10px; border-top:1px solid var(--border);}
.mg-neglected-label{font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em; font-weight:700;}
.mg-chip{
  display:inline-flex; align-items:baseline; gap:5px;
  background:var(--surface3); border:1px solid var(--border); border-radius:20px;
  padding:4px 10px; font-size:12px; color:var(--text-dim);
}
.mg-chip-days{font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--fail); font-weight:700;}

/* Grouping switch on the Exercises tab, and the session proposal. */
.ex-groupby{display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:14px;}
.ex-groupby-label{font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em; font-weight:700;}
.ex-groupby .seg-btn{font-family:'Inter',sans-serif; font-size:12px;}

.sg-why{font-size:12.5px; color:var(--text-dim); line-height:1.5; margin-bottom:14px;}
.sg-why .sg-days{font-family:'JetBrains Mono',monospace; font-size:11.5px; color:var(--fail); font-weight:700;}
.sg-item{
  display:flex; align-items:flex-start; gap:12px; cursor:pointer;
  background:var(--surface2); border:1px solid var(--border); border-radius:12px;
  padding:12px 14px; margin-bottom:8px;
}
.sg-item input{width:20px; height:20px; accent-color:var(--accent); flex-shrink:0; margin:1px 0 0;}
.sg-body{min-width:0;}
.sg-name{display:block; font-weight:700; font-size:14.5px;}
.sg-meta{display:block; color:var(--text-faint); font-size:12px; margin-top:3px;}

/* The two actions in the Log tab header. Sized here rather than inline because there are three
   controls plus a date competing for one row on a phone: at the old 13px/8-12px padding the pair
   measured 240px of a 358px row, which squeezed "THU, AUG 6" onto two lines — and three at
   360px. Tightened, and the labels drop below 380px where the date has to win. */
/* Two classes deep, and width reset: .btn-ghost is declared further down this file with
   `width:100%` and its own padding, so a single-class rule here would silently lose to it. */
.btn-ghost.head-action{
  display:flex; align-items:center; gap:5px; margin:0;
  width:auto; flex:0 0 auto;
  padding:6px 9px; font-size:11.5px; letter-spacing:0.03em;
  color:var(--text-dim);
}
.btn-ghost.head-action svg{width:14px; height:14px; stroke:currentColor; fill:none; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round;}
.btn-ghost.head-action.accent{color:var(--accent);}
/* Labels go before the date does, and the familiar one goes first. On a 390px phone ROUTINES
   becomes its icon and GENERATE keeps its word — it is the newer action and the one nobody is
   looking for yet. Below 360px both are icons; the date is the one thing on this row you cannot
   guess from context. */
@media (max-width: 419px){
  .btn-ghost.head-action.secondary{padding:7px;}
  .btn-ghost.head-action.secondary .head-label{display:none;}
  .btn-ghost.head-action.secondary svg{width:17px; height:17px;}
}
@media (max-width: 359px){
  .btn-ghost.head-action{padding:7px; gap:0;}
  .btn-ghost.head-action .head-label{display:none;}
  .btn-ghost.head-action svg{width:17px; height:17px;}
}

/* The attach menu: the way back to a block you switched off, for one day, without going to
   Settings. It was a row of dashed chips under the date and cost a whole line of the tab it was
   meant to shorten, so it is one icon and a popover now. */
/* The menu is positioned against the HEADER ROW, not against the button. Anchoring it to the
   button put it off-screen either right or left depending on the width, because the button's x
   moves as the labels next to it come and go. The header spans the content column, so aligning
   the menu to its right edge always fits. */
#tab-today .session-head{position:relative;}
/* Same reason, same anchor: the Exercises menu hangs off the header row, not off its button. */
#tab-exercises .session-head{position:relative;}
.attach-wrap{position:static; display:flex;}
.attach-btn{
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  width:30px; height:30px; padding:0;
  background:transparent; border:1px dashed var(--border); border-radius:50%;
  color:var(--text-faint);
}
.attach-btn svg{width:15px; height:15px; stroke:currentColor; fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}
.attach-btn[aria-expanded="true"]{border-color:var(--accent); color:var(--accent); border-style:solid;}
.attach-btn:active{background:var(--surface2); color:var(--text);}
/* The one action on the Exercises row that is not a way of looking at the list but a thing that
   changes it. Solid rather than dashed, and in the accent, for the same reason GENERATE is. */
.attach-btn.accent{border-style:solid; border-color:var(--accent-dim); color:var(--accent);}
.attach-btn.accent:active{background:var(--accent-soft); color:var(--accent);}
/* Select mode's only exit is inside this menu, so while it is on the button says so. Without it the
   bottom bar is the only sign you are in a mode, and it has no way out of itself. */
.attach-btn.active{border-style:solid; border-color:var(--accent); color:var(--accent); background:var(--accent-soft);}

/* Four controls and a 28px Bebas title on one row. The gap is tighter than the Log tab's 8px
   because there are two more of them here and "EXERCISES" is the longer word. */
.ex-head-actions{display:flex; align-items:center; gap:6px;}

/* Anchored to the button's RIGHT edge, opening leftwards under the date. Left-aligned it ran off
   the screen at every common phone width — the button sits ~200px in and the menu is 210px wide,
   so its right edge landed past 390. max-width is the belt to that braces. */
.attach-menu{
  position:absolute; top:calc(100% + 6px); right:0; z-index:40;
  min-width:210px; max-width:calc(100vw - 24px); padding:6px;
  background:var(--surface2); border:1px solid var(--border); border-radius:12px;
  box-shadow:0 10px 28px rgba(0,0,0,0.45);
  display:flex; flex-direction:column; gap:2px;
}
.attach-item{
  display:flex; align-items:flex-start; gap:9px; cursor:pointer; text-align:left;
  background:transparent; border:none; border-radius:8px; padding:9px 10px;
  color:var(--text); font-family:'Inter',sans-serif; font-size:13.5px; font-weight:600;
}
.attach-item svg{width:13px; height:13px; margin-top:2px; flex-shrink:0; stroke:var(--accent); fill:none; stroke-width:2.5; stroke-linecap:round;}
.attach-item-text{min-width:0;}
.attach-item-hint{display:block; font-size:11px; font-weight:400; color:var(--text-faint); margin-top:2px;}
.attach-item:active{background:var(--surface3);}

/* ---------- Supplement log ---------- */
/* Sits with the body-weight fields rather than with the rows, because it is a fact about the
   day rather than a set you performed. Deliberately quieter than the row cards: dashed and
   unfilled, so a day's training still reads as the main thing on the tab. */
.supp-card{
  border:1px dashed var(--border); border-radius:var(--radius);
  padding:11px 13px; margin-bottom:16px;
}
.supp-head{display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:9px;}
/* The header is a button now — the whole line folds the card — so it sheds the UA button
   chrome and keeps the header's own look. Folded, its margin is the card's only inner space. */
.supp-fold{width:100%; background:none; border:none; padding:0; cursor:pointer; text-align:left; font:inherit;}
.supp-fold:last-child{margin-bottom:0;}
/* The folded card's one line: the day's most recent dose, dimmed so it reads as a recap rather
   than an editable row. Tapping it unfolds — it is the only thing showing, and a tap on it
   means "show me the rest". */
.supp-latest{cursor:pointer; opacity:0.72;}
.supp-label{font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em; font-weight:700;}
.supp-count{font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--text-faint);}
/* Full width and always present. It used to be a btn-mini in the corner of the header, which
   made the smallest control on the card the ONLY route to the amount and time fields. */
.supp-add{
  display:flex; align-items:center; gap:8px; width:100%; margin-top:10px;
  background:transparent; border:1px dashed var(--border); border-radius:10px;
  padding:10px 12px; cursor:pointer; text-align:left;
  color:var(--text-dim); font-family:'Inter',sans-serif; font-size:13.5px; font-weight:600;
}
.supp-add svg{width:16px; height:16px; stroke:var(--accent); fill:none; stroke-width:2.5; stroke-linecap:round; flex-shrink:0;}
.supp-add-sub{display:block; font-size:11px; font-weight:400; color:var(--text-faint); margin-top:2px;}
.supp-add:active{background:var(--surface2); color:var(--text);}
.supp-entry{
  display:flex; align-items:center; gap:10px;
  padding:7px 0; border-top:1px solid var(--border); cursor:pointer;
}
.supp-entry:first-of-type{border-top:none;}
.supp-time{font-family:'JetBrains Mono',monospace; font-size:12.5px; color:var(--accent); font-weight:700; flex-shrink:0;}
.supp-name{font-size:13.5px; font-weight:600; flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.supp-dose{font-family:'JetBrains Mono',monospace; font-size:12.5px; color:var(--text-dim); flex-shrink:0;}
.supp-del{width:26px; height:26px; border:none; background:transparent; flex-shrink:0;}
.supp-del svg{width:13px; height:13px;}
.supp-empty{font-size:12px; color:var(--text-faint);}
.supp-hist-day{margin-top:12px;}
.supp-hist-day:first-of-type{margin-top:2px;}
.supp-hist-date{font-size:11px; color:var(--text-faint); margin-bottom:2px;}
.supp-hist-day .supp-entry{cursor:default;}

/* ---------- Preferences panel ---------- */
/* The switch and .toggle-row already existed; these are the rows that carry a choice rather
   than an on/off, plus the note that explains a preference whose scope isn't obvious. */
.pref-row{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  background:var(--surface2); border:1px solid var(--border); padding:11px 13px; border-radius:10px; margin-bottom:12px;
}
.pref-row .pref-name{font-size:14px; font-weight:500;}
/* Both contexts, because the note was scoped to `.pref-row` only and a toggle that grew a note
   rendered it at full body size — louder than the label it was explaining. */
.pref-row .pref-note, .toggle-text .pref-note{font-size:11px; color:var(--text-faint); line-height:1.4; margin-top:3px; max-width:230px;}
/* No 230px cap here: in a .pref-row the note sits beside a segment control, but a toggle's note has
   the whole row minus the switch, and these two are three sentences that should not be a column. */
.toggle-text .pref-note{max-width:none;}
.pref-group{margin-top:18px;}
.pref-group-head{
  font-family:'Bebas Neue',sans-serif; letter-spacing:0.06em; text-transform:uppercase;
  font-size:15px; color:var(--text-dim); margin-bottom:4px;
}

/* A folding group.

   The panel had grown to nineteen controls in one scroll — five sounds, four volumes, six Log-tab
   switches, four assistants — of which most people change about three. Closed by default, so the
   whole of Preferences fits a phone screen again.

   **The summary on the right is what makes this better than just hiding things.** A drawer labelled
   only "What it sounds like" costs a tap to answer "which one is it?". One that reads "Three beeps ·
   Full" has already answered, so opening it is only ever for changing it. */
.pref-group-toggle{
  display:flex; align-items:center; justify-content:space-between; gap:10px; width:100%;
  background:var(--surface2); border:1px solid var(--border); border-radius:10px;
  padding:11px 13px; cursor:pointer; font-family:inherit; text-align:left; color:var(--text);
}
.pref-group-toggle:active{background:var(--surface3);}
.pgt-text{display:flex; flex-direction:column; gap:2px; min-width:0;}
.pgt-title{font-size:14px; font-weight:500; line-height:1.3;}
.pgt-summary{font-size:11.5px; color:var(--accent); font-weight:600; letter-spacing:0.01em;}
.pgt-chevron{
  width:18px; height:18px; flex:0 0 auto; fill:none; stroke:var(--text-faint); stroke-width:2.4;
  stroke-linecap:round; stroke-linejoin:round; transition:transform 0.18s;
}
.pref-group-toggle[aria-expanded="true"] .pgt-chevron{transform:rotate(180deg); stroke:var(--accent);}
/* The note and the controls sit under the header once opened; the note was above the group before, and
   inside is where it belongs now that the group is a thing you deliberately open. */
.pref-group-body{padding-top:10px;}
.pref-group-body .pref-group-note{margin-bottom:10px;}
/* Inside a drawer the volume row is the last thing, so its bottom margin doubles the padding. */
.pref-group-body .cue-volume-row:last-child{margin-bottom:0;}
.pref-group-note{font-size:11.5px; color:var(--text-faint); line-height:1.45; margin-bottom:10px;}
/* The label and its explanation share one line-height so the switch stays centred on the pair. */
.pref-hint{display:block; font-size:11px; font-weight:400; color:var(--text-faint); margin-top:2px;}
.toggle-row span{min-width:0;}
.seg{display:flex; gap:4px; flex-shrink:0; flex-wrap:wrap;}
.seg-btn{
  font-family:'JetBrains Mono',monospace; font-size:12px; font-weight:700;
  background:var(--surface); border:1px solid var(--border); color:var(--text-faint);
  padding:6px 10px; border-radius:8px; cursor:pointer; line-height:1;
}
.seg-btn.active{background:var(--accent-soft); border-color:var(--accent); color:var(--accent);}

/* A .pref-row whose control is too wide to sit beside its label. The four volume steps fit on the
   right of their label; five sounds each carrying a sentence do not, at any phone width. */
.pref-row.pref-stack{flex-direction:column; align-items:stretch; gap:10px;}
.pref-row.pref-stack .pref-note{max-width:none;}

/* The sounds.

   One row per sound, and the row is the whole control: tapping it selects that sound AND plays it.
   Those are the same intention — nobody picks an alarm tone they have not heard — and splitting them
   into a selectable row plus a play button beside it would make you aim at a phone screen mid-workout
   to do the obvious thing. The speaker is an affordance, not a second target. */
.cue-list{display:flex; flex-direction:column; gap:6px;}
.cue-opt{
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  background:var(--surface); border:1px solid var(--border); color:var(--text);
  padding:9px 11px; border-radius:9px; cursor:pointer; font-family:inherit;
}
.cue-opt.active{background:var(--accent-soft); border-color:var(--accent);}
.cue-text{min-width:0; flex:1;}
.cue-name{display:block; font-size:13.5px; font-weight:600; line-height:1.3;}
.cue-opt.active .cue-name{color:var(--accent);}
/* The description is what makes this a list and not a segment, so it has to stay readable rather
   than being truncated — five short sentences at 11px is two lines at worst. */
.cue-desc{display:block; font-size:11px; color:var(--text-faint); line-height:1.4; margin-top:2px;}
.cue-play{display:flex; flex:0 0 auto;}
.cue-play svg{
  width:17px; height:17px; fill:none; stroke:var(--text-faint); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
}
.cue-opt.active .cue-play svg{stroke:var(--accent);}
.cue-opt:active{background:var(--surface3);}
.cue-opt.active:active{background:var(--accent-soft);}

/* Rest timer.
   The bar is pinned just above the tab bar so it stays readable while you scroll your rows —
   a countdown you have to scroll to find is not doing its job. body.resting lifts the FAB out
   of its way; both are fixed, and 96px is the FAB's own resting offset. */
.rest-start{display:flex; align-items:center; gap:10px; margin-bottom:16px;}
.rest-start-label{font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em; font-weight:700; flex-shrink:0;}
/* Tightened from 6px gap and 10px padding when the row grew a sixth control. Measured, not guessed:
   at the old sizes six buttons needed 319px and the content column at 390px is 318, so the `+` was
   landing on a line of its own — 30px of the Log tab spent on one glyph, on the very tab the
   Show-on-the-Log-tab preferences exist to shorten. At these sizes the row is one line down to 375px
   and wraps below that, which is where a sixth button was always going to wrap. */
.rest-presets{display:flex; flex-wrap:wrap; gap:4px;}
.rest-preset{font-family:'JetBrains Mono',monospace !important; padding:5px 9px !important;}
/* "None of the above". Dashed to match the location row's own `+`, since it is the same kind of
   control — the presets are the answers on offer and this is the one that asks.
   Tighter padding than a preset because it holds one glyph rather than four, which is also the ~14px
   that lets the row fit. */
.rest-preset.rest-custom{
  border-style:dashed; color:var(--text-faint);
  padding:5px 8px !important; line-height:1;
}
.rest-preset.rest-custom:active{border-style:solid; color:var(--accent);}

.rest-bar{
  position:fixed; bottom:calc(64px + env(safe-area-inset-bottom)); left:0; right:0; z-index:28;
  max-width:600px; margin:0 auto; overflow:hidden;
  background:var(--surface2); border-top:1px solid var(--border); border-bottom:1px solid var(--border);
}
body.resting .fab{bottom:164px;}
/* Behind the text, not over it: a progress fill that dims the numbers defeats the point. */
.rest-fill{position:absolute; inset:0 auto 0 0; background:var(--accent-soft); transition:width 0.25s linear;}
.rest-body{position:relative; display:flex; align-items:center; gap:12px; padding:10px 16px;}
.rest-clock{font-family:'JetBrains Mono',monospace; font-size:22px; font-weight:700; color:var(--accent); line-height:1; min-width:64px;}
.rest-clock.done{color:var(--good); font-size:17px;}
.rest-sub{font-size:12px; color:var(--text-dim); flex:1; min-width:0;}
.rest-actions{display:flex; gap:6px; flex-shrink:0;}
.rest-btn{
  background:var(--surface); color:var(--text-dim); border:1px solid var(--border);
  border-radius:8px; padding:6px 10px; font-family:'Inter',sans-serif; font-size:12px;
  font-weight:600; cursor:pointer;
}
.rest-btn:active{background:var(--surface3); color:var(--text);}

/* One-tap logging for the exercises the builder is awkward for. Sits directly above the day's
   rows, because that is where "add something" belongs. */
.quick-log{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:16px;}
/* The pill itself is NOT scoped to .quick-log. It was, and three other places already carried
   the class without being inside that container -- the Rest presets, and now the supplement
   pills -- so they fell back to a browser default button and rendered as white boxes on a dark
   page. .quick-log is the layout; .ql-btn is the pill. */
.ql-btn{
  display:flex; align-items:center; gap:6px;
  background:var(--surface2); color:var(--text-dim); border:1px dashed var(--border);
  border-radius:20px; padding:7px 14px; font-family:'Inter',sans-serif; font-size:13px;
  font-weight:600; cursor:pointer;
}
.ql-btn:active{background:var(--surface3); color:var(--text);}

/* The one-tap assistant links on the AI screen. Anchors wearing .ql-btn, so they need the two
   things a link does not inherit from it: no underline, and no visited colour. */
.ai-apps-label{
  font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em;
  font-weight:700; margin:14px 0 8px;
}
.ai-apps-row{display:flex; flex-wrap:wrap; gap:8px;}
.ai-apps-note{font-size:11px; color:var(--text-faint); line-height:1.45; margin-top:8px;}

/* The pickers. Same pill as the quick-log buttons, with the selected one filled in — each is a
   single choice, so the active state has to be unmistakable rather than a border tint. */
.ai-locs, .ai-chips{display:flex; flex-wrap:wrap; gap:8px;}
.ai-loc.active, .ai-chip.active{background:var(--accent-soft); color:var(--accent); border-color:var(--accent); border-style:solid;}

/* The step numbers. The round trip is a sequence and its middle happens in another app, so the
   order is worth stating rather than implying. */
.ai-step{
  display:inline-flex; align-items:center; justify-content:center;
  width:16px; height:16px; margin-right:6px; border-radius:50%;
  background:var(--accent-soft); color:var(--accent);
  font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:700;
}
.ai-optional{color:var(--text-faint); font-weight:400; text-transform:none; letter-spacing:0;}

/* What the chosen intensity will actually tell the model. Shown rather than hidden: "Brutal" is a
   mood, and the instruction underneath it is about reps in reserve. */
.ai-hint{font-size:11px; color:var(--text-faint); line-height:1.45; margin-top:7px;}
.ai-app, .ai-app:visited{text-decoration:none; color:var(--text-dim);}
.ai-app:active{background:var(--surface3); color:var(--text);}
.ql-btn svg{width:14px; height:14px; stroke:var(--accent); fill:none; stroke-width:2.5; stroke-linecap:round;}

/* The assistants' own marks.

   TWO CLASSES ON PURPOSE. `.ql-btn svg` above is (0,1,1) and is declared LAST, so a single-class
   `.brand-mark` would tie on specificity and lose on source order — the exact trap the Log header
   buttons fell into. `.ai-app svg.brand-mark` is (0,2,1) and wins wherever it sits in the file.

   Brand marks are FILLED shapes, so `fill:none; stroke:var(--accent)` renders them as nothing at
   all. They also inherit `currentColor` rather than taking the accent: these are somebody else's
   trademarks, and tinting one orange to match this app is the sort of "modification" a brand
   guideline is about. Slightly larger than the 14px stroke glyphs because a solid mark reads
   smaller than an outline at the same box. */
.ai-app svg.brand-mark{width:15px; height:15px; fill:currentColor; stroke:none; flex:0 0 auto;}
/* The Grok stand-in is one of ours, not a mark, so it is stroked like the rest of the app's icons.
   It takes `currentColor` and NOT the accent, though — accent is what every other IronLog glyph in
   a `.ql-btn` uses, and it made the one button whose logo is a placeholder the loudest thing in the
   row. A stand-in should sit quietly next to the real marks, not outshine them. */
.ai-app svg.brand-mark-neutral{fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}

/* What the builder was prefilled from. Accent-tinted rather than dashed like .history-hint —
   this one is a live statement about the numbers on screen, not a list to browse. */
.prefill-hint{
  display:flex; align-items:baseline; flex-wrap:wrap; gap:6px 8px;
  background:var(--accent-soft); border:1px solid var(--accent-dim); border-radius:10px;
  padding:9px 12px; margin-bottom:12px;
}
.prefill-hint .ph-label{font-size:10.5px; color:var(--accent); text-transform:uppercase; letter-spacing:0.06em; font-weight:700;}
.prefill-hint .ph-date{font-size:11px; color:var(--text-dim); font-family:'Inter'; font-weight:600;}
/* min-width:0 so a long cardio distance wraps inside the strip instead of widening the sheet. */
.prefill-hint .ph-detail{flex:1 1 100%; min-width:0; font-size:13px; font-family:'JetBrains Mono'; color:var(--text); overflow-wrap:anywhere;}

.history-hint{background:var(--surface2); border:1px dashed var(--border); border-radius:10px; padding:11px 13px; margin-bottom:16px;}
.history-hint .hh-title{font-size:11px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.05em; font-weight:700; margin-bottom:8px;}
.hh-item{display:flex; justify-content:space-between; align-items:center; gap:8px; padding:7px 0; border-top:1px solid var(--border);}
.hh-item:first-of-type{border-top:none;}
.hh-item .hh-text{font-size:13px; font-family:'JetBrains Mono'; color:var(--text);}
.hh-item .hh-date{font-size:11px; color:var(--text-faint); font-family:'Inter'; font-weight:600;}
.hh-use{
  background:var(--accent-soft); color:var(--accent); border:1px solid var(--accent-dim); font-size:13px; font-weight:700;
  padding:8px 12px; border-radius:8px; cursor:pointer; flex-shrink:0;
}

.btn-primary{
  background:var(--accent); color:#fff; border:none; border-radius:12px; padding:15px; width:100%;
  font-family:'Inter'; font-weight:700; font-size:15px; cursor:pointer; margin-top:6px;
}
.btn-primary:active{opacity:0.85;}
.btn-secondary{
  background:var(--surface2); color:var(--text-dim); border:1px solid var(--border); border-radius:12px; padding:13px;
  width:100%; font-weight:600; font-size:14px; cursor:pointer; margin-top:8px;
}
.btn-secondary:active{background:var(--border); color:var(--text);}
.btn-ghost{
  background:transparent; color:var(--accent); border:none; border-radius:12px; padding:13px;
  width:100%; font-weight:600; font-size:14px; cursor:pointer; margin-top:8px;
}
.btn-ghost:active{background:var(--accent-soft);}
.btn-mini{
  background:var(--surface2); color:var(--text); border:1px solid var(--border); border-radius:8px; padding:6px 10px;
  font-weight:600; font-size:12px; cursor:pointer; font-family:'Inter', sans-serif;
}
.btn-mini:active{background:var(--border);}

/* ---------- SETTINGS TAB ---------- */
/* Deliberately the How'd I Do card language, because that screen is the one that reads best in the
   app: a tinted square holding an icon, a heading, and one line saying what the thing is for. Settings
   was a flat stack of `.section-label` text and identical grey buttons, which made "Backup Data" and
   "Export to Text" look like the same decision. */

/* The hero card. Same construction as .cmp-verdict — icon block, Bebas headline, dim detail. */
.set-summary{
  display:flex; align-items:center; gap:13px;
  padding:15px; border-radius:12px; margin-bottom:18px;
  background:var(--surface2); border:1px solid var(--border); border-left:3px solid var(--accent);
}
.set-summary-icon{
  display:flex; align-items:center; justify-content:center; flex:0 0 auto;
  width:38px; height:38px; border-radius:10px; background:var(--accent-soft);
}
.set-summary-icon svg{width:20px; height:20px; stroke:var(--accent); fill:none; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round;}
.set-summary-main{min-width:0;}
.set-summary-line{font-family:'Bebas Neue'; font-size:25px; line-height:1.1; letter-spacing:0.03em;}
.set-summary-sub{font-size:12px; color:var(--text-dim); line-height:1.5; margin-top:3px;}

.set-section{
  background:var(--surface2); border:1px solid var(--border); border-radius:12px;
  padding:15px; margin-bottom:14px;
}
.set-head{display:flex; align-items:flex-start; gap:11px; margin-bottom:13px;}
.set-icon{
  display:flex; align-items:center; justify-content:center; flex:0 0 auto;
  width:32px; height:32px; border-radius:9px; background:var(--surface3);
}
.set-icon svg{width:17px; height:17px; stroke:var(--text-dim); fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}
/* Filled brand marks need the opposite treatment to the app's own stroked glyphs. */
.set-icon svg.brand-mark{fill:var(--text-dim); stroke:none; width:18px; height:18px;}
.set-icon-warn{background:var(--accent-soft);}
.set-icon-warn svg{stroke:var(--accent);}
.set-head h3{font-size:15px; font-weight:600; margin:0; line-height:1.3;}
.set-head p{font-size:11.5px; color:var(--text-faint); line-height:1.5; margin:3px 0 0;}

/* Two lines per button: what it does, and the one thing worth knowing before tapping it. The old
   single-label buttons all looked alike, which is a bad property for a row where one of them
   overwrites everything you have. */
.btn-secondary.set-btn{
  display:flex; align-items:flex-start; gap:11px; text-align:left;
  margin-top:0; margin-bottom:8px; padding:12px 13px;
}
.set-btn:last-child{margin-bottom:0;}
.set-btn svg{width:17px; height:17px; stroke:currentColor; fill:none; stroke-width:2; flex:0 0 auto; margin-top:1px;}
.set-btn span{display:flex; flex-direction:column; gap:2px; min-width:0;}
.set-btn strong{font-size:13.5px; font-weight:600; color:var(--text); line-height:1.3;}
.set-btn em{font-size:11px; font-style:normal; color:var(--text-faint); line-height:1.45;}

/* ---------- GOOGLE DRIVE ---------- */
/* Same two-line shape as the local backup buttons, because they do the same job to a different
   destination — a different visual treatment would imply a different kind of action. */
/* What the last backup did, on the card rather than in a toast that erases itself. A backup is the
   one operation whose entire value is knowing it happened, and it was reported as returning nothing
   at all — so the answer stays on screen for as long as you are on this tab. */
.drive-outcome{
  display:flex; align-items:center; gap:8px; margin:12px 0 0;
  font-size:12px; line-height:1.4; padding:9px 11px; border-radius:9px;
  background:var(--surface2); border:1px solid var(--border);
}
.drive-outcome svg{width:15px; height:15px; fill:none; stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round; flex:0 0 auto;}
.drive-outcome.ok{border-color:var(--good);}
.drive-outcome.ok svg{stroke:var(--good);}
/* Not a red sentence: the text says what happened and the border says how it went. A failed backup
   changed nothing on the device, so it is a disappointment rather than an error. */
.drive-outcome.fail{border-color:var(--fail);}
.drive-outcome.fail svg{stroke:var(--fail);}
.drive-note{font-size:11px; color:var(--text-faint); line-height:1.5; margin:10px 2px 0;}

/* ---------- RESTORE A BACKUP ---------- */
/* A destructive action needs a button that looks like one. .btn-primary is the accent, which is the
   same orange as every harmless Save in the app — using it here would make "overwrite a year of
   training" and "save a set" the same colour. */
.btn-danger{
  background:var(--fail); color:#fff; border:none; border-radius:12px; padding:15px; width:100%;
  font-family:'Inter'; font-weight:700; font-size:15px; cursor:pointer;
}
.btn-danger:active{opacity:0.85;}

.rst-verdict{
  padding:14px; border-radius:12px; margin-bottom:16px;
  background:var(--surface2); border:1px solid var(--border); border-left-width:3px;
}
.rst-headline{font-size:14.5px; font-weight:600; line-height:1.45;}
.rst-warning{font-size:13px; color:var(--fail); line-height:1.5; margin-top:8px; font-weight:600;}
.rst-safe, .rst-gain{border-left-color:var(--good);}
.rst-identical, .rst-minor-loss{border-left-color:var(--text-faint);}
.rst-mixed{border-left-color:var(--accent);}
.rst-loss{border-left-color:var(--fail);}

.rst-cols{display:flex; gap:10px; margin-bottom:14px;}
.rst-col{
  flex:1 1 0; min-width:0; padding:11px 12px; border-radius:10px;
  background:var(--surface2); border:1px solid var(--border);
}
.rst-col-title{font-size:12px; font-weight:700; line-height:1.3;}
.rst-col-sub{font-size:10.5px; color:var(--text-faint); text-transform:uppercase; letter-spacing:0.06em; margin-top:2px;}
.rst-range{font-size:11px; color:var(--text-dim); margin-top:6px; line-height:1.4;}

.rst-table{width:100%; border-collapse:collapse; margin-bottom:14px; font-size:13px;}
.rst-table thead th{
  font-size:10px; text-transform:uppercase; letter-spacing:0.07em; color:var(--text-faint);
  font-weight:700; text-align:right; padding:0 0 6px;
}
.rst-table thead th:first-child{text-align:left;}
.rst-table tbody th{
  text-align:left; font-weight:500; color:var(--text-dim); padding:7px 0;
  border-top:1px solid var(--border);
}
.rst-table td{padding:7px 0; border-top:1px solid var(--border); text-align:right;}
.rst-num{font-family:'JetBrains Mono',monospace; font-size:12.5px; min-width:44px;}
.rst-arrow{color:var(--text-faint); width:22px; text-align:center;}
/* The number that moved is the one worth colouring, and only the direction that matters. */
.rst-up td:last-child{color:var(--good);}
.rst-down-bad td:last-child{color:var(--fail); font-weight:700;}
.rst-down-bad .rst-arrow{color:var(--fail);}
.rst-flat th, .rst-flat td{color:var(--text-faint);}

.rst-days{
  font-size:12px; color:var(--text-dim); line-height:1.55;
  padding:10px 12px; border-radius:0 8px 8px 0; margin-bottom:10px;
  background:var(--surface); border-left:2px solid var(--border);
}
.rst-days-lose{border-left-color:var(--fail);}
.rst-days-label{
  display:block; font-size:10px; text-transform:uppercase; letter-spacing:0.07em;
  font-weight:700; color:var(--text-faint); margin-bottom:3px;
}
.rst-notes{margin:14px 0 4px;}
.rst-notes p{font-size:11.5px; color:var(--text-faint); line-height:1.55; margin:0 0 7px;}

/* Cancel FIRST and Replace second, on their own rows. Side by side on a phone puts a destructive
   button under the thumb next to a safe one, and the safe one should be the easy reach. */
.rst-actions{display:flex; flex-direction:column-reverse; gap:9px; margin:18px 0 26px;}
.rst-actions .btn-secondary{margin-top:0;}

/* ---------- HOW'D I DO? ---------- */
/* The entry point, under the rows rather than in the header — this is the question you ask after the
   last set, and the last set is what you have just scrolled past. */
.btn-secondary.compare-cta{
  display:flex; align-items:center; justify-content:center; gap:8px;
  margin:22px 0 8px; padding:14px;
}
.compare-cta svg{width:16px; height:16px; stroke:var(--accent); fill:none; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round;}
.compare-cta span{font-size:14px; font-weight:600;}

/* The day's answer. Tinted by outcome, because the point of a verdict is that it lands before it
   is read — but the tint is a border and a wash, never the text colour: a red sentence reads as an
   error, and a heavy week is not an error. */
.cmp-verdict{
  display:flex; align-items:flex-start; gap:12px;
  padding:15px; border-radius:12px; margin:14px 0 18px;
  background:var(--surface2); border:1px solid var(--border);
}
.cmp-verdict-icon{
  display:flex; align-items:center; justify-content:center; flex:0 0 auto;
  width:36px; height:36px; border-radius:10px; background:var(--surface3);
}
.cmp-verdict-icon svg{width:20px; height:20px; fill:none; stroke:var(--text-dim); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round;}
.cmp-verdict-line{font-family:'Bebas Neue'; font-size:25px; line-height:1.1; letter-spacing:0.03em;}
.cmp-verdict-detail{font-size:12.5px; color:var(--text-dim); line-height:1.5; margin-top:5px;}
.cmp-v-up{border-color:var(--good);}
.cmp-v-up .cmp-verdict-icon svg{stroke:var(--good);}
.cmp-v-down{border-color:var(--fail);}
.cmp-v-down .cmp-verdict-icon svg{stroke:var(--fail);}
.cmp-v-mixed{border-color:var(--accent-dim);}
.cmp-v-mixed .cmp-verdict-icon svg{stroke:var(--accent);}

/* What is missing from today, next to what is in it. Dashed, like the app's other "here is some
   context you did not ask for" strips, so it reads as an aside rather than a warning. */
.cmp-shape{
  border:1px dashed var(--border); border-radius:12px; padding:13px; margin-bottom:18px;
  font-size:13px; color:var(--text-dim); line-height:1.55;
}
.cmp-shape-label{
  font-size:10px; text-transform:uppercase; letter-spacing:0.07em; font-weight:700;
  color:var(--text-faint); margin-right:6px;
}
.cmp-shape-rule{font-size:11.5px; color:var(--text-faint); margin-top:8px; line-height:1.5;}

.cmp-list{display:flex; flex-direction:column; gap:11px; margin-bottom:26px;}
.cmp-card{
  background:var(--surface2); border:1px solid var(--border); border-radius:12px; padding:14px;
  border-left-width:3px;
}
.cmp-improved{border-left-color:var(--good);}
.cmp-regressed{border-left-color:var(--fail);}
.cmp-mixed{border-left-color:var(--accent);}
.cmp-same{border-left-color:var(--text-faint);}
.cmp-first, .cmp-unreadable{border-left-color:var(--border);}

.cmp-top{display:flex; align-items:baseline; justify-content:space-between; gap:10px;}
.cmp-name{font-weight:600; font-size:15px; line-height:1.3;}
.cmp-badge{
  flex:0 0 auto; font-size:10px; text-transform:uppercase; letter-spacing:0.07em; font-weight:700;
  color:var(--text-faint); padding-top:2px;
}
.cmp-improved .cmp-badge{color:var(--good);}
.cmp-regressed .cmp-badge{color:var(--fail);}
.cmp-mixed .cmp-badge{color:var(--accent);}
.cmp-headline{font-size:13.5px; color:var(--text); margin-top:5px; line-height:1.45;}

/* The working. Mono, because these are numbers being compared and they should line up. */
.cmp-nums{
  display:flex; align-items:center; flex-wrap:wrap; gap:6px 8px; margin-top:8px;
  font-family:'JetBrains Mono',monospace; font-size:12px; line-height:1.5;
}
.cmp-then{color:var(--text-faint); text-decoration:line-through; text-decoration-color:var(--border);}
.cmp-arrow{color:var(--text-faint);}
.cmp-now{color:var(--text);}
.cmp-when{font-size:11px; color:var(--text-faint); margin-top:6px;}
.cmp-volume{
  font-size:11.5px; color:var(--text-dim); line-height:1.5; margin-top:9px;
  padding:8px 10px; border-radius:0 8px 8px 0;
  background:var(--surface); border-left:2px solid var(--accent-dim);
}
.cmp-aside{font-size:11.5px; color:var(--text-faint); line-height:1.5; margin-top:8px;}

/* ---------- THE WELCOME ---------- */
/* A column with a scrolling middle and a pinned footer, so Skip and Next are reachable without
   scrolling to find them — on a 360px phone the longest step is taller than the viewport, and an
   introduction whose way out is below the fold is the exact thing people resent.

   `display:flex` here is safe against `.hidden`, which is `display:none !important`. */
#introModal{
  display:flex; flex-direction:column; overflow:hidden;
  padding-bottom:calc(16px + env(safe-area-inset-bottom));
}
.intro-head{display:flex; justify-content:space-between; align-items:center; flex:0 0 auto; margin-bottom:4px;}
.intro-brand{
  font-family:'Bebas Neue'; font-size:26px; letter-spacing:0.08em; color:var(--accent);
}
/* The one element that scrolls. min-height:0 is what actually lets it: a flex child defaults to
   min-height:auto and refuses to shrink below its content, which pushes the footer off-screen. */
.intro-body{flex:1 1 auto; min-height:0; overflow-y:auto; padding:8px 2px 16px;}
.intro-icon{
  display:flex; align-items:center; justify-content:center;
  width:52px; height:52px; margin:10px 0 16px; border-radius:14px;
  background:var(--accent-soft); border:1px solid var(--accent-dim);
}
.intro-icon svg{width:26px; height:26px; stroke:var(--accent); fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}
.intro-title{
  font-family:'Bebas Neue'; font-size:34px; line-height:1.05; margin:0 0 12px; letter-spacing:0.03em;
}
.intro-body p{font-size:14.5px; line-height:1.6; color:var(--text-dim); margin:0 0 12px;}
.intro-body p:last-child{margin-bottom:0;}
.intro-body strong{color:var(--text); font-weight:600;}

.intro-foot{
  flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding-top:14px; border-top:1px solid var(--border);
}
.intro-btns{display:flex; align-items:center; gap:8px;}
/* Two classes: .btn-primary is width:100% and is declared earlier, so a single-class rule would
   tie on specificity and lose on source order. */
.btn-primary.intro-next{width:auto; margin-top:0; padding:11px 20px; border-radius:10px;}
.intro-dots{display:flex; gap:6px;}
.intro-dot{
  width:6px; height:6px; border-radius:50%; background:var(--border); transition:background 0.2s;
}
.intro-dot.active{background:var(--accent);}

/* Reachable from every help section rather than buried in one, since help opens on the tab you
   happen to be standing on. */
.help-replay{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  margin:4px 0 28px; padding:14px; border:1px dashed var(--border); border-radius:12px;
}
.help-replay span{font-size:13px; color:var(--text-faint); line-height:1.5;}

/* ---------- THE FULL TOUR ---------- */
/* The same sticky-header construction as the help modal, and the same gotcha with it: the modal
   must have NO top padding or `top:0` resolves 20px down and the content slides up through a
   transparent strip. See the note above `.help-head`. */
#tourModal{padding-top:0; padding-bottom:0; display:flex; flex-direction:column;}
#tourBody{flex:1 1 auto; overflow-y:auto; padding-top:4px;}

/* At the top of every help section, because help opens on whichever tab you were standing on and
   somebody still reading it is the person who wanted the ordered version. */
.help-tour-cta{
  display:flex; align-items:center; gap:11px; width:100%; text-align:left; cursor:pointer;
  margin:16px 0 4px; padding:12px 13px;
  background:var(--surface2); border:1px solid var(--accent-dim); border-radius:12px; color:var(--text);
  font-family:'Inter',sans-serif;
}
.help-tour-cta svg{width:18px; height:18px; flex:0 0 auto; stroke:var(--accent); fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}
.help-tour-cta span{display:flex; flex-direction:column; gap:2px; min-width:0; font-size:11.5px; color:var(--text-faint); line-height:1.45;}
.help-tour-cta strong{font-size:13.5px; font-weight:600; color:var(--text);}
.help-tour-cta:active{background:var(--accent-soft);}

.tour-progress{
  font-size:11px; color:var(--text-faint); text-transform:uppercase; letter-spacing:0.06em;
  font-weight:700; margin:0 0 7px;
}
/* Twenty-five steps is a long way, and a tour that does not say how far in you are is one people
   abandon at step four on the assumption there are forty. */
.tour-bar{height:3px; border-radius:2px; background:var(--surface3); overflow:hidden; margin-bottom:11px;}
.tour-bar span{display:block; height:100%; background:var(--accent); transition:width 0.25s;}
/* One row that scrolls sideways, NOT the help modal's wrapping strip. Eight chapters wrap to three
   rows on a 390px phone, and this header is sticky — that is 110px of a 844px screen given up
   permanently to navigation you use twice. The active chip is scrolled into view by the renderer,
   so the one you are on is never the one off the edge. */
.tour-chapters{
  display:flex; gap:6px; flex-wrap:nowrap; overflow-x:auto;
  padding-bottom:12px; border-bottom:1px solid var(--border);
  scrollbar-width:none; -ms-overflow-style:none;
}
.tour-chapters::-webkit-scrollbar{display:none;}
.tour-chapters .help-tab{flex:0 0 auto;}
/* Which tab the card in front of you is actually about. The running order is by task, so a card
   can turn up two chapters away from the tab it describes. */
.tour-where{
  font-size:11.5px; color:var(--text-faint); margin:14px 2px 0;
}
.tour-where strong{color:var(--accent); font-weight:600;}

/* The way from the short version to the long one. Quiet, because most steps will not need it. */
.tour-more{
  display:flex; align-items:center; gap:5px; cursor:pointer;
  margin:10px 2px 0; padding:6px 0;
  background:none; border:none; color:var(--accent);
  font-family:'Inter',sans-serif; font-size:12.5px; font-weight:600;
}
.tour-more svg{width:13px; height:13px; stroke:currentColor; fill:none; stroke-width:2.5; stroke-linecap:round; stroke-linejoin:round;}

.tour-foot{
  flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:14px 0 calc(14px + env(safe-area-inset-bottom));
  border-top:1px solid var(--border); background:var(--surface);
}
/* Two classes, same reason as .btn-primary.intro-next: .btn-primary is width:100% and declared
   earlier, so one class would tie on specificity and lose on source order. */
.btn-primary.tour-next{width:auto; margin-top:0; padding:11px 22px; border-radius:10px;}
/* Back is hidden on step one, and the footer must not collapse Next to the left when it goes. */
#tourBack.hidden + .tour-next{margin-left:auto;}

/* The one-time offer, at the top of the Log tab. Dashed like the attach button and the classify
   CTA were: this is an invitation, not a control the tab needs. */
.tour-offer{
  display:flex; align-items:flex-start; gap:11px; flex-wrap:wrap;
  margin-bottom:16px; padding:13px;
  background:var(--surface2); border:1px dashed var(--accent-dim); border-radius:12px;
}
.tour-offer svg{width:18px; height:18px; flex:0 0 auto; margin-top:1px; stroke:var(--accent); fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}
.tour-offer-text{flex:1 1 190px; min-width:0; display:flex; flex-direction:column; gap:3px;}
.tour-offer-text strong{font-size:13.5px; font-weight:600; color:var(--text);}
.tour-offer-text span{font-size:11.5px; color:var(--text-faint); line-height:1.45;}
.tour-offer-actions{display:flex; gap:8px; margin-left:auto;}
.tour-offer-go{border-color:var(--accent); color:var(--accent);}

#toast{
  position:fixed; bottom:100px; left:50%; transform:translateX(-50%) translateY(20px); z-index:60;
  background:var(--surface3); color:var(--text); padding:10px 18px; border-radius:30px; font-size:13px;
  border:1px solid var(--border); opacity:0; transition:all 0.25s; pointer-events:none;
}
#toast.show{opacity:1; transform:translateX(-50%) translateY(0);}

::-webkit-scrollbar{width:0; height:0;}

.fail { color: var(--fail) !important; font-weight: 700; }

#toggleFail {
  border-color: var(--fail);
  color: var(--text-dim);
  background: var(--surface2);
  transition: all 0.2s;
}
#toggleFail.on {
  background: rgba(255, 67, 104, 0.15);
  border-color: var(--fail);
  color: var(--fail);
}

#historyList .hist-edit-btn {
  display: none !important;
}
#historyList.edit-mode .hist-edit-btn {
  display: flex !important;
  align-items: center;
  justify-content: center;
}

/* ---------- Progress chart ---------- */
/* Hand-rolled SVG, no library. The element is width:100% height:auto, so the viewBox is a
   shape rather than a pixel size and the whole thing scales into a phone-width card. */
.chart-card{
  background:var(--surface2); border:1px solid var(--border);
  border-radius:var(--radius); padding:12px 12px 8px; margin-bottom:16px;
}
.chart-head{display:flex; justify-content:space-between; align-items:baseline; gap:10px; margin-bottom:4px;}
.chart-title{
  font-family:'Bebas Neue',sans-serif; font-size:17px; letter-spacing:0.04em;
  color:var(--text-dim); text-transform:uppercase;
}
.chart-tabs{display:flex; gap:4px; flex-shrink:0;}
.chart-tab{
  font-family:'Bebas Neue',sans-serif; font-size:15px; letter-spacing:0.04em; text-transform:uppercase;
  background:transparent; border:1px solid transparent; color:var(--text-faint);
  padding:2px 8px; border-radius:7px; cursor:pointer; line-height:1.5;
}
.chart-tab.active{background:var(--accent-soft); border-color:var(--accent-dim); color:var(--accent);}
.chart-latest{
  font-family:'JetBrains Mono',monospace; font-size:15px; font-weight:700;
  color:var(--text); text-align:right; white-space:nowrap;
}
.chart-unit{font-size:10px; font-weight:400; color:var(--text-faint);}
.chart-review{
  display:block; width:100%; margin-top:6px; padding:6px 0;
  background:transparent; border:none; border-top:1px solid var(--border);
  color:var(--accent); font-family:'Inter',sans-serif; font-size:11.5px;
  text-align:left; cursor:pointer;
}
.chart-card svg{display:block; width:100%; height:auto; overflow:visible;}
/* The record, under the chart it belongs to. Not accent-coloured: the line above it already
   owns that, and a second orange thing in one card competes with it. */
.chart-pb{display:flex; align-items:baseline; gap:8px; margin-top:8px; padding-top:8px; border-top:1px solid var(--border);}
.chart-pb .pb-label{font-size:10.5px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.06em; font-weight:700;}
.chart-pb .pb-value{font-family:'JetBrains Mono'; font-size:14px; color:var(--text); font-weight:700;}
.chart-pb .pb-date{font-size:11px; color:var(--text-faint); font-family:'Inter'; margin-left:auto;}

.chart-note{font-size:11px; color:var(--text-faint); line-height:1.45; margin-top:6px;}

.chart-grid{stroke:var(--border); stroke-width:1;}
.chart-line{fill:none; stroke:var(--accent); stroke-width:2; stroke-linejoin:round; stroke-linecap:round;}
.chart-dot{fill:var(--accent);}
/* Hollow: the day was only partly readable, so the value is a floor, not a measurement. */
.chart-dot-partial{fill:var(--surface2); stroke:var(--accent); stroke-width:2;}
/* A day you trained that nothing could be read from. Marked, never joined to the line. */
.chart-blank{stroke:var(--text-faint); stroke-width:2;}
.chart-label{fill:var(--text-faint); font-family:'Inter',sans-serif; font-size:9px;}

/* ---------- CHECK MY EXERCISES ---------- */
/* The round trip that corrects the type and the muscle groups of what you already have. Every row on
   this screen replaces a decision you made, so the shape borrowed here is the restore panel's — the
   diff first, the cost stated — rather than the generator's list of things to add. */
.classify-summary{
  font-size:12.5px; color:var(--text-dim); line-height:1.55;
  background:var(--surface2); border:1px solid var(--border); border-radius:10px; padding:10px 12px;
}
.classify-summary strong{color:var(--text);}

.cf-section{margin-bottom:20px;}
.cf-head{
  font-family:'Bebas Neue',sans-serif; letter-spacing:0.06em; text-transform:uppercase;
  font-size:16px; color:var(--text-dim); margin-bottom:3px;
}
.cf-note{font-size:11.5px; color:var(--text-faint); line-height:1.45; margin-bottom:10px;}

/* One row per change, ticked by default: the list only holds disagreements, and somebody who asked
   for corrections wants them — so unticking is the deliberate act. The opposite default from the
   restore panel, because nothing here is destructive on its own. */
.cf-row{
  display:flex; align-items:flex-start; gap:10px; cursor:pointer;
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  padding:10px 12px; margin-bottom:6px;
}
.cf-row.on{border-color:var(--accent-dim); background:var(--accent-soft);}
.cf-row input{margin:2px 0 0; accent-color:var(--accent); flex:0 0 auto; width:16px; height:16px;}
.cf-body{min-width:0; display:flex; flex-direction:column; gap:3px;}
.cf-name{font-size:13.5px; font-weight:600; color:var(--text); line-height:1.3;}
.cf-line{display:flex; flex-wrap:wrap; align-items:baseline; gap:6px; font-size:11.5px; line-height:1.4;}
.cf-what{color:var(--text-faint); text-transform:uppercase; letter-spacing:0.05em; font-size:9.5px; font-weight:700;}
/* Struck through, because "what it is now" is the thing being replaced and reading the two as a pair
   is the whole point of showing both. */
.cf-from{color:var(--text-faint); text-decoration:line-through;}
.cf-arrow{color:var(--text-faint);}
.cf-to{color:var(--accent); font-weight:600;}

.cf-none{
  font-size:13px; color:var(--text-dim); line-height:1.55;
  background:var(--surface2); border:1px solid var(--good); border-radius:10px; padding:12px 14px;
}
.cf-none strong{color:var(--text);}
/* Reported rather than dropped, and set apart rather than mixed into the list — these are things you
   might want to act on, not changes you can tick. */
.cf-aside{
  font-size:11.5px; color:var(--text-faint); line-height:1.5; margin-top:12px;
  border:1px dashed var(--border); border-radius:10px; padding:10px 12px;
}
.cf-aside strong{color:var(--text-dim);}

/* The flagged exercises: the one block on this screen that might be telling you the APP is missing
   something rather than that your data is. A heading and the reasoning, not a footnote — and sorted by
   how many exercises want the same thing, because that count is the actual decision. */
.cf-flagged .cf-head{color:var(--accent);}
.cf-flag{
  background:var(--surface); border:1px solid var(--border); border-left:2px solid var(--accent-dim);
  border-radius:10px; padding:10px 12px; margin-bottom:6px;
}
.cf-flag-head{display:flex; align-items:baseline; justify-content:space-between; gap:8px;}
.cf-flag-name{font-size:13px; font-weight:600; color:var(--text); line-height:1.3;}
/* Only drawn when it applies to more than one, so its presence is itself the signal. */
.cf-flag-count{
  flex:0 0 auto; font-size:10px; font-weight:700; letter-spacing:0.04em; text-transform:uppercase;
  color:var(--accent); background:var(--accent-soft); border-radius:20px; padding:2px 8px;
}
.cf-flag-needs{font-size:11.5px; color:var(--text-dim); line-height:1.45; margin-top:4px;}
.cf-flag-for{font-size:11px; color:var(--text-faint); line-height:1.4; margin-top:4px;}
.cf-flagged .btn-mini{margin-top:4px;}
