diff --git a/.claude/skills/dcore-citizen/schema.md b/.claude/skills/dcore-citizen/schema.md index afbbbea..d091e7a 100644 --- a/.claude/skills/dcore-citizen/schema.md +++ b/.claude/skills/dcore-citizen/schema.md @@ -26,11 +26,11 @@ contain them. ```json { - "eyebrow": "TV debate · 21 minutes · quick read · tap any row for detail", + "eyebrow": "TV debate · 21 minutes · quick read · tap any row for detail", // full page only; the compact page does not show it "question": "Should the Election Commission chief resign?", "context": "One or two plain sentences: what triggered the conversation.", - "progress_caption": "Five steps were within reach. The panel took two.", + "progress_caption": "Five steps were within reach. The panel took two.", // full page only; the compact page writes its own line "progress": [ {"status": "reached", "thread": "explain", "text": "Everyone agreed: the Commission must explain itself in public", diff --git a/.claude/skills/dcore-citizen/template-compact.html b/.claude/skills/dcore-citizen/template-compact.html index ed0eafe..c0564c2 100644 --- a/.claude/skills/dcore-citizen/template-compact.html +++ b/.claude/skills/dcore-citizen/template-compact.html @@ -23,84 +23,78 @@ * { box-sizing: border-box; } body { margin: 0; background: var(--bg); color: var(--fg); font: 15px/1.4 var(--f-body); } -.wrap { max-width: 600px; margin: 0 auto; padding: 20px max(16px, env(safe-area-inset-right, 0px)) 48px max(16px, env(safe-area-inset-left, 0px)); display: grid; gap: 26px; } +.wrap { max-width: 600px; margin: 0 auto; padding: 20px max(16px, env(safe-area-inset-right, 0px)) 48px max(16px, env(safe-area-inset-left, 0px)); display: grid; gap: 24px; } h1, h2 { font-family: var(--f-head); margin: 0; text-wrap: balance; } h1 { font-size: 1.45rem; line-height: 1.15; } -h2 { font-size: 1rem; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; } +h2 { font-size: 1.35rem; line-height: 1.2; letter-spacing: -.01em; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; } h2 small { font: 600 .8rem var(--f-body); color: var(--muted); } p { margin: 0; } -section { display: grid; gap: 8px; min-width: 0; } -.eyebrow { font-size: .72rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); } -header { display: grid; gap: 6px; } -.top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; } +section { display: grid; gap: 16px; min-width: 0; } +header { display: grid; gap: 8px; position: relative; } +.top { position: absolute; top: 0; right: 0; } +header h1 { padding-right: 84px; } .theme { flex: none; min-height: 32px; font: 600 .75rem var(--f-body); color: var(--muted); background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; cursor: pointer; } .theme:hover { color: var(--fg); } .theme:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; } .ctx { color: var(--muted); font-size: .92rem; } -.ts { font: 500 .72rem var(--f-mono); color: var(--muted); white-space: nowrap; } +.ts { font: 500 .78rem var(--f-mono); color: var(--muted); white-space: nowrap; } /* padding widens the tap area to about 32px; the negative margin keeps the layout unchanged */ a.ts { color: var(--link); text-decoration: underline dotted; text-underline-offset: 3px; padding: 9px 4px; margin: -9px -4px; border-radius: 4px; } .muted { color: var(--muted); } /* In short: two lines a reader can repeat */ -.summary { border-bottom: 1px solid var(--line); padding: 2px 0 16px; display: grid; gap: 6px; } +.summary { border-bottom: 1px solid var(--line); padding: 2px 0 16px; display: grid; gap: 12px; } .summary .hook { font: 700 1.55rem/1.15 var(--f-head); letter-spacing: -.01em; text-wrap: balance; margin-bottom: 4px; } -.summary .hook em { font-style: normal; font-size: 2.6rem; line-height: 1; letter-spacing: -.02em; color: var(--bad); margin-right: 2px; } -.summary p:not(.hook) { font-size: 1.02rem; color: var(--fg); } -.summary p:not(.hook) b { font: 700 1.05rem var(--f-head); } +.summary .hook em { font-style: normal; font-size: 2.6rem; line-height: 1; letter-spacing: -.02em; color: var(--good); margin-right: 2px; } +.summary > p:not(.hook) { font-size: 1.02rem; color: var(--fg); } +.summary .pies { margin-top: 4px; } +.reach { background: var(--bad-soft); border-left: 3px solid var(--bad); border-radius: 0 8px 8px 0; padding: 10px 14px; font-size: .92rem; line-height: 1.45; } +.reach b:first-of-type { color: var(--bad); } +.summary > p.hook-sub { font-size: .88rem; color: var(--muted); margin-top: -10px; } +.summary > p:not(.hook) b { font: 700 1.05rem var(--f-head); } @media (max-width: 480px) { .summary .hook { font-size: 1.35rem; } .summary .hook em { font-size: 2.2rem; } } -/* Minimap: a quiet rail on the left; a dot per section, names beside it when there is room */ -.aside-col { display: grid; gap: 14px; } -.side-h { font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; } -.minimap { display: none; } -#minimap { position: relative; display: grid; gap: 2px; } -#minimap::before { content: ""; position: absolute; left: 3px; top: 10px; bottom: 10px; width: 1px; background: var(--line); } -#minimap a { position: relative; display: flex; align-items: center; gap: 9px; min-height: 22px; text-decoration: none; color: var(--muted); font-size: .8rem; } -#minimap a::before { content: ""; flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--bg); box-shadow: inset 0 0 0 1.5px var(--muted); transition: transform .2s, background .2s; } -#minimap a[aria-current="true"] { color: var(--fg); font-weight: 600; } -#minimap a[aria-current="true"]::before { background: var(--fg); box-shadow: none; transform: scale(1.3); } -#minimap a:hover { color: var(--fg); } -#minimap a:focus-visible { outline: 2px solid var(--link); outline-offset: 1px; border-radius: 4px; } section[id] { scroll-margin-top: 16px; } - -/* How to read: a quiet "?" that opens a floating panel, so nothing on the page moves */ -.help { position: relative; } -.help-btn { display: inline-flex; align-items: center; gap: 7px; font: 600 .78rem var(--f-body); color: var(--muted); background: none; border: 0; padding: 2px 0; cursor: pointer; } -.help-btn:hover, .help-btn[aria-expanded="true"] { color: var(--fg); } -.help-btn:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; border-radius: 4px; } -.q { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; border: 1.5px dotted currentColor; font-size: .72rem; font-weight: 700; } -.guide { margin-top: 8px; } -.guide > summary { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); } -.guide > div { background: var(--surface); border: 1.5px dotted var(--muted); border-radius: 10px; padding: 12px 14px; display: grid; gap: 7px; font-size: .84rem; line-height: 1.4; } -.guide-h { font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } -.guide b { font-weight: 600; } -.kinds { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; } -.kinds li { display: grid; grid-template-columns: 9px minmax(0, 1fr); gap: 8px; align-items: baseline; } -.kinds i { width: 9px; height: 9px; border-radius: 50%; display: block; transform: translateY(1px); } -@media (min-width: 1120px) { - .aside-col { position: fixed; z-index: 4; top: 20px; right: 24px; width: min(280px, calc(50vw - 300px - 56px)); max-height: calc(100vh - 40px); overflow-y: auto; scrollbar-width: thin; } - .minimap { display: block; padding: 0 2px; } - .guide > div { font-size: .8rem; } -} +/* a thin rule between sections, like the one under the summary */ +section ~ section { border-top: 1px solid var(--line); padding-top: 22px; } +/* Section tabs: one section at a time under the header; sticks to the top while reading */ +.sectabs { position: sticky; top: 0; z-index: 3; display: flex; align-items: flex-end; gap: 2px; overflow-x: auto; scrollbar-width: none; background: var(--bg); border-bottom: 1px solid var(--line); } +.sectabs::-webkit-scrollbar { display: none; } +.sectabs button { flex: none; font: 600 1rem var(--f-body); color: var(--muted); background: none; border: 0; border-bottom: 3px solid transparent; padding: 10px 10px 8px; margin-bottom: -1px; cursor: pointer; } +.sectabs button:hover { color: var(--fg); } +.sectabs button[aria-selected="true"] { color: var(--fg); border-bottom-color: var(--fg); font-weight: 700; } +.sectabs button:focus-visible { outline: 2px solid var(--link); outline-offset: -2px; } +section.pane, section.pane ~ section.pane { border-top: 0; padding-top: 0; } +#ask { padding-top: 16px; gap: 4px; } +#trs { border-top: 0; padding-top: 0; margin-top: -24px; } +.summary.pane { border-bottom: 0; padding-bottom: 0; } /* Rows: one line each, tap to open */ -.list { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; } +.list { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; overflow: clip; } details.row { border-top: 1px solid var(--line); } details.row:first-child { border-top: 0; } -details.row > summary { list-style: none; cursor: pointer; padding: 9px 12px; display: grid; grid-template-columns: 18px minmax(0, 1fr) 12px; gap: 2px 8px; align-items: start; } +details.row > summary { list-style: none; cursor: pointer; padding: 14px 14px; display: grid; grid-template-columns: 18px minmax(0, 1fr) 12px; gap: 5px 10px; align-items: start; line-height: 1.35; } +/* an open row keeps its title in view under the tabs while its detail is read */ +details.row[open] > summary { position: sticky; top: var(--tabs-h, 44px); z-index: 2; background: var(--surface); border-bottom: 1px dashed var(--line); } details.row > summary::-webkit-details-marker { display: none; } details.row > summary::after { content: "▸"; color: var(--muted); font-size: .9rem; line-height: 1.2; grid-column: 3; grid-row: 1; transition: transform .15s; } details.row > summary:hover::after { color: var(--fg); } details.row[open] > summary::after { transform: rotate(90deg); } details.row > summary:focus-visible { outline: 2px solid var(--link); outline-offset: -2px; } -.ic { font-weight: 700; grid-row: 1; } -.ic.g { color: var(--good); } .ic.r { color: var(--bad); } +/* outcome rows: a faint green or red wash and edge instead of a tick or cross */ +details.step > summary { grid-template-columns: minmax(0, 1fr) 12px; } +details.step .tx-main, details.step .tx-sub { grid-column: 1; } +details.step > summary::after { grid-column: 2; } +details.step .body { padding-left: 14px; } +details.step.ok { --row: color-mix(in srgb, var(--good) 13%, var(--surface)); --edge: var(--good); } +details.step.miss { --row: color-mix(in srgb, var(--bad) 12%, var(--surface)); --edge: var(--bad); } +details.step, details.step[open] > summary { background: var(--row); box-shadow: inset 3px 0 var(--edge); } .tx-main { font-weight: 600; grid-column: 2; grid-row: 1; } -.tx-sub { grid-column: 2; font-size: .84rem; color: var(--muted); } +details.row[open] .tx-main { font-size: 1.4em; line-height: 1.25; } +.tx-sub { grid-column: 2; font-size: .86rem; line-height: 1.4; color: var(--muted); } .tx-sub .why { color: var(--fg); } -.body { padding: 2px 12px 12px 38px; display: grid; gap: 8px; font-size: .88rem; } -.body h4 { margin: 4px 0 0; font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } +.body { padding: 12px 14px 16px 42px; display: grid; gap: 10px; font-size: .9rem; line-height: 1.45; } +.body h4 { margin: 4px 0 0; font-size: .76rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } .chain { display: grid; gap: 3px; margin: 0; padding: 0; list-style: none; } .chain li { padding-left: 14px; position: relative; } .chain li::before { content: ""; position: absolute; left: 0; top: .5em; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .55; } @@ -110,8 +104,8 @@ .mo.neg { grid-template-columns: 1fr; padding-left: 50px; color: var(--muted); font-style: italic; } .mo.dot::before { content: none; } ol.plain { margin: 0; padding-left: 18px; display: grid; gap: 2px; } -.outcome { border-left: 3px solid var(--bad); padding: 2px 0 2px 10px; font-weight: 600; font-size: .92rem; display: grid; gap: 2px; } -.outcome .lbl { font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } +.outcome { border-left: 3px solid var(--bad); margin-top: 8px; padding: 8px 0 8px 14px; font-weight: 600; font-size: .95rem; line-height: 1.4; display: grid; gap: 6px; } +.outcome .lbl { font-size: .76rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } .outcome .note { font-weight: 400; color: var(--muted); font-size: .8rem; } /* Time */ @@ -135,10 +129,12 @@ .bl .pc { text-align: right; font-weight: 600; font-size: .86rem; } .bl .k { color: var(--muted); font-size: .76rem; } .card { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; display: grid; gap: 6px; } -.card-h { font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } -.insight { border-left: 3px solid var(--line); padding: 2px 0 2px 10px; font-size: .9rem; } -.insight b { display: block; } -details.more > summary { list-style: none; cursor: pointer; font-size: .8rem; font-weight: 600; color: var(--link); display: inline-flex; gap: 5px; padding: 2px 0; } +.card-h { font-size: .76rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } +.insight { border-left: 3px solid var(--line); padding: 4px 0 4px 12px; font-size: .92rem; line-height: 1.5; } +#s-dist { gap: 14px; } +#s-dist > p { line-height: 1.5; } +.insight b { display: block; margin-bottom: 4px; } +details.more > summary { list-style: none; cursor: pointer; font-size: .85rem; font-weight: 600; color: var(--link); display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0; } details.more > summary::-webkit-details-marker { display: none; } details.more > summary::before { content: "▸"; transition: transform .15s; } details.more[open] > summary::before { transform: rotate(90deg); } @@ -150,18 +146,18 @@ /* Two donuts side by side: how the time was used, and what the distractions were */ .pies { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } .pie { margin: 0; background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; display: grid; gap: 8px; align-content: start; min-width: 0; } -.pie figcaption { font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } +.pie figcaption { font-size: .76rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } .pie svg { width: 112px; height: 112px; justify-self: center; display: block; } .pie svg circle.seg { fill: none; stroke-width: 16; } .pie svg circle.seg:hover { stroke-width: 19; } -.pie svg .big { font: 700 20px var(--f-head); fill: var(--fg); } -.pie svg .big.long { font-size: 16px; } +.pie svg .big { font: 700 17px var(--f-head); fill: var(--fg); } .pie svg .small { font: 600 9.5px var(--f-body); fill: var(--muted); } .lg { display: grid; gap: 3px; font-size: .8rem; line-height: 1.25; } .lg p { display: grid; grid-template-columns: 9px minmax(0, 1fr) auto; gap: 6px; align-items: baseline; } .lg i { width: 9px; height: 9px; border-radius: 2px; display: block; align-self: center; } .lg b { font-weight: 600; } -details.more h4 { margin: 6px 0 0; font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } +.moments { display: grid; gap: 6px; font-size: .86rem; } +.moments h4, details.more h4 { margin: 6px 0 0; font-size: .76rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } /* stacked on narrow screens: donut beside its legend, so labels keep one line */ @media (max-width: 520px) { .pies { grid-template-columns: 1fr; } @@ -195,10 +191,11 @@ details.thr > summary { grid-template-columns: minmax(0, 1fr) auto 12px; } details.thr .tx-main { grid-column: 1; } details.thr .badge { grid-column: 2; grid-row: 1; margin-top: 2px; } -details.thr > summary .track { grid-column: 1 / 3; grid-row: 2; height: 4px; margin: 5px 0 1px; } +details.thr > summary .track { grid-column: 1 / 3; grid-row: 2; height: 4px; margin: 8px 0 2px; opacity: .5; } +.lane-key { color: var(--muted); } .track { position: relative; height: 6px; background: var(--track); border-radius: 3px; } .track i { position: absolute; top: 0; bottom: 0; } -details.thr .body { padding-left: 12px; } +details.thr .body { padding-left: 14px; } .pulled { color: var(--fg); } .fl { display: grid; grid-template-columns: 8px 44px minmax(0, 1fr); gap: 6px; align-items: baseline; } .fl::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--quiet); } @@ -219,7 +216,7 @@ .dots .h { background: transparent; box-shadow: inset 0 0 0 2px var(--quiet); } details.vo .note { font-size: .82rem; color: var(--muted); min-width: 0; } details.vo summary::after { grid-column: 4; } -details.vo .body { padding-left: 12px; } +details.vo .body { padding-left: 14px; max-height: 340px; overflow-y: auto; overscroll-behavior: contain; } .mv { display: grid; grid-template-columns: 8px 44px minmax(0, 1fr); gap: 6px; align-items: baseline; } .mv::before { content: ""; width: 7px; height: 7px; border-radius: 50%; } .mv.g::before { background: var(--good); } .mv.o::before { background: var(--quiet); } .mv.r::before { background: var(--bad); } @@ -228,7 +225,7 @@ .mv .better b, .mv .cost b { color: var(--fg); font-weight: 600; } .ask ol { margin: 0; padding-left: 18px; display: grid; gap: 3px; } -.ask h4 { margin: 4px 0 0; font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } +.ask h4 { margin: 4px 0 0; font-size: .76rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); } .txs { max-height: 55vh; overflow-y: auto; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; } .txs p { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 6px; padding: 2px; } .txs p.hit { background: var(--quiet-soft); } @@ -246,56 +243,34 @@
How this report works
-We follow each question the debate took up (a thread) and sort every moment into one of three kinds:
-Wasted time is distractions plus points left open.
-Failed to reach is a step that was close: one or two moves away, using only what had already been said.
-Accountability shows each voice's moves, one dot per moment, in the same three colours. We judge moves, never sides or opinions.
-Each thread's replay is one fair way it could have gone, not what happened.
-What pulled the debate off course.
-Who moved the debate forward, and who held it back.
' + wasted + ' of ' + Math.round(total / 60) + ' minutes was wasted.
' + - 'Distractions took ' + share("side") + ', and points nobody answered took ' + share("talk") + '.
' + - 'Only ' + fwd + ' moved the debate forward.
' + - '' + (missed.length ? 'It failed to reach ' + things(missed.length) + ' that ' + (missed.length === 1 ? "was" : "were") + ' close, and settled ' : 'It settled ') + - (reached.length ? (missed.length ? 'only ' : '') + '' + reached.length + '.' : 'nothing.') + '
'; + '' + (fwdSec < total / 2 ? "Only " : "") + '' + fwd + ' of ' + Math.round(total / 60) + ' minutes was fruitful.
' + + 'Fruitful: time where something got agreed or answered.
'; +// The progress report opens with how many steps were missed and how many settled. +$("reach").innerHTML = (missed.length ? 'It failed to reach ' + things(missed.length) + ' that ' + (missed.length === 1 ? "was" : "were") + ' close, and settled ' : 'It settled ') + + (reached.length ? (missed.length ? 'only ' : '') + '' + reached.length + '.' : 'nothing.'); -// Within reach: one line per step; missed steps show when they were lost and the consequence that matters most. -if (DATA.progress_caption) $("progress-caption").textContent = DATA.progress_caption; -else $("progress-caption").hidden = true; +// Outcome analysis: one line per step; missed steps show when they were lost and the consequence that matters most. const blocks = bs => (bs || []).map(b => (b.heading ? '' + esc(p.label) + '' + esc(p.pc) + '
').join("") + 'Minute by minute
' + esc(d.label) + ' · ' + esc(d.who) + (d.length ? ' · ' + esc(d.length) + '' : "") + '
' + esc(d.what) + '
' + '' + (d.victim ? "Left unanswered: " + esc(d.victim) : "Thread: " + esc((THREADS[d.thread] || {}).title || "none")) + '
Follow-up that would close it: "' + esc(g.follow_up) + '"
' : "") + '').join(""); } else { $("gaps-line").hidden = true; $("tab-gaps").hidden = true; } -// Tabs inside the expand: distractions, and points left unanswered. +// Tabs under the distraction analysis: distractions, and points left unanswered. (function () { const tabs = [$("tab-dist"), $("tab-unans"), $("tab-gaps")]; $("tab-dist").textContent = "Distractions (" + (DATA.distractions || []).length + ")"; @@ -1605,7 +1580,6 @@' + esc(th.summary) + '
' + (th.pulled ? '' + esc(th.pulled) + '
' : "") + '