/* ============================================================
   FeAx Fit — application stylesheet
   Tokens inherited from the FeAx design system; the animated
   aurora/grain layers are deliberately NOT here. They belong on
   a landing page you look at once, not on a tool you stare at
   for six hours. Backgrounds are static, contrast is high, and
   nothing moves unless you moved it.

   Tokens and primitives are shared verbatim with feax-notes; the
   data-visualisation section at the end of this file is new. Charts
   here are hand-drawn SVG rather than a library: three chart types
   and no build step means a dependency would cost more than it saves.
   ============================================================ */

/* ---------- fonts (self-hosted, same files as feax-film) ---------- */
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/Inter-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/Inter-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA,U+1E00-1E9F,U+2113}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/Inter-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/Inter-500-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA,U+1E00-1E9F,U+2113}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/Inter-600-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/Inter-600-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA,U+1E00-1E9F,U+2113}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/Inter-700-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/SpaceGrotesk-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/SpaceGrotesk-700-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}
@font-face{font-family:'Inconsolata';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/Inconsolata-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}
@font-face{font-family:'Inconsolata';font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/Inconsolata-700-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122}

/* Cyrillic. Inter has real Cyrillic; Space Grotesk and Inconsolata have none,
   so Manrope and IBM Plex Mono stand in over the Cyrillic unicode-range under
   the SAME family names, metric-matched with size-adjust. Without this, any
   Russian note silently falls back to a system font mid-sentence. */
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/Inter-400-cyrillic.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/Inter-500-cyrillic.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/Inter-600-cyrillic.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/Inter-700-cyrillic.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/Manrope-500-cyrillic.woff2) format('woff2');size-adjust:94.6%;ascent-override:104%;descent-override:30.9%;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/Manrope-700-cyrillic.woff2) format('woff2');size-adjust:94.6%;ascent-override:104%;descent-override:30.9%;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Inconsolata';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/IBMPlexMono-400-cyrillic.woff2) format('woff2');size-adjust:87.2%;ascent-override:98.5%;descent-override:21.8%;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Inconsolata';font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/IBMPlexMono-700-cyrillic.woff2) format('woff2');size-adjust:87.2%;ascent-override:98.5%;descent-override:21.8%;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}

/* ============================================================
   TOKENS
   Dark is the default (FeAx house look). Light is a real theme,
   not an inversion — a notes app gets used in daylight.
   ============================================================ */
:root{
  --ax1:#7C5CFF;
  --ax2:#38E1FF;
  --grad:linear-gradient(100deg,var(--ax1),var(--ax2));

  /* The brand colours are chosen to glow on a near-black background. Used as
     TEXT on the light theme they fail contrast badly — #38E1FF on white is
     about 1.6:1. So anything that paints an accent as text uses these tokens
     instead, and only fills/borders/gradients use --ax1/--ax2 directly. */
  --ax1-ink:#B4A0FF;
  --ax2-ink:#38E1FF;

  --bg:#0A0C14;
  --bg-rail:#080A11;
  --bg-list:#0C0F18;
  --bg-edit:#0A0C14;
  --panel:rgba(255,255,255,.04);
  --panel2:rgba(255,255,255,.07);
  --panel3:rgba(255,255,255,.10);
  --line:rgba(255,255,255,.08);
  --line2:rgba(255,255,255,.15);
  --ink:#EEF2FF;
  --ink2:#C3CCE4;
  --mut:#8B97B4;
  --dim:#5A6580;
  --ok:#4ADE80;
  --warn:#FBBF24;
  --bad:#FB7185;

  --f-b:'Inter',system-ui,'Segoe UI',sans-serif;
  --f-d:'Space Grotesk','Inter',system-ui,sans-serif;
  --f-m:'Inconsolata',ui-monospace,'SF Mono',Menlo,monospace;

  --rad:12px;
  --rad-sm:9px;
  --rail-w:238px;
  --list-w:336px;
  --shadow:0 18px 50px -20px rgba(0,0,0,.75);
  --tap:44px;              /* minimum comfortable touch target */
}

:root[data-theme="light"]{
  --ax1-ink:#6D28D9;   /* violet-700  — 6.8:1 on the light background */
  --ax2-ink:#0E7490;   /* cyan-700    — 4.9:1 on the light background */
  --bg:#FBFBFD;
  --bg-rail:#F3F4F8;
  --bg-list:#F8F9FC;
  --bg-edit:#FFFFFF;
  --panel:rgba(10,14,30,.035);
  --panel2:rgba(10,14,30,.06);
  --panel3:rgba(10,14,30,.09);
  --line:rgba(10,14,30,.10);
  --line2:rgba(10,14,30,.18);
  --ink:#131726;
  --ink2:#38405A;
  --mut:#606B87;
  --dim:#8791A8;
  --ok:#16A34A;
  --warn:#B45309;
  --bad:#DC2626;
  --shadow:0 14px 40px -22px rgba(16,22,44,.35);
}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  font:15px/1.6 var(--f-b);
  background:var(--bg);
  color:var(--ink);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overscroll-behavior:none;
}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit;background:none;border:none}
button{cursor:pointer}
h1,h2,h3,h4{font-family:var(--f-d);letter-spacing:-.02em;line-height:1.25;font-weight:700}
::selection{background:color-mix(in srgb,var(--ax1) 55%,transparent);color:#fff}

/* Focus: invisible for mouse users, unmissable for keyboard users. */
:focus{outline:none}
:focus-visible{outline:2px solid var(--ax2);outline-offset:2px;border-radius:4px}

/* Scrollbars — thin and out of the way, but still grabbable. */
*{scrollbar-width:thin;scrollbar-color:var(--line2) transparent}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background:var(--line2);border-radius:99px;border:3px solid transparent;background-clip:content-box}
*::-webkit-scrollbar-thumb:hover{background:var(--dim);background-clip:content-box}

/* ============================================================
   SHELL — three panes on desktop, one at a time on mobile
   ============================================================ */
.shell{
  display:grid;
  grid-template-columns:var(--rail-w) var(--list-w) 1fr;
  height:100dvh;
  overflow:hidden;
}

/* ---------- rail ---------- */
.rail{
  background:var(--bg-rail);
  border-right:1px solid var(--line);
  display:flex;flex-direction:column;
  min-height:0;
  padding:14px 10px 0;
}
.rail-brand{display:flex;align-items:center;gap:9px;padding:4px 8px 14px}
.rail-brand img{height:22px;flex:none}
.rail-brand b{font:700 11px/1 var(--f-m);letter-spacing:.2em;text-transform:uppercase;color:var(--ax2-ink)}

.rail-actions{display:flex;gap:8px;padding:0 4px 12px}
.rail-scroll{flex:1;overflow-y:auto;min-height:0;padding:0 4px 10px}

.rail-group{margin:16px 0 6px;padding:0 10px;display:flex;align-items:center;justify-content:space-between}
.rail-group span{font:700 10px/1 var(--f-m);letter-spacing:.18em;text-transform:uppercase;color:var(--dim)}
.rail-group button{color:var(--dim);font-size:16px;line-height:1;padding:3px 5px;border-radius:6px}
.rail-group button:hover{color:var(--ink);background:var(--panel2)}

.rail-item{
  display:flex;align-items:center;gap:10px;
  width:100%;padding:9px 10px;border-radius:var(--rad-sm);
  color:var(--mut);font-weight:500;font-size:14px;text-align:left;
  transition:background .15s,color .15s;
  position:relative;
}
.rail-item:hover{background:var(--panel2);color:var(--ink)}
.rail-item.is-on{background:var(--panel3);color:var(--ink);font-weight:600}
.rail-item.is-on::before{
  content:"";position:absolute;left:-4px;top:50%;transform:translateY(-50%);
  width:3px;height:16px;border-radius:0 3px 3px 0;background:var(--grad);
}
.rail-item .ico{width:17px;height:17px;flex:none;opacity:.85}
.rail-item .label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail-item .count{font:600 11px/1 var(--f-m);color:var(--dim);flex:none}
.rail-item .swatch{width:9px;height:9px;border-radius:3px;flex:none}

.sw-violet{background:#8B5CF6}.sw-cyan{background:#22D3EE}.sw-green{background:#34D399}
.sw-amber{background:#FBBF24}.sw-rose{background:#FB7185}.sw-slate{background:#94A3B8}

.rail-foot{
  border-top:1px solid var(--line);
  padding:10px 6px calc(10px + env(safe-area-inset-bottom));
  display:flex;align-items:center;gap:9px;
}
.avatar{
  width:28px;height:28px;border-radius:50%;flex:none;
  background:var(--grad);color:#fff;
  display:grid;place-items:center;
  font:700 11px/1 var(--f-b);letter-spacing:.02em;
}
.rail-foot .who{flex:1;min-width:0}
.rail-foot .who b{display:block;font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail-foot .who small{display:block;font-size:11px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---------- list ---------- */
.list{
  background:var(--bg-list);
  border-right:1px solid var(--line);
  display:flex;flex-direction:column;min-height:0;
}
.list-head{
  padding:14px 14px 10px;border-bottom:1px solid var(--line);
  display:flex;flex-direction:column;gap:10px;flex:none;
}
.list-title{display:flex;align-items:center;gap:10px}
.list-title h2{font-size:16px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.list-title .n{font:600 11px/1 var(--f-m);color:var(--dim)}

.search{
  display:flex;align-items:center;gap:8px;
  background:var(--panel);border:1px solid var(--line);
  border-radius:var(--rad-sm);padding:0 10px;
  transition:border-color .15s;
}
.search:focus-within{border-color:color-mix(in srgb,var(--ax2) 60%,transparent)}
.search svg{width:15px;height:15px;color:var(--dim);flex:none}
.search input{flex:1;padding:9px 0;font-size:14px;min-width:0}
.search input::placeholder{color:var(--dim)}
.search kbd{
  font:600 10px/1 var(--f-m);color:var(--dim);
  border:1px solid var(--line2);border-radius:4px;padding:3px 5px;flex:none;
}
.search .clear{color:var(--dim);font-size:15px;padding:4px;line-height:1}
.search .clear:hover{color:var(--ink)}

.list-scroll{flex:1;overflow-y:auto;min-height:0;padding:6px}

.card{
  display:block;width:100%;text-align:left;
  padding:11px 12px;border-radius:var(--rad-sm);
  border:1px solid transparent;
  transition:background .13s,border-color .13s;
  position:relative;
}
.card:hover{background:var(--panel)}
.card.is-on{background:var(--panel2);border-color:var(--line2)}
.card + .card{margin-top:2px}
.card h3{
  font-family:var(--f-b);font-size:14px;font-weight:600;line-height:1.35;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  display:flex;align-items:center;gap:6px;
}
.card h3 .pin{color:var(--ax2-ink);flex:none}
.card p{
  font-size:12.5px;color:var(--mut);line-height:1.45;margin-top:3px;
  display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.card .meta{display:flex;align-items:center;gap:7px;margin-top:7px;flex-wrap:wrap}
.card .meta time{font:500 11px/1 var(--f-m);color:var(--dim)}

/* ---------- drag to reorder ---------- */
.card.is-sortable{padding-left:30px}
.card .grip{
  position:absolute;left:6px;top:50%;transform:translateY(-50%);
  width:20px;height:30px;display:grid;place-items:center;
  color:var(--dim);opacity:.5;cursor:grab;
  /* The browser must never claim a gesture that starts here as a scroll —
     without this, a drag on touch just scrolls the list instead. */
  touch-action:none;
  transition:opacity .15s,color .15s;
}
.card:hover .grip{opacity:1;color:var(--mut)}
.card .grip svg{width:15px;height:15px}
.card .grip:active{cursor:grabbing}

.card.is-dragging{
  /* Lifted off the page: shadow, slight scale, and above its neighbours. */
  position:relative;z-index:30;
  box-shadow:var(--shadow);
  background:var(--bg-list);
  border-color:var(--ax2);
  cursor:grabbing;
  transform-origin:center;
}
.card.is-dragging .grip{opacity:1;color:var(--ax2-ink)}
/* Neighbours glide into place; the dragged card must NOT animate or it lags
   behind the finger. */
.list-scroll .card:not(.is-dragging){transition:transform .16s cubic-bezier(.2,.8,.2,1)}

/* Kill text selection everywhere while a drag is live — otherwise dragging
   over the list highlights note previews as you go. */
body.is-reordering{user-select:none;-webkit-user-select:none;cursor:grabbing}
body.is-reordering .card{cursor:grabbing}

@media (prefers-reduced-motion:reduce){
  .list-scroll .card:not(.is-dragging){transition:none}
}

/* On touch the grip needs a real target, and hover never fires so it must be
   permanently visible. */
@media (max-width:860px){
  .card.is-sortable{padding-left:38px}
  .card .grip{width:30px;height:44px;left:2px;opacity:.85;color:var(--mut)}
  .card .grip svg{width:17px;height:17px}
}

.badge{
  display:inline-flex;align-items:center;gap:4px;
  font:600 10px/1 var(--f-m);letter-spacing:.04em;
  padding:3px 6px;border-radius:5px;
  background:var(--panel2);color:var(--mut);
}
.badge.team{color:var(--ax2-ink);background:color-mix(in srgb,var(--ax2) 14%,transparent)}
.badge.shared{color:var(--ax1-ink);background:color-mix(in srgb,var(--ax1) 16%,transparent)}
.badge.todo{color:var(--ok);background:color-mix(in srgb,var(--ok) 13%,transparent)}
.badge.todo.done{color:var(--ok)}
.badge.tag{color:var(--mut)}
.badge.owner{color:var(--dim)}

/* ---------- editor ---------- */
.editor{background:var(--bg-edit);display:flex;flex-direction:column;min-height:0}
.ed-head{
  flex:none;border-bottom:1px solid var(--line);
  padding:10px 16px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  min-height:52px;
}
.ed-head .grow{flex:1;min-width:0}
.ed-title{
  width:100%;font:700 19px/1.3 var(--f-d);letter-spacing:-.02em;
  padding:4px 0;background:transparent;
}
.ed-title::placeholder{color:var(--dim);font-weight:500}
.ed-sub{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--dim);flex-wrap:wrap}
.ed-sub .sep{opacity:.4}

.ed-body{flex:1;overflow-y:auto;min-height:0;position:relative}
.ed-inner{max-width:760px;margin:0 auto;padding:22px 26px 45vh}

/* ---------- write mode: the TEXTAREA owns the scrolling ---------- */
/*
   This used to be an auto-growing textarea inside a scrolling ancestor. To
   measure its content, auto-grow has to reset the height to `auto` on every
   keystroke — which momentarily collapses the content, so the browser clamps
   the ancestor's scrollTop, and the note visibly jumps on every Enter. Worse,
   nothing then kept the caret on screen: on a note longer than the viewport you
   ended up typing blind against the bottom edge.

   Letting the textarea scroll itself hands caret tracking back to the browser,
   which does it correctly, natively, and on every platform — including with a
   phone keyboard open. There is no height maths left to get wrong.
*/
.editor.is-writing .ed-body{overflow:hidden}
.editor.is-writing .ed-inner{
  height:100%;
  display:flex;
  flex-direction:column;
  padding-bottom:0;
}

textarea.ed-text{
  flex:1;min-height:0;
  width:100%;resize:none;overflow-y:auto;
  font:15px/1.75 var(--f-b);
  background:transparent;color:var(--ink);
  white-space:pre-wrap;word-wrap:break-word;
  tab-size:2;
  /* Trailing room so the last line can be scrolled up away from the bottom
     edge — you should never be typing on the final pixel row of the screen. */
  padding-bottom:32vh;
  scroll-padding-bottom:12vh;
}
textarea.ed-text::placeholder{color:var(--dim)}

/* ---------- rendered markdown ---------- */
.md{font-size:15px;line-height:1.75;color:var(--ink)}
.md > *:first-child{margin-top:0}
.md h1{font-size:25px;margin:26px 0 10px}
.md h2{font-size:20px;margin:24px 0 9px}
.md h3{font-size:16.5px;margin:20px 0 7px}
.md p{margin:0 0 13px}
.md strong{font-weight:700;color:var(--ink)}
.md em{font-style:italic}
.md del{opacity:.55}
.md a{color:var(--ax2-ink);text-decoration:underline;text-underline-offset:2px;word-break:break-word}
.md a:hover{color:var(--ax1-ink)}
.md code{
  font:.88em/1.5 var(--f-m);background:var(--panel2);
  padding:2px 5px;border-radius:5px;word-break:break-word;
}
.md pre{
  background:var(--panel);border:1px solid var(--line);
  border-radius:var(--rad-sm);padding:13px 15px;margin:0 0 14px;
  overflow-x:auto;
}
.md pre code{background:none;padding:0;font-size:13px;line-height:1.6}
.md blockquote{
  border-left:2px solid var(--line2);padding:2px 0 2px 14px;
  margin:0 0 13px;color:var(--mut);
}
.md ul,.md ol{margin:0 0 13px;padding-left:22px}
.md li{margin:3px 0}
.md hr{border:0;border-top:1px solid var(--line);margin:22px 0}
.md table{border-collapse:collapse;width:100%;margin:0 0 14px;font-size:14px;display:block;overflow-x:auto}
.md th,.md td{border:1px solid var(--line);padding:7px 10px;text-align:left}
.md th{background:var(--panel);font-weight:600}

/* Checklists. The whole row is the tap target — a 13px box is a miss on a
   phone, and missing means you scroll instead of ticking. */
.md ul.todo{list-style:none;padding-left:0;margin:0 0 13px}
.md li.todo{
  display:flex;align-items:flex-start;gap:10px;
  margin:0;padding:5px 6px;border-radius:7px;
  min-height:var(--tap);cursor:pointer;
  transition:background .12s;
}
.md li.todo:hover{background:var(--panel)}
.md li.todo .box{
  flex:none;width:18px;height:18px;margin-top:4px;border-radius:5px;
  border:1.5px solid var(--line2);
  display:grid;place-items:center;transition:.15s;
}
.md li.todo .box svg{width:11px;height:11px;opacity:0;color:#fff}
.md li.todo.done .box{background:var(--grad);border-color:transparent}
.md li.todo.done .box svg{opacity:1}
.md li.todo.done .txt{color:var(--mut);text-decoration:line-through;text-decoration-color:var(--dim)}
.md li.todo .txt{flex:1;padding-top:1px}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  padding:8px 14px;border-radius:var(--rad-sm);
  border:1px solid var(--line2);
  font-size:13.5px;font-weight:600;white-space:nowrap;
  transition:background .15s,border-color .15s,color .15s,opacity .15s;
  min-height:36px;
}
.btn:hover{background:var(--panel2);border-color:var(--line2)}
.btn svg{width:15px;height:15px;flex:none}
.btn-pri{background:var(--grad);border-color:transparent;color:#fff}
.btn-pri:hover{filter:brightness(1.1);background:var(--grad)}
.btn-ghost{border-color:transparent;color:var(--mut)}
.btn-ghost:hover{color:var(--ink);background:var(--panel2)}
.btn-danger{border-color:color-mix(in srgb,var(--bad) 45%,transparent);color:var(--bad)}
.btn-danger:hover{background:color-mix(in srgb,var(--bad) 12%,transparent)}
.btn-sm{padding:5px 10px;font-size:12.5px;min-height:30px}
.btn-icon{padding:0;width:34px;height:34px;min-height:34px;border-color:transparent;color:var(--mut)}
.btn-icon:hover{color:var(--ink);background:var(--panel2)}
.btn-icon.is-on{color:var(--ax2-ink);background:var(--panel2)}
.btn:disabled{opacity:.4;cursor:not-allowed}
.btn-block{width:100%}

.seg{display:inline-flex;background:var(--panel);border:1px solid var(--line);border-radius:var(--rad-sm);padding:2px}
.seg button{padding:5px 11px;border-radius:7px;font-size:12.5px;font-weight:600;color:var(--mut);transition:.15s}
.seg button.is-on{background:var(--panel3);color:var(--ink)}

/* ---------- form fields ---------- */
.field{display:block;margin-bottom:14px}
.field > span{display:block;font:600 11px/1 var(--f-m);letter-spacing:.12em;text-transform:uppercase;color:var(--dim);margin-bottom:7px}
.field input[type=text],.field input[type=email],.field input[type=number],.field select,.field textarea{
  width:100%;padding:9px 11px;border-radius:var(--rad-sm);
  background:var(--panel);border:1px solid var(--line);font-size:14px;
  transition:border-color .15s;
}
.field input:focus,.field select:focus,.field textarea:focus{border-color:color-mix(in srgb,var(--ax2) 60%,transparent)}
.field .hint{display:block;font-size:12px;color:var(--dim);margin-top:6px;line-height:1.5}
.check{display:flex;align-items:center;gap:9px;cursor:pointer;padding:6px 0;font-size:14px}
.check input{width:16px;height:16px;accent-color:var(--ax1);flex:none}

/* ---------- modal ---------- */
/* The `hidden` attribute only sets display:none through the UA stylesheet, so
   ANY author `display` here silently outranks it. Without this rule the scrim
   is permanently laid over the whole app: a blurred, unclickable page that
   still looks almost right in a screenshot, and that scripted .click() tests
   sail straight through because they bypass hit-testing. Keep the two rules
   adjacent so nobody separates them. */
.scrim[hidden]{display:none}
.scrim{
  position:fixed;inset:0;z-index:80;
  background:rgba(4,6,12,.62);backdrop-filter:blur(3px);
  display:grid;place-items:center;padding:20px;
  animation:fade .14s ease-out;
}
@keyframes fade{from{opacity:0}to{opacity:1}}
.modal{
  width:min(520px,100%);max-height:min(80dvh,720px);overflow-y:auto;
  background:var(--bg-list);border:1px solid var(--line2);
  border-radius:var(--rad);box-shadow:var(--shadow);
  padding:22px;
}
.modal h3{font-size:17px;margin-bottom:6px}
.modal > p.sub{font-size:13px;color:var(--mut);margin-bottom:18px;line-height:1.55}
.modal-foot{display:flex;gap:9px;justify-content:flex-end;margin-top:20px;flex-wrap:wrap}

/* command palette / quick search */
.palette{width:min(620px,100%);align-self:start;margin-top:12vh}
.palette .search{border-radius:var(--rad);padding:2px 12px}
.palette .search input{padding:13px 0;font-size:15px}
.palette .results{margin-top:8px;max-height:52dvh;overflow-y:auto}
.palette .results .card.is-cursor{background:var(--panel2);border-color:var(--ax2)}

/* ---------- share rows ---------- */
.person{display:flex;align-items:center;gap:10px;padding:8px 0}
.person + .person{border-top:1px solid var(--line)}
.person .who{flex:1;min-width:0}
.person .who b{display:block;font-size:13.5px;font-weight:600}
.person .who small{display:block;font-size:11.5px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.person select{padding:5px 8px;border-radius:7px;background:var(--panel2);border:1px solid var(--line);font-size:12.5px}

/* ---------- empty / status ---------- */
.empty{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:9px;height:100%;padding:36px 26px;text-align:center;color:var(--dim);
}
.empty svg{width:34px;height:34px;opacity:.35}
.empty h3{font-size:15px;color:var(--mut);font-family:var(--f-b);font-weight:600}
.empty p{font-size:13px;max-width:34ch;line-height:1.6}

.saving{font:500 11.5px/1 var(--f-m);color:var(--dim);display:inline-flex;align-items:center;gap:6px}
.saving .dot{width:6px;height:6px;border-radius:50%;background:var(--dim)}
.saving.is-dirty .dot{background:var(--warn)}
.saving.is-saved .dot{background:var(--ok)}
.saving.is-error .dot{background:var(--bad)}

.banner{
  display:flex;align-items:flex-start;gap:10px;flex-wrap:wrap;
  padding:11px 14px;border-radius:var(--rad-sm);font-size:13px;line-height:1.55;
  margin-bottom:14px;
}
.banner.warn{background:color-mix(in srgb,var(--warn) 12%,transparent);color:var(--warn);border:1px solid color-mix(in srgb,var(--warn) 30%,transparent)}
.banner.bad{background:color-mix(in srgb,var(--bad) 12%,transparent);color:var(--bad);border:1px solid color-mix(in srgb,var(--bad) 30%,transparent)}
.banner.info{background:var(--panel);color:var(--mut);border:1px solid var(--line)}
.banner .grow{flex:1;min-width:180px}

.toast-wrap{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(22px + env(safe-area-inset-bottom));z-index:120;display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
.toast{
  background:var(--bg-list);border:1px solid var(--line2);box-shadow:var(--shadow);
  border-radius:99px;padding:9px 17px;font-size:13px;font-weight:500;
  animation:rise .18s ease-out;pointer-events:auto;
  display:flex;align-items:center;gap:9px;max-width:min(90vw,460px);
}
.toast.bad{border-color:color-mix(in srgb,var(--bad) 50%,transparent);color:var(--bad)}
.toast button{font-weight:700;color:var(--ax2-ink);flex:none}
@keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* ============================================================
   MOBILE — one pane at a time, driven by data-pane on .shell
   ============================================================ */
.mobile-only{display:none}
.back-btn{display:none}

@media (max-width:1080px){
  :root{--list-w:300px;--rail-w:212px}
}

@media (max-width:860px){
  .shell{grid-template-columns:1fr;position:relative}
  .rail,.list,.editor{
    grid-area:1/1;
    min-width:0;
    border-right:0;
  }

  /* Panes stack; the active one is the only one laid out. Using display
     rather than transforms keeps the phone keyboard from resizing an
     off-screen pane and scrolling the wrong thing. */
  .shell[data-pane="list"] .rail,
  .shell[data-pane="list"] .editor{display:none}
  .shell[data-pane="editor"] .rail,
  .shell[data-pane="editor"] .list{display:none}
  .shell[data-pane="rail"] .list,
  .shell[data-pane="rail"] .editor{display:none}

  .mobile-only{display:inline-flex}
  .back-btn{display:inline-flex}

  .ed-inner{padding:18px 16px 50vh}
  .list-head{padding:12px 12px 10px}

  /* Two rows, not one. On a 375px screen the back button, the Read/Write
     toggle and three icon buttons leave the title about 40px — `flex:1` with
     `min-width:0` happily collapses to that and renders "Shoo…". Giving the
     title a full-width basis pushes it onto its own line underneath instead. */
  .ed-head{padding:9px 12px 10px;gap:6px 8px;align-items:center}
  .ed-head .grow{order:2;flex-basis:100%;min-width:100%}
  .back-btn{order:0;margin-right:auto}
  .ed-head .seg,.ed-head .btn-icon,.ed-head .btn{order:1}
  .ed-title{font-size:19px;padding:0}
  .ed-sub{gap:6px}

  /* No physical keyboard, no keyboard hint. */
  .search kbd{display:none}
  .rail{padding-top:calc(10px + env(safe-area-inset-top))}

  /* iOS zooms any input under 16px on focus, which then leaves the layout
     shifted after blur. Bumping the two fields you actually type into is
     cheaper than fighting it with maximum-scale, which breaks pinch-zoom. */
  .search input,textarea.ed-text,.ed-title{font-size:16px}

  .card{padding:12px 12px;min-height:var(--tap)}
  .btn{min-height:var(--tap);padding:10px 15px}
  .btn-icon{width:var(--tap);height:var(--tap);min-height:var(--tap)}
  .btn-sm{min-height:36px}
  .modal{padding:18px;max-height:88dvh}
  .palette{margin-top:6vh}
  .toast-wrap{bottom:calc(72px + env(safe-area-inset-bottom))}
}

/* Landscape phones: the rail's own scroll is what should move, not the page. */
@media (max-height:520px){
  .ed-inner{padding-bottom:24vh}
}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important;transition-duration:.01ms !important}
}

/* Print: just the note, no chrome. Someone will want a call sheet on paper. */
@media print{
  .rail,.list,.ed-head,.toast-wrap{display:none !important}
  .shell{display:block;height:auto}
  .editor{background:#fff}
  /* Write mode hands scrolling to the textarea; for print everything must flow
     back into the page or only the first screenful comes out. */
  .ed-body,.editor.is-writing .ed-body{overflow:visible;height:auto}
  .ed-inner,.editor.is-writing .ed-inner{max-width:none;padding:0;height:auto;display:block}
  textarea.ed-text{height:auto;overflow:visible;padding-bottom:0}
  .md{color:#000}
  .md a{color:#000}
}

/* ============================================================
   FIT — layout
   Two columns on desktop: a rail and one scrolling dashboard.
   Not the three-pane shape of notes; a fitness app has one
   subject per day, not a list to browse.
   ============================================================ */
.fit-shell{display:grid;grid-template-columns:var(--rail-w) 1fr;height:100dvh;overflow:hidden}
.fit-main{overflow-y:auto;overscroll-behavior:contain;background:var(--bg)}
.fit-inner{max-width:940px;margin:0 auto;padding:26px 22px 96px}

.day-head{display:flex;align-items:center;gap:10px;margin-bottom:20px;flex-wrap:wrap}
.day-title{font-family:var(--f-d);font-size:23px;font-weight:700;letter-spacing:-.02em}
.day-sub{color:var(--mut);font-size:13px}
.day-nav{display:flex;gap:6px;margin-left:auto}

.grid{display:grid;gap:14px}
.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}

.panel-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--rad);padding:18px}
.panel-head{display:flex;align-items:baseline;gap:10px;margin-bottom:14px}
.panel-title{font-family:var(--f-d);font-size:14px;font-weight:700;letter-spacing:.01em}
.panel-note{font-size:12px;color:var(--mut);margin-left:auto}

/* Inputs styled by carrying .field THEMSELVES.
   In the inherited design system .field is a wrapper (a <label> whose child
   input gets the styling). FeAx Fit builds most of its forms by hand in JS and
   puts .field straight on the control, which matched nothing at all — the
   global reset strips borders and backgrounds from form elements, so every
   input rendered as invisible bare text. Rather than rewrite every call site
   into a wrapper, this makes the direct spelling work too; both are supported.
   Deliberately mirrors the wrapper rule's declarations — if you change one,
   change the other. */
input.field,select.field,textarea.field{
  width:100%;padding:9px 11px;border-radius:var(--rad-sm);
  background:var(--panel);border:1px solid var(--line);font-size:14px;
  color:var(--ink);transition:border-color .15s;
}
input.field:focus,select.field:focus,textarea.field:focus{
  border-color:color-mix(in srgb,var(--ax2) 60%,transparent);
}
input.field::placeholder,textarea.field::placeholder{color:var(--dim)}
textarea.field{font:inherit;line-height:1.6;resize:vertical}
/* The design system's .field wrapper sets a bottom margin; a bare control laid
   out in a flex row must not inherit that or rows come out misaligned. */
input.field,select.field{margin-bottom:0}

/* Rail navigation. .rail-group is the design system's group HEADER (a flex
   row with space-between, meant for a label plus one action button) — nav
   items crammed into it share one line and start truncating at four entries.
   The nav gets its own vertical stack instead. */
.rail-nav{display:flex;flex-direction:column;gap:2px;padding:12px 4px 4px}
.rail-nav .rail-item{width:100%;text-align:left}
.rail-nav-title{font:700 10px/1 var(--f-m);letter-spacing:.18em;text-transform:uppercase;
  color:var(--dim);padding:14px 10px 6px}

/* ============================================================
   FIT — data visualisation
   Rule followed throughout: colour never carries meaning on its
   own. Over/under target is stated in words as well as hue, and
   the macro ring legend is labelled, because roughly 8% of men
   cannot reliably separate the amber and green used here.
   ============================================================ */

/* Calorie ring — one big number, because that is the one people
   actually read. The ring is the context, not the content. */
.ring-wrap{display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.ring{position:relative;flex:0 0 auto}
.ring svg{display:block;transform:rotate(-90deg)}
.ring-track{fill:none;stroke:var(--panel3);stroke-width:11}
.ring-fill{fill:none;stroke:url(#ringgrad);stroke-width:11;stroke-linecap:round;
  transition:stroke-dasharray .45s cubic-bezier(.4,0,.2,1)}
.ring-fill.is-over{stroke:var(--warn)}
.ring-mid{position:absolute;inset:0;display:grid;place-content:center;text-align:center}
.ring-num{font-family:var(--f-d);font-size:27px;font-weight:700;line-height:1;letter-spacing:-.02em}
.ring-lbl{font-size:11px;color:var(--mut);margin-top:3px;letter-spacing:.03em;text-transform:uppercase}

/* Macro bars. Bars rather than three more rings: comparing three
   arcs against three different targets is genuinely hard, and a
   bar chart with a target tick is not. */
.macros{display:grid;gap:11px;flex:1 1 240px;min-width:220px}
.macro{display:grid;grid-template-columns:58px 1fr auto;gap:10px;align-items:center}
.macro-name{font-size:12px;color:var(--ink2);font-weight:500}
.macro-track{height:9px;border-radius:99px;background:var(--panel3);position:relative;overflow:hidden}
.macro-fill{height:100%;border-radius:99px;transition:width .45s cubic-bezier(.4,0,.2,1)}
.macro-fill.p{background:linear-gradient(90deg,#7C5CFF,#A78BFA)}
.macro-fill.c{background:linear-gradient(90deg,#38E1FF,#67E8F9)}
.macro-fill.f{background:linear-gradient(90deg,#FBBF24,#FCD34D)}
.macro-val{font-family:var(--f-m);font-size:12px;color:var(--ink2);white-space:nowrap;font-variant-numeric:tabular-nums}
.macro-val b{color:var(--ink);font-weight:700}

/* Weight trend. Raw points stay visible under the smoothed line so
   nobody thinks the app is inventing numbers. */
.chart{width:100%;height:auto;display:block;overflow:visible}
.chart-grid{stroke:var(--line);stroke-width:1}
.chart-axis{fill:var(--dim);font-size:10px;font-family:var(--f-m)}
.chart-trend{fill:none;stroke:var(--ax1-ink);stroke-width:2.5;stroke-linejoin:round;stroke-linecap:round}
/* --ax2-ink, not --ax2. These dots are CONTENT, and the raw accent is a glow
   colour: #38E1FF on the light theme's white is about 1.6:1. The -ink tokens
   exist for exactly this and swap to a readable teal in light mode. */
.chart-raw{fill:var(--ax2-ink);opacity:.7}
.chart-band{fill:var(--ax1);opacity:.09}
.chart-empty{fill:var(--dim);font-size:12px;font-family:var(--f-b)}
.chart-hit{fill:transparent;cursor:crosshair}
.chart-cursor{stroke:var(--line2);stroke-width:1;stroke-dasharray:3 3}

/* Week strip — 7 dots, one per day. The single densest thing on
   the page: logged/trained/weighed for a week in one glance. */
.strip{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}
.strip-day{background:var(--panel);border:1px solid var(--line);border-radius:var(--rad-sm);
  padding:9px 4px;text-align:center;cursor:pointer;transition:border-color .15s,background .15s}
.strip-day:hover{border-color:var(--line2);background:var(--panel2)}
.strip-day.is-today{border-color:var(--ax1)}
.strip-day.is-on{background:var(--panel2)}
.strip-dow{font-size:10px;color:var(--mut);text-transform:uppercase;letter-spacing:.05em}
.strip-num{font-family:var(--f-d);font-size:15px;font-weight:700;margin-top:2px}
.strip-marks{display:flex;gap:3px;justify-content:center;margin-top:6px;height:6px}
.strip-mark{width:6px;height:6px;border-radius:99px;background:var(--panel3)}
.strip-mark.food{background:var(--ax2-ink)}
.strip-mark.train{background:var(--ax1-ink)}
.strip-mark.weight{background:var(--ok)}

/* Food list */
.food-row{display:grid;grid-template-columns:1fr auto auto;gap:10px;align-items:center;
  padding:10px 0;border-bottom:1px solid var(--line)}
.food-row:last-child{border-bottom:none}
.food-name{font-size:14px;font-weight:500}
.food-meta{font-size:11.5px;color:var(--mut);margin-top:1px}
.food-kcal{font-family:var(--f-m);font-size:13px;font-variant-numeric:tabular-nums}
.food-src{font-size:10px;padding:2px 6px;border-radius:99px;border:1px solid var(--line2);color:var(--mut)}
.food-src.manual{border-color:var(--warn);color:var(--warn)}

/* Candidate picker — the "which of these is your toast" step.
   Deliberately a choice, never an auto-pick. */
.cand{display:block;width:100%;text-align:left;padding:11px 12px;border-radius:var(--rad-sm);
  border:1px solid var(--line);background:var(--panel);margin-bottom:7px;cursor:pointer;
  transition:border-color .15s,background .15s}
.cand:hover{border-color:var(--ax1);background:var(--panel2)}
.cand.is-on{border-color:var(--ax1);background:var(--panel2)}
.cand-name{font-size:13.5px;font-weight:500}
.cand-meta{font-size:11.5px;color:var(--mut);margin-top:2px;font-family:var(--f-m)}

/* Coach card */
.coach{background:linear-gradient(135deg,color-mix(in srgb,var(--ax1) 12%,transparent),
  color-mix(in srgb,var(--ax2) 8%,transparent));border:1px solid var(--line2);
  border-radius:var(--rad);padding:18px}
.coach-msg{font-size:14.5px;line-height:1.65;color:var(--ink)}
.coach-foot{display:flex;align-items:center;gap:8px;margin-top:12px;font-size:11px;color:var(--mut)}

/* Workout checklist */
.ex{display:flex;gap:10px;align-items:flex-start;padding:7px 0}
.ex-box{flex:0 0 auto;width:19px;height:19px;border-radius:5px;border:1.5px solid var(--line2);
  margin-top:1px;cursor:pointer;display:grid;place-items:center;transition:border-color .15s,background .15s}
.ex-box.is-on{background:var(--ax1);border-color:var(--ax1)}
.ex-box svg{opacity:0}
.ex-box.is-on svg{opacity:1}
.ex-txt{font-size:14px;line-height:1.5}
.ex.is-done .ex-txt{color:var(--mut);text-decoration:line-through}

/* Nudge */
.nudge{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:14px;
  border:1px dashed var(--line2);border-radius:var(--rad);background:var(--panel)}
.nudge-q{font-size:13.5px;flex:1 1 220px}

/* Onboarding */
.onb{max-width:560px;margin:0 auto;padding:40px 22px}
.onb-step{display:none}
.onb-step.is-on{display:block}
.seg-wrap{display:grid;gap:8px}
.seg-opt{padding:13px 15px;border:1px solid var(--line);border-radius:var(--rad-sm);
  background:var(--panel);cursor:pointer;text-align:left;transition:border-color .15s,background .15s}
.seg-opt:hover{border-color:var(--line2)}
.seg-opt.is-on{border-color:var(--ax1);background:var(--panel2)}
.seg-opt b{display:block;font-size:14px;margin-bottom:2px}
.seg-opt span{font-size:12px;color:var(--mut)}

.stat-row{display:flex;gap:22px;flex-wrap:wrap}
.stat{min-width:88px}
.stat-v{font-family:var(--f-d);font-size:21px;font-weight:700;letter-spacing:-.02em}
.stat-l{font-size:11px;color:var(--mut);text-transform:uppercase;letter-spacing:.04em;margin-top:2px}

.hint{font-size:12px;color:var(--mut);line-height:1.55}
.hint-strong{color:var(--ink2)}

/* Mobile nav toggle. Hidden on desktop, where the rail is always visible. */
.rail-toggle{display:none;position:fixed;top:10px;left:10px;z-index:86;
  width:var(--tap);height:var(--tap);border-radius:var(--rad-sm);
  border:1px solid var(--line);background:var(--bg-rail);color:var(--ink);
  align-items:center;justify-content:center}
.rail-toggle:hover{border-color:var(--line2)}
.rail-toggle{transition:opacity .18s ease}

@media (max-width:860px){
  .rail-toggle{display:flex}
  .fit-shell{grid-template-columns:1fr}
  /* ABOVE the scrim (z-index 80), not below it. The scrim carries
     backdrop-filter:blur(3px) and a 62% dark wash, so a menu underneath it
     renders blurred, dimmed AND unclickable — elementFromPoint over the menu
     returned the scrim. The backdrop is meant to dim the PAGE behind the menu,
     never the menu itself. */
  /* While the menu is open the toggle would sit on top of the rail's own
     brand mark. The menu closes by tapping the backdrop or picking an item,
     so the button has no job in that state. */
  .rail.is-open ~ .rail-toggle,
  body:has(.rail.is-open) .rail-toggle{opacity:0;pointer-events:none}
  .rail{position:fixed;inset:0 auto 0 0;z-index:85;transform:translateX(-100%);
    transition:transform .22s ease;width:var(--rail-w);
    box-shadow:var(--shadow)}
  .rail.is-open{transform:none}
  /* Top padding clears the fixed menu button, which would otherwise sit
     directly on top of the day title. */
  .fit-inner{padding:64px 15px 92px}
  .grid-2,.grid-3{grid-template-columns:1fr}
  .ring-wrap{gap:16px}
}
