/* ═══════════════════════════════════════════════════════════════════════════
   Trade Planner — shell + design system.

   ONE stylesheet, one dark theme, no light mode, no external fonts, no CDN:
   the PWA has to boot with the network off.

   This file owns: tokens, reset, layout shell, header, chart frame, ticket,
   positions, footer tabs, sheets. Component stylesheets injected by the JS
   modules read the tokens below through var() — the names in the TOKEN
   CONTRACT block are the public API and must not be renamed.

   BREAKPOINTS (must stay in step with core.js)
     base            phone, stacked, footer tabs switch Plan / Trade
     <360px          very small phones: 4-up grids fold to 2-up
     >=900px         tablet: chart + side column, tools become a vertical rail,
                     footer hidden.  === TP.isWide() in core.js — do not move ===
     >=1280px        desktop: wider side column, comfortable density
     >=1800px        ultrawide: side column capped, chart takes the rest
     landscape phone short-viewport trim so the chart still gets height
     (pointer:coarse) >=44px hit targets.  === TP.isTouch() in core.js ===
   ═════════════════════════════════════════════════════════════════════════ */

/* ── TOKEN CONTRACT ─────────────────────────────────────────────────────────
   Palette (pre-existing, unchanged):
     --bg --panel --panel2 --line --ink --ink2 --ink3
     --up --down --buy --sell --tp --sl --entry --ok --bad --warn --zone --draw
   Added surfaces / lines:
     --panel3 --line2 --line-soft --shadow-line
   Added tints — 1px borders and fills that keep a colour readable on --panel:
     --up-dim --down-dim --buy-dim --sell-dim --ok-dim --bad-dim --warn-dim
     --tp-dim --sl-dim --entry-dim --zone-dim
     --tp-line --sl-line --entry-line --ok-line --bad-line --warn-line
   Added system scales:
     --s0..--s8            spacing rhythm (2 → 32px)
     --r1..--r5 --r-pill   radii
     --fs-micro..--fs-2xl  type scale
     --font-ui --font-mono
     --sh1 --sh2 --sh3     elevation
     --focus --ring        focus colour + ring shadow
     --dur-1 --dur-2 --ease
     --z-overlay --z-sticky --z-header --z-sheet
     --top-h --tf-h --footer-h --side-w --tools-w --tap
   ──────────────────────────────────────────────────────────────────────── */

:root{
  color-scheme:dark;

  /* palette — the trading colours, unchanged */
  --bg:#0d1117; --panel:#141b25; --panel2:#1b2430; --line:#243040;
  --ink:#e6edf3; --ink2:#8b98a8; --ink3:#5a6675;
  --up:#26a69a; --down:#ef5350;
  --buy:#1e88e5; --sell:#e5533d;
  --tp:#26a69a; --sl:#ef5350; --entry:#f0b429;
  --ok:#2ea043; --bad:#f85149; --warn:#d29922;
  --zone:#4c8dff; --draw:#b48ead;

  /* extra surfaces: panel3 is the raised/active step above panel2 */
  --panel3:#22303f;
  --line2:#31404f;
  --line-soft:#1c2531;
  --shadow-line:rgba(0,0,0,.45);
  --scroll-thumb:#2b3644;
  --scroll-thumb-hi:#3d4c5e;

  /* tints — low-alpha fills so a hue can sit behind text without hurting it */
  --up-dim:rgba(38,166,154,.10);   --down-dim:rgba(239,83,80,.10);
  --buy-dim:rgba(30,136,229,.14);  --sell-dim:rgba(229,83,61,.14);
  --ok-dim:rgba(46,160,67,.12);    --bad-dim:rgba(248,81,73,.12);
  --warn-dim:rgba(210,153,34,.12); --zone-dim:rgba(76,141,255,.12);
  --tp-dim:rgba(38,166,154,.07);   --sl-dim:rgba(239,83,80,.07);
  --entry-dim:rgba(240,180,41,.09);
  --tp-line:#1f4f49; --sl-line:#5a2320; --entry-line:#5a4415;
  --ok-line:#1f6b41; --bad-line:#6d2620; --warn-line:#4a3a12;

  /* spacing rhythm — every gap/pad in this file comes from here */
  --s0:2px; --s1:4px; --s2:6px; --s3:8px; --s4:12px;
  --s5:16px; --s6:20px; --s7:24px; --s8:32px;

  --r1:4px; --r2:6px; --r3:8px; --r4:10px; --r5:14px; --r-pill:999px;

  --fs-micro:9px; --fs-tiny:10px; --fs-xs:11px; --fs-sm:12px;
  --fs-md:13px; --fs-base:14px; --fs-lg:16px; --fs-xl:18px; --fs-2xl:22px;

  --font-ui:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",
            Arial,"Noto Sans",sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,
            "Liberation Mono",monospace;

  --sh1:0 1px 2px rgba(0,0,0,.35);
  --sh2:0 4px 14px rgba(0,0,0,.40);
  --sh3:0 -12px 40px rgba(0,0,0,.55);

  --focus:#58a6ff;
  --ring:0 0 0 3px rgba(88,166,255,.35);

  --dur-1:90ms; --dur-2:160ms; --ease:cubic-bezier(.2,.7,.3,1);

  --z-overlay:5; --z-sticky:20; --z-header:30; --z-sheet:60;

  /* layout dimensions — overridden per breakpoint further down */
  --top-h:52px; --tf-h:38px; --footer-h:54px;
  --side-w:340px; --tools-w:44px; --tap:44px;
}

/* ── reset / base ───────────────────────────────────────────────────────── */
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
.hidden{display:none!important}

html{height:100%;background:var(--bg)}
body{
  margin:0;
  height:100%;
  height:100dvh;                       /* dvh so mobile browser chrome cannot clip the shell */
  background:var(--bg);color:var(--ink);
  font:var(--fs-base)/1.45 var(--font-ui);
  -webkit-text-size-adjust:100%;
  text-rendering:optimizeLegibility;
  display:flex;flex-direction:column;
  overflow:hidden;overscroll-behavior:none;
  /* notch / home-indicator insets: the shell is inset, never the content boxes */
  padding-top:env(safe-area-inset-top);
  padding-left:env(safe-area-inset-left);
  padding-right:env(safe-area-inset-right);
}

button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer}
button:disabled{cursor:not-allowed}
h1,h2,h3,p,ul{margin:0}
::selection{background:rgba(76,141,255,.32)}

/* numeric text never reflows as digits change */
.prices,#bid,#ask,#cdText,#rpTime,.levels input,.rrnow span,.stat b,.posPl,
.posProfit,.posCell b,.big,.planRow,.ticket td:last-child,#posCount{
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}

/* number inputs: strip the spinners, they are useless at these step sizes */
input[type=number]{-moz-appearance:textfield;appearance:textfield}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

code{font-family:var(--font-mono);font-size:.92em;background:var(--panel3);
  border:1px solid var(--line);border-radius:var(--r1);padding:1px 5px;color:var(--ink)}

/* ── focus: keyboard users must always see where they are ───────────────── */
:focus{outline:none}
:focus-visible{
  outline:2px solid var(--focus);
  outline-offset:2px;
  border-radius:var(--r2);
}
.levels input:focus,.field input:focus,.field select:focus,#rpSpeed:focus{
  outline:none;border-color:var(--focus);box-shadow:var(--ring);
}

/* ── scrollbars: thin, dark, out of the way ─────────────────────────────── */
*{scrollbar-width:thin;scrollbar-color:var(--scroll-thumb) transparent}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{
  background:var(--scroll-thumb);border:2px solid transparent;
  background-clip:content-box;border-radius:var(--r-pill);
}
::-webkit-scrollbar-thumb:hover{background:var(--scroll-thumb-hi);background-clip:content-box}
::-webkit-scrollbar-corner{background:transparent}

/* ═══ HEADER ════════════════════════════════════════════════════════════ */
#top{
  flex:0 0 auto;position:relative;z-index:var(--z-header);
  display:flex;align-items:center;gap:var(--s3);
  height:var(--top-h);padding:0 var(--s4);
  background:var(--panel);
  border-bottom:1px solid var(--line);
  box-shadow:0 1px 0 var(--shadow-line);
}
.brand{display:flex;align-items:center;gap:var(--s3);min-width:0}
.brand strong,#symLabel{
  font-size:var(--fs-lg);font-weight:700;letter-spacing:.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* connection lamp — the pulse is the only ambient motion in the app */
.dot{width:8px;height:8px;border-radius:50%;background:var(--ink3);flex:0 0 auto}
.dot.live{background:var(--ok);box-shadow:0 0 0 0 rgba(46,160,67,.55);animation:lamp 2.6s var(--ease) infinite}
.dot.err{background:var(--bad);box-shadow:0 0 8px rgba(248,81,73,.6);animation:none}
@keyframes lamp{
  0%,100%{box-shadow:0 0 0 0 rgba(46,160,67,.45)}
  50%    {box-shadow:0 0 0 4px rgba(46,160,67,0)}
}

.badge{
  flex:0 0 auto;font-size:var(--fs-micro);font-weight:800;letter-spacing:.09em;
  text-transform:uppercase;padding:3px 7px;border-radius:var(--r1);
  background:var(--panel2);color:var(--ink2);border:1px solid var(--line);white-space:nowrap;
}
.badge.demo{color:var(--warn);border-color:var(--warn-line);background:var(--warn-dim)}
.badge.real{color:var(--bad);border-color:var(--bad-line);background:var(--bad-dim)}

.prices{
  margin-left:auto;display:flex;align-items:baseline;gap:var(--s4);
  font-size:var(--fs-md);font-weight:600;
}
#bid,.bid{color:var(--down)}
#ask,.ask{color:var(--up)}
#bid,#ask{min-width:7ch;text-align:right}          /* reserve the digits: no jitter on tick */

.icon{
  flex:0 0 auto;width:36px;height:36px;display:grid;place-items:center;
  background:none;border:1px solid transparent;border-radius:var(--r2);
  color:var(--ink2);font-size:var(--fs-xl);line-height:1;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.icon.on{color:var(--warn);background:var(--warn-dim);border-color:var(--warn-line)}

/* ═══ COOLDOWN BANNER ═══════════════════════════════════════════════════
   Deliberately loud. This is the rule that exists because a 3-minute
   re-entry cost a whole day; it should be impossible to miss. */
#cooldown,.cooldown{
  flex:0 0 auto;
  display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;
  padding:var(--s3) var(--s4);
  background:linear-gradient(90deg,rgba(248,81,73,.20),rgba(248,81,73,.08));
  border-bottom:1px solid var(--bad-line);
  border-left:3px solid var(--bad);
  color:#ffb4ab;
}
.cooldown strong{font-size:var(--fs-xs);font-weight:800;letter-spacing:.14em}
.cooldown span,#cdText{font-size:var(--fs-xl);font-weight:800;min-width:5ch}
.cooldown small,#cdWhy{width:100%;font-size:var(--fs-xs);color:#c98a84;line-height:1.4}

/* ═══ APP SHELL ═════════════════════════════════════════════════════════
   Phone default: one column. Chart on top, side panel under it, footer tabs
   swap which section of the side panel is mounted. */
#app{flex:1 1 auto;display:flex;flex-direction:column;min-height:0;min-width:0}

#chartCol{flex:1 1 auto;display:flex;flex-direction:column;min-height:32dvh;min-width:0}

/* ── timeframe bar ──────────────────────────────────────────────────────── */
#tfbar{
  flex:0 0 auto;display:flex;align-items:center;gap:var(--s1);
  height:var(--tf-h);padding:0 var(--s2);
  background:var(--panel);border-bottom:1px solid var(--line);
  overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;
  scrollbar-width:none;
}
#tfbar::-webkit-scrollbar{display:none}
#tfbar button{
  flex:0 0 auto;min-width:40px;height:28px;padding:0 var(--s3);
  background:none;border:1px solid transparent;border-radius:var(--r2);
  color:var(--ink2);font-size:var(--fs-sm);font-weight:700;letter-spacing:.02em;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
#tfbar button.on{
  background:var(--panel3);color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--line2),inset 0 -2px 0 var(--zone);
}
.spacer{flex:1 1 auto}

.ghost{background:transparent;border:1px solid var(--line);color:var(--ink2)}
#tfbar .ghost{border-color:var(--line);color:var(--ink2)}

/* ── chart area ─────────────────────────────────────────────────────────
   PHONE: column — the tools rail becomes a horizontal scrolling strip that
   sits above the chart. A 44px vertical rail would eat 12% of a 360px
   screen for the entire session; horizontally it costs height once and
   scrolls. DOM order is #tools then #chartHost, so flex-direction alone
   places it correctly — no order:-1 needed. */
#chartArea{
  flex:1 1 auto;display:flex;flex-direction:column;
  min-height:0;min-width:0;background:var(--bg);
}
#tools{
  flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:var(--s1);
  padding:var(--s2) var(--s3);
  background:var(--panel);border-bottom:1px solid var(--line);
  overflow-x:auto;overflow-y:hidden;overscroll-behavior:contain;
  scrollbar-width:none;
}
#tools::-webkit-scrollbar{display:none}
.tool{
  flex:0 0 auto;width:34px;height:34px;display:flex;align-items:center;justify-content:center;
  background:none;border:1px solid transparent;border-radius:var(--r2);
  color:var(--ink2);font-size:var(--fs-lg);line-height:1;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.tool.on{background:var(--zone-dim);color:var(--zone);border-color:rgba(76,141,255,.35)}
.tool.sep{margin-left:auto}                       /* phone: clear-all parks at the far end */
#btnClearAll{color:var(--ink3)}

#chartHost{
  position:relative;flex:1 1 auto;
  min-height:0;min-width:0;
  touch-action:none;                              /* the chart owns pan / pinch */
}
#chartHost canvas{display:block}
#overlay{position:absolute;inset:0;pointer-events:none;z-index:var(--z-overlay)}

/* centred hint line, for any prompt a chart module drops into #chartHost */
.hint{
  position:absolute;inset:auto 0 var(--s4) 0;text-align:center;
  color:var(--ink3);font-size:var(--fs-sm);pointer-events:none;padding:0 var(--s4);
}
#drawHint{color:var(--zone);font-weight:600}

/* ── replay bar ─────────────────────────────────────────────────────────── */
#replayBar{
  flex:0 0 auto;display:flex;align-items:center;gap:var(--s3);
  padding:var(--s2) var(--s3);
  background:#1a1408;border-top:1px solid var(--entry-line);
}
#replayBar button{
  flex:0 0 auto;min-width:36px;height:32px;padding:0 var(--s3);
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r2);
  color:var(--ink);font-size:var(--fs-md);
}
#rpTime{
  flex:0 0 auto;font-size:var(--fs-xs);color:var(--entry);
  white-space:nowrap;min-width:11ch;text-align:center;
}
#rpRange{flex:1 1 auto;min-width:70px;height:22px;background:none;
  -webkit-appearance:none;appearance:none;accent-color:var(--entry)}
#rpRange::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:var(--line2)}
#rpRange::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;
  margin-top:-6px;border-radius:50%;background:var(--entry);border:2px solid #1a1408}
#rpRange::-moz-range-track{height:4px;border-radius:2px;background:var(--line2)}
#rpRange::-moz-range-thumb{width:14px;height:14px;border-radius:50%;
  background:var(--entry);border:2px solid #1a1408}
#rpSpeed{
  flex:0 0 auto;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r2);
  color:var(--ink2);padding:var(--s1) var(--s2);font-size:var(--fs-xs);
}
#replayBar .ghost{background:transparent;border-color:var(--entry-line);color:var(--entry)}

/* ═══ SIDE COLUMN ═══════════════════════════════════════════════════════
   One scroll container for the whole column (both on phone and desktop) so
   .posHead can stay sticky against it and nested scrollers never fight. */
#side{
  flex:0 1 auto;display:flex;flex-direction:column;
  min-height:0;max-height:62dvh;
  background:var(--panel);
  border-top:1px solid var(--line);
  box-shadow:0 -1px 0 var(--shadow-line);
  overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
}

/* ── ticket ─────────────────────────────────────────────────────────────── */
#ticket{
  flex:0 0 auto;display:flex;flex-direction:column;gap:var(--s3);
  padding:var(--s4) var(--s4) var(--s5);
}
.row{display:flex;gap:var(--s3);margin:0}

/* level inputs: floating micro-label, colour-coded per leg */
.levels .lvl{flex:1 1 0;min-width:0;position:relative}
.levels label{
  position:absolute;top:6px;left:10px;pointer-events:none;
  font-size:var(--fs-micro);font-weight:800;letter-spacing:.09em;color:var(--ink3);
}
.levels input{
  width:100%;height:54px;padding:20px 10px 6px;
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r3);
  color:var(--ink);font-size:var(--fs-lg);font-weight:700;
  transition:border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease);
}
.lvl.tp input{border-color:var(--tp-line);background:var(--tp-dim)}
.lvl.tp label{color:var(--tp)}
.lvl.sl input{border-color:var(--sl-line);background:var(--sl-dim)}
.lvl.sl label{color:var(--sl)}
.lvl.en input{border-color:var(--entry-line);background:var(--entry-dim)}
.lvl.en label{color:var(--entry)}
.lvl.liveEntry input{background:#241d08;border-color:var(--entry);cursor:not-allowed}
.lvl.liveEntry label::after{content:' ● LIVE';color:var(--entry)}

/* RR presets + live RR readout */
.rrbar{align-items:stretch}
.rr{
  flex:1 1 0;min-width:0;
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r3);
  color:var(--ink2);padding:10px 0;font-size:var(--fs-md);font-weight:700;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.rr.on,.rr:active{background:var(--panel3);color:var(--ink);border-color:var(--line2)}
.rrnow{
  flex:0 0 78px;display:flex;flex-direction:column;align-items:center;justify-content:center;
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r3);
}
.rrnow span,#rrVal{font-size:var(--fs-xl);font-weight:800;line-height:1.1;min-width:4ch;text-align:center}
.rrnow small{font-size:var(--fs-micro);color:var(--ink3);letter-spacing:.1em}
.rrnow.good span{color:var(--ok)}
.rrnow.bad span{color:var(--bad)}

/* the four derived numbers — grid, not flex, so the columns cannot drift */
.stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s2)}
.stat{
  min-width:0;padding:var(--s2) var(--s1);text-align:center;
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r3);
}
.stat small{
  display:block;font-size:var(--fs-micro);letter-spacing:.07em;color:var(--ink3);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.stat small.short{color:var(--warn)}
.stat b{
  display:block;min-height:19px;font-size:var(--fs-base);font-weight:700;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

.verdict,#verdict{
  margin:0;font-size:var(--fs-sm);line-height:1.4;min-height:18px;color:var(--ink2);
}
.verdict:not(:empty)::before{
  content:'';display:inline-block;width:6px;height:6px;border-radius:50%;
  background:currentColor;margin-right:var(--s2);vertical-align:middle;
}
.verdict.bad{color:var(--bad);font-weight:600}
.verdict.good{color:var(--ok)}
.verdict.warn{color:var(--warn)}

/* direction buttons */
.sides{gap:var(--s3)}
.side{
  flex:1 1 0;min-width:0;border:none;border-radius:var(--r3);
  padding:13px 0;font-size:var(--fs-md);font-weight:800;letter-spacing:.04em;
  color:#fff;opacity:.86;
  transition:opacity var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease);
}
.side.buy{background:var(--buy)}
.side.sell{background:var(--sell)}
.side.now{opacity:.55;font-size:var(--fs-sm);padding:10px 0}
.side.on{opacity:1;box-shadow:inset 0 0 0 2px var(--ink),0 0 0 1px rgba(0,0,0,.4)}
.side:disabled{opacity:.22}

.confirm{
  width:100%;background:var(--ok);color:#fff;border:none;border-radius:var(--r4);
  padding:14px;font-size:var(--fs-lg);font-weight:800;letter-spacing:.05em;
  box-shadow:var(--sh1);
  transition:filter var(--dur-1) var(--ease);
}
.confirm:disabled{background:var(--line);color:var(--ink3);box-shadow:none}
.ghostwide{
  width:100%;background:transparent;border:1px solid var(--line);color:var(--ink2);
  border-radius:var(--r4);padding:12px;font-size:var(--fs-base);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.foot{margin:var(--s1) 0 0;font-size:var(--fs-tiny);color:var(--ink3);text-align:center;line-height:1.4}

/* ═══ POSITIONS ═════════════════════════════════════════════════════════ */
#tradeView{flex:1 1 auto;min-height:0}
.posHead{
  position:sticky;top:0;z-index:var(--z-sticky);
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:var(--s4);
  background:var(--panel);border-bottom:1px solid var(--line);
  box-shadow:0 1px 0 var(--shadow-line);
  font-size:var(--fs-md);font-weight:700;
}
#posCount{min-width:12ch}
.posPl,#posPl{font-size:var(--fs-lg);font-weight:800;min-width:9ch;text-align:right;color:var(--ink2)}
.posPl.up{color:var(--up)}
.posPl.down{color:var(--down)}

.pos{
  padding:var(--s4);border-bottom:1px solid var(--line);
  transition:background var(--dur-1) var(--ease);
}
.posTop{display:flex;align-items:center;gap:var(--s3);margin-bottom:var(--s3)}
.tag{
  flex:0 0 auto;font-size:var(--fs-tiny);font-weight:800;letter-spacing:.06em;
  padding:3px 7px;border-radius:var(--r1);color:#fff;
}
.tag.buy{background:var(--buy-dim);color:#7fbcf5;border:1px solid rgba(30,136,229,.45)}
.tag.sell{background:var(--sell-dim);color:#f39a86;border:1px solid rgba(229,83,61,.45)}
.posSym{font-size:var(--fs-lg);font-weight:700;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.posProfit{margin-left:auto;font-size:var(--fs-lg);font-weight:800;min-width:9ch;text-align:right}
.posProfit.up{color:var(--up)}
.posProfit.down{color:var(--down)}

.posGrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s2);margin-bottom:var(--s3)}
.posCell{min-width:0}
.posCell small{display:block;font-size:var(--fs-micro);letter-spacing:.06em;color:var(--ink3);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.posCell b{display:block;min-height:18px;font-size:var(--fs-md);font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.posCell b.none{color:var(--bad)}      /* S/L = 0.00 is a REJECT — it reads red on purpose */
.posCell b.set{color:var(--up)}

.posBtns{display:flex;gap:var(--s3)}
.posBtns button{
  flex:1 1 0;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r3);
  color:var(--ink2);padding:10px 0;font-size:var(--fs-sm);font-weight:700;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.posBtns button.be{background:var(--ok-dim);border-color:var(--ok-line);color:#7ee2a8}
.posBtns button:disabled{opacity:.35}
.posEmpty{padding:var(--s8) var(--s6);text-align:center;color:var(--ink3);font-size:var(--fs-md)}
#posNote{padding:0 var(--s4) var(--s4)}

/* ═══ FOOTER TABS (phone only) ══════════════════════════════════════════ */
#footer{
  flex:0 0 auto;display:flex;
  background:var(--panel);border-top:1px solid var(--line);
  box-shadow:0 -1px 0 var(--shadow-line);
  height:calc(var(--footer-h) + env(safe-area-inset-bottom));
  padding-bottom:env(safe-area-inset-bottom);
}
#footer .tab{
  flex:1 1 0;position:relative;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  background:none;border:none;color:var(--ink3);
  font-size:var(--fs-xs);font-weight:700;letter-spacing:.04em;
  transition:color var(--dur-1) var(--ease);
}
#footer .tab span{font-size:var(--fs-xl);line-height:1}
#footer .tab.on{color:var(--ink)}
#footer .tab.on::before{
  content:'';position:absolute;top:0;left:24%;right:24%;height:2px;
  background:var(--ok);border-radius:0 0 2px 2px;
}
.tabBadge{
  position:absolute;top:6px;left:calc(50% + 8px);
  background:var(--ok);color:#fff;
  font-size:var(--fs-micro);font-style:normal;font-weight:800;
  border-radius:var(--r-pill);padding:1px 5px;min-width:16px;text-align:center;line-height:1.5;
}

/* ═══ SHEETS / MODALS ═══════════════════════════════════════════════════ */
.sheet{
  position:fixed;inset:0;z-index:var(--z-sheet);
  display:flex;align-items:flex-end;justify-content:center;
  background:rgba(3,7,12,.72);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  padding-top:env(safe-area-inset-top);
}
.sheetBody{
  width:100%;max-width:520px;
  max-height:92dvh;overflow-y:auto;overscroll-behavior:contain;
  background:var(--panel);border-top:1px solid var(--line2);
  border-radius:var(--r5) var(--r5) 0 0;
  box-shadow:var(--sh3);
  padding:var(--s6) var(--s5) calc(var(--s6) + env(safe-area-inset-bottom));
  animation:sheetUp var(--dur-2) var(--ease);
}
.sheetBody.narrow{max-width:420px}
@keyframes sheetUp{from{transform:translateY(16px);opacity:.4}to{transform:none;opacity:1}}
.sheetBody h2{
  margin:0 0 var(--s5);padding-bottom:var(--s4);
  font-size:var(--fs-xl);font-weight:700;letter-spacing:.01em;
  border-bottom:1px solid var(--line);
}
.sheet .row{margin-top:var(--s5)}

.field{display:flex;flex-direction:column;gap:var(--s2);margin-bottom:var(--s3)}
.field span{font-size:var(--fs-sm);color:var(--ink2);font-weight:600}
.field.row2{flex-direction:row;align-items:center;justify-content:space-between;margin:var(--s5) 0}
.field input,.field select{
  height:46px;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r3);
  color:var(--ink);padding:0 var(--s4);font-size:var(--fs-lg);
  transition:border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease);
}
.field select{
  -webkit-appearance:none;appearance:none;padding-right:var(--s8);
  /* inline caret so no image file is needed offline */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8'><path d='M1 1.5 6 6.5l5-5' fill='none' stroke='%238b98a8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat:no-repeat;background-position:right var(--s4) center;
}
.field input[type=checkbox]{
  width:24px;height:24px;flex:0 0 auto;padding:0;accent-color:var(--ok);
}

.chips{display:flex;flex-wrap:wrap;gap:var(--s2);margin-bottom:var(--s4)}
.chips button{
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-pill);
  color:var(--ink2);padding:7px 14px;font-size:var(--fs-sm);font-weight:600;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.chips button.on{background:var(--panel3);color:var(--ink);border-color:var(--line2)}

.note{margin:0 0 var(--s5);padding:0 var(--s0);font-size:var(--fs-xs);
  color:var(--ink3);line-height:1.55}
.note.warn{color:var(--warn)}
.note strong{color:var(--ink2)}
.big{margin:0 0 var(--s4);font-size:var(--fs-lg);font-weight:700;line-height:1.4}
.check{margin:0 0 var(--s5);padding-left:var(--s6);font-size:var(--fs-md);color:var(--ink2)}
.check li{margin-bottom:var(--s3);line-height:1.5}
.check em{color:var(--ink);font-style:normal;font-weight:600}

/* the MT5 ticket — read off a phone while typing into the terminal, so the
   values get the mono face and the two stop rows get the entry colour */
.ticket{width:100%;border-collapse:collapse;margin-bottom:var(--s5);font-size:var(--fs-base)}
.ticket td{padding:10px var(--s2);border-bottom:1px solid var(--line)}
.ticket td:first-child{width:42%;color:var(--ink3);font-size:var(--fs-sm)}
.ticket td:last-child{text-align:right;font-weight:700;font-family:var(--font-mono)}
.ticket tr.hi td:last-child{color:var(--entry)}

.planRow{
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r3);
  padding:var(--s3) var(--s4);margin-bottom:var(--s2);font-size:var(--fs-sm);
}
.planRow b{font-size:var(--fs-md)}
.planRow small{display:block;color:var(--ink3);margin-top:3px}

/* ═══════════════════════════════════════════════════════════════════════
   VERY SMALL PHONES (<360px) — fold the 4-up grids so labels stay readable
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width:359px){
  #top{padding:0 var(--s3);gap:var(--s2)}
  .prices{gap:var(--s3);font-size:var(--fs-sm)}
  #bid,#ask{min-width:6ch}
  .stats,.posGrid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .rrnow{flex:0 0 66px}
}

/* ═══════════════════════════════════════════════════════════════════════
   LANDSCAPE PHONE — short viewport, still below the 900px switch.
   Trim every fixed chrome height so the chart keeps usable height.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-height:520px) and (orientation:landscape) and (max-width:899px){
  :root{--top-h:44px;--tf-h:32px;--footer-h:46px}
  #chartCol{min-height:38dvh}
  #side{max-height:70dvh}
  #ticket{padding:var(--s3) var(--s4) var(--s4);gap:var(--s2)}
  .levels input{height:46px;padding-top:18px}
  .sheet{align-items:center}
  .sheetBody{border-radius:var(--r5);max-height:94dvh;padding-bottom:var(--s6)}
}

/* ═══════════════════════════════════════════════════════════════════════
   TABLET AND UP (>=900px) — the layout switch. Matches TP.isWide().
   The point of the app is seeing the plan and the price in the same glance,
   so above this width nothing hides behind a tab: chart and side column are
   both on screen, the footer disappears, and the tools become a rail.
   ═══════════════════════════════════════════════════════════════════════ */
@media (min-width:900px){
  :root{--top-h:48px;--tf-h:36px}

  #app{flex-direction:row}
  #chartCol{flex:1 1 auto;min-width:0;min-height:0}

  #side{
    flex:0 0 var(--side-w);width:var(--side-w);max-height:none;
    border-top:none;border-left:1px solid var(--line);
    box-shadow:-1px 0 0 var(--shadow-line);
    padding-bottom:env(safe-area-inset-bottom);   /* footer is gone; inset moves here */
  }
  /* both sections are always mounted here — beats .hidden on specificity */
  #side #ticket,#side #tradeView{display:block!important}
  #side #ticket{display:flex!important}
  #tradeView{border-top:1px solid var(--line);margin-top:var(--s2)}

  #footer{display:none}

  /* tools rail: vertical, left of the chart */
  #chartArea{flex-direction:row}
  #tools{
    flex:0 0 var(--tools-w);width:var(--tools-w);
    flex-direction:column;align-items:center;
    padding:var(--s2) 0;
    border-bottom:none;border-right:1px solid var(--line);
    overflow-x:hidden;overflow-y:auto;
  }
  .tool.sep{margin-left:0;margin-top:auto}

  /* header gets room for bid/ask captions */
  .prices{gap:var(--s5);font-size:var(--fs-base)}
  #bid::before,#ask::before{
    content:'BID';display:inline-block;margin-right:var(--s2);
    font-size:var(--fs-micro);font-weight:800;letter-spacing:.1em;color:var(--ink3);
    vertical-align:middle;
  }
  #ask::before{content:'ASK'}

  .sheet{align-items:center;padding:var(--s6)}
  .sheetBody{border-radius:var(--r5);border:1px solid var(--line2);
    padding-bottom:var(--s6);max-height:86dvh}
  @keyframes sheetUp{from{transform:translateY(8px) scale(.99);opacity:.4}to{transform:none;opacity:1}}
}

/* ═══════════════════════════════════════════════════════════════════════
   DESKTOP (>=1280px) — wider side column, slightly more air, real hover.
   ═══════════════════════════════════════════════════════════════════════ */
@media (min-width:1280px){
  :root{--side-w:380px;--tools-w:48px;--top-h:50px}
  #ticket{padding:var(--s5);gap:var(--s4)}
  .tool{width:36px;height:36px}
  .pos{padding:var(--s4) var(--s5)}
  .posHead{padding:var(--s4) var(--s5)}
  #posNote{padding:0 var(--s5) var(--s5)}
  .levels input{height:56px}
}

/* ═══════════════════════════════════════════════════════════════════════
   ULTRAWIDE (>=1800px) — cap the side column; every extra pixel of a 27"
   monitor belongs to the chart, not to a wider ticket.
   ═══════════════════════════════════════════════════════════════════════ */
@media (min-width:1800px){
  :root{--side-w:420px}
  #side{max-width:420px}
  #ticket{padding:var(--s5) var(--s6)}
}

/* ═══════════════════════════════════════════════════════════════════════
   HOVER — only where a real pointer exists, so touch never sticks.
   ═══════════════════════════════════════════════════════════════════════ */
@media (hover:hover) and (pointer:fine){
  .icon:hover{background:var(--panel2);color:var(--ink)}
  #tfbar button:hover{background:var(--panel2);color:var(--ink)}
  .tool:hover{background:var(--panel2);color:var(--ink)}
  .rr:hover{background:var(--panel3);color:var(--ink)}
  .side:hover:not(:disabled){opacity:1}
  .confirm:hover:not(:disabled){filter:brightness(1.10)}
  .ghostwide:hover{background:var(--panel2);color:var(--ink)}
  .chips button:hover{background:var(--panel3);color:var(--ink)}
  .posBtns button:hover:not(:disabled){background:var(--panel3);color:var(--ink)}
  .pos:hover{background:rgba(255,255,255,.02)}
  #replayBar button:hover{background:var(--panel3)}
  #footer .tab:hover{color:var(--ink2)}
}

/* ═══════════════════════════════════════════════════════════════════════
   COARSE POINTERS — matches TP.isTouch(). Nothing tappable below 44px, and
   16px form text so iOS Safari does not zoom the viewport on focus.
   ═══════════════════════════════════════════════════════════════════════ */
@media (pointer:coarse){
  .icon,.tool{width:var(--tap);height:var(--tap)}
  #tfbar{height:auto;padding:var(--s2)}
  #tfbar button{height:36px;min-width:46px}
  #tools{padding:var(--s2)}
  .rr,.posBtns button,.chips button{min-height:var(--tap)}
  .side{min-height:var(--tap)}
  .side.now{min-height:40px}
  .confirm,.ghostwide{min-height:48px}
  #replayBar button{min-width:var(--tap);height:40px}
  #footer .tab{min-height:var(--tap)}
  .levels input,.field input,.field select{font-size:var(--fs-lg)}
  .field input[type=checkbox]{width:26px;height:26px}
  #rpSpeed{min-height:36px}
}

/* ═══════════════════════════════════════════════════════════════════════
   REDUCED MOTION — kill every transition and the lamp pulse.
   ═══════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important;
  }
  .dot.live{animation:none;box-shadow:0 0 8px rgba(46,160,67,.5)}
}


/* ── narrow-phone header ────────────────────────────────────────────────────
   At 390px the badge, both prices and two icon buttons crowd the symbol down to
   an ellipsis. The symbol is the single most important word on the screen, so it
   keeps its width and the balance badge gives way instead. */
@media (max-width:430px){
  #top{gap:var(--s2);padding:0 var(--s3)}
  .brand{flex:0 0 auto;min-width:0}
  .brand strong{overflow:visible;text-overflow:clip;max-width:none}
  #acctBadge{max-width:86px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .prices{gap:var(--s2);font-size:var(--fs-sm)}
  #top .icon{padding:4px}
}
@media (max-width:360px){
  #acctBadge{display:none}     /* the balance lives in Settings; the symbol does not */
}


/* ══ PHONE: chart first ═══════════════════════════════════════════════════
   The ticket used to take ~60% of a phone screen, leaving the chart too small to
   read — and reading the chart is the whole reason to open the app. Below 900px
   the ticket becomes a bottom sheet over a full-height chart, in two states:
   peek (a one-line summary) and open (the full ticket).

   The sheet is FIXED and anchored ABOVE the footer, not absolute inside #app.
   Absolute positioning left the Plan/Trade tabs rendering in the middle of the
   sheet, because the footer is a later sibling in normal flow. */
#sideGrab{display:none}

@media (max-width:899px){
  body{overflow:hidden}
  #app{position:relative;min-height:0;flex:1 1 auto}

  /* chart takes everything that is not the peek bar */
  #chartCol{position:absolute;inset:0;padding-bottom:var(--peek-h,54px)}

  #side{
    position:fixed;left:0;right:0;
    bottom:calc(var(--footer-h) + env(safe-area-inset-bottom));
    z-index:var(--z-sticky);
    border-top:1px solid var(--line2);border-radius:var(--r5) var(--r5) 0 0;
    background:var(--panel);box-shadow:var(--sh3);
    max-height:calc(100dvh - var(--top-h) - var(--footer-h) - 40px);
    display:flex;flex-direction:column;
    transform:translateY(calc(100% - var(--peek-h,54px)));
    transition:transform var(--dur-2) var(--ease);
    padding-bottom:0;
  }
  body.sheet-open #side{transform:translateY(0)}

  #sideGrab{
    display:flex;flex-direction:column;align-items:center;gap:3px;
    flex:0 0 auto;height:var(--peek-h,54px);width:100%;
    background:var(--panel);border:none;padding:7px 12px 4px;color:var(--ink2);
    border-radius:var(--r5) var(--r5) 0 0;
  }
  .grabPill{width:36px;height:4px;border-radius:var(--r-pill);background:var(--line2);flex:0 0 auto}
  #grabSummary{
    font-size:var(--fs-sm);font-variant-numeric:tabular-nums;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;
  }
  #grabSummary b{color:var(--ink)}
  #grabSummary .gs-buy{color:var(--buy)} #grabSummary .gs-sell{color:var(--sell)}
  #grabSummary .gs-bad{color:var(--bad)}

  #side>section{
    overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
    min-height:0;
  }

  /* footer pinned at the very bottom, always above the sheet */
  #footer{
    position:fixed;left:0;right:0;bottom:0;
    z-index:calc(var(--z-sticky) + 2);
    height:calc(var(--footer-h) + env(safe-area-inset-bottom));
  }
}

@media (max-width:899px) and (max-height:520px) and (orientation:landscape){
  :root{--peek-h:44px}
}
@media (pointer:coarse){ #sideGrab{min-height:var(--tap)} }


/* ── proximity alert bar ────────────────────────────────────────────────────
   Fixed to the top under the header so it is visible whichever view is open,
   and it must survive the phone sheet being expanded. */
.alertBar{
  position:fixed;left:0;right:0;top:calc(var(--top-h) + env(safe-area-inset-top));
  z-index:calc(var(--z-sheet) - 1);
  display:flex;align-items:center;gap:var(--s3);
  padding:10px var(--s4);font-size:var(--fs-sm);
  transform:translateY(-130%);transition:transform var(--dur-2) var(--ease);
  border-bottom:1px solid var(--line2);
}
.alertBar.show{transform:translateY(0)}
.alertBar strong{font-size:var(--fs-tiny);letter-spacing:1px;flex:0 0 auto}
.alertBar span{flex:1 1 auto;font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.alertBar button{background:none;border:none;color:inherit;font-size:20px;
  line-height:1;padding:0 4px;opacity:.75;cursor:pointer}
.alertBar.tp{background:#0f3a33;color:#7ee2c8;border-color:#1f6b5c}
.alertBar.sl{background:#3d1a1a;color:#ffb4ab;border-color:#5a2020}
@media (prefers-reduced-motion:reduce){ .alertBar{transition:none} }


/* ── account switcher ────────────────────────────────────────────────────────
 * Rows are tap targets on a phone, so they carry the 44px minimum the rest of the
 * touch UI uses. The current account is marked rather than hidden: knowing which
 * account you are planning against is the whole point of the control. */
.subhead {
  font-size: .82rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); margin: 18px 0 8px;
}
.acctRow {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 10px 12px; margin-bottom: 6px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface2, var(--surface)); cursor: pointer;
}
.acctRow:hover { border-color: var(--accent); }
.acctRow.on { border-color: var(--ok); cursor: default; }
.acctMain { flex: 1 1 auto; min-width: 0; }
.acctMain b { font-variant-numeric: tabular-nums; }
.acctMain small { display: block; color: var(--muted); font-size: .78rem; margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acctRow .tag {
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ok); border: 1px solid var(--ok); border-radius: 999px; padding: 1px 7px;
  margin-left: 6px; vertical-align: middle;
}
.acctX {
  flex: 0 0 auto; width: 32px; height: 32px; line-height: 1;
  font-size: 1.2rem; color: var(--muted);
  background: transparent; border: 1px solid transparent; border-radius: 8px;
  cursor: pointer;
}
.acctX:hover { color: var(--bad); border-color: var(--bad); }


/* price alert add-row: price + note + button on one line, stacking on a phone */
.priceAdd { display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.priceAdd input { flex: 1 1 120px; min-width: 0; }
.priceAdd button { flex: 0 0 auto; }
.planRow { position: relative; }
.planRow .acctX { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); }


/* the link code is read off one screen and typed into another, so it is set big and
   monospaced with unambiguous glyphs -- the alphabet already excludes I, O, 0 and 1 */
.bindCode {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.6rem; font-weight: 700; letter-spacing: .12em; text-align: center;
  padding: 14px 10px; margin: 8px 0;
  border: 1px dashed var(--accent); border-radius: 10px;
  background: var(--surface2, var(--surface)); user-select: all;
}
