diff --git a/app.css b/app.css index ba94cf3..3021eca 100644 --- a/app.css +++ b/app.css @@ -1,319 +1,455 @@ /* ═══════════════════════════════════════════════════════════ - Emmy 投資台 — 學習教材 / 財報健檢 / 交易復盤 的樣式 - 沿用 index.html 既有的 CSS 變數(--bg/--surface/--card…) + Emmy 投資台 — Apple 風格 UI(簡潔、色塊、幾何互動) ═══════════════════════════════════════════════════════════ */ -/* ── 主視圖切換 tabs ── */ -.view-tabs{display:flex;gap:4px;flex-wrap:wrap} -.view-tabs a{ - padding:7px 16px;border-radius:8px;font-size:.9rem;font-weight:600;color:var(--text2);cursor:pointer; - transition:background .15s,color .15s; +/* ── 主視圖切換(膠囊分段)── */ +.view-tabs{ + display:flex;gap:2px;flex-wrap:wrap; + background:rgba(0,0,0,.04);border-radius:12px;padding:3px; +} +.view-tabs a{ + padding:8px 18px;border-radius:10px;font-size:.88rem;font-weight:600;color:var(--text2); + cursor:pointer;transition:background .2s,color .2s,box-shadow .2s; +} +.view-tabs a:hover{color:var(--text)} +.view-tabs a.active{ + background:var(--surface);color:var(--text); + box-shadow:0 1px 4px rgba(0,0,0,.08); } -.view-tabs a:hover{color:var(--text);background:rgba(77,166,255,.08)} -.view-tabs a.active{background:rgba(77,166,255,.16);color:var(--blue)} .view[hidden]{display:none} - -/* 非總經視圖時,隱藏總經的群組子導覽 */ body[data-view="macro"] #navLinks{display:flex} body:not([data-view="macro"]) #navLinks{display:none} -/* ── 共用:頁面區塊標題 ── */ -.page{margin:24px 32px 0;animation:fadeInUp .4s ease both} -.page-head{margin-bottom:18px} -.page-title{font-size:1.35rem;font-weight:700;letter-spacing:-.01em;display:flex;align-items:center;gap:10px} -.page-sub{font-size:.85rem;color:var(--text2);margin-top:6px;line-height:1.6;max-width:880px} -.disclaimer{font-size:.72rem;color:var(--text2);background:rgba(255,138,77,.08);border:1px solid rgba(255,138,77,.2); - border-radius:8px;padding:8px 14px;margin-top:14px;line-height:1.6} +/* ── 頁面 ── */ +.page{margin:28px 32px 0;animation:fadeInUp .35s ease both} +.page-head{margin-bottom:22px} +.page-title{font-size:1.5rem;font-weight:700;letter-spacing:-.02em} +.page-sub{font-size:.9rem;color:var(--text2);margin-top:8px;line-height:1.65;max-width:720px} +.disclaimer{ + font-size:.78rem;color:var(--text2); + background:rgba(255,149,0,.08);border:1px solid rgba(255,149,0,.18); + border-radius:var(--radius);padding:12px 16px;margin-top:16px;line-height:1.6; +} -@media(max-width:900px){ .page{margin:18px 16px 0} } +@keyframes fadeInUp{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}} +@keyframes spin{to{transform:rotate(360deg)}} + +@media(max-width:900px){ .page{margin:20px 16px 0} } + +/* ── 色塊 / 分段控制(取代下拉)── */ +.chip-row,.chip-group{display:flex;flex-wrap:wrap;gap:8px} +.chip,.chip-item{ + display:inline-flex;align-items:center;gap:6px; + padding:10px 18px;border-radius:12px;font-size:.86rem;font-weight:600; + border:1.5px solid var(--border);background:var(--surface);color:var(--text2); + cursor:pointer;transition:all .18s;font-family:inherit;user-select:none; +} +.chip:hover,.chip-item:hover{border-color:rgba(0,113,227,.35);color:var(--text)} +.chip.on,.chip-item.on{ + background:var(--blue);border-color:var(--blue);color:#fff; + box-shadow:0 4px 14px rgba(0,113,227,.28); +} +.chip.sm,.chip-item.sm{padding:6px 14px;font-size:.8rem;border-radius:10px} +.chip.tint-green.on{background:var(--green);border-color:var(--green);box-shadow:0 4px 14px rgba(52,199,89,.25)} +.chip.tint-red.on{background:var(--red);border-color:var(--red);box-shadow:0 4px 14px rgba(255,59,48,.25)} +.chip.tint-purple.on{background:var(--purple);border-color:var(--purple);box-shadow:0 4px 14px rgba(175,82,222,.25)} + +.seg-pill{ + display:inline-flex;background:rgba(0,0,0,.05);border-radius:12px;padding:3px;gap:2px; +} +.seg-pill button{ + padding:8px 16px;border:none;border-radius:10px;font-size:.84rem;font-weight:600; + background:transparent;color:var(--text2);cursor:pointer;transition:.18s;font-family:inherit; +} +.seg-pill button.on{background:var(--surface);color:var(--text);box-shadow:0 1px 4px rgba(0,0,0,.08)} + +/* 大色塊選項(交易方向等) */ +.tile-row{display:flex;gap:10px;flex-wrap:wrap} +.tile{ + flex:1;min-width:120px;padding:16px 18px;border-radius:var(--radius); + border:2px solid var(--border);background:var(--surface);cursor:pointer; + text-align:center;transition:all .18s; +} +.tile .tile-label{font-size:.95rem;font-weight:700} +.tile .tile-sub{font-size:.72rem;color:var(--text2);margin-top:4px} +.tile.on{border-color:var(--blue);background:rgba(0,113,227,.06);box-shadow:0 4px 16px rgba(0,113,227,.12)} +.tile.on.tint-green{border-color:var(--green);background:rgba(52,199,89,.08)} +.tile.on.tint-red{border-color:var(--red);background:rgba(255,59,48,.06)} /* ═══════════ 學習教材 ═══════════ */ -.learn-layout{display:grid;grid-template-columns:230px 1fr;gap:22px;align-items:start} -.learn-side{position:sticky;top:78px;display:flex;flex-direction:column;gap:4px} -.learn-side .side-group{font-size:.7rem;color:var(--text2);letter-spacing:.06em;margin:12px 4px 4px;text-transform:uppercase} -.learn-side a{ - padding:7px 12px;border-radius:7px;font-size:.85rem;color:var(--text);cursor:pointer;transition:.15s; - display:flex;justify-content:space-between;align-items:center;gap:8px; +.learn-layout{display:grid;grid-template-columns:240px 1fr;gap:24px;align-items:start} +.learn-side{ + position:sticky;top:88px;display:flex;flex-direction:column;gap:6px; } -.learn-side a:hover{background:rgba(77,166,255,.08)} -.learn-side a.active{background:rgba(77,166,255,.15);color:var(--blue)} -.learn-side a .count{font-size:.68rem;color:var(--text2)} +.learn-side .side-group{ + font-size:.68rem;color:var(--text2);letter-spacing:.08em;margin:14px 4px 6px; + text-transform:uppercase;font-weight:600; +} +.learn-side a,.side-tile{ + padding:10px 14px;border-radius:12px;font-size:.86rem;color:var(--text); + cursor:pointer;transition:.15s;display:flex;justify-content:space-between;align-items:center;gap:8px; + border:1px solid transparent;background:transparent;text-decoration:none; +} +.learn-side a:hover,.side-tile:hover{background:rgba(0,0,0,.04)} +.learn-side a.active,.side-tile.active{ + background:var(--surface);border-color:var(--border); + box-shadow:var(--shadow);font-weight:600; +} +.learn-side a .count{font-size:.68rem;color:var(--text2);background:rgba(0,0,0,.05); + padding:2px 8px;border-radius:20px} .learn-content{min-width:0} @media(max-width:780px){ .learn-layout{grid-template-columns:1fr} - .learn-side{position:static;flex-direction:row;flex-wrap:wrap;gap:6px;margin-bottom:14px} - .learn-side .side-group{width:100%;margin:6px 0 0} + .learn-side{position:static;flex-direction:row;flex-wrap:wrap} + .learn-side .side-group{width:100%} } -/* 三階段課綱卡片 */ -.stage{margin-bottom:24px} -.stage-title{font-size:1.05rem;font-weight:700;margin-bottom:4px;display:flex;align-items:center;gap:8px} -.stage-badge{font-size:.66rem;font-weight:700;padding:2px 9px;border-radius:20px} -.stage-desc{font-size:.82rem;color:var(--text2);margin-bottom:12px;line-height:1.6} -.module-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px} +.stage{margin-bottom:28px} +.stage-title{font-size:1.1rem;font-weight:700;margin-bottom:6px} +.stage-badge{font-size:.66rem;font-weight:700;padding:3px 10px;border-radius:20px} +.stage-desc{font-size:.84rem;color:var(--text2);margin-bottom:14px;line-height:1.6} +.module-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px} .module-card{ - background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:16px 18px;cursor:pointer; - transition:border-color .2s,box-shadow .2s;display:flex;flex-direction:column;gap:8px; + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:18px 20px;cursor:pointer;transition:transform .15s,box-shadow .2s; + display:flex;flex-direction:column;gap:8px;box-shadow:var(--shadow); } -.module-card:hover{border-color:rgba(77,166,255,.35);box-shadow:0 0 18px rgba(77,166,255,.06)} +.module-card:hover{transform:translateY(-2px);box-shadow:0 8px 28px rgba(0,0,0,.1)} .module-card .mod-name{font-size:.98rem;font-weight:700} -.module-card .mod-meta{font-size:.74rem;color:var(--text2);line-height:1.55} -.module-card .mod-tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:2px} -.chip{font-size:.68rem;color:var(--text2);background:var(--surface);border:1px solid var(--border); - border-radius:20px;padding:2px 9px;cursor:pointer;transition:.15s;white-space:nowrap} -.chip:hover{border-color:var(--blue);color:var(--blue)} +.module-card .mod-meta{font-size:.76rem;color:var(--text2);line-height:1.55} +.module-card .mod-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px} +.chip-tag{ + font-size:.68rem;color:var(--text2);background:rgba(0,0,0,.04); + border-radius:20px;padding:3px 10px; +} -/* 速查(名詞 / 公司 / 單集)搜尋 */ -.search-box{display:flex;gap:8px;margin-bottom:14px} +.search-box{display:flex;gap:10px;margin-bottom:16px} .search-box input{ - flex:1;background:var(--surface);border:1px solid var(--border);border-radius:8px;color:var(--text); - padding:10px 14px;font-size:.9rem;outline:none;transition:.15s;font-family:inherit; + flex:1;background:var(--surface);border:1px solid var(--border);border-radius:12px; + color:var(--text);padding:12px 16px;font-size:.92rem;outline:none; + box-shadow:var(--shadow);font-family:inherit; } -.search-box input:focus{border-color:var(--blue)} -.glossary-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px} +.search-box input:focus{border-color:var(--blue);box-shadow:0 0 0 4px rgba(0,113,227,.15)} +.glossary-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px} .gloss-item{ - background:var(--card);border:1px solid var(--border);border-radius:8px;padding:9px 12px;cursor:pointer;transition:.15s; + background:var(--card);border:1px solid var(--border);border-radius:12px; + padding:12px 14px;cursor:pointer;transition:.15s;box-shadow:var(--shadow); } -.gloss-item:hover{border-color:var(--blue);background:rgba(77,166,255,.06)} -.gloss-item .gi-title{font-size:.85rem;font-weight:600;color:var(--text)} -.gloss-item .gi-sub{font-size:.7rem;color:var(--text2);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} -.list-meta{font-size:.76rem;color:var(--text2);margin-bottom:10px} +.gloss-item:hover{border-color:rgba(0,113,227,.3);transform:translateY(-1px)} +.gloss-item .gi-title{font-size:.86rem;font-weight:600} +.gloss-item .gi-sub{font-size:.72rem;color:var(--text2);margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} +.list-meta{font-size:.78rem;color:var(--text2);margin-bottom:12px} -/* Markdown 內文渲染 */ -.md{font-size:.9rem;line-height:1.75;color:var(--text)} -.md h1{font-size:1.5rem;font-weight:700;margin:.2em 0 .5em} -.md h2{font-size:1.18rem;font-weight:700;margin:1.3em 0 .5em;padding-bottom:.3em;border-bottom:1px solid var(--border)} -.md h3{font-size:1.02rem;font-weight:700;margin:1.1em 0 .4em;color:var(--text)} -.md h4{font-size:.92rem;font-weight:700;margin:1em 0 .3em;color:var(--text2)} -.md p{margin:.6em 0} +/* Markdown */ +.md{font-size:.94rem;line-height:1.75;color:var(--text)} +.md h1{font-size:1.55rem;font-weight:700;margin:.2em 0 .5em;letter-spacing:-.02em} +.md h2{font-size:1.22rem;font-weight:700;margin:1.4em 0 .5em;padding-bottom:.35em;border-bottom:1px solid var(--border)} +.md h3{font-size:1.05rem;font-weight:700;margin:1.2em 0 .4em} +.md h4{font-size:.94rem;font-weight:600;margin:1em 0 .3em;color:var(--text2)} +.md p{margin:.65em 0} .md ul,.md ol{margin:.5em 0 .5em 1.3em} -.md li{margin:.25em 0} -.md blockquote{border-left:3px solid var(--blue);background:var(--surface);margin:.8em 0;padding:.6em 1em; - color:var(--text2);border-radius:0 8px 8px 0} -.md blockquote p{margin:.2em 0} -.md code{background:var(--surface);padding:2px 6px;border-radius:4px;color:var(--yellow);font-size:.86em; - font-family:ui-monospace,SFMono-Regular,Menlo,monospace} -.md pre{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 14px;overflow:auto;margin:.8em 0} -.md pre code{background:none;padding:0;color:var(--text2)} -.md hr{border:none;border-top:1px solid var(--border);margin:1.2em 0} -.md table{border-collapse:collapse;width:100%;margin:.9em 0;font-size:.84rem;display:block;overflow-x:auto} -.md th,.md td{border:1px solid var(--border);padding:7px 11px;text-align:left;vertical-align:top} -.md th{background:var(--surface);font-weight:600;color:var(--text);white-space:nowrap} -.md td{color:var(--text2)} -.md a{color:var(--blue)} -.md .wlink{color:var(--purple);border-bottom:1px dashed rgba(179,136,255,.4);cursor:pointer} -.md .wlink:hover{border-bottom-style:solid} -.md .wlink.dead{color:var(--text2);border-bottom-color:transparent;cursor:default} - -.back-link{display:inline-flex;align-items:center;gap:6px;font-size:.82rem;color:var(--text2);cursor:pointer;margin-bottom:14px} -.back-link:hover{color:var(--blue)} -.note-frontmatter{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px} -.fm-tag{font-size:.7rem;color:var(--text2);background:var(--surface);border:1px solid var(--border);border-radius:20px;padding:2px 10px} - -/* 練習題庫 */ -.quiz-q{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px 16px;margin-bottom:10px} -.quiz-q .q-text{font-size:.9rem;line-height:1.6} -.quiz-q .q-src{font-size:.72rem;color:var(--text2);margin-top:8px;cursor:pointer} -.quiz-q .q-src:hover{color:var(--blue)} - -/* ═══════════ 財報健檢 ═══════════ */ -.finbox-search{display:flex;gap:8px;margin-bottom:6px;max-width:520px} -.finbox-search input{ - flex:1;background:var(--surface);border:1px solid var(--border);border-radius:8px;color:var(--text); - padding:11px 15px;font-size:1rem;outline:none;font-family:inherit;letter-spacing:.04em;text-transform:uppercase; +.md li{margin:.3em 0} +.md blockquote{ + border-left:4px solid var(--blue);background:rgba(0,113,227,.05); + margin:.9em 0;padding:.7em 1.1em;color:var(--text2);border-radius:0 12px 12px 0; } -.finbox-search input:focus{border-color:var(--blue)} +.md code{background:rgba(0,0,0,.05);padding:2px 8px;border-radius:6px;color:var(--purple);font-size:.88em} +.md pre{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:14px;overflow:auto;margin:.9em 0;box-shadow:var(--shadow)} +.md pre code{background:none;padding:0;color:var(--text2)} +.md table{border-collapse:collapse;width:100%;margin:1em 0;font-size:.86rem;display:block;overflow-x:auto;border-radius:12px} +.md th,.md td{border:1px solid var(--border);padding:10px 14px;text-align:left} +.md th{background:rgba(0,0,0,.03);font-weight:600} +.md hr{border:none;border-top:1px solid var(--border);margin:1.4em 0} +.md a{color:var(--blue)} +.md .wlink{color:var(--purple);border-bottom:1px dashed rgba(175,82,222,.4);cursor:pointer;font-weight:500} +.md .wlink:hover{border-bottom-style:solid} +.md .wlink.dead{color:var(--text2);border-bottom:none;cursor:default} + +/* Mermaid 圖表 */ +.mermaid-wrap{ + background:var(--surface);border:1px solid var(--border);border-radius:var(--radius); + padding:20px;margin:1.2em 0;overflow-x:auto;box-shadow:var(--shadow); +} +.mermaid-wrap .mermaid{display:flex;justify-content:center} +.mermaid-wrap svg{max-width:100%;height:auto} + +.note-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px} +.back-link{ + display:inline-flex;align-items:center;gap:6px;font-size:.84rem;color:var(--text2); + cursor:pointer;margin-bottom:16px;padding:6px 12px;border-radius:10px; + background:rgba(0,0,0,.04);transition:.15s; +} +.back-link:hover{color:var(--blue);background:rgba(0,113,227,.08)} +.note-frontmatter{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px} +.fm-tag{ + font-size:.72rem;color:var(--text2);background:var(--surface); + border:1px solid var(--border);border-radius:20px;padding:4px 12px;box-shadow:var(--shadow); +} + +/* 知識圖譜 */ +.graph-panel{ + background:var(--surface);border:1px solid var(--border);border-radius:var(--radius); + box-shadow:var(--shadow);overflow:hidden; +} +.graph-toolbar{ + display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding:14px 16px; + border-bottom:1px solid var(--border); +} +.graph-canvas{height:min(62vh,520px);background:linear-gradient(180deg,#fafafa 0%,#f5f5f7 100%)} +.graph-foot{font-size:.74rem;color:var(--text2);padding:10px 16px;border-top:1px solid var(--border)} +.graph-legend{display:flex;flex-wrap:wrap;gap:12px;font-size:.72rem} +.graph-legend span{display:inline-flex;align-items:center;gap:5px} +.graph-legend i{width:10px;height:10px;border-radius:50%;display:inline-block} + +.quiz-q{ + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:16px 18px;margin-bottom:12px;box-shadow:var(--shadow); +} +.quiz-q .q-text{font-size:.92rem;line-height:1.65} +.quiz-q .q-src{font-size:.74rem;color:var(--text2);margin-top:10px;cursor:pointer} + +/* ═══════════ 個股工具 ═══════════ */ +.finbox-search{display:flex;gap:10px;margin-bottom:8px;max-width:480px} +.finbox-search input{ + flex:1;background:var(--surface);border:1px solid var(--border);border-radius:12px; + color:var(--text);padding:14px 18px;font-size:1.05rem;outline:none; + box-shadow:var(--shadow);font-family:inherit;letter-spacing:.03em;text-transform:uppercase; +} +.finbox-search input:focus{border-color:var(--blue);box-shadow:0 0 0 4px rgba(0,113,227,.12)} .finbox-search button{ - background:var(--blue);color:#08111d;border:none;padding:0 22px;border-radius:8px;font-weight:700;font-size:.92rem;cursor:pointer; + background:var(--blue);color:#fff;border:none;padding:0 24px;border-radius:12px; + font-weight:600;font-size:.92rem;cursor:pointer;box-shadow:0 4px 14px rgba(0,113,227,.25); } .finbox-search button:disabled{opacity:.5;cursor:wait} -.finbox-examples{font-size:.76rem;color:var(--text2);margin-bottom:18px} -.finbox-examples b{cursor:pointer;color:var(--blue);font-weight:600;margin:0 4px} +.finbox-examples{font-size:.78rem;color:var(--text2);margin-bottom:20px} +.finbox-examples b{cursor:pointer;color:var(--blue);font-weight:600;margin:0 6px} -.fin-summary{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:20px 24px;margin-bottom:18px; - display:grid;grid-template-columns:auto 1fr;gap:24px;align-items:center} -.fin-verdict{text-align:center} -.fin-verdict .v-big{font-size:2.4rem;font-weight:800;line-height:1} +.sub-tabs{ + display:flex;gap:4px;background:rgba(0,0,0,.04);border-radius:12px; + padding:4px;margin:8px 0 20px;flex-wrap:wrap;width:fit-content; +} +.sub-tabs a{ + padding:10px 20px;border-radius:10px;font-size:.86rem;font-weight:600; + color:var(--text2);cursor:pointer;transition:.15s; +} +.sub-tabs a:hover{color:var(--text)} +.sub-tabs a.active{background:var(--surface);color:var(--blue);box-shadow:0 1px 4px rgba(0,0,0,.08)} +.stk-pane[hidden]{display:none} + +.chart-wrap{ + position:relative;width:100%;background:var(--surface); + border:1px solid var(--border);border-radius:var(--radius);padding:12px;box-shadow:var(--shadow); +} +.chart-wrap svg{display:block;width:100%;height:auto} +.chart-empty{padding:48px 0;text-align:center;color:var(--text2)} +.chart-legend{display:flex;gap:16px;font-size:.78rem;color:var(--text2);margin-bottom:8px} +.chart-legend i{display:inline-block;width:12px;height:12px;border-radius:4px;margin-right:6px} +.chart-hover{font-size:.8rem;color:var(--text2);margin-top:8px;min-height:1.2em} +.range-btns{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px} +.range-btns button{ + background:var(--surface);border:1px solid var(--border);color:var(--text2); + border-radius:10px;padding:8px 16px;font-size:.82rem;font-weight:600; + cursor:pointer;font-family:inherit;box-shadow:var(--shadow);transition:.15s; +} +.range-btns button:hover{border-color:var(--blue)} +.range-btns button.active{background:var(--blue);border-color:var(--blue);color:#fff} + +.fin-summary{ + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:22px 26px;margin-bottom:20px;display:grid;grid-template-columns:auto 1fr; + gap:24px;align-items:center;box-shadow:var(--shadow); +} +.fin-verdict .v-big{font-size:2.5rem;font-weight:800;line-height:1} .fin-verdict .v-sub{font-size:.78rem;color:var(--text2);margin-top:4px} -.fin-lights{display:flex;gap:18px} +.fin-lights{display:flex;gap:20px} .fin-light{text-align:center} -.fin-light .fl-num{font-size:1.6rem;font-weight:700;line-height:1} -.fin-light .fl-lab{font-size:.72rem;color:var(--text2);margin-top:3px} -.fin-co{font-size:.82rem;color:var(--text2);margin-bottom:8px} -.fin-co b{color:var(--text);font-size:1.05rem} -.fin-fresh{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap; - font-size:.74rem;color:var(--text2);margin-bottom:16px} +.fin-light .fl-num{font-size:1.55rem;font-weight:700} +.fin-light .fl-lab{font-size:.72rem;color:var(--text2);margin-top:4px} +.fin-co{font-size:.84rem;color:var(--text2);margin-bottom:10px} +.fin-co b{color:var(--text);font-size:1.08rem} +.fin-fresh{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;font-size:.76rem;color:var(--text2);margin-bottom:18px} -.fin-step{margin-bottom:18px} -.fin-step-head{display:flex;align-items:center;gap:10px;margin-bottom:8px} -.fin-step-num{width:24px;height:24px;border-radius:7px;background:rgba(77,166,255,.15);color:var(--blue); - font-size:.78rem;font-weight:700;display:flex;align-items:center;justify-content:center} -.fin-step-title{font-size:1rem;font-weight:700} +.fin-step{margin-bottom:20px} +.fin-step-head{display:flex;align-items:center;gap:10px;margin-bottom:10px} +.fin-step-num{ + width:28px;height:28px;border-radius:10px;background:rgba(0,113,227,.1); + color:var(--blue);font-size:.8rem;font-weight:700; + display:flex;align-items:center;justify-content:center; +} +.fin-step-title{font-size:1.02rem;font-weight:700} .check-row{ - background:var(--card);border:1px solid var(--border);border-radius:9px;padding:11px 14px;margin-bottom:8px; - display:grid;grid-template-columns:8px 1fr auto;gap:12px;align-items:center;border-left:3px solid var(--border); + background:var(--card);border:1px solid var(--border);border-radius:12px; + padding:14px 16px;margin-bottom:8px;display:grid;grid-template-columns:10px 1fr auto; + gap:14px;align-items:center;border-left:4px solid var(--border);box-shadow:var(--shadow); } .check-row.good{border-left-color:var(--green)} .check-row.warn{border-left-color:var(--yellow)} .check-row.bad{border-left-color:var(--red)} -.check-row.na{border-left-color:var(--text2);opacity:.7} -.check-dot{width:9px;height:9px;border-radius:50%} +.check-row.na{border-left-color:var(--text2);opacity:.75} +.check-dot{width:10px;height:10px;border-radius:50%} .check-row.good .check-dot{background:var(--green)} .check-row.warn .check-dot{background:var(--yellow)} .check-row.bad .check-dot{background:var(--red)} -.check-row.na .check-dot{background:var(--text2)} -.check-main .ck-label{font-size:.88rem;font-weight:600} -.check-main .ck-note{font-size:.78rem;color:var(--text2);line-height:1.55;margin-top:3px} -.check-main .ck-links{margin-top:5px;display:flex;flex-wrap:wrap;gap:6px} -.check-main .ck-links .wlink{font-size:.72rem} -.check-val{font-size:1.05rem;font-weight:700;text-align:right;white-space:nowrap} -.check-val.good{color:var(--green)}.check-val.warn{color:var(--yellow)}.check-val.bad{color:var(--red)}.check-val.na{color:var(--text2)} - -/* ═══════════ 交易復盤 ═══════════ */ -.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-bottom:22px} -.stat-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:16px 18px} -.stat-card .st-lab{font-size:.74rem;color:var(--text2);margin-bottom:6px} -.stat-card .st-val{font-size:1.7rem;font-weight:700;line-height:1} -.stat-card .st-sub{font-size:.72rem;color:var(--text2);margin-top:4px} - -.btn{background:var(--blue);color:#08111d;border:none;padding:8px 16px;border-radius:7px;font-weight:600;font-size:.85rem;cursor:pointer;transition:.15s} -.btn:hover{filter:brightness(1.08)} -.btn.ghost{background:var(--surface);border:1px solid var(--border);color:var(--text2)} -.btn.ghost:hover{border-color:var(--blue);color:var(--blue)} -.btn.danger{background:var(--surface);border:1px solid var(--border);color:var(--red)} -.btn.danger:hover{border-color:var(--red)} -.btn.sm{padding:4px 10px;font-size:.76rem} - -.journal-bar{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:14px;flex-wrap:wrap} -.seg{display:flex;gap:4px;background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:3px} -.seg a{padding:6px 14px;border-radius:6px;font-size:.82rem;color:var(--text2);cursor:pointer;transition:.15s} -.seg a.active{background:var(--card);color:var(--text)} - -.trade-table{width:100%;border-collapse:collapse;font-size:.82rem} -.trade-table th{text-align:left;padding:9px 10px;color:var(--text2);font-weight:600;font-size:.74rem; - border-bottom:1px solid var(--border);white-space:nowrap} -.trade-table td{padding:10px;border-bottom:1px solid var(--border);vertical-align:middle} -.trade-table tr:hover td{background:rgba(77,166,255,.04)} -.t-sym{font-weight:700;color:var(--text)} -.t-sym .t-name{font-weight:400;color:var(--text2);font-size:.76rem;margin-left:5px} -.pill{font-size:.68rem;font-weight:600;padding:2px 8px;border-radius:20px;white-space:nowrap} -.pill.long{background:rgba(0,212,170,.12);color:var(--green)} -.pill.short{background:rgba(255,77,106,.12);color:var(--red)} -.pill.invest{background:rgba(77,166,255,.12);color:var(--blue)} -.pill.trade{background:rgba(179,136,255,.12);color:var(--purple)} -.pill.open{background:rgba(255,193,77,.12);color:var(--yellow)} -.pill.mistake{background:rgba(255,77,106,.14);color:var(--red)} -.pnl-pos{color:var(--green);font-weight:700} -.pnl-neg{color:var(--red);font-weight:700} -.t-actions{display:flex;gap:6px;justify-content:flex-end} -.empty-state{text-align:center;color:var(--text2);padding:50px 20px;font-size:.9rem} - -.group-stat{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px 16px;margin-bottom:10px} -.group-stat h4{font-size:.86rem;margin-bottom:10px;color:var(--text)} -.gs-row{display:grid;grid-template-columns:1fr auto auto auto;gap:10px;font-size:.8rem;padding:5px 0;border-top:1px solid var(--border)} -.gs-row:first-of-type{border-top:none} -.gs-row .gs-name{color:var(--text)} -.gs-row .gs-cell{color:var(--text2);text-align:right;min-width:64px} - -/* Modal 表單(沿用 index.html 的 #modalOverlay 樣式,這裡補表單元素) */ -.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px 14px;margin-top:6px} -.form-grid .full{grid-column:1/-1} -.field label{display:block;font-size:.74rem;color:var(--text2);margin-bottom:4px} -.field input,.field select,.field textarea{ - width:100%;background:var(--surface);border:1px solid var(--border);border-radius:7px;color:var(--text); - padding:8px 11px;font-size:.86rem;outline:none;font-family:inherit; -} -.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--blue)} -.field textarea{resize:vertical;min-height:60px} -.form-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:18px} -.check-inline{display:flex;align-items:center;gap:8px;font-size:.84rem;color:var(--text)} -.check-inline input{width:auto} -@media(max-width:600px){ .form-grid{grid-template-columns:1fr} } - -/* ═══════════ 個股工具(子分頁 / 圖表 / 投資地圖 / 回測)═══════════ */ -.sub-tabs{display:flex;gap:4px;background:var(--surface);border:1px solid var(--border);border-radius:9px;padding:3px;margin:4px 0 18px;flex-wrap:wrap;width:fit-content} -.sub-tabs a{padding:7px 16px;border-radius:7px;font-size:.85rem;font-weight:600;color:var(--text2);cursor:pointer;transition:.15s} -.sub-tabs a:hover{color:var(--text)} -.sub-tabs a.active{background:var(--card);color:var(--blue)} -.stk-pane[hidden]{display:none} - -/* 共用折線圖 */ -.chart-wrap{position:relative;width:100%;background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:8px} -.chart-wrap svg{display:block;width:100%;height:auto} -.chart-empty{padding:40px 0;text-align:center;color:var(--text2);font-size:.85rem} -.chart-legend{display:flex;gap:16px;font-size:.78rem;color:var(--text2);margin-bottom:6px} -.chart-legend i{display:inline-block;width:11px;height:11px;border-radius:3px;margin-right:5px;vertical-align:middle} -.chart-hover{font-size:.78rem;color:var(--text2);margin-top:6px;min-height:1.2em} -.range-btns{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:12px} -.range-btns button{background:var(--surface);border:1px solid var(--border);color:var(--text2);border-radius:7px; - padding:5px 13px;font-size:.8rem;cursor:pointer;font-family:inherit;transition:.15s} -.range-btns button:hover{border-color:var(--blue);color:var(--text)} -.range-btns button.active{background:rgba(77,166,255,.16);border-color:var(--blue);color:var(--blue);font-weight:600} +.check-main .ck-label{font-size:.9rem;font-weight:600} +.check-main .ck-note{font-size:.8rem;color:var(--text2);line-height:1.55;margin-top:4px} +.check-main .ck-links{margin-top:6px;display:flex;flex-wrap:wrap;gap:6px} +.check-main .ck-links .wlink{font-size:.74rem;color:var(--purple);cursor:pointer} +.check-val{font-size:1.05rem;font-weight:700;text-align:right} +.check-val.good{color:var(--green)}.check-val.warn{color:var(--yellow)}.check-val.bad{color:var(--red)} /* 投資地圖 */ -.map-core{background:rgba(179,136,255,.08);border:1px solid rgba(179,136,255,.25);border-radius:10px; - padding:13px 16px;font-size:.85rem;font-weight:700;color:var(--purple);margin-bottom:14px;line-height:1.5} -.map-core span{display:block;font-weight:400;color:var(--text2);font-size:.8rem;margin-top:5px;line-height:1.6} -.map-verdict{background:var(--card);border:1px solid var(--border);border-radius:11px;padding:15px 18px;margin-bottom:16px; - border-left:4px solid var(--text2)} +.map-core{ + background:linear-gradient(135deg,rgba(175,82,222,.08),rgba(0,113,227,.06)); + border:1px solid rgba(175,82,222,.2);border-radius:var(--radius); + padding:16px 20px;font-weight:700;margin-bottom:16px;box-shadow:var(--shadow); +} +.map-core span{display:block;font-weight:400;color:var(--text2);font-size:.84rem;margin-top:6px;line-height:1.6} +.map-verdict{ + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:18px 22px;margin-bottom:18px;border-left:5px solid var(--text2);box-shadow:var(--shadow); +} .map-verdict.good{border-left-color:var(--green)} .map-verdict.warn{border-left-color:var(--yellow)} .map-verdict.bad{border-left-color:var(--red)} -.map-verdict .mv-lab{font-size:.74rem;color:var(--text2);margin-bottom:4px} -.map-verdict .mv-text{font-size:.96rem;font-weight:700;line-height:1.5} -.map-verdict .mv-actions{display:flex;gap:8px;margin-top:12px} -.map-layer{background:var(--card);border:1px solid var(--border);border-radius:11px;padding:15px 18px;margin-bottom:12px; - border-left:3px solid var(--border)} +.map-verdict .mv-lab{font-size:.76rem;color:var(--text2)} +.map-verdict .mv-text{font-size:1rem;font-weight:700;line-height:1.5;margin-top:4px} +.map-verdict .mv-actions{display:flex;gap:10px;margin-top:14px;flex-wrap:wrap} +.map-layer{ + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:18px 22px;margin-bottom:14px;border-left:4px solid var(--border);box-shadow:var(--shadow); +} .map-layer.pass{border-left-color:var(--green)} .map-layer.watch{border-left-color:var(--yellow)} .map-layer.out{border-left-color:var(--red)} -.ml-head{display:flex;align-items:center;gap:10px;margin-bottom:6px} -.ml-num{width:24px;height:24px;border-radius:7px;background:rgba(77,166,255,.15);color:var(--blue); - font-size:.78rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0} -.ml-title{font-size:1rem;font-weight:700;flex:1} -.ml-badge{font-size:.68rem;font-weight:700;padding:2px 10px;border-radius:20px} -.ml-badge.good{background:rgba(0,212,170,.14);color:var(--green)} -.ml-badge.warn{background:rgba(255,193,77,.14);color:var(--yellow)} -.ml-badge.bad{background:rgba(255,77,106,.14);color:var(--red)} -.ml-badge.na{background:var(--surface);color:var(--text2)} -.ml-ask{font-size:.82rem;color:var(--text);line-height:1.6} -.ml-pillar{font-size:.74rem;color:var(--text2);margin:3px 0 10px} -.map-q{border-top:1px solid var(--border);padding:10px 0} -.map-q:last-of-type{border-bottom:1px solid var(--border)} -.mq-text{font-size:.85rem;line-height:1.55;margin-bottom:7px} -.mq-text .gate{font-size:.64rem;font-weight:700;background:rgba(255,138,77,.16);color:var(--orange); - border-radius:4px;padding:1px 6px;margin-right:7px;vertical-align:middle} -.mq-ans{display:flex;gap:7px;flex-wrap:wrap} -.ans{font-size:.78rem;padding:4px 13px;border-radius:7px;border:1px solid var(--border);background:var(--surface); - color:var(--text2);cursor:pointer;transition:.15s;user-select:none} +.ml-head{display:flex;align-items:center;gap:12px;margin-bottom:8px} +.ml-num{ + width:32px;height:32px;border-radius:10px;background:rgba(0,113,227,.1); + color:var(--blue);font-weight:700;display:flex;align-items:center;justify-content:center; +} +.ml-title{font-size:1.05rem;font-weight:700;flex:1} +.ml-badge{font-size:.68rem;font-weight:700;padding:4px 12px;border-radius:20px} +.ml-badge.good{background:rgba(52,199,89,.12);color:var(--green)} +.ml-badge.warn{background:rgba(255,149,0,.12);color:var(--orange)} +.ml-badge.bad{background:rgba(255,59,48,.12);color:var(--red)} +.ml-badge.na{background:rgba(0,0,0,.05);color:var(--text2)} +.ml-ask,.ml-pillar{font-size:.82rem;line-height:1.6} +.ml-pillar{color:var(--text2);margin:4px 0 12px} +.map-q{border-top:1px solid var(--border);padding:12px 0} +.mq-text{font-size:.88rem;line-height:1.55;margin-bottom:8px} +.mq-text .gate{ + font-size:.64rem;font-weight:700;background:rgba(255,149,0,.15);color:var(--orange); + border-radius:6px;padding:2px 8px;margin-right:8px; +} +.mq-ans{display:flex;gap:8px;flex-wrap:wrap} +.ans{ + font-size:.8rem;padding:8px 16px;border-radius:10px;border:1.5px solid var(--border); + background:var(--surface);color:var(--text2);cursor:pointer;transition:.15s; +} .ans input{display:none} -.ans:hover{border-color:var(--blue)} -.ans.yes.on{background:rgba(0,212,170,.16);border-color:var(--green);color:var(--green)} -.ans.unsure.on{background:rgba(255,193,77,.16);border-color:var(--yellow);color:var(--yellow)} -.ans.no.on{background:rgba(255,77,106,.16);border-color:var(--red);color:var(--red)} -.ml-out{font-size:.72rem;color:var(--text2);margin-top:9px;font-style:italic} -.map-q .ck-links{margin-top:6px;display:flex;flex-wrap:wrap;gap:6px} -.map-q .ck-links .wlink{font-size:.72rem} +.ans.yes.on{background:rgba(52,199,89,.12);border-color:var(--green);color:var(--green);font-weight:600} +.ans.unsure.on{background:rgba(255,149,0,.1);border-color:var(--orange);color:var(--orange);font-weight:600} +.ans.no.on{background:rgba(255,59,48,.1);border-color:var(--red);color:var(--red);font-weight:600} +.ml-out{font-size:.74rem;color:var(--text2);margin-top:10px;font-style:italic} /* 回測 */ -.bt-controls{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;background:var(--card);border:1px solid var(--border); - border-radius:10px;padding:14px 16px;margin-bottom:16px} -.bt-params{display:flex;gap:12px;flex-wrap:wrap} -.bt-field{display:flex;flex-direction:column;gap:4px} -.bt-field label{font-size:.72rem;color:var(--text2)} -.bt-field select,.bt-field input{background:var(--surface);border:1px solid var(--border);border-radius:7px;color:var(--text); - padding:8px 11px;font-size:.85rem;outline:none;font-family:inherit;min-width:120px} -.bt-field input{width:100px;min-width:0} -.bt-field select:focus,.bt-field input:focus{border-color:var(--blue)} -.bt-controls .btn{align-self:flex-end} -.bt-stats{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:14px} -.bt-stat{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px 16px} -.bt-stat .bts-title{font-size:.84rem;font-weight:700;margin-bottom:10px} -.bts-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px 14px} -.bts-grid div{display:flex;flex-direction:column;gap:2px} +.bt-controls{ + display:flex;gap:14px;align-items:flex-end;flex-wrap:wrap; + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:18px 20px;margin-bottom:18px;box-shadow:var(--shadow); +} +.bt-field label{font-size:.72rem;color:var(--text2);font-weight:600;margin-bottom:6px;display:block} +.bt-params{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end} +.bt-stats{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:16px} +.bt-stat{ + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:16px 18px;box-shadow:var(--shadow); +} +.bt-stat .bts-title{font-size:.86rem;font-weight:700;margin-bottom:12px} +.bts-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px 16px} .bts-grid span{font-size:.7rem;color:var(--text2)} -.bts-grid b{font-size:1.02rem;font-weight:700} -.bt-note{font-size:.76rem;color:var(--text2);margin-top:12px;line-height:1.6} +.bts-grid b{font-size:1.02rem} +.bt-note{font-size:.78rem;color:var(--text2);margin-top:14px;line-height:1.6} @media(max-width:680px){ .bt-stats{grid-template-columns:1fr} } + +/* ═══════════ 交易復盤 ═══════════ */ +.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:14px;margin-bottom:24px} +.stat-card{ + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:18px 20px;box-shadow:var(--shadow); +} +.stat-card .st-lab{font-size:.76rem;color:var(--text2);margin-bottom:8px} +.stat-card .st-val{font-size:1.75rem;font-weight:700;line-height:1} +.stat-card .st-sub{font-size:.74rem;color:var(--text2);margin-top:6px} + +.btn{ + background:var(--blue);color:#fff;border:none;padding:10px 20px;border-radius:12px; + font-weight:600;font-size:.88rem;cursor:pointer;transition:.15s; + box-shadow:0 4px 14px rgba(0,113,227,.2);font-family:inherit; +} +.btn:hover{filter:brightness(1.05);transform:translateY(-1px)} +.btn.ghost{background:var(--surface);border:1px solid var(--border);color:var(--text2);box-shadow:var(--shadow)} +.btn.ghost:hover{border-color:var(--blue);color:var(--blue)} +.btn.danger{background:var(--surface);border:1px solid var(--border);color:var(--red);box-shadow:var(--shadow)} +.btn.danger:hover{border-color:var(--red)} +.btn.sm{padding:6px 14px;font-size:.8rem;border-radius:10px} + +.journal-bar{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-bottom:18px;flex-wrap:wrap} +.seg{display:flex;gap:3px;background:rgba(0,0,0,.04);border-radius:12px;padding:4px} +.seg a{ + padding:8px 16px;border-radius:10px;font-size:.84rem;font-weight:600; + color:var(--text2);cursor:pointer;transition:.15s; +} +.seg a.active{background:var(--surface);color:var(--text);box-shadow:0 1px 4px rgba(0,0,0,.08)} + +.trade-table{width:100%;border-collapse:separate;border-spacing:0;font-size:.84rem} +.trade-table th{ + text-align:left;padding:12px 14px;color:var(--text2);font-weight:600;font-size:.74rem; + border-bottom:1px solid var(--border); +} +.trade-table td{padding:12px 14px;border-bottom:1px solid var(--border);vertical-align:middle} +.trade-table tr:hover td{background:rgba(0,113,227,.03)} +.t-sym{font-weight:700} +.t-sym .t-name{font-weight:400;color:var(--text2);font-size:.76rem;margin-left:6px} +.pill{font-size:.68rem;font-weight:600;padding:3px 10px;border-radius:20px} +.pill.long{background:rgba(52,199,89,.12);color:var(--green)} +.pill.short{background:rgba(255,59,48,.12);color:var(--red)} +.pill.invest{background:rgba(0,113,227,.1);color:var(--blue)} +.pill.trade{background:rgba(175,82,222,.1);color:var(--purple)} +.pill.open{background:rgba(255,149,0,.12);color:var(--orange)} +.pill.mistake{background:rgba(255,59,48,.12);color:var(--red)} +.pnl-pos{color:var(--green);font-weight:700} +.pnl-neg{color:var(--red);font-weight:700} +.t-actions{display:flex;gap:8px;justify-content:flex-end} +.empty-state{text-align:center;color:var(--text2);padding:56px 24px;font-size:.92rem} + +.group-stat{ + background:var(--card);border:1px solid var(--border);border-radius:var(--radius); + padding:16px 18px;margin-bottom:12px;box-shadow:var(--shadow); +} +.group-stat h4{font-size:.88rem;margin-bottom:12px} +.gs-row{display:grid;grid-template-columns:1fr auto auto auto;gap:12px;font-size:.82rem;padding:6px 0;border-top:1px solid var(--border)} +.gs-row:first-of-type{border-top:none} +.gs-row .gs-cell{text-align:right;min-width:64px;color:var(--text2)} + +/* Modal */ +#tradeModal .modal-panel{background:var(--surface);border-radius:18px;box-shadow:0 24px 80px rgba(0,0,0,.18)} +.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px 16px;margin-top:8px} +.form-grid .full{grid-column:1/-1} +.field label{display:block;font-size:.74rem;color:var(--text2);font-weight:600;margin-bottom:6px} +.field input,.field textarea{ + width:100%;background:var(--bg);border:1px solid var(--border);border-radius:12px; + color:var(--text);padding:10px 14px;font-size:.88rem;outline:none;font-family:inherit; +} +.field input:focus,.field textarea:focus{border-color:var(--blue);box-shadow:0 0 0 4px rgba(0,113,227,.12)} +.field textarea{resize:vertical;min-height:72px} +.field select{display:none} +.principle-chips{ + display:flex;flex-wrap:wrap;gap:8px;max-height:160px;overflow-y:auto; + padding:12px;background:var(--bg);border-radius:12px;border:1px solid var(--border); +} +.form-actions{display:flex;justify-content:flex-end;gap:12px;margin-top:20px} +.check-inline{display:flex;align-items:center;gap:10px;font-size:.88rem;cursor:pointer} +.check-inline input{width:18px;height:18px;accent-color:var(--blue)} +@media(max-width:600px){ .form-grid{grid-template-columns:1fr} } diff --git a/app.js b/app.js index b14d376..a230ce6 100644 --- a/app.js +++ b/app.js @@ -33,6 +33,52 @@ function fmtMoney(v) { return s + '$' + a.toFixed(2); } +// ═══════════════════════════════════════════════════════════ +// UI 元件:色塊分段(取代傳統下拉) +// ═══════════════════════════════════════════════════════════ +function mountChips(container, items, value, onChange, opts = {}) { + const cls = opts.sm ? 'chip sm' : 'chip'; + container.innerHTML = items.map(it => { + const tint = it.tint ? ` tint-${it.tint}` : ''; + const on = it.id === value ? ' on' : ''; + return ``; + }).join(''); + $$('button', container).forEach(btn => btn.addEventListener('click', () => { + const v = btn.dataset.v; + onChange(v); + $$('button', container).forEach(b => b.classList.toggle('on', b.dataset.v === v)); + })); +} +function mountTiles(container, items, value, onChange) { + container.innerHTML = items.map(it => { + const on = it.id === value ? ' on' : ''; + const tint = it.tint ? ` tint-${it.tint}` : ''; + return `
' + escapeHtml(code) + ''; i++; continue; }
+ if (fm) {
+ const idx = +fm[1];
+ const raw = fences[idx];
+ const lang = fenceLangs[idx];
+ const code = raw.replace(/^```[^\n]*\n?/, '').replace(/```\s*$/, '');
+ if (lang === 'mermaid') html += `${escapeHtml(code)}' + escapeHtml(code) + '';
+ i++; continue;
+ }
const h = line.match(/^(#{1,6})\s+(.*)$/);
if (h) { const l = h[1].length; html += `