fix: UI改善・バッジ/図解/試験ポイント追加、Alpine SRI復元

This commit is contained in:
posimai 2026-04-18 23:19:35 +09:00
parent d67e537191
commit f25dc37ff7
2 changed files with 147 additions and 12 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.vercel

View File

@ -228,6 +228,75 @@ header{display:flex;align-items:center;justify-content:space-between;padding:0 1
::-webkit-scrollbar{width:4px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}
/* Badges */
.badge-row{display:flex;align-items:center;gap:6px;margin-bottom:8px;flex-wrap:wrap}
.badge{display:inline-flex;align-items:center;gap:3px;font-size:10px;font-weight:600;padding:3px 8px;border-radius:20px;letter-spacing:.04em}
.badge-high{background:rgba(248,113,113,.12);border:1px solid rgba(248,113,113,.3);color:var(--err)}
.badge-mid{background:rgba(251,146,60,.10);border:1px solid rgba(251,146,60,.28);color:var(--warn)}
.badge-base{background:rgba(34,211,238,.08);border:1px solid rgba(34,211,238,.2);color:var(--accent)}
.badge-diff{background:var(--surface2);border:1px solid var(--border);color:var(--text3)}
.score-chip{font-family:'JetBrains Mono',monospace;font-size:9px;font-weight:600;padding:1px 5px;border-radius:4px;background:rgba(74,222,128,.12);border:1px solid rgba(74,222,128,.25);color:var(--ok);margin-left:auto;flex-shrink:0}
.score-chip.partial{background:rgba(251,146,60,.10);border-color:rgba(251,146,60,.28);color:var(--warn)}
.score-chip.zero{background:var(--surface2);border-color:var(--border);color:var(--text3)}
/* Exam tips card */
.exam-tips-text{font-size:13px;line-height:1.8;color:var(--text2)}
.exam-tips-text strong{color:var(--text);font-weight:600}
.exam-tips-text .hl{color:var(--accent);font-weight:500}
.tips-point{display:flex;gap:8px;margin-bottom:8px;font-size:12px;color:var(--text2);line-height:1.65}
.tips-point:last-child{margin-bottom:0}
.tips-icon{flex-shrink:0;width:16px;height:16px;border-radius:50%;background:rgba(248,113,113,.15);border:1px solid rgba(248,113,113,.3);display:flex;align-items:center;justify-content:center;margin-top:2px;font-size:9px;color:var(--err);font-weight:700}
/* Visual diagrams */
.viz-taccount{background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin:14px 0}
.tac-header{text-align:center;padding:7px;font-size:10px;font-weight:600;letter-spacing:.07em;color:var(--text3);text-transform:uppercase;border-bottom:1px solid var(--border)}
.tac-body{display:grid;grid-template-columns:1fr 2px 1fr;min-height:90px}
.tac-side{padding:12px 14px}
.tac-side-label{font-size:11px;font-weight:600;letter-spacing:.04em;margin-bottom:8px}
.tac-dr .tac-side-label{color:var(--accent)}
.tac-cr .tac-side-label{color:var(--warn)}
.tac-side-desc{font-size:11px;color:var(--text2);line-height:1.85}
.tac-divider{background:var(--border)}
.viz-groups{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;margin:14px 0}
@media(max-width:580px){.viz-groups{grid-template-columns:repeat(3,1fr)}}
.vg-card{border-radius:var(--radius-sm);padding:10px 8px;text-align:center;border:1px solid}
.vg-name{font-size:12px;font-weight:600;margin-bottom:5px}
.vg-rule{font-size:10px;line-height:1.65;color:var(--text2)}
.vg-asset{background:rgba(34,211,238,.08);border-color:rgba(34,211,238,.22)}.vg-asset .vg-name{color:var(--accent)}
.vg-liability{background:rgba(251,146,60,.07);border-color:rgba(251,146,60,.22)}.vg-liability .vg-name{color:var(--warn)}
.vg-equity{background:rgba(167,139,250,.07);border-color:rgba(167,139,250,.22)}.vg-equity .vg-name{color:#A78BFA}
.vg-revenue{background:rgba(74,222,128,.07);border-color:rgba(74,222,128,.22)}.vg-revenue .vg-name{color:var(--ok)}
.vg-expense{background:rgba(248,113,113,.07);border-color:rgba(248,113,113,.22)}.vg-expense .vg-name{color:var(--err)}
.viz-flow{display:flex;align-items:center;gap:6px;margin:14px 0;flex-wrap:wrap;justify-content:center}
.vf-node{background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 14px;text-align:center;font-size:12px;font-weight:600;color:var(--text);min-width:68px}
.vf-sub{font-size:10px;color:var(--text3);font-weight:400;margin-top:3px}
.vf-hl{border-color:var(--accent-border) !important;background:var(--accent-dim) !important;color:var(--accent) !important}
.vf-hl .vf-sub{color:rgba(34,211,238,.65)}
.vf-arrow{color:var(--text3);font-size:15px;flex-shrink:0}
.viz-cost3{display:flex;align-items:center;gap:10px;margin:14px 0;background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);padding:14px;flex-wrap:wrap;justify-content:center}
.vc3-inputs{display:flex;flex-direction:column;gap:5px}
.vc3-item{font-size:11px;padding:5px 10px;border-radius:4px;font-weight:500;border:1px solid;white-space:nowrap}
.vc3-mat{background:rgba(34,211,238,.08);border-color:rgba(34,211,238,.2);color:var(--accent)}
.vc3-lab{background:rgba(74,222,128,.08);border-color:rgba(74,222,128,.2);color:var(--ok)}
.vc3-ovh{background:rgba(167,139,250,.08);border-color:rgba(167,139,250,.2);color:#A78BFA}
.vc3-note{font-size:9px;opacity:.7;margin-left:2px}
.vc3-arr{font-size:18px;color:var(--text3);flex-shrink:0}
.vc3-box{padding:12px 16px;border-radius:var(--radius-sm);text-align:center;font-size:13px;font-weight:600;min-width:68px}
.vc3-sublbl{font-size:10px;font-weight:400;margin-top:3px;opacity:.7}
.vc3-wip{border:1px solid var(--accent-border);background:var(--accent-dim);color:var(--accent)}
.vc3-fin{border:1px solid var(--border);background:var(--surface);color:var(--text)}
.viz-org{display:flex;flex-direction:column;align-items:center;margin:14px 0;gap:0}
.vo-row{display:flex;gap:20px;justify-content:center;align-items:flex-start}
.vo-branch{display:flex;flex-direction:column;align-items:center}
.vo-node{border-radius:var(--radius-sm);padding:10px 18px;text-align:center;min-width:140px;font-size:12px;font-weight:600;border:1px solid var(--border);background:var(--surface2);color:var(--text)}
.vo-parent{border-color:var(--accent-border);background:var(--accent-dim);color:var(--accent)}
.vo-child1{border-color:rgba(74,222,128,.3);background:rgba(74,222,128,.06);color:var(--ok)}
.vo-child2{border-color:rgba(167,139,250,.3);background:rgba(167,139,250,.06);color:#A78BFA}
.vo-sub{font-size:10px;font-weight:400;margin-top:3px;opacity:.75}
.vo-vline{width:2px;height:16px;background:var(--border)}
.vo-hline{display:flex;align-items:center;gap:0}
.vo-hseg{height:2px;width:60px;background:var(--border)}
.vo-pct{font-size:10px;color:var(--text3);background:var(--surface2);border:1px solid var(--border);border-radius:20px;padding:2px 7px;white-space:nowrap;margin-bottom:2px}
.vo-connector{display:flex;flex-direction:column;align-items:center}
</style>
</head>
<body>
@ -286,7 +355,8 @@ header{display:flex;align-items:center;justify-content:space-between;padding:0 1
@click="openUnit(u); sidebarOpen=false">
<span class="item-num" x-text="u.num"></span>
<span class="item-title" x-text="u.title"></span>
<i data-lucide="check" class="item-check" style="width:11px;height:11px"></i>
<span class="score-chip" x-show="bestScore(u.id)" :class="scoreChipCls(u.id)" x-text="bestScore(u.id)"></span>
<i data-lucide="check" class="item-check" style="width:11px;height:11px" x-show="!bestScore(u.id)"></i>
</div>
</template>
</div>
@ -338,7 +408,11 @@ header{display:flex;align-items:center;justify-content:space-between;padding:0 1
一覧
</button>
<div class="unit-meta" x-show="currentUnit">
<div class="badge-row">
<div class="unit-cat-badge" x-text="currentUnit?.catLabel"></div>
<div class="badge" :class="freqBadgeCls" x-text="freqLabel"></div>
<div class="badge badge-diff" x-text="diffLabel"></div>
</div>
<div class="unit-title" x-text="currentUnit?.title"></div>
</div>
</div>
@ -352,6 +426,19 @@ header{display:flex;align-items:center;justify-content:space-between;padding:0 1
<div class="concept-text" x-html="currentUnit?.concept"></div>
</div>
<!-- Exam tips -->
<div class="card" x-show="currentUnit?.examtips?.length" style="border-color:rgba(248,113,113,.18);background:rgba(248,113,113,.03)">
<div class="card-title" style="color:var(--err)">
<i data-lucide="triangle-alert" style="width:13px;height:13px;color:var(--err)"></i>
試験対策メモ
</div>
<template x-for="tip in (currentUnit?.examtips||[])" :key="tip">
<div class="tips-point">
<div class="tips-icon">!</div>
<span x-html="tip"></span>
</div>
</template>
</div>
<!-- Keypoints -->
<div class="card" x-show="currentUnit?.keypoints?.length">
<div class="card-title">
@ -443,22 +530,28 @@ header{display:flex;align-items:center;justify-content:space-between;padding:0 1
<script>
const CATEGORIES = [
{ id:'commercial', label:'商業簿記', icon:'landmark', units:[
{ id:'c01', num:'C01', title:'仕訳の基礎復習',
concept:`<p><strong>仕訳</strong>とは取引を借方(左)と貸方(右)に分けて記録する作業です。<span class="hl">借方合計 = 貸方合計</span> が常に成立します。</p><p>勘定科目は5グループです。</p><div class="formula-box"><div class="formula-label">5グループと増減の方向</div>資産(増加→借方 / 減少→貸方)<br>負債(増加→貸方 / 減少→借方)<br>純資産(増加→貸方 / 減少→借方)<br>収益(発生→貸方)<br>費用(発生→借方)</div><p>商品¥100,000を掛けで仕入れた</p><div class="journal-wrap"><table class="journal-table"><tr><th>借方</th><th>金額</th><th>貸方</th><th>金額</th></tr><tr><td class="dr">仕入</td><td class="amount">100,000</td><td class="cr">買掛金</td><td class="amount">100,000</td></tr></table></div>`,
{ id:'c01', num:'C01', title:'仕訳の基礎復習', freq:'high', diff:1,
concept:`<p><strong>仕訳</strong>とは取引を借方(左)と貸方(右)に分けて記録する作業です。<span class="hl">借方合計 = 貸方合計</span> が常に成立します。</p><div class="viz-taccount"><div class="tac-header">T 勘 定</div><div class="tac-body"><div class="tac-side tac-dr"><div class="tac-side-label">借方(左側)</div><div class="tac-side-desc">資産の増加<br>負債の減少<br>純資産の減少<br>費用の発生</div></div><div class="tac-divider"></div><div class="tac-side tac-cr"><div class="tac-side-label">貸方(右側)</div><div class="tac-side-desc">資産の減少<br>負債の増加<br>純資産の増加<br>収益の発生</div></div></div></div><p>勘定科目は5グループに分類されます。</p><div class="viz-groups"><div class="vg-card vg-asset"><div class="vg-name">資産</div><div class="vg-rule">増加→借方<br>減少→貸方</div></div><div class="vg-card vg-liability"><div class="vg-name">負債</div><div class="vg-rule">増加→貸方<br>減少→借方</div></div><div class="vg-card vg-equity"><div class="vg-name">純資産</div><div class="vg-rule">増加→貸方<br>減少→借方</div></div><div class="vg-card vg-revenue"><div class="vg-name">収益</div><div class="vg-rule">発生→貸方<br>消滅→借方</div></div><div class="vg-card vg-expense"><div class="vg-name">費用</div><div class="vg-rule">発生→借方<br>消滅→貸方</div></div></div><p>商品¥100,000を掛けで仕入れた</p><div class="journal-wrap"><table class="journal-table"><tr><th>借方</th><th>金額</th><th>貸方</th><th>金額</th></tr><tr><td class="dr">仕入</td><td class="amount">100,000</td><td class="cr">買掛金</td><td class="amount">100,000</td></tr></table></div>`,
examtips:['第1問の仕訳問題は5問×4点<strong>20点</strong>。確実に取りに行く単元。','勘定科目名は<strong>正式名称</strong>で書くこと(例:「売掛」ではなく「売掛金」)。略称は不正解。','複合仕訳(借方または貸方が複数行)も頻出。合計金額が一致するか必ず確認。'],
keypoints:['資産の増加 → 借方、減少 → 貸方','負債・純資産の増加 → 貸方、減少 → 借方','費用の発生 → 借方、収益の発生 → 貸方','<strong>貸借平均の原理</strong>:借方合計と貸方合計は必ず一致する'],
quiz:[
{q:'現金¥50,000を受け取り売上として計上した。正しい仕訳はどれか。',choices:['(借)現金 50,000 /(貸)売上 50,000','(借)売上 50,000 /(貸)現金 50,000','(借)現金 50,000 /(貸)買掛金 50,000','(借)売掛金 50,000 /(貸)売上 50,000'],answer:0,exp:'現金(資産)の増加は借方。売上(収益)の発生は貸方。'},
{q:'負債が増加するとき、仕訳上どちらに記載するか。',choices:['借方(左側)','貸方(右側)','どちらでもよい','仕訳不要'],answer:1,exp:'負債の増加は貸方(右側)に記載します。減少は借方です。'},
{q:'費用の発生は仕訳のどちらに記載するか。',choices:['貸方','借方','どちらでもない','発生しない'],answer:1,exp:'費用の発生は借方(左側)に記載します。'}
{q:'費用の発生は仕訳のどちらに記載するか。',choices:['貸方','借方','どちらでもない','発生しない'],answer:1,exp:'費用の発生は借方(左側)に記載します。'},
{q:'建物¥5,000,000を購入し、代金のうち¥2,000,000は現金で支払い、残額は来月払いとした。この取引の仕訳として正しいものはどれか。',choices:['建物5,000,000 現金2,000,000・未払金3,000,000','建物2,000,000 現金2,000,000','現金5,000,000 建物5,000,000','建物5,000,000 買掛金5,000,000'],answer:0,exp:'複合仕訳。建物(資産)全額借方、現金(資産)減少と未払金(負債)増加を貸方に。買掛金は商品の掛け仕入に使う勘定で、固定資産は未払金を使う。'},
{q:'当期に未収収益¥30,000前期に計上した利息の未収分を現金で受け取った。仕訳として正しいものはどれか。',choices:['現金30,000 受取利息30,000','現金30,000 未収収益30,000','未収収益30,000 現金30,000','受取利息30,000 現金30,000'],answer:1,exp:'前期に未収収益(資産)として計上済みの利息を受け取ったので、未収収益(資産)を減らし現金(資産)を増やす。受取利息を使うと二重計上になる。'}
]
},
{ id:'c02', num:'C02', title:'商品売買と売上原価',
{ id:'c02', num:'C02', title:'商品売買と売上原価', freq:'high', diff:1,
concept:`<p>2級では<strong>三分法</strong>が基本です。仕入・売上・繰越商品の3勘定を使います。</p><div class="formula-box"><div class="formula-label">売上原価の算定(決算整理仕訳)</div>①(借)仕入 /(貸)繰越商品 ← 期首商品を仕入に振替<br>②(借)繰越商品 /(貸)仕入 ← 期末商品を控除<br><br>売上原価 期首商品 当期仕入 期末商品</div><p>期首¥30,000・仕入¥200,000・期末¥40,000 → 売上原価 <span class="hl">¥190,000</span></p>`,
examtips:['精算表第3問で必出。決算整理仕訳の<strong>2本セット</strong>(期首振替・期末控除)を忘れずに。','「売上原価 期首 仕入 期末」の公式は反射的に出るまで暗記。','仕入値引・仕入返品は仕入勘定を減額。売上値引・売上返品は売上勘定を減額することを覚えておく。'],
keypoints:['三分法:仕入(費用)・売上(収益)・繰越商品(資産)','売上原価 期首 仕入 期末','決算整理で「仕入」勘定を売上原価に確定させる','売上総利益 売上高 売上原価'],
quiz:[
{q:'期首商品¥20,000、当期仕入¥150,000、期末商品¥25,000のとき売上原価はいくらか。',choices:['¥145,000','¥155,000','¥170,000','¥125,000'],answer:0,exp:'売上原価 20,000 150,000 25,000 145,000円'},
{q:'決算整理で期末商品¥40,000を計上する仕訳はどれか。',choices:['(借)仕入 40,000 /(貸)繰越商品 40,000','(借)繰越商品 40,000 /(貸)仕入 40,000','(借)売上 40,000 /(貸)繰越商品 40,000','(借)繰越商品 40,000 /(貸)売上 40,000'],answer:1,exp:'期末商品は(借)繰越商品 /(貸)仕入 で仕入勘定から控除します。'},
{q:'売上高¥300,000、売上原価¥190,000のとき売上総利益はいくらか。',choices:['¥490,000','¥110,000','¥190,000','¥300,000'],answer:1,exp:'売上総利益 300,000 190,000 110,000円'}
{q:'売上高¥300,000、売上原価¥190,000のとき売上総利益はいくらか。',choices:['¥490,000','¥110,000','¥190,000','¥300,000'],answer:1,exp:'売上総利益 300,000 190,000 110,000円'},
{q:'当期中に仕入¥500,000のうち¥20,000分を品質不良で返品した。仕入勘定の純額はいくらか。',choices:['¥520,000','¥480,000','¥500,000','¥20,000'],answer:1,exp:'仕入返品は仕入勘定を減額。純仕入額 500,000 20,000 480,000円'},
{q:'売上高¥800,000、期首商品¥50,000、当期仕入¥600,000、期末商品¥80,000のとき売上総利益はいくらか。',choices:['¥230,000','¥170,000','¥250,000','¥800,000'],answer:0,exp:'売上原価 50,000 600,000 80,000 570,000。売上総利益 800,000 570,000 230,000円'}
]
},
{ id:'c03', num:'C03', title:'固定資産と減価償却',
@ -552,7 +645,7 @@ const CATEGORIES = [
]
},
{ id:'c13', num:'C13', title:'連結会計の基礎',
concept:`<p><strong>連結財務諸表</strong>は親会社と子会社を一体とみなして作成します。</p><div class="formula-box"><div class="formula-label">支配獲得時の連結修正仕訳</div>(借)子会社純資産 × 持分率<br>(借)のれん(差額)<br>(貸)子会社株式(投資)<br><br>のれん 投資額 子会社純資産の持分相当額</div><p>のれんは20年以内で規則的に償却。<br>毎期:①配当金消去 ②内部取引消去 ③未実現利益消去</p>`,
concept:`<p><strong>連結財務諸表</strong>は親会社と子会社を一体とみなして作成します。議決権の<span class="hl">50%超</span>を保有する会社が子会社です。</p><div class="viz-org"><div class="vo-node vo-parent">親会社<div class="vo-sub">連結財務諸表を作成</div></div><div class="vo-connector"><div class="vo-vline"></div><div class="vo-pct">議決権 51〜100% 保有</div><div class="vo-vline"></div></div><div class="vo-row"><div class="vo-branch"><div class="vo-node vo-child1">子会社100%<div class="vo-sub">完全子会社</div></div></div><div class="vo-branch" style="margin-top:32px"><div class="vo-node vo-child2">子会社60%<div class="vo-sub">非支配株主持分 40%</div></div></div></div></div><div class="formula-box"><div class="formula-label">支配獲得時の連結修正仕訳</div>(借)子会社純資産 × 持分率<br>(借)のれん(差額)<br>(貸)子会社株式(投資)<br><br>のれん 投資額 子会社純資産の持分相当額</div><p>のれんは20年以内で規則的に償却。毎期①配当金消去 ②内部取引消去 ③未実現利益消去</p>`,
keypoints:['連結の範囲議決権の過半数50%超)を持つ子会社','のれん:超過収益力(投資超過額)、規則的に償却','非支配株主持分:子会社純資産のうち親が持たない部分','内部取引・未実現利益は連結上消去する'],
quiz:[
{q:'子会社株式¥800,000取得子会社純資産¥700,000・持分100%)ののれんはいくらか。',choices:['¥700,000','¥100,000','¥800,000','のれんは発生しない'],answer:1,exp:'のれん 800,000 700,000 100,000円'},
@ -581,7 +674,7 @@ const CATEGORIES = [
]},
{ id:'industrial', label:'工業簿記', icon:'factory', units:[
{ id:'i01', num:'I01', title:'工業簿記の基礎と勘定体系',
concept:`<p><strong>工業簿記</strong>は製造業の原価計算を記録する簿記です。製造過程を「材料→仕掛品→製品」の流れで管理します。</p><div class="formula-box"><div class="formula-label">製造原価の3要素</div>直接材料費(原材料など)<br>直接労務費(直接作業者の賃金)<br>製造間接費(工場家賃・間接材料・間接労務費など)</div><div class="formula-box"><div class="formula-label">主要な工業簿記勘定の流れ</div>材料 → 仕掛品 → 製品 → 売上原価<br>賃金・給料 → 仕掛品直接費or 製造間接費(間接費)<br>製造間接費 → 仕掛品(配賦)</div>`,
concept:`<p><strong>工業簿記</strong>は製造業の原価計算を記録する簿記です。<span class="hl">材料 → 仕掛品 → 製品</span> の流れで原価を管理します。</p><div class="viz-flow"><div class="vf-node"><div>材料</div><div class="vf-sub">材料費</div></div><div class="vf-arrow"></div><div class="vf-node vf-hl"><div>仕掛品</div><div class="vf-sub">製造途中</div></div><div class="vf-arrow"></div><div class="vf-node"><div>製品</div><div class="vf-sub">完成品</div></div><div class="vf-arrow"></div><div class="vf-node"><div>売上原価</div><div class="vf-sub">販売時</div></div></div><p>仕掛品には製造原価の3要素が集計されます。</p><div class="viz-cost3"><div class="vc3-inputs"><div class="vc3-item vc3-mat">直接材料費</div><div class="vc3-item vc3-lab">直接労務費</div><div class="vc3-item vc3-ovh">製造間接費<span class="vc3-note">(配賦)</span></div></div><div class="vc3-arr"></div><div class="vc3-box vc3-wip">仕掛品<div class="vc3-sublbl">製造途中</div></div><div class="vc3-arr"></div><div class="vc3-box vc3-fin">製品<div class="vc3-sublbl">完成品</div></div></div>`,
keypoints:['直接費:特定製品に直接跡付けできる原価','間接費:複数製品に共通して発生→配賦が必要','仕掛品:製造途中の未完成品(期末に残る)','製造原価報告書→損益計算書の売上原価へ連動'],
quiz:[
{q:'工場の電力料は製造原価のどの区分に含まれるか。',choices:['直接材料費','直接労務費','製造間接費','販売費及び一般管理費'],answer:2,exp:'電力料は複数製品に共通して発生するため製造間接費に分類されます。'},
@ -644,7 +737,7 @@ const CATEGORIES = [
]
},
{ id:'i08', num:'I08', title:'直接原価計算とCVP分析',
concept:`<p><strong>直接原価計算</strong>は変動費のみを製品原価とし、固定費は期間費用として処理します。</p><div class="formula-box"><div class="formula-label">直接原価計算P/L</div>売上高<br> 変動費(変動製造原価 変動販売費)<br> 貢献利益<br> 固定費(固定製造間接費 固定販売費 一般管理費)<br> 営業利益</div><div class="formula-box"><div class="formula-label">CVP分析損益分岐点</div>貢献利益率 貢献利益 ÷ 売上高<br>損益分岐点売上高 固定費 ÷ 貢献利益率<br>目標利益達成売上高 =(固定費 目標利益)÷ 貢献利益率</div>`,
concept:`<p><strong>直接原価計算</strong>は変動費のみを製品原価とし、固定費は期間費用として処理します。</p><div class="formula-box"><div class="formula-label">直接原価計算P/L</div>売上高<br> 変動費(変動製造原価 変動販売費)<br> 貢献利益<br> 固定費(固定製造間接費 固定販売費 一般管理費)<br> 営業利益</div><div class="formula-box"><div class="formula-label">CVP分析損益分岐点</div>貢献利益率 貢献利益 ÷ 売上高<br>損益分岐点売上高 固定費 ÷ 貢献利益率<br>目標利益達成売上高 =(固定費 目標利益)÷ 貢献利益率</div><p>損益分岐点グラフ:売上高線と総原価線の交点が損益分岐点です。</p><svg viewBox="0 0 300 190" style="width:100%;max-width:380px;display:block;margin:12px auto;font-family:JetBrains Mono,monospace" aria-label="CVP分析グラフ"><rect width="300" height="190" fill="none"/><line x1="44" y1="10" x2="44" y2="155" stroke="rgba(255,255,255,0.15)" stroke-width="1.5"/><line x1="44" y1="155" x2="285" y2="155" stroke="rgba(255,255,255,0.15)" stroke-width="1.5"/><text x="38" y="158" text-anchor="end" font-size="9" fill="#64748B">0</text><text x="155" y="170" text-anchor="middle" font-size="9" fill="#64748B">販売量</text><text x="22" y="85" text-anchor="middle" font-size="9" fill="#64748B" transform="rotate(-90,22,85)">金額</text><line x1="44" y1="105" x2="275" y2="105" stroke="rgba(251,146,60,0.6)" stroke-width="1.5" stroke-dasharray="5,3"/><text x="278" y="108" font-size="9" fill="#FB923C">固定費</text><line x1="44" y1="155" x2="255" y2="25" stroke="#22D3EE" stroke-width="2"/><text x="258" y="22" font-size="9" fill="#22D3EE">売上高</text><line x1="44" y1="105" x2="255" y2="55" stroke="rgba(167,139,250,0.85)" stroke-width="2"/><text x="258" y="58" font-size="9" fill="#A78BFA">総原価</text><line x1="44" y1="105" x2="44" y2="155" stroke="rgba(251,146,60,0.4)" stroke-width="1.5" stroke-dasharray="3,3"/><circle cx="152" cy="90" r="5" fill="none" stroke="#4ADE80" stroke-width="2"/><line x1="152" y1="90" x2="152" y2="155" stroke="rgba(74,222,128,0.4)" stroke-width="1" stroke-dasharray="3,3"/><text x="152" y="180" text-anchor="middle" font-size="9" fill="#4ADE80">損益分岐点</text><text x="200" y="70" font-size="9" fill="rgba(74,222,128,0.8)">利益ゾーン</text><text x="75" y="135" font-size="9" fill="rgba(248,113,113,0.8)">損失ゾーン</text></svg>`,
keypoints:['直接原価計算:固定製造間接費は期間費用として全額計上','損益分岐点:利益ゼロの売上高(固定費をちょうど回収できる点)','安全余裕率 =(実際売上 損益分岐点売上)÷ 実際売上 × 100','全部原価計算との利益差額 固定費の期首・期末仕掛品への含み'],
quiz:[
{q:'売上高¥1,000,000・変動費¥600,000・固定費¥300,000のとき貢献利益は',choices:['¥400,000','¥100,000','¥700,000','¥300,000'],answer:0,exp:'貢献利益 売上高 変動費 1,000,000 600,000 400,000円'},
@ -664,6 +757,7 @@ function bokiApp(){
sidebarOpen:false,
isDark:true,
progress:{},
scores:{},
keys:['A','B','C','D','E'],
init(){
@ -673,6 +767,8 @@ function bokiApp(){
}));
try{ this.progress = JSON.parse(localStorage.getItem('posimai-boki-progress')||'{}'); }
catch{ this.progress = {}; }
try{ this.scores = JSON.parse(localStorage.getItem('posimai-boki-scores')||'{}'); }
catch{ this.scores = {}; }
const t = localStorage.getItem('posimai-boki-theme')||'system';
this.isDark = t==='dark'||(t==='system'&&matchMedia('(prefers-color-scheme:dark)').matches);
this.$nextTick(()=>{ if(window.lucide) lucide.createIcons(); });
@ -718,6 +814,41 @@ function bokiApp(){
this.progress[this.currentUnit.id]=true;
localStorage.setItem('posimai-boki-progress',JSON.stringify(this.progress));
},
bestScore(id){
const s=this.scores[id];
if(!s) return '';
return s.best+'/'+s.total;
},
scoreChipCls(id){
const s=this.scores[id];
if(!s) return 'zero';
if(s.best===s.total) return '';
if(s.best>=s.total*0.6) return 'partial';
return 'zero';
},
saveScore(id,correct,total){
const prev=this.scores[id];
if(!prev||correct>prev.best){
this.scores[id]={best:correct,total};
localStorage.setItem('posimai-boki-scores',JSON.stringify(this.scores));
}
},
get freqBadgeCls(){
const f=this.currentUnit?.freq;
if(f==='high') return 'badge badge-high';
if(f==='mid') return 'badge badge-mid';
return 'badge badge-base';
},
get freqLabel(){
const f=this.currentUnit?.freq;
if(f==='high') return '頻出';
if(f==='mid') return '重要';
return '基礎';
},
get diffLabel(){
const d=this.currentUnit?.diff||1;
return '難易度 '+'★'.repeat(d)+'☆'.repeat(3-d);
},
openUnit(unit){
this.currentUnit=unit;
@ -762,13 +893,16 @@ function bokiApp(){
},
get resultScore(){
const correct=Object.values(this.quizState).filter(s=>s?.correct).length;
return correct+' / '+(this.currentUnit?.quiz?.length||0);
const total=this.currentUnit?.quiz?.length||0;
if(this.currentUnit) this.saveScore(this.currentUnit.id,correct,total);
return correct+' / '+total;
},
get resultMsg(){
const correct=Object.values(this.quizState).filter(s=>s?.correct).length;
const total=this.currentUnit?.quiz?.length||0;
if(correct===total) return '完璧です!次の単元へ進みましょう。';
if(correct>=total*0.67) return 'よくできました。解説を確認してもう一度解いてみましょう。';
if(correct>=total*0.8) return 'よくできました。あと少しで完璧です。';
if(correct>=total*0.6) return '合格ラインです。間違えた問題の解説を確認しましょう。';
return '解説をよく読んで、もう一度チャレンジしてみましょう。';
},
resetQuiz(){ this.quizState={}; },