:root{
  --bg:#f7f5f0; --surface:#fffefb; --surface-2:#f1efe9;
  --border:rgba(26,24,20,.11); --border-strong:rgba(26,24,20,.2);
  --text:#1a1814; --text-2:#55514a; --muted:#8c877c;
  --accent:#2f6f5e; --accent-soft:rgba(47,111,94,.1);
  /* Colour convention is a system-wide setting. --up / --down are the
     semantic pair: up = gain / long / positive exposure. Everything else
     (candles, direction chips, exposure bars, stat numbers) reads through
     --long / --short, so flipping these two lines flips the whole app.
     Default is 紅漲綠跌, the Taiwan convention. */
  --up:#c02626; --down:#15803d;
  --long:var(--up); --short:var(--down); --amber:#b45309;
  --r:10px; --r-sm:6px;
  --sans:'Space Grotesk',system-ui,-apple-system,'PingFang TC','Noto Sans TC',sans-serif;
  --num:'JetBrains Mono',ui-monospace,monospace;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--text);font-family:var(--sans);
  font-size:14.5px;line-height:1.6;-webkit-font-smoothing:antialiased}
a{color:inherit}
.wrap{max-width:1800px;margin:0 auto;padding:0 30px;
  /* width:100% is load-bearing. body is a flex column for the sticky footer,
     and in flexbox an auto margin on the cross axis BEATS align-items:stretch
     — so without this the element shrinks to its content and centres, which
     is what dragged the stock page's sidebar into the middle of wide screens. */
  width:100%}
.btn{display:inline-block;border:1px solid var(--accent);background:var(--accent);
  color:#fff;padding:9px 18px;border-radius:var(--r-sm);font:inherit;font-size:14px;
  font-weight:500;cursor:pointer;text-decoration:none}
.btn:hover{filter:brightness(1.08)}
.btn.ghost{background:transparent;color:var(--text);border-color:var(--border-strong)}
.card{background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r);padding:16px}
.muted{color:var(--muted)}
.tag{display:inline-block;border:1px solid var(--border);border-radius:var(--r-sm);
  padding:1px 7px;font-size:12px;color:var(--text-2)}
.tag.num{font-family:var(--num)}
.tag.th{color:var(--accent);border-color:var(--accent-soft);background:var(--accent-soft)}
.long{color:var(--long)} .short{color:var(--short)}
input,textarea{background:var(--surface);border:1px solid var(--border);
  color:var(--text);padding:10px 12px;border-radius:var(--r-sm);
  font:inherit;font-size:14px;width:100%}
input:focus,textarea:focus{outline:none;border-color:var(--accent)}
label{display:block;font-size:12.5px;color:var(--text-2);margin:0 0 5px}
.field{margin:0 0 13px}
.err{color:var(--short);font-size:12.5px;min-height:18px;margin:4px 0 0}

/* Footer pinned to the viewport bottom while content is short, so it does not
   ride up and then jump down as data arrives. */
:root[data-cc="west"]{ --up:#15803d; --down:#c0392b; }

html{height:100%}
body{min-height:100vh;display:flex;flex-direction:column}
body > main{flex:1 0 auto}
body > footer{flex-shrink:0;margin-top:auto}

/* Loading indicator. Pages wait on several round trips (the research proxy
   alone can take seconds), and a blank panel reads as broken. */
.spin{display:inline-block;width:15px;height:15px;vertical-align:-2px;
  border:2px solid var(--border-strong);border-top-color:var(--accent);
  border-radius:50%;animation:spin .7s linear infinite}
.loading{display:flex;align-items:center;gap:9px;color:var(--muted);
  font-size:13px;padding:36px 0}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  /* Respect the OS setting: pulse instead of spin. */
  .spin{animation:pulse 1.4s ease-in-out infinite}
  @keyframes pulse{0%,100%{opacity:.35}50%{opacity:1}}
}

/* Brand lockup, shared so the pages cannot drift apart. */
.brand{display:flex;align-items:center;gap:9px;font-weight:600;font-size:18.5px;
  letter-spacing:-.012em;text-decoration:none;flex:0 0 auto;color:var(--text)}
.brand svg{width:23px;height:23px;flex:0 0 auto}
@media(max-width:700px){
  .wrap{padding:0 18px}
  .brand{font-size:17px}
  .brand svg{width:21px;height:21px}
}

/* Add-to-note affordance on news rows. */
.notebtn{border:1px solid var(--border);background:var(--surface);color:var(--muted);
  width:22px;height:22px;border-radius:var(--r-sm);font:inherit;font-size:14px;
  line-height:1;cursor:pointer;padding:0;flex:0 0 auto}
.notebtn:hover{border-color:var(--accent);color:var(--accent)}
.notebtn.done{color:var(--accent);border-color:var(--accent)}
.notepop{position:absolute;z-index:200;width:260px;background:var(--surface);
  border:1px solid var(--border-strong);border-radius:var(--r);
  box-shadow:0 12px 36px rgba(0,0,0,.18);padding:10px}
.notepop .np-head{font-size:12px;color:var(--muted);margin:0 0 7px}
.notepop .np-new{display:block;width:100%;text-align:left;border:1px solid var(--accent);
  background:var(--accent-soft);color:var(--accent);border-radius:var(--r-sm);
  padding:7px 10px;font:inherit;font-size:13px;cursor:pointer;margin:0 0 8px}
.notepop .np-q{padding:6px 9px;font-size:13px;margin:0 0 6px}
.notepop .np-list button{display:block;width:100%;text-align:left;background:none;
  border:none;padding:6px 9px;font:inherit;font-size:13px;color:var(--text-2);
  cursor:pointer;border-radius:var(--r-sm)}
.notepop .np-list button:hover{background:var(--surface-2);color:var(--text)}
.notepop .np-empty{font-size:12px;color:var(--muted);margin:4px 9px}

/* Subscription picker */
.subpop{position:absolute;z-index:200;width:290px;background:var(--surface);
  border:1px solid var(--border-strong);border-radius:var(--r);
  box-shadow:0 12px 36px rgba(0,0,0,.18);padding:10px}
.subpop .tabs{display:flex;gap:6px;margin:0 0 8px}
.subpop .tabs button{flex:1;border:1px solid var(--border);background:var(--surface);
  color:var(--text-2);border-radius:var(--r-sm);padding:5px;font:inherit;
  font-size:12.5px;cursor:pointer}
.subpop .tabs button.on{background:var(--text);color:var(--bg);border-color:var(--text)}
.subpop input{padding:6px 9px;font-size:13px;margin:0 0 6px}
.subpop .list{max-height:220px;overflow-y:auto}
.subpop .list button{display:flex;gap:9px;width:100%;text-align:left;background:none;
  border:none;padding:6px 9px;font:inherit;font-size:13px;color:var(--text-2);
  cursor:pointer;border-radius:var(--r-sm)}
.subpop .list button:hover{background:var(--surface-2);color:var(--text)}
.subpop .list .c{font-family:var(--num);color:var(--muted);flex:0 0 46px}

/* generic search popover — shared by the notes link picker and the dashboard's
   opinion->note picker, so the two cannot drift apart visually */
.pop{position:absolute;z-index:200;width:330px;background:var(--surface);
  border:1px solid var(--border-strong);border-radius:var(--r);padding:11px;
  box-shadow:0 10px 32px rgba(0,0,0,.17)}
.pop input{padding:6px 9px;font-size:13px;margin:0 0 8px;width:100%}
.pop .grp{font-size:10.5px;color:var(--muted);text-transform:uppercase;
  letter-spacing:.04em;margin:8px 0 3px}
.pop .res{max-height:260px;overflow-y:auto}
.pop .res button{display:block;width:100%;text-align:left;background:none;
  border:none;padding:5px 8px;font:inherit;font-size:12.5px;color:var(--text-2);
  cursor:pointer;border-radius:var(--r-sm);line-height:1.4}
.pop .res button:hover{background:var(--surface-2);color:var(--text)}
.pop .res .c{font-family:var(--num);color:var(--muted);margin-right:7px}
.pop .hint{font-size:11px;color:var(--muted);margin:8px 0 0;line-height:1.5}
.pop .row{display:block;width:100%;text-align:left;background:none;
  border:1px solid var(--border);border-radius:var(--r-sm);padding:7px 10px;
  font:inherit;font-size:12.5px;color:var(--text);cursor:pointer;margin:0 0 6px}
.pop .row:hover{border-color:var(--accent);color:var(--accent)}
.pop .row[disabled]{opacity:.5;cursor:not-allowed}
/* A disabled .btn used to render identically to an enabled one, so a form
   that was waiting on input looked like a button that simply did nothing. */
.btn[disabled]{opacity:.45;cursor:not-allowed}
.pop .row .s{display:block;font-size:10.5px;color:var(--muted);margin-top:2px}

/* follow-from-a-news-row */
/* factor-mix donut — ported from the signal site's 個股研究 */
.rmwrap{display:flex;gap:24px;align-items:center;flex-wrap:wrap}
.rmchart{flex:0 0 auto}
.rmchart svg path{transition:opacity .12s;cursor:default}
.rm-c1{font-size:15px;font-weight:600;fill:var(--text);font-family:var(--sans)}
.rm-c2{font-size:11px;fill:var(--muted);font-family:var(--num)}
.rmlegend{flex:1 1 300px;min-width:260px}
.rmrow{display:flex;align-items:center;gap:9px;padding:5px 7px;
  border-radius:5px;font-size:12.2px}
.rmrow.on{background:var(--surface-2)}
.rmsw{width:11px;height:11px;border-radius:3px;flex:0 0 auto}
.rmnm{flex:1;overflow-wrap:anywhere;line-height:1.3;color:var(--text-2)}
.rmnorm{font-family:var(--num);font-weight:600;font-feature-settings:"tnum";
  min-width:56px;text-align:right}
.rmnorm.pos{color:var(--long)} .rmnorm.neg{color:var(--short)}
.rmr2{font-family:var(--num);color:var(--text);font-feature-settings:"tnum";
  min-width:50px;text-align:right;font-weight:600}
.rmrow.rmhd{font-size:10.6px;color:var(--muted);font-weight:600;
  letter-spacing:.03em;padding-bottom:2px;border-bottom:1px solid var(--border);
  border-radius:0;margin-bottom:3px}
.rmrow.rmhd .rmnorm,.rmrow.rmhd .rmr2{font-family:var(--sans);font-weight:600;
  color:var(--muted)}
.rmrow.rmidio{border-top:1px solid var(--border);margin-top:4px;padding-top:7px;
  border-radius:0;color:var(--muted)}
.rmexp{margin-top:16px;padding:14px 16px;background:var(--surface-2);
  border-radius:var(--r-sm)}
.rmexp-h{font-size:12.5px;font-weight:600;color:var(--text);margin-bottom:9px}
.rmexp-b{font-size:12.8px;line-height:1.9;color:var(--text-2);max-width:70ch}
.rmexp-b b{color:var(--text)}
.rmwarn{display:block;margin-top:10px;padding-left:11px;line-height:1.85;
  border-left:3px solid var(--amber);color:var(--text-2)}
@media(max-width:640px){.rmwrap{gap:14px}.rmlegend{min-width:0}}

.tlbar[data-op]{cursor:pointer}
.tlbar[data-op]:hover{outline:2px solid var(--text);outline-offset:1px}
.pop.opedit .opsum{font-size:12px;color:var(--text-2);line-height:1.6;
  margin:0 0 9px;padding:0 0 8px;border-bottom:1px solid var(--border)}
.pop.opedit .opsum .num{font-family:var(--num);color:var(--muted);font-size:11px}
.pop .row.danger{border-color:color-mix(in srgb,var(--short) 32%,transparent);
  color:var(--short)}
.pop .row.danger:hover{border-color:var(--short);
  background:color-mix(in srgb,var(--short) 7%,transparent);color:var(--short)}

/* destructive action: present but never the thing you hit by accident */
.btn.danger{color:var(--short);border-color:color-mix(in srgb,var(--short) 35%,transparent)}
.btn.danger:hover{border-color:var(--short);
  background:color-mix(in srgb,var(--short) 8%,transparent)}
.tbar .btn.danger{margin-left:4px}

/* ── card grid ────────────────────────────────────────────────────────────
   The dashboard lists were full-width stacks, so four sections of them meant
   a very long column and a lot of dead horizontal space. These tile instead.
   auto-fill + minmax means the column count follows the viewport rather than
   a breakpoint guess, and `.grid` is opt-in so the news and stock pages keep
   their single-column reading layout. */
.rows.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:12px;align-content:start}
@media(max-width:1040px){.rows.grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
.rows.grid .row{display:flex;flex-direction:column;padding:14px 15px;
  min-height:118px}
.rows.grid .row .hl,.rows.grid .row .tgt{font-size:15px;line-height:1.55}
/* a headline is the only unbounded text in a card; clamp it so one long
   title cannot set the height of the whole row of cards */
.rows.grid .row .hl{display:-webkit-box;-webkit-line-clamp:3;
  -webkit-box-orient:vertical;overflow:hidden}
.rows.grid .row .sub{margin-top:auto;padding-top:6px}
.rows.grid.scrollbox{max-height:none}
@media(max-width:620px){.rows.grid{grid-template-columns:1fr}}

/* linked notes inside the view-detail popup */
.pop.opedit .opnotes{margin:0 0 7px}
.pop.opedit .opnote{display:flex;align-items:center;gap:7px;
  font-size:11.5px;color:var(--text-2);text-decoration:none;padding:4px 7px;
  border-radius:var(--r-sm);border:1px solid var(--border);margin:0 0 4px}
.pop.opedit .opnote:hover{border-color:var(--k-note);color:var(--k-note)}
.pop.opedit .opnote .x{margin-left:auto;color:var(--muted);font-size:13px}
.pop.opedit .opnote .x:hover{color:var(--short)}

/* ── shared collapsible sidebar ───────────────────────────────────────────
   總覽, 個股 and 看法 each had (or lacked) their own outline nav. One
   implementation now, matching the signal site's behaviour: persistent
   collapse, scroll-spy, and a gutter that disappears entirely on a phone. */
:root{--sbw:170px}
.layout{display:grid;grid-template-columns:var(--sbw) minmax(0,1fr);gap:28px;
  align-items:start;min-height:78vh;position:relative;
  transition:grid-template-columns .18s ease,gap .18s ease}
.layout.sbclosed > .side{opacity:0;visibility:hidden;pointer-events:none}
.side{position:sticky;top:76px;display:flex;flex-direction:column;gap:2px;
  padding:18px 0 0;transition:opacity .14s ease;min-width:0}
.side .cap{font-size:11px;color:var(--muted);text-transform:uppercase;
  letter-spacing:.05em;margin:0 0 6px;padding:0 10px;display:flex;
  align-items:center;gap:6px}
.side .cap button{margin-left:auto;background:none;border:none;padding:0;
  font:inherit;color:var(--muted);cursor:pointer;line-height:0}
.side .cap button:hover{color:var(--text)}
.sbbars{display:inline-flex;align-items:center;justify-content:center}
.sbbars svg{width:16px;height:16px;fill:none}
.side a{display:block;padding:6px 10px;font-size:13.5px;color:var(--muted);
  text-decoration:none;border-radius:var(--r-sm);border-left:2px solid transparent;
  line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side a:hover{color:var(--text);background:var(--surface-2)}
.side a.on{color:var(--text);border-left-color:var(--accent);
  background:var(--accent-soft)}
.side a .n{float:right;font-family:var(--num);font-size:10.5px;
  color:var(--muted);font-weight:400}
/* the re-open handle, only present once the rail is closed */
/* The toggle sits in the header beside the brand, always in the same place
   whether the rail is open or shut. */
.sbtop{display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;padding:0;margin-right:2px;background:none;
  border:1px solid var(--border);border-radius:var(--r-sm);
  color:var(--text-2);cursor:pointer;flex:0 0 auto}
.sbtop:hover{color:var(--text);border-color:var(--border-strong)}
#mobdrawer{display:none}
/* The handle takes the collapsed rail's place in the grid, so the content
   never slides underneath it. */
.layout.sbclosed{grid-template-columns:30px minmax(0,1fr);gap:14px}
/* The rail stays pinned to column 1 so the content auto-places beside it
   rather than under the fixed handle. */
.layout > .side{grid-column:1;grid-row:1}
[id^="s-"]{scroll-margin-top:72px}
@media(max-width:900px){
  /* No rail on a phone: a 170px column leaves nothing for the content, and
     the horizontal chip strip it used to become cost a row of height on
     every page while showing three sections at a time. */
  .layout,.layout.sbclosed{grid-template-columns:1fr;gap:0}
  .layout > .side{display:none}

  /* Header: hamburger + brand + one action, on a single row that cannot
     wrap. Everything else lives in the drawer. */
  .nav{flex-wrap:nowrap;gap:8px;min-width:0}
  .nav .brand{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
    white-space:nowrap}
  .nav #navlinks,.nav .navlinks{display:none}
  .navright{gap:6px;flex:0 0 auto;margin-left:auto}
  .navright > .lang,.navright > #ccsw{display:none}

  #mobdrawer{display:block;position:fixed;inset:0;z-index:200}
  #mobdrawer[hidden]{display:none}
  .mdscrim{position:absolute;inset:0;background:rgba(24,23,20,.45);
    opacity:0;transition:opacity .2s ease}
  #mobdrawer.open .mdscrim{opacity:1}
  .mdpanel{position:absolute;left:0;top:0;bottom:0;width:min(272px,80vw);
    background:var(--bg);border-right:1px solid var(--border);
    padding:calc(14px + env(safe-area-inset-top)) 12px
            calc(16px + env(safe-area-inset-bottom));
    overflow-y:auto;transform:translateX(-100%);
    transition:transform .2s ease;box-shadow:0 0 40px rgba(24,23,20,.2)}
  #mobdrawer.open .mdpanel{transform:translateX(0)}
  .sblinks{display:flex;flex-direction:column;gap:1px}
  .sblinks.top{margin:0 0 14px;padding:0 0 14px;
    border-bottom:1px solid var(--border)}
  .sblinks a{display:block;padding:9px 10px;font-size:15px;color:var(--text);
    text-decoration:none;border-radius:var(--r-sm);line-height:1.4;
    white-space:normal}
  .sblinks a:hover,.sblinks a.on{background:var(--surface-2)}
  .sblinks a.on{color:var(--accent);font-weight:500}
  .sbcap{font-size:10.5px;color:var(--muted);text-transform:uppercase;
    letter-spacing:.05em;margin:0 0 6px;padding:0 10px}
  .sbswitches{display:flex;gap:8px;flex-wrap:wrap;padding:16px 10px 0;
    margin-top:14px;border-top:1px solid var(--border)}
}
}

/* collapsible view cards on /views */
.vop .top{cursor:pointer;user-select:none}
.vop .car{font-size:9px;color:var(--muted);flex:0 0 9px}
.vop .hasnote{color:var(--k-note);font-size:11px}
.vop:not(.open):hover{border-color:var(--border-strong)}

/* hover explanation */
.tip{position:relative;display:inline-flex;align-items:center;
  justify-content:center;width:15px;height:15px;border-radius:50%;
  border:1px solid var(--border-strong);color:var(--muted);font-size:9.5px;
  font-style:normal;cursor:help;margin-left:6px;vertical-align:1px;
  flex:0 0 auto;font-family:var(--sans);line-height:1}
.tip:hover,.tip:focus{color:var(--text);border-color:var(--text-2);outline:none}
.tip i{font-style:normal;font-weight:600}
.tipbox{position:absolute;z-index:300;top:calc(100% + 7px);left:50%;
  transform:translateX(-50%);width:310px;background:var(--surface);
  border:1px solid var(--border-strong);border-radius:var(--r);
  padding:11px 13px;box-shadow:0 10px 30px rgba(0,0,0,.16);
  font-size:11.5px;line-height:1.8;color:var(--text-2);text-align:left;
  font-weight:400;opacity:0;visibility:hidden;transition:opacity .12s;
  pointer-events:none;white-space:normal}
.tip.wide .tipbox{width:390px}
.tip:hover .tipbox,.tip:focus .tipbox,
.tip:focus-within .tipbox{opacity:1;visibility:visible}
.tipbox p{margin:0 0 8px}
.tipbox p:last-child{margin:0}
.tipbox b{color:var(--text)}
.tipbox p.warn{padding-left:9px;border-left:3px solid var(--amber);
  color:var(--text-2);margin-top:8px}
/* keep it on screen near the right edge */
.tipbox{max-width:min(390px,calc(100vw - 32px))}
@media(max-width:620px){.tipbox{left:auto;right:0;transform:none}}

/* expandable note cards on 總覽 */
.row.kind-note .notehead{cursor:pointer}
.row.kind-note .car{font-size:9px;color:var(--muted);margin-right:6px;
  vertical-align:1px}
/* an opened note needs the row: a markdown body in a third of the width is
   unreadable, and growing one cell would shove its neighbours down */
.rows.grid .row.kind-note.open{grid-column:1/-1}
.notebody{border-top:1px solid var(--border);margin:10px 0 0;padding:11px 0 0}
.notebody .md{font-size:13.5px;line-height:1.8}
.notebody .md h1{font-size:16px;margin:14px 0 6px}
.notebody .md h2{font-size:14.5px;margin:13px 0 6px}
.notebody .md h3{font-size:13.5px;margin:12px 0 5px}
.notebody .md p{margin:0 0 9px}
.notebody .md table{font-size:12px}
.notebody .md th,.notebody .md td{padding:4px 8px}
.notebody .plain{font-size:13.5px;line-height:1.8;white-space:pre-wrap;
  word-break:break-word;margin:0;font-family:var(--sans)}
.notebody .md,.notebody .plain{max-height:360px;overflow-y:auto}
.noteopen{margin:10px 0 0;padding-top:9px;border-top:1px solid var(--border);
  text-align:right}
.noteopen a{font-size:11.5px;color:var(--k-note);text-decoration:none}
.noteopen a:hover{text-decoration:underline}
/* an opened card is a reading surface, so drop the hover tint it has when
   it is just a clickable tile */
.row.kind-note.open:hover{background:var(--surface)}
.row.kind-note.open{cursor:default}

/* 我的追蹤 — one collapsible block per followed name */
.subhint{font-size:11.5px;color:var(--muted);margin:0 0 9px}
.subblocks{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:12px;align-items:start}
@media(max-width:1040px){.subblocks{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* an opened block takes the full row: its news list needs the width, and
   letting it grow inside one narrow column would push its neighbours down */
.subblock.open{grid-column:1/-1}
@media(max-width:620px){.subblocks{grid-template-columns:1fr}}
.subblock{border:1px solid var(--border);border-left:3px solid
  color-mix(in srgb,var(--k-sub) 45%,transparent);border-radius:var(--r);
  background:var(--surface);overflow:hidden}
.subblock.open{border-left-color:var(--k-sub);
  box-shadow:0 1px 0 color-mix(in srgb,var(--k-sub) 10%,transparent)}
.subhead{display:grid;grid-template-areas:'car nm kd act' 'prev prev prev prev';
  grid-template-columns:12px 1fr auto auto;align-items:center;gap:7px 8px;
  padding:14px 15px;cursor:pointer;font-size:14px;user-select:none}
.subblock:not(.open) .subhead{min-height:104px;align-content:start}
.subhead .car{grid-area:car} .subhead .nm{grid-area:nm}
.subhead .kd{grid-area:kd} .subhead .acts{grid-area:act;display:flex;gap:2px}
.subhead .prev{grid-area:prev;font-size:12.5px;color:var(--muted);
  line-height:1.7;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;margin:2px 0 0}
.subblock.open .subhead .prev{display:none}
.subhead .prev .d{font-family:var(--num);margin-right:6px;opacity:.8}
.subhead:hover{background:color-mix(in srgb,var(--k-sub) 4%,transparent)}
.subhead .car{flex:0 0 10px;font-size:9px;color:var(--muted);line-height:1}
.subhead .nm{font-weight:600;color:var(--text);min-width:0;font-size:15.5px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.subhead .kd{font-size:10.5px;color:var(--muted);border:1px solid var(--border);
  border-radius:999px;padding:0 7px;line-height:16px}
.subhead .cnt{font-family:var(--num);font-size:11px;color:#fff;
  background:var(--k-sub);border-radius:999px;padding:0 7px;line-height:18px}
.subhead .go{color:var(--muted);text-decoration:none;font-size:12px;padding:0 3px}
.subhead .go:hover{color:var(--k-sub)}
.subhead .x{color:var(--muted);cursor:pointer;font-size:14px;line-height:1;
  padding:0 2px}
.subhead .x:hover{color:var(--short)}
.subbody{padding:12px;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;
  border-top:1px solid var(--border)}
@media(max-width:1040px){.subbody{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:620px){.subbody{grid-template-columns:1fr}}
.subbody .row{background:var(--bg)}
.subbody .loading{padding:12px 2px}

/* ── block identity ───────────────────────────────────────────────────────
   Every list was the same cream card, so 追蹤 / 看法 / 筆記 / 消息 all read as
   one undifferentiated stream. Each kind now carries a hue on its left edge
   and a matching section marker, so you can tell where you are from the
   corner of your eye. The hues stay desaturated — this is a reading surface,
   not a dashboard of alerts. --long/--short are NOT reused here: those mean
   direction and flip with the colour-convention setting. */
:root{
  --k-sub:#2f6f5e;    /* 追蹤  — the accent, it is the "yours" colour */
  --k-op:#b45309;     /* 看法  — amber, a judgement */
  --k-note:#6d5bb5;   /* 筆記  — violet, writing */
  --k-news:#5b7389;   /* 消息  — slate, incoming */
}
.row.kind-news{border-left:3px solid color-mix(in srgb,var(--k-news) 42%,transparent)}
.row.kind-op{border-left:3px solid color-mix(in srgb,var(--k-op) 52%,transparent)}
.row.kind-note{border-left:3px solid color-mix(in srgb,var(--k-note) 48%,transparent);
  cursor:pointer;transition:border-color .12s,background .12s}
.row.kind-note:hover{border-left-color:var(--k-note);
  background:color-mix(in srgb,var(--k-note) 5%,var(--surface))}
.row.kind-note:hover .tgt{color:var(--k-note)}

/* section markers: a short rule in the section's hue before the heading */
h2[id^="s-"]::before{content:'';display:inline-block;width:3px;height:13px;
  border-radius:2px;margin-right:8px;vertical-align:-1px;background:var(--muted)}
h2#s-subs::before{background:var(--k-sub)}
h2#s-ops::before,h2#s-style::before{background:var(--k-op)}
h2#s-notes::before{background:var(--k-note)}
h2#s-today::before{background:var(--k-news)}
.side a[data-sec="s-subs"].on{border-left-color:var(--k-sub)}
.side a[data-sec="s-ops"].on,.side a[data-sec="s-style"].on{border-left-color:var(--k-op)}
.side a[data-sec="s-notes"].on{border-left-color:var(--k-note)}
.side a[data-sec="s-today"].on{border-left-color:var(--k-news)}

/* the two analysis panels are surfaces, not list items — give them a tint so
   they read as "computed" rather than "something you wrote" */
.tl,.pf{background:linear-gradient(var(--surface),var(--surface)) padding-box,
  linear-gradient(180deg,color-mix(in srgb,var(--k-op) 22%,transparent),
                  var(--border)) border-box;
  border:1px solid transparent}

/* search box inside the follow menu */
.pop.submenu .subq{width:100%;padding:6px 9px;font-size:12.5px;margin:7px 0 0}

/* sources & disclaimer — collapsed by default, present on every page */
.legal{border-top:1px solid var(--border);margin:26px 0 0;padding:12px 0 0}
.lgmore{border:none;background:none;padding:0;font:inherit;font-size:11px;
  color:var(--muted);cursor:pointer;text-decoration:underline;
  text-underline-offset:2px}
.lgmore:hover,.lgmore.on{color:var(--text-2)}
.lgbody{margin:9px 0 0;max-width:72ch}
.lgbody p{font-size:11.5px;line-height:1.9;color:var(--muted);margin:0 0 9px}
.lgbody a{color:var(--accent)}
.lgbody p.lgrefs{margin:11px 0 4px;color:var(--text-2);font-weight:500}
.lgbody ul.lgrefs{margin:0;padding-left:16px}
.lgbody ul.lgrefs li{font-size:11px;line-height:1.8;color:var(--muted);
  margin:0 0 7px}

/* colour-convention switch, sits beside the language switch */
.cc{display:flex;border:1px solid var(--border);border-radius:999px;
  overflow:hidden}
.cc button{background:none;border:none;padding:3px 8px;font:inherit;
  font-size:11px;color:var(--muted);cursor:pointer;line-height:1.5}
.cc button.on{background:var(--text);color:var(--bg)}
.cc button i{font-style:normal;font-weight:700}

/* factor exposure bars — shared by the stock page and the style dashboard */
.fx{display:flex;flex-direction:column;gap:4px}
.fxrow{display:grid;grid-template-columns:minmax(120px,1.4fr) 2fr 54px 40px;
  align-items:center;gap:9px;font-size:12px}
.fxname{color:var(--text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fxbar{position:relative;height:13px;background:var(--surface-2);
  border-radius:3px;overflow:hidden}
.fxfill{position:absolute;top:0;bottom:0;border-radius:2px}
.fxfill.p{background:color-mix(in srgb,var(--long) 72%,transparent)}
.fxfill.n{background:color-mix(in srgb,var(--short) 72%,transparent)}
.fxmid{position:absolute;left:50%;top:0;bottom:0;width:1px;background:rgba(26,24,20,.22)}
.fxval{text-align:right;font-size:11.5px}
.fxshare{text-align:right;font-size:11px;color:var(--muted)}

/* style dashboard */
.pf{background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r);padding:14px 16px;margin:0 0 12px}
.pfstats{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 12px}
/* A bare number floating on the page background reads as a caption, not a
   figure. The border is what makes each one legible as its own reading. */
.pfstat{border:1px solid var(--border);border-radius:var(--r-sm);
  background:var(--surface);padding:9px 14px;min-width:94px}
.pfstat b{display:block;font-family:var(--num);font-size:19px;font-weight:500;
  line-height:1.25}
.pfstat span{font-size:11px;color:var(--muted)}
.pfstat b.pos{color:var(--long)} .pfstat b.neg{color:var(--short)}
.pfcurve{height:180px;position:relative;margin:0 0 6px}
.pfcurve canvas{width:100%;height:100%;display:block}
.pfleg{display:flex;gap:14px;font-size:11px;color:var(--muted);margin:0 0 12px}
.pfleg i{display:inline-block;width:14px;height:2px;vertical-align:3px;
  margin-right:5px}
.pfgrid{display:grid;grid-template-columns:1fr 1fr;gap:22px}
.pfgrid h4{font-size:11.5px;font-weight:600;margin:0 0 7px;color:var(--text-2)}
.pfbars{display:flex;flex-direction:column;gap:4px}
.pfb{display:grid;grid-template-columns:1fr 2.1fr 42px;align-items:center;
  gap:8px;font-size:11.5px}
.pfb .n{color:var(--text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pfb .t{height:11px;background:var(--surface-2);border-radius:3px;overflow:hidden}
.pfb .t i{display:block;height:100%;background:var(--accent);opacity:.75}
.pfb .v{text-align:right;font-family:var(--num);font-size:10.5px;color:var(--muted)}
.pfperiod{font-size:11.5px;color:var(--muted);margin:0 0 12px;
  display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.pfperiod .num{font-family:var(--num)}
.pfhow{border:1px solid var(--border);background:var(--surface);
  color:var(--muted);border-radius:999px;padding:1px 9px;font:inherit;
  font-size:10.5px;cursor:pointer}
.pfhow:hover,.pfhow.on{border-color:var(--accent);color:var(--accent)}
.pfexp{background:var(--surface-2);border-radius:var(--r-sm);
  padding:14px 16px;margin:0 0 14px}
.pfexp h4{font-size:12.5px;font-weight:600;margin:0 0 9px;color:var(--text)}
.pfexp p{font-size:12.5px;line-height:1.9;color:var(--text-2);margin:0 0 10px;
  max-width:68ch}
.pfexp p:last-child{margin-bottom:0}
.pfexp b{color:var(--text);font-weight:600}
.pfcaveat{font-size:11.5px;color:var(--muted);line-height:1.85;margin:14px 0 0;
  max-width:72ch;
  padding-top:10px;border-top:1px solid var(--border)}
@media(max-width:700px){.pfgrid{grid-template-columns:1fr;gap:16px}
  .fxrow{grid-template-columns:minmax(90px,1fr) 1.4fr 46px 34px}}

.opbtn{border:1px dashed var(--border-strong);background:none;color:var(--muted);
  border-radius:999px;padding:1px 8px;font:inherit;font-size:11px;cursor:pointer;
  white-space:nowrap}
.opbtn:hover{border-color:var(--k-op);color:var(--k-op);border-style:solid}

.subbtn{border:1px dashed var(--border-strong);background:none;color:var(--muted);
  border-radius:999px;padding:1px 8px;font:inherit;font-size:10.5px;cursor:pointer;
  white-space:nowrap}
.subbtn:hover{border-color:var(--accent);color:var(--accent);border-style:solid}
.pop.submenu .row.sub{display:flex;align-items:center;gap:8px;margin:0 0 5px}
.pop.submenu .row.sub .l{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.pop.submenu .row.sub .s{display:inline;font-size:10px;color:var(--muted);
  margin:0;flex:0 0 auto}
.pop.submenu .row.sub .mk{flex:0 0 auto;font-family:var(--num);color:var(--muted)}
.pop.submenu .row.sub.on{border-color:var(--accent);color:var(--accent)}
.pop.submenu .row.sub.on .mk{color:var(--accent)}

/* opinion entry popover */
.oppop{position:absolute;z-index:200;width:276px;background:var(--surface);
  border:1px solid var(--border-strong);border-radius:var(--r);padding:12px;
  box-shadow:0 10px 32px rgba(0,0,0,.17)}
.oppop .oh{font-size:12px;color:var(--muted);margin:0 0 9px}
.oppop .fl{font-size:11.5px;color:var(--muted);margin:0 0 4px}
.oppop .seg{display:flex;gap:5px;margin:0 0 10px}
.oppop .seg button{flex:1;border:1px solid var(--border);background:var(--surface);
  color:var(--text-2);border-radius:var(--r-sm);padding:5px 0;font:inherit;
  font-size:12.5px;cursor:pointer}
.oppop .seg button.on{background:var(--text);color:var(--bg);border-color:var(--text)}
.oppop .seg button.on[data-d="long"]{background:var(--long);border-color:var(--long);color:#fff}
.oppop .seg button.on[data-d="short"]{background:var(--short);border-color:var(--short);color:#fff}
.oppop .go{width:100%;margin:2px 0 0}
.oppop .err{font-size:11.5px;color:var(--short);margin:7px 0 0}
.oppop .hint{font-size:11px;color:var(--muted);margin:8px 0 0;line-height:1.5}
/* target picker inside the opinion popover */
.oppop .q{padding:6px 9px;font-size:13px;margin:0 0 8px;width:100%}
.oppop .res{max-height:240px;overflow-y:auto}
.oppop .grp{font-size:10px;color:var(--muted);text-transform:uppercase;
  letter-spacing:.05em;margin:7px 0 2px}
.oppop .res button{display:block;width:100%;text-align:left;background:none;
  border:none;padding:5px 8px;font:inherit;font-size:12.5px;color:var(--text-2);
  cursor:pointer;border-radius:var(--r-sm);line-height:1.4}
.oppop .res button:hover{background:var(--surface-2);color:var(--text)}
.oppop .res .c{font-family:var(--num);color:var(--muted);margin-right:6px}
.oppop .oh .back{background:none;border:none;font:inherit;font-size:11px;
  color:var(--accent);cursor:pointer;padding:0 0 0 4px;text-decoration:underline}

.subchip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--border);
  background:var(--surface);border-radius:999px;padding:4px 11px;font-size:12.5px;
  color:var(--text-2);text-decoration:none}
.subchip:hover{border-color:var(--border-strong)}
.subchip .x{cursor:pointer;color:var(--muted);font-size:14px;line-height:1}
.subchip .x:hover{color:var(--short)}


/* ── notifications ─────────────────────────────────────────────────────── */
.bell{position:relative;display:inline-flex;align-items:center;
  justify-content:center;width:30px;height:30px;padding:0;background:none;
  border:1px solid var(--border);border-radius:999px;color:var(--text-2);
  cursor:pointer}
.bell:hover{border-color:var(--border-strong);color:var(--text)}
.bell svg{width:17px;height:17px}
.bell .dot{position:absolute;top:-4px;right:-4px;min-width:15px;height:15px;
  padding:0 3px;border-radius:999px;background:var(--accent);color:#fff;
  font-family:var(--num);font-size:10px;line-height:15px;text-align:center}
.notifpop{width:330px}
.notifpop .res{max-height:320px;overflow-y:auto}
.nrow{display:block;text-decoration:none;color:var(--text);
  border-bottom:1px solid var(--border);padding:9px 2px}
.nrow:last-child{border-bottom:none}
.nrow:hover .h{color:var(--accent)}
.nrow .k,.toast .k{display:inline-block;font-size:10px;padding:1px 6px;
  border-radius:var(--r-sm);background:var(--surface-2);color:var(--muted);
  margin-right:6px;vertical-align:1px}
.nrow .k.mat,.toast.mat .k{background:color-mix(in srgb,var(--amber) 16%,transparent);
  color:var(--amber)}
.nrow .h,.toast .h{font-size:13.5px;line-height:1.5}
.nrow .m,.toast .m{display:block;font-size:11px;color:var(--muted);margin-top:3px}
.pfoot{display:flex;gap:12px;align-items:center;margin-top:9px;
  padding-top:9px;border-top:1px solid var(--border)}
.pfoot .lnk{background:none;border:none;padding:0;font:inherit;font-size:11.5px;
  color:var(--muted);text-decoration:none;cursor:pointer}
.pfoot .lnk:hover{color:var(--accent)}
.pfoot a.lnk{margin-left:auto}

.toasts{position:fixed;right:16px;bottom:16px;z-index:300;display:flex;
  flex-direction:column;gap:8px;max-width:min(360px,calc(100vw - 32px));
  pointer-events:none}
.toast{pointer-events:auto;display:block;text-decoration:none;color:var(--text);
  background:var(--surface);border:1px solid var(--border-strong);
  border-left:3px solid var(--accent);border-radius:var(--r-sm);
  padding:10px 12px;box-shadow:0 6px 22px rgba(0,0,0,.18);
  animation:toastin .22s ease-out}
.toast.mat{border-left-color:var(--amber)}
.toast:hover{border-color:var(--accent)}
@keyframes toastin{from{opacity:0;transform:translateY(8px)}to{opacity:1}}
@media(prefers-reduced-motion:reduce){.toast{animation:none}}
@media(max-width:700px){.toasts{left:16px;right:16px;bottom:12px}}


/* ── AI note suggestion ────────────────────────────────────────────────── */
.aibtn{display:inline-flex;align-items:center;justify-content:center;
  width:22px;height:22px;padding:0;background:none;border:1px solid var(--border);
  border-radius:var(--r-sm);color:var(--muted);cursor:pointer}
.aibtn svg{width:13px;height:13px}
.aibtn:hover{border-color:var(--accent);color:var(--accent)}
.aiwrap{position:fixed;inset:0;z-index:420;background:rgba(0,0,0,.45);
  display:flex;align-items:flex-start;justify-content:center;
  padding:40px 20px;overflow-y:auto}
.aibox{background:var(--bg);border:1px solid var(--border-strong);
  border-radius:var(--r);padding:20px 22px;width:min(640px,100%)}
.aibox h2{font-size:17px;margin:0 0 14px;font-weight:600;letter-spacing:-.01em}
.aiload{padding:40px 0;display:flex;justify-content:center}
.aimode{display:block;width:100%;text-align:left;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--r-sm);padding:11px 13px;
  margin:0 0 8px;font:inherit;cursor:pointer}
.aimode:hover{border-color:var(--border-strong)}
.aimode.on{border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 7%,var(--surface))}
.aimode .l{display:block;font-size:14px;color:var(--text)}
.aimode .h{display:block;font-size:12px;color:var(--muted);margin-top:3px;
  line-height:1.6}
.ail{display:block;font-size:10.5px;color:var(--muted);text-transform:uppercase;
  letter-spacing:.06em;margin:12px 0 5px}
.ail .hint{text-transform:none;letter-spacing:0;margin-left:8px;opacity:.8}
.aititle,.aitext{width:100%;font:inherit;background:var(--surface);
  color:var(--text);border:1px solid var(--border);border-radius:var(--r-sm);
  padding:8px 10px}
.aitext{font-size:13.5px;line-height:1.75;resize:vertical}
.aititle:focus,.aitext:focus{outline:none;border-color:var(--accent)}
.ainote{font-size:12px;color:var(--muted);margin:9px 0 0;line-height:1.6}
.aiup{border:1px solid var(--border);border-radius:var(--r-sm);
  background:var(--surface);padding:10px 12px;margin:0 0 8px}
.aiup .t{display:flex;align-items:center;gap:9px;font-size:13.5px}
.aiup .t a{color:var(--text);text-decoration:none;font-weight:500}
.aiup .t a:hover{color:var(--accent)}
.aiup .t button{margin-left:auto}
.aiup .w{font-size:12px;color:var(--muted);margin:5px 0 0;line-height:1.6}
.aiup .a{font-size:12.5px;line-height:1.7;white-space:pre-wrap;
  word-break:break-word;margin:7px 0 0;padding:8px 10px;border-radius:var(--r-sm);
  background:var(--surface-2);color:var(--text-2);font-family:inherit;
  max-height:170px;overflow-y:auto}
.aimeta{font-size:11px;color:var(--muted);margin:12px 0 0;font-family:var(--num)}
.aidisc{font-size:11px;color:var(--muted);margin:5px 0 0;line-height:1.6}
.aierr{font-size:13px;color:var(--short);margin:8px 0 0}
.aifoot{display:flex;align-items:center;gap:8px;margin-top:16px;
  padding-top:13px;border-top:1px solid var(--border)}
.aifoot .n{font-size:11.5px;color:var(--muted);margin-right:auto}
@media(max-width:700px){.aiwrap{padding:16px}}


/* ── new-note composer ─────────────────────────────────────────────────── */
.ncwrap{position:fixed;inset:0;z-index:420;background:rgba(0,0,0,.45);
  display:flex;align-items:flex-start;justify-content:center;
  padding:40px 20px;overflow-y:auto}
.ncbox{background:var(--bg);border:1px solid var(--border-strong);
  border-radius:var(--r);padding:20px 22px;width:min(620px,100%)}
.ncbox h2{font-size:17px;margin:0 0 14px;font-weight:600;letter-spacing:-.01em}
.nctpls{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px}
.nctpl{text-align:left;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r-sm);padding:9px 11px;font:inherit;cursor:pointer}
.nctpl:hover{border-color:var(--border-strong)}
.nctpl.on{border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 7%,var(--surface))}
.nctpl .l{display:block;font-size:13.5px;color:var(--text)}
.nctpl .h{display:block;font-size:11px;color:var(--muted);margin-top:2px;
  line-height:1.5}
/* The AI offer, only ever shown next to a body the user is already writing. */
.ncai{display:inline-flex;align-items:center;gap:5px;float:right;
  background:none;border:1px solid var(--border);border-radius:999px;
  padding:2px 10px;font:inherit;font-size:11.5px;color:var(--muted);
  cursor:pointer;text-transform:none;letter-spacing:0}
.ncai svg{width:11px;height:11px}
.ncai:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.ncai:disabled{opacity:.4;cursor:not-allowed}
.nclinks{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px;
  max-height:120px;overflow-y:auto}
.ncsug{background:var(--surface);border:1px solid var(--border);
  border-radius:999px;padding:4px 11px;font:inherit;font-size:12.5px;
  color:var(--text-2);cursor:pointer;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.ncsug:hover{border-color:var(--accent);color:var(--accent)}
.nclinks .hint{font-size:12px;color:var(--muted);margin:0}
/* The picker list used to stop at eight notes with no way to see the rest. */
.notepop .np-list{max-height:260px;overflow-y:auto}
@media(max-width:700px){.ncwrap{padding:16px}
  .nctpls{grid-template-columns:repeat(2,minmax(0,1fr))}}


/* ── disclosure ────────────────────────────────────────────────────────── */
.disc{margin:0 0 12px}
.disc.block{display:block}
.discbtn{display:inline-flex;align-items:center;gap:5px;background:none;
  border:1px solid var(--border);border-radius:999px;padding:4px 12px 4px 9px;
  font:inherit;font-size:12.5px;color:var(--muted);cursor:pointer}
.discbtn:hover{border-color:var(--border-strong);color:var(--text)}
.discbtn.on{color:var(--accent);border-color:var(--accent)}
.discbtn .chev{width:12px;height:12px;flex:0 0 auto;
  transition:transform .15s ease}
.discbtn.on .chev{transform:rotate(90deg)}
.discbody{margin:9px 0 0;padding:12px 14px;border:1px solid var(--border);
  border-radius:var(--r-sm);background:var(--surface);max-width:72ch}
.discbody[hidden]{display:none}
.discbody p{font-size:13px;line-height:1.85;color:var(--text-2);margin:0 0 7px}
.discbody p:last-child{margin-bottom:0}
.discbody b{color:var(--text);font-weight:600}
@media(prefers-reduced-motion:reduce){.discbtn .chev{transition:none}}
