/* TED Document Validator — component library (Loop 2c, redone 2026-09-07 § 37 F7).
   Tokens: the approved SOP editor mock's set (§ 27; the mock is retired to prototypes/mvp01/_backup/, § 52) — one palette, one type scale, one button scale.
   The old POC1 names (--primary, --outline, --on-surface, --muted, --surface, --surface-variant, --primary-container)
   stay as aliases because sopview.js reads them. */
@import url('https://fonts.googleapis.com/css2?family=Sarabun:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap');
:root{
  /* palette (mock, light) */
  --ground:#f4f5f7;--sheet:#fff;--ink:#1c2430;--ink-2:#4b5563;--ink-3:#7b8494;--rule:#e1e4e8;--rule-2:#eef0f2;
  --accent:#1e4fa3;--accent-soft:#e8eefb;--active:#f7f8fa;--sel:#cfe0ff;--cta:#e8781e;
  --hint:#9a5b00;--hint-soft:#fff3d6;--ok:#2b6b3f;--ok-soft:#e2f0e6;--fail:#8c2f2f;--fail-soft:#f7e3e3;
  --val:#0f5f7a;--val-soft:#e6f2f6;--badge:#5b6474;--badge-bg:#f0f2f5;--bbox:#00cfff;
  /* Story 9.7b (ruling § 60, 05_components Delta of 2026-09-15 evening): the **numbered** boxes of
     the manual's specimen are the fund's own red — measured off the page the fund sent
     (`memory/source/2026-09-11_feedback/image copy.png`, the mean of its 2,983 red pixels).
     `--bbox` stays #00cfff for the unnumbered highlight. */
  --bbox-manual:#d7252e;--bbox-manual-soft:rgba(215,37,46,.22);--bbox-manual-ring:rgba(215,37,46,.5);
  --shadow:0 1px 2px rgba(20,24,32,.06),0 6px 20px rgba(20,24,32,.05);
  /* type scale: 14 body · 12.5 meta · 18 page title · 16 card title */
  --font:Sarabun,"Noto Sans Thai",system-ui,sans-serif;--mono:"IBM Plex Mono",ui-monospace,Menlo,monospace;
  --fs:14px;--fs-meta:12.5px;--fs-title:18px;--fs-card:16px;
  /* rhythm: 8 / 16 / 24; radius 6; buttons 32.
     Story 2.28 — `--s3` completes the scale. It was **spent and never defined**: the empty projects
     card asked for `padding:var(--s3) var(--s2)`, an undefined `var()` makes the whole declaration
     invalid at computed-value time, and the first screen a new advisor ever sees was a 22-pixel
     strip with no padding at all ([[walk-pre-2026-09-18]] § D). 24px is the step the rhythm was
     already counting in, and `.review .empty` beside it. Guarded now:
     `tests/architecture/test_every_css_token_is_defined.py`. */
  --s1:8px;--s2:16px;--s3:24px;--radius:6px;--btn-h:32px;--nav-w:212px;--header-h:52px;--card-action-w:260px;--main-pad:24px;
  /* the measure a page's content sits on — 1106 px; see `.main` below for where it comes from */
  --measure:calc(1366px - var(--nav-w) - var(--main-pad) * 2);
  /* aliases for sopview.js and the editor styles */
  --primary:var(--accent);--primary-dark:#163b7a;--primary-container:var(--accent-soft);--on-primary:#fff;
  --surface:var(--ground);--surface-variant:var(--active);--on-surface:var(--ink);--muted:var(--ink-3);--outline:var(--rule);
  --danger:var(--fail);--danger-bg:var(--fail-soft);--success:var(--ok);--success-bg:var(--ok-soft);--warning:var(--hint);--warning-bg:var(--hint-soft);
  --info:var(--accent);--info-bg:var(--accent-soft);--grey:var(--ink-3);--grey-bg:var(--badge-bg);
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{font-family:var(--font);font-size:var(--fs);line-height:1.5;color:var(--ink);background:var(--ground)}
input,textarea,button,select{font-family:var(--font);font-size:var(--fs);color:inherit}
a{color:var(--accent)}
[hidden]{display:none!important}
h1,h2,h3,h4{font-weight:600;line-height:1.3}

/* ── shell ── */
.shell{display:grid;grid-template-columns:var(--nav-w) 1fr;grid-template-rows:var(--header-h) 1fr;height:100vh;min-width:1280px}
.header{grid-column:1/3;display:flex;align-items:center;gap:var(--s2);padding:0 22px;background:var(--sheet);border-bottom:1px solid var(--rule)}
.header .brand{font-weight:600;color:var(--ink);font-size:15px;letter-spacing:.005em}
.header .spacer,.spacer{flex:1}
.header .who{color:var(--ink-3);font-size:var(--fs-meta)}
.nav{background:var(--sheet);border-right:1px solid var(--rule);padding:12px 10px;display:flex;flex-direction:column;gap:2px}
.nav a{display:block;padding:7px 12px;border-radius:5px;color:var(--ink-2);text-decoration:none;font-weight:500;border-left:3px solid transparent}
.nav a.active{background:var(--accent-soft);color:var(--accent);border-left-color:var(--accent)}
.nav a:hover{background:var(--active)}
.nav .group{margin-top:14px;padding:0 12px 4px;font-size:11.5px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.06em;font-weight:600}
.nav a.sub{padding-left:22px;font-weight:400}
/* ── the measure (Story 2.22) ──────────────────────────────────────────────────
   `.main` is handed the whole second column of `.shell` and nothing capped what a
   page put in it, so on a 1575 px screen a card with two lines in it was a band
   the width of the window. Every block a page puts in `.main` now sits on one
   measure and centres on it.

   **The measure is 1106 px: what `.main` hands its content at 1366 px**, the width
   the design was drawn for (`01_goals.md:89`). Every approved drawing was drawn at
   or below that width, so above it nothing was ever designed and the honest cap is
   the design's own measure — written as the subtraction it is, so that changing the
   nav or `.main`'s padding moves it too.

   Two things were checked against it rather than guessed at. **The widest thing
   that must fit** is the review workspace P-017 as it is actually rendered,
   `.review.w013`: 260 px + 340 px of fixed rails and, in the middle, the page sheet
   at its own 420 px inside the stage's 12 px of padding each side — 1044 px, which
   sits inside the measure with 62 px to spare, so the page image is never the thing
   that shrinks. **The SOP editor** with its gate panel open asks 270 px + 360 px and
   two 16 px gaps, leaving its editor column exactly the 444 px it has at 1366 px
   today.

   And **nothing moves at 1366 px**: the cap is inert at exactly that width and first
   bites at 1367 px.

   `.shell{min-width:1280px}` and the fact that this file carries no breakpoint rule
   at all are deliberate (`01_goals.md:89` Desktop Chrome ≥ 1366 px;
   `04_wireframes.md:41` 1280 px minimum) and are **not** touched here — making the
   product work below 1280 px is Epic 11's, and
   `tests/architecture/test_the_measure.py` holds that line shut. */
.main{overflow:auto;padding:20px var(--main-pad)}
.main>*{max-width:var(--measure);margin-inline:auto}
/* The opt-outs, said out loud rather than left to accident:
   · the full page viewer — the one surface where a person zooms a page to 840 px to
     read a stamp on it — takes the whole window, and so does the round stepper above
     it, so that page stays one piece (AC 2);
   · `.full` is the escape hatch for any later page that must do the same;
   · the fixed overlays were never on a measure and are not put on one now. */
.main:has(>.review.vfull)>*{max-width:none}
.main>.full{max-width:none}
.main>.drawer,.main>.modal-back{max-width:none;margin-inline:0}
.page-title{display:flex;align-items:center;gap:12px;margin-bottom:var(--s2);min-height:var(--btn-h)}
.page-title h1{font-size:var(--fs-title);font-weight:600;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.page-title .meta{color:var(--ink-3);font-size:var(--fs-meta);white-space:nowrap;flex-shrink:0}
.page-title .actions{display:flex;gap:var(--s1);align-items:center;margin-left:auto}

/* ── buttons: one scale (mock .tb). 32 px; `primary` filled = the page's one next action; `danger` outlined; `small` 26 px inside table rows, toolbars, and a card title's actions (Story 2.26 — 05_components.md § Tokens carries the rule and what moved it); `icon` = the label is a glyph and the button is square ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:var(--btn-h);padding:0 12px;border-radius:5px;border:1px solid var(--rule);background:var(--sheet);color:var(--ink-2);cursor:pointer;font-weight:500;font-size:13.5px;line-height:1;white-space:nowrap;text-decoration:none}
.btn:hover{border-color:var(--accent);color:var(--accent)}
.btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.btn.primary{background:var(--cta);border-color:var(--cta);color:#fff;font-weight:600;padding:0 16px}
.btn.primary:hover{filter:brightness(1.06);color:#fff}
.btn.danger{color:var(--fail);border-color:var(--fail)}
.btn.danger:hover{background:var(--fail-soft)}
.btn.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
.btn.link{border-color:transparent;background:transparent;color:var(--accent);padding:0 6px}
.btn.small{height:26px;padding:0 9px;font-size:12.5px}
/* `icon`: the label is one glyph, so the box is square at whatever height the scale gives it and
   the padding goes. The name is never on the screen — `U.Btn`'s `icon` option emits it as
   `aria-label` and `title`, which is why this rule can afford to draw nothing but the glyph. */
.btn.icon{width:var(--btn-h);padding:0;font-size:15px}
.btn.icon.small{width:26px;font-size:13.5px}
.btn:disabled,.btn[aria-disabled=true]{opacity:.45;cursor:not-allowed;filter:none}
.btn.loading::before{content:"";width:12px;height:12px;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.gate{display:inline-flex;flex-direction:column;gap:3px;align-items:flex-end}
.gate .reason{font-size:var(--fs-meta);color:var(--ink-3)}
.gate .reason.block{color:var(--fail)}
.keycap{display:inline-block;border:1px solid var(--rule);border-bottom-width:2px;border-radius:4px;padding:0 5px;font-size:11px;background:var(--sheet);color:var(--ink-3)}
.btnrow{display:flex;gap:var(--s1);align-items:center}
.btnrow.end{justify-content:flex-end}

/* ── chips, pills, tags ── */
.chip{display:inline-flex;align-items:center;gap:5px;padding:1px 9px;border-radius:999px;font-size:12px;font-weight:500;white-space:nowrap;line-height:1.6}
.chip::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.chip.fail{background:var(--fail-soft);color:var(--fail)}
.chip.confirm_by_eye{background:var(--hint-soft);color:var(--hint)}
.chip.pass{background:var(--ok-soft);color:var(--ok)}
.chip.cannot_check,.chip.not_applicable,.chip.queued{background:var(--badge-bg);color:var(--badge)}
.chip.running{background:var(--accent-soft);color:var(--accent)}
.chip.running::before{animation:pulse 1s ease-in-out infinite}
@keyframes pulse{50%{opacity:.3}}
.chip.done{background:var(--ok-soft);color:var(--ok)}
.chip.failed{background:var(--fail-soft);color:var(--fail)}
.chip.superseded{background:var(--sheet);color:var(--ink-3);border:1px solid var(--rule)}
.chip.role{background:var(--accent-soft);color:var(--accent)}
.chip.role::before,.chip.plain::before{display:none}
.chip.state-active{background:var(--ok-soft);color:var(--ok)}
.chip.state-invited{background:var(--hint-soft);color:var(--hint)}
.chip.state-disabled{background:var(--badge-bg);color:var(--badge)}
.status-pill{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;border-radius:999px;background:var(--ok-soft);color:var(--ok);font-size:var(--fs-meta);font-weight:500}
.status-pill.warn{background:var(--hint-soft);color:var(--hint)}
.status-pill i{width:7px;height:7px;border-radius:50%;background:currentColor;display:inline-block}
.src{font-family:var(--mono);font-size:10.5px;padding:0 5px;border-radius:3px;background:var(--badge-bg);color:var(--badge);margin-left:6px;vertical-align:1px}
.src.tool{background:var(--val-soft);color:var(--val)}
.sched{display:inline-flex;gap:5px;align-items:center;padding:1px 9px;border-radius:999px;border:1px solid var(--rule);font-size:12px;background:var(--sheet);margin-right:6px;line-height:1.6}
.sched em{font-style:normal;color:var(--ink-3)}
.sched.open{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.sched.open em{color:var(--accent)}
.sched.paid{color:var(--ok);border-color:var(--ok)}
.sched.postponed,.sched.merged{color:var(--hint);border-color:var(--hint)}
.stale{color:var(--hint);font-size:var(--fs-meta);margin-left:6px}
.lock{display:inline-flex;gap:6px;align-items:center;font-size:12px;color:var(--ink-3);background:var(--active);padding:3px 8px;border-radius:999px}
.cite{font-family:var(--mono);font-size:12px;color:var(--accent)}

/* ── surfaces ── */
.card{background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);box-shadow:var(--shadow);padding:var(--s2)}
.card+.card{margin-top:var(--s2)}
.card>h3,.card .card-title{font-size:var(--fs-card);font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:10px}
.card .card-title .meta{font-size:var(--fs-meta);color:var(--ink-3);font-weight:400}
.card .card-title .actions{margin-left:auto;display:flex;gap:var(--s1)}
.card .foot{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s2);padding-top:12px;border-top:1px solid var(--rule-2)}
.card .foot .note{color:var(--ink-3);font-size:var(--fs-meta);flex:1}
.section{margin-top:var(--s2)}
.section>h4{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);margin-bottom:6px;font-weight:600}
.table{width:100%;border-collapse:collapse;font-size:13.5px}
.table th,.table td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--rule-2);vertical-align:middle}
.table th{font-size:12px;color:var(--ink-2);font-weight:600;background:var(--active);border-bottom:1px solid var(--rule)}
.table td.num,.table th.num{text-align:right;font-variant-numeric:tabular-nums}
.table tr.clickable{cursor:pointer}
.table tr.clickable:hover,.table tr.sel{background:var(--accent-soft)}
.table tr.dim td{color:var(--ink-3)}
.table tr.warn td{background:var(--hint-soft)}
.table .actions{display:flex;gap:6px;justify-content:flex-end}
.table .actions .btn{min-width:92px}
.field{display:flex;flex-direction:column;gap:4px;margin-bottom:12px}
.field label{font-size:var(--fs-meta);color:var(--ink-3)}
.field input,.field select,.field textarea,.input{height:var(--btn-h);padding:0 10px;border:1px solid var(--rule);border-radius:5px;background:var(--sheet)}
.field textarea{height:auto;padding:6px 10px}
.field input:focus,.field textarea:focus,.field select:focus,.input:focus{outline:2px solid var(--accent);outline-offset:-1px}
.field.invalid input,.field.invalid textarea{border-color:var(--fail)}
.field .error{font-size:var(--fs-meta);color:var(--fail)}
.field.locked textarea{background:var(--active);color:var(--ink-3)}
.input.w-sm{width:150px}.input.grow{flex:1;min-width:0}
.row{display:flex;gap:12px}
.row>*{flex:1}
.two{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2);align-items:start}
.muted{color:var(--ink-3)}
.small,.meta{font-size:var(--fs-meta)}
.mono{font-family:var(--mono);font-size:12.5px}
.ok-t{color:var(--ok)}.fail-t{color:var(--fail)}.hint-t{color:var(--hint)}.accent-t{color:var(--accent)}
.mt1{margin-top:var(--s1)}.mt2{margin-top:var(--s2)}.mb1{margin-bottom:var(--s1)}
.inline{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.empty{padding:36px;text-align:center;color:var(--ink-3)}
.banner{padding:10px 14px;border-radius:var(--radius);margin-bottom:12px;display:flex;gap:10px;align-items:center;font-size:13.5px}
.banner.danger{background:var(--fail-soft);color:var(--fail)}
.banner.warning{background:var(--hint-soft);color:var(--hint)}
.banner.success{background:var(--ok-soft);color:var(--ok)}
.banner.info{background:var(--accent-soft);color:var(--accent)}
.refusal{margin-top:8px;padding:8px 10px;border-left:3px solid var(--fail);background:var(--fail-soft);color:var(--fail);font-size:13px}
.refusal pre{margin:6px 0;font-family:var(--mono);font-size:12px;white-space:pre-wrap}
.whoami{margin-top:8px;font-size:13px}
.whoami.ok{color:var(--ok)}
.whoami.err{color:var(--fail)}
.progress{height:6px;background:var(--active);border-radius:3px;overflow:hidden}
.progress>i{display:block;height:100%;background:var(--accent)}
.kv{display:grid;grid-template-columns:170px 1fr;gap:5px 12px;font-size:13.5px}
.kv dt{color:var(--ink-3)}
.kv dd{margin:0}
.radio{display:flex;gap:16px;margin-bottom:12px;flex-wrap:wrap}
.radio label{display:flex;gap:6px;align-items:center}
/* RequiredFormsList (W-011): the fund forms a งวด must carry, ✓ / ? / ✗ ขาด (จะเป็นผลตรวจ) */
.reqforms{display:flex;flex-wrap:wrap;gap:6px 14px;align-items:baseline;padding:8px 12px;border-top:1px solid var(--rule);font-size:var(--fs-meta);color:var(--ink-2)}
.reqforms.col{display:block;padding:0;border:0}
.reqforms .k{color:var(--ink);font-weight:600}
.reqforms .rf{white-space:nowrap}
.reqforms.col .rf{display:block;white-space:normal}
.reqforms .rf em{font-style:normal;font-weight:600}
.reqforms .rf.present em{color:var(--ok)}
.reqforms .rf.missing em{color:var(--fail)}
.reqforms .rf.unknown em,.reqforms .rf.unreadable em{color:var(--ink-2)}
.reqforms .none{color:var(--ink-2)}
/* .retention — deleted with the Retention component (Story 2.25, ruling § 71) */
details.fold>summary{cursor:pointer;color:var(--accent);font-size:13.5px;list-style:none;display:inline-flex;gap:6px;align-items:center;padding:4px 0}
details.fold>summary::before{content:"▸";font-size:11px;color:var(--ink-3)}
details.fold[open]>summary::before{content:"▾"}

/* ── modal / drawer / toast ── */
.modal-back{position:fixed;inset:0;background:rgba(28,36,48,.4);display:flex;align-items:center;justify-content:center;z-index:50}
.modal{background:var(--sheet);border-radius:8px;width:720px;max-height:88vh;overflow:auto;padding:22px;box-shadow:0 20px 40px rgba(0,0,0,.2)}
.modal h2{font-size:17px;margin-bottom:14px}
.modal .foot{display:flex;justify-content:flex-end;gap:8px;margin-top:14px}
.drawer{position:fixed;top:0;right:0;bottom:0;width:560px;background:var(--sheet);border-left:1px solid var(--rule);box-shadow:-10px 0 30px rgba(0,0,0,.12);padding:20px;overflow:auto;z-index:40}
.toast-host{position:fixed;bottom:20px;right:20px;display:flex;flex-direction:column;gap:8px;z-index:60}
.toast{padding:10px 14px;border-radius:var(--radius);background:var(--ink);color:#fff;box-shadow:0 6px 20px rgba(0,0,0,.2);font-size:13px}
.toast a{color:#fff}
.toast.danger{background:var(--fail)}
.toast.success{background:var(--ok)}
.offline{position:fixed;top:0;left:0;right:0;background:var(--fail);color:#fff;text-align:center;padding:4px;z-index:70;font-size:12px}

/* ── sign-in ── */
.signin{min-height:100vh;display:grid;place-items:center;background:var(--ground)}
.signin .card{width:400px;padding:28px}
.signin .brand{color:var(--ink);font-weight:600;font-size:18px;text-align:center;margin-bottom:20px}
.signin .as{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-bottom:12px;color:var(--ink-3);font-size:var(--fs-meta)}

/* ── RoundStepper: the six steps of a round, one thread through P-020/P-015/P-021/P-016/P-017/P-022 ── */
.stepper{display:flex;align-items:flex-start;gap:0;background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);padding:12px 8px;margin-bottom:var(--s2);box-shadow:var(--shadow)}
.stepper .step{flex:1;display:flex;flex-direction:column;align-items:center;text-align:center;gap:4px;position:relative;text-decoration:none;color:var(--ink-3);padding:0 6px;min-width:0}
.stepper .step:not(:last-child)::after{content:"";position:absolute;top:13px;left:calc(50% + 16px);right:calc(-50% + 16px);height:2px;background:var(--rule)}
.stepper .step.done:not(:last-child)::after{background:var(--ok)}
.stepper .step .n{width:26px;height:26px;border-radius:50%;border:2px solid var(--rule);display:grid;place-items:center;font-size:12.5px;font-weight:600;background:var(--sheet);color:var(--ink-3);font-family:var(--mono)}
.stepper .step .t{font-size:13px;font-weight:600;color:var(--ink-2);white-space:nowrap}
.stepper .step .m{font-size:11.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.stepper .step.done .n{background:var(--ok);border-color:var(--ok);color:#fff}
.stepper .step.done .t{color:var(--ok)}
.stepper .step.live .n{background:var(--accent);border-color:var(--accent);color:#fff}
.stepper .step.live .t{color:var(--accent)}
.stepper .step.live .m{color:var(--accent)}
.stepper .step.todo .t{color:var(--ink-3);font-weight:500}
.stepper a.step:hover .t{text-decoration:underline}

/* ── StageBar: the engine's five stages as a compact stepper ── */
.stages{display:flex;align-items:stretch;gap:0;border:1px solid var(--rule);border-radius:var(--radius);overflow:hidden;background:var(--sheet)}
.stages .stage{flex:1;padding:8px 12px;border-right:1px solid var(--rule);display:flex;flex-direction:column;gap:2px;min-width:0}
.stages .stage:last-child{border-right:0}
.stages .stage b{font-size:13px;font-weight:600;color:var(--ink-3);display:flex;gap:6px;align-items:center}
.stages .stage .m{font-size:11.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
.stages .stage.done b{color:var(--ok)}
.stages .stage.live{background:var(--accent-soft)}
.stages .stage.live b,.stages .stage.live .m{color:var(--accent)}
.stages .stage.fail{background:var(--fail-soft)}
.stages .stage.fail b,.stages .stage.fail .m{color:var(--fail)}
.stages.compact .stage{padding:2px 8px}
.stages.compact .stage b{font-size:12px}
.stages.compact .stage .m{display:none}

/* ── P-013 project cards ── */
.projcard{background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);box-shadow:var(--shadow);padding:var(--s2);margin-bottom:var(--s2)}
.projcard .head{display:flex;align-items:flex-start;gap:12px}
.projcard .head h2{font-size:var(--fs-card);font-weight:600}
.projcard .head .meta{color:var(--ink-3);font-size:var(--fs-meta);margin-top:2px}
.projcard .head .actions{margin-left:auto;display:flex;gap:var(--s1);align-items:center;flex:none;padding-right:12px}
.projcard .head .actions .btn,.projcard .next .btn{width:var(--card-action-w);justify-content:center}
.projcard .sched-row{margin:12px 0 10px;display:flex;flex-wrap:wrap;gap:4px 0}
.projcard .next{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--active);border-radius:var(--radius);font-size:13.5px}
.projcard .next .lbl{color:var(--ink-3);font-size:var(--fs-meta)}
.projcard .next .btn{margin-left:auto}
.projcard details{margin-top:10px}
.projcard.empty,.projcard.skeleton{color:var(--ink-3);text-align:center;padding:var(--s3) var(--s2)}
.protomark{display:inline-block;margin-bottom:10px;padding:3px 10px;border:1px dashed var(--rule);border-radius:999px;background:var(--active);color:var(--ink-3);font-size:var(--fs-meta)}
.home{display:grid;grid-template-columns:1fr 300px;gap:var(--s2);align-items:start}
.home.solo{grid-template-columns:1fr}
.chg{color:var(--accent);font-weight:600}
.howto{background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);box-shadow:var(--shadow);padding:14px 16px;position:sticky;top:0}
.howto h3{font-size:14px;display:flex;align-items:center;gap:8px;margin-bottom:8px}
.howto h3 .btn{margin-left:auto}
.howto ol{padding-left:20px;font-size:13px;color:var(--ink-2);display:flex;flex-direction:column;gap:5px}
.howto ol b{color:var(--ink)}
.howto .note{margin-top:10px;font-size:var(--fs-meta);color:var(--ink-3)}
.search{height:var(--btn-h);padding:0 10px;border:1px solid var(--rule);border-radius:5px;background:var(--sheet);width:220px}

/* ── P-020 setup / P-014 facts ── */
.setup .stepcard{display:grid;grid-template-columns:36px 1fr;gap:12px;align-items:start}
.setup .stepcard .n{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-weight:600;font-size:13px;background:var(--accent);color:#fff;font-family:var(--mono)}
.setup .stepcard.done .n{background:var(--ok)}
.setup .stepcard.todo .n{background:var(--badge-bg);color:var(--ink-3)}
.setup .stepcard.todo{opacity:.55}
.setup .stepcard h3{font-size:var(--fs-card);margin-bottom:4px}
.setup .stepcard .lead{color:var(--ink-3);font-size:13.5px;margin-bottom:10px}
.card .lead{color:var(--ink-3);font-size:13.5px}
.linkrow .muted{white-space:nowrap}
.linkrow{display:flex;gap:var(--s1);align-items:center}
.linkrow .input{flex:1}
.seen{display:flex;gap:8px;align-items:center;font-size:var(--fs-meta);color:var(--ink-2);margin-top:8px}
.seen .sa{font-family:var(--mono);font-size:12px;background:var(--badge-bg);padding:1px 6px;border-radius:3px}
.drive{border:1px solid var(--rule);border-radius:var(--radius);overflow:hidden;margin-top:10px}
.drive .dh{display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--active);border-bottom:1px solid var(--rule);font-size:13px}
.drive .dh b{font-weight:600}
.drive .dh .crumb{color:var(--ink-3)}
.drive .drow{display:grid;grid-template-columns:28px 1fr 130px 120px 190px 110px;gap:10px;align-items:center;padding:7px 12px;border-bottom:1px solid var(--rule-2);font-size:13.5px}
.drive .drow:last-child{border-bottom:0}
.drive .drow.head{font-size:12px;color:var(--ink-3);font-weight:600;background:var(--sheet)}
.drive .drow .ic{font-size:16px}
.drive .drow .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drive .drow .nm b{font-weight:500}
.drive .drow .own,.drive .drow .mod{color:var(--ink-3);font-size:var(--fs-meta)}
.drive .drow .map{font-size:13px}
.drive .drow.sel{background:var(--accent-soft)}
.drive .drow.dim{color:var(--ink-3)}
.drive .drow .act{display:flex;justify-content:flex-end}
.drive .drow .act .btn{min-width:96px}
/* Story 2.23 — a row that is a control looks and behaves like one; a loose row keeps the arrow
   cursor and does not light up. The focus ring is inset because `.drive` clips its overflow. */
.drive .drow[data-pick-folder]{cursor:pointer}
.drive .drow[data-pick-folder]:hover{background:var(--active)}
.drive .drow.sel[data-pick-folder]:hover{background:var(--accent-soft)}
.drive .drow:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.drive .drow .act .on{color:var(--ok);font-size:var(--fs-meta);font-weight:600;white-space:nowrap}
.table td.src{background:none;color:var(--ink-3);font-family:var(--font);font-size:var(--fs-meta);margin:0;padding:7px 10px}
.facts-tbl td .cur{color:var(--ink-3)}
.facts-tbl .actions .btn{min-width:110px}
.dev{display:inline-flex;gap:8px;align-items:center;font-size:var(--fs-meta);color:var(--ink-3)}
.dev .tag{font-family:var(--mono);font-size:11px;border:1px dashed var(--ink-3);padding:0 6px;border-radius:3px}

/* ── P-015 intake snapshot ── */
.snap .filerow{display:grid;grid-template-columns:1fr 200px 130px 70px 1fr;gap:10px;padding:6px 10px;border-bottom:1px solid var(--rule-2);font-size:13px;align-items:center}
.snap .filerow.head{font-size:12px;color:var(--ink-2);font-weight:600;background:var(--active);border-bottom:1px solid var(--rule)}
.snap .filerow.skip{color:var(--ink-3)}
.snap .chg{color:var(--accent);font-weight:600}
.snap .read{color:var(--ok)}
.snap .pres{color:var(--ink-3)}
.facts-line{display:flex;gap:var(--s2);flex-wrap:wrap;font-size:13.5px;margin:10px 0;align-items:center}

/* ── P-016 run ── */
.runpage .tabs{display:flex;gap:var(--s1);margin:var(--s2) 0 12px}
.runpage .panel{border:1px solid var(--rule);border-radius:var(--radius);padding:12px;max-height:56vh;overflow:auto}
.fact{display:grid;grid-template-columns:170px 1fr 20px;gap:6px;padding:4px 0;border-bottom:1px solid var(--rule-2);font-size:13px}
.fact .k{color:var(--ink-3)}.fact .ok.ok{color:var(--ok)}.fact .ok.no{color:var(--fail)}.fact .ok.unknown{color:var(--hint)}
.docblock{margin-bottom:12px}
.docblock .dh{display:flex;gap:8px;align-items:center;margin-bottom:4px}
.docblock .chips{margin-top:4px;display:flex;gap:6px;flex-wrap:wrap;font-size:12.5px;align-items:center}
.assess{border:1px solid var(--rule);border-radius:var(--radius);padding:10px 12px;background:var(--sheet);font-size:13.5px}
.assess+.assess{margin-top:8px}
.assess .tag{font-size:var(--fs-meta);color:var(--ink-3);margin-bottom:4px}
.assess ol{margin:6px 0 0 18px;padding:0}
.assess .hist{color:var(--ink-3);font-size:var(--fs-meta);margin-top:6px}
.remark{margin-top:8px;font-size:var(--fs-meta)}
.remark .saved{color:var(--ink-3);margin-bottom:4px}
.remark .row{display:flex;gap:6px}
.remark .row>.btn{flex:none}
.remark input{flex:1;height:26px;padding:0 8px;border:1px solid var(--rule);border-radius:5px;font-size:12.5px;min-width:0}
/* Story 2.6 — E-015's flag line, the disabled reason, E-007's retry and the ข้อความก่อนหน้า disclosure */
.remark .flag{margin-bottom:4px;padding:3px 6px;border-radius:4px;background:var(--warn-bg,#fdf3e3);color:var(--warn-ink,#8a5a00);font-size:var(--fs-meta)}
.remark .reason.block{display:block;margin-top:3px;color:var(--ink-3)}
.remark .err{display:inline-flex;align-items:center;gap:6px;margin-top:4px;color:var(--bad,#b00020)}
.remark .hist{margin-top:4px}
.remark .hist summary{cursor:pointer;color:var(--ink-3)}
.remark .hist .prev{margin:3px 0 0 10px;padding-left:8px;border-left:2px solid var(--rule);color:var(--ink-2)}
.remark .hist .prev.reverted{opacity:.7;font-style:italic}

/* ── P-017 review — Story 2.15: W-013′, three columns on the payment (the `.settile` strip is retired) ── */
.review{display:grid;grid-template-columns:250px 1fr 440px;grid-template-rows:1fr auto;height:calc(100vh - var(--header-h) - 40px - 118px);background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow)}
.review.w013{grid-template-columns:260px minmax(0,1fr) 340px}
.review .plist,.review .ppanel,.review .letter{overflow:auto;min-height:0}
.review .plist{border-right:1px solid var(--rule);padding:0 8px 8px}
.review .letter{border-left:1px solid var(--rule);display:flex;flex-direction:column}
.review .hd{display:flex;align-items:baseline;justify-content:space-between;gap:8px;padding:10px 8px 6px;position:sticky;top:0;background:var(--sheet);z-index:1}
.review .hd h4{font-size:13.5px;font-weight:600}
.review .ppanel .hd{padding:10px 14px 6px;border-bottom:1px solid var(--rule)}
.review .ppanel .hd h4{font-size:15px}
.review .sec{padding:10px 14px;border-top:1px solid var(--rule-2)}
.review .sec:first-of-type{border-top:0}
.review .row.between{justify-content:space-between;align-items:center;margin-bottom:6px}
.review .nosheet{padding:4px 6px 8px}
.review .empty{padding:24px;text-align:center;color:var(--ink-3)}
.review .chip.mdl{background:var(--val-soft);color:var(--val);border-color:transparent}
.review .chip.ending.open{background:var(--badge-bg);color:var(--badge)}
.review .chip.ending.approved,.review .chip.ending.carried{background:var(--ok-soft);color:var(--ok)}
.review .chip.ending.returned{background:var(--fail-soft);color:var(--fail)}
/* Story 2.17 — a later round: the three groups (AD-3 5′), a carried row's note, a หายไป row that is not a button */
.review .chip.ending.gone{color:var(--ink-3);border:1px dashed var(--rule);background:transparent}
.review .pgroup .ghd{display:flex;gap:6px;align-items:baseline;padding:8px 2px 4px;font-size:11.5px;font-weight:600;color:var(--ink-2)}
.review .pgroup .ghd .cnt{font-family:var(--mono);font-weight:400;color:var(--ink-3)}
.payrow .note{margin-top:3px}
.payrow.gone{opacity:.8;border-style:dashed;cursor:default}
.payrow.gone .bar{background:transparent}
/* PaymentRow — the bar is the worst outcome under it, the way the set tile's border was */
.payrow{display:flex;gap:0;background:var(--sheet);border:1px solid var(--rule);border-radius:5px;margin-bottom:6px;cursor:pointer;font-size:12.5px;color:var(--ink);overflow:hidden}
.payrow .bar{width:4px;flex:none;background:var(--rule)}
.payrow.fail .bar{background:var(--fail)}.payrow.confirm_by_eye .bar{background:var(--hint)}.payrow.pass .bar,.payrow.done .bar{background:var(--ok)}.payrow.cannot_check .bar{background:var(--ink-3)}
.payrow .b{padding:7px 9px;min-width:0;flex:1}
.payrow .t{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.payrow .m{display:flex;flex-wrap:wrap;gap:4px 8px;align-items:center;margin-top:3px;color:var(--ink-2);font-size:11.5px}
.payrow .m .num{font-family:var(--mono);color:var(--ink)}
.payrow.sel{background:var(--accent-soft);border-color:var(--accent)}
.payrow:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* DocumentRow and its in-place preview (ruling § 32's first click) */
.docrow{border:1px solid var(--rule);border-radius:5px;margin-bottom:6px;background:var(--sheet);font-size:12.5px}
.docrow .dh{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:7px 9px;cursor:pointer}
.docrow .dh .n{font-family:var(--mono);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.docrow .dh .row{display:flex;gap:5px;flex:none}
.docrow.open{border-color:var(--accent)}
.docrow.open .dh{background:var(--accent-soft)}
.docrow.none{border-style:dashed}
.docrow.none .dh{cursor:default;color:var(--fail)}
.docrow .prev{display:grid;grid-template-columns:150px 1fr;gap:12px;padding:10px;border-top:1px solid var(--rule)}
.docrow .prev img{display:block;width:150px;height:auto;border:1px solid var(--rule);box-shadow:0 1px 4px rgba(0,0,0,.12);background:#fff}
.docrow .prev .noimg{width:150px;min-height:80px;display:flex;align-items:center;justify-content:center;border:1px dashed var(--rule);text-align:center;padding:8px}
.docrow .prev .kv{font-size:12.5px;line-height:1.6}
.docrow .prev .kv .num{font-family:var(--mono)}
.review .fnd{margin-top:8px}
/* InstructionBox and the two endings */
.instr .ed{display:block;width:100%;min-height:64px;padding:8px 10px;border:1px solid var(--rule);border-radius:5px;font:inherit;font-size:13px;line-height:1.5;resize:vertical;background:var(--sheet)}
.instr .ed:focus{outline:2px solid var(--accent);outline-offset:1px}
.instr .err{display:block;margin-top:4px;color:var(--fail);font-size:var(--fs-meta)}
.review .endings{margin-top:10px}
.btn.ret{color:var(--cta);border-color:var(--cta);font-weight:600}
.btn.ret:hover{background:var(--hint-soft);color:var(--cta)}
/* the letter's column: the returned items, then the page's one primary */
.review .letterlist{flex:1}
.review .letterlist ol{margin:0 0 0 18px;padding:0;font-size:13px}
.review .letterlist li{margin-bottom:10px}
.review .letterlist .who{font-weight:600}
.review .letterlist .txt{color:var(--ink-2);margin-top:2px;white-space:pre-wrap}
.review .letter .foot{display:flex;align-items:center;gap:8px;padding:10px 12px;border-top:1px solid var(--rule);background:var(--active)}
/* the viewer on the second click (ruling § 32): it fills the page — documents · the page · what was read */
.review.vfull{grid-template-columns:200px minmax(0,1fr) 400px;grid-template-rows:auto 1fr}
.review.vfull .vtop{grid-column:1/4;display:flex;align-items:center;gap:12px;padding:8px 12px;border-bottom:1px solid var(--rule);background:var(--sheet);font-size:13px}
.review.vfull .vdocs{border-right:1px solid var(--rule);overflow:auto;padding:0 8px 8px}
.review.vfull .vdoc{padding:7px 9px;border:1px solid var(--rule);border-radius:5px;margin-bottom:6px;cursor:pointer;font-size:12.5px}
.review.vfull .vdoc .n{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.review.vfull .vdoc.sel{background:var(--accent-soft);border-color:var(--accent)}
.review.vfull .vpage{display:flex;flex-direction:column;min-height:0;background:var(--ground)}
.review.vfull .vfacts{border-left:1px solid var(--rule);overflow:auto;font-size:13px}
.review.vfull .vfacts .hd{border-top:1px solid var(--rule)}
.review.vfull .vfacts .hd:first-child{border-top:0}
.kv2{display:grid;grid-template-columns:110px 1fr;gap:6px;padding:4px 0;border-bottom:1px solid var(--rule-2);font-size:13px;align-items:baseline}
.kv2 .k{color:var(--ink-3)}
.kv2.hit{cursor:pointer}
.kv2.hit:hover{background:var(--active)}
.kv2.on{background:var(--accent-soft)}
.chip.acc{background:var(--accent-soft);color:var(--accent);border-color:transparent}
.chip.ok{background:var(--ok-soft);color:var(--ok)}
.review .viewer{overflow:auto;display:flex;flex-direction:column;background:var(--ground)}
.review .viewer .bar{padding:8px 12px;border-bottom:1px solid var(--rule);display:flex;gap:10px;align-items:center;font-size:13px;background:var(--sheet);flex-wrap:wrap}
.review .viewer .bar .cache{color:var(--ink-3);font-size:var(--fs-meta)}
.review .viewer .bar .tabs{display:flex;gap:6px;margin-left:auto}
.review .viewer .stagearea{flex:1;display:flex;align-items:center;justify-content:center}
.mockpage{position:relative;width:420px;height:560px;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.15);border:1px solid var(--rule);font-size:11px;color:#777;padding:30px 24px;overflow:hidden}
.mockpage .l{height:7px;background:#e6e6e6;margin:9px 0;border-radius:3px}
.mockpage .l.w60{width:60%}.mockpage .l.w80{width:80%}.mockpage .l.w40{width:40%}.mockpage .l.w70{width:70%}
.mockpage .box{position:absolute;border:2px solid var(--bbox);box-shadow:0 0 0 3px rgba(0,207,255,.25)}
/* PageViewer (Story 2.5c): the real page image from GET /api/runs/{id}/pages/{file}/{n} — the box is
   the finding's `box` at box/1000 of the image, so the overlay tracks the picture at any width. */
.pageview{flex:1;display:flex;flex-direction:column;min-height:0}
.pageview .pagebar{display:flex;gap:6px;align-items:center;justify-content:center;padding:6px;border-bottom:1px solid var(--rule);background:var(--sheet)}
.pageview .pagebar .n{font-size:12.5px;color:var(--ink-2);min-width:92px;text-align:center}
.pageview .stage{flex:1;overflow:auto;display:flex;align-items:flex-start;justify-content:center;padding:12px}
.pageview .sheet{position:relative;display:inline-block;max-width:100%;box-shadow:0 2px 8px rgba(0,0,0,.15);border:1px solid var(--rule);background:#fff}
/* Story 2.22: the image keeps using the width it is given — `max-width:100%` of the
   column, never the page's reading measure, and the zoomed 840 px opts out of even
   that and scrolls inside `.stage`. The measure above was chosen so that the 420 px
   sheet is never the thing that shrinks. */
.pageview .sheet img{display:block;width:420px;max-width:100%;height:auto}
.pageview .sheet.zoomed img{width:840px;max-width:none}
.pageview .sheet .box{position:absolute;border:2px solid var(--bbox);box-shadow:0 0 0 3px rgba(0,207,255,.25);pointer-events:none}
/* Story 9.5 (W-013″, 05_components Delta 2026-09-15): every placed item of the manual's specimen is
   drawn on open, each carrying the manual's own number; one is `hot` and the rest stay drawn. */
/* Story 9.7b (ruling § 60, third): one token, `--bbox-manual`, on the numbered box, its badge, the hot
   state and `.nrow.on`. The **unnumbered** `.box` above is untouched and stays #00cfff. */
.pageview .sheet .box.numbered{border-color:var(--bbox-manual);box-shadow:0 0 0 3px var(--bbox-manual-soft);opacity:.8;pointer-events:auto;cursor:pointer}
.pageview .sheet .box.numbered .bn{position:absolute;top:-9px;left:-9px;min-width:16px;height:16px;padding:0 3px;border-radius:9px;background:var(--bbox-manual);color:#fff;font:600 11px/16px var(--mono);text-align:center;box-shadow:0 1px 3px rgba(0,0,0,.35)}
.pageview .sheet .box.numbered:hover{opacity:1}
.pageview .sheet .box.hot{opacity:1;border-width:3px;box-shadow:0 0 0 4px rgba(0,207,255,.45),0 0 0 9999px rgba(0,0,0,.08)}
/* the hot numbered one is the **same** red, stronger: a 3px border and a wider, denser ring */
.pageview .sheet .box.numbered.hot{box-shadow:0 0 0 5px var(--bbox-manual-ring),0 0 0 9999px rgba(0,0,0,.08)}
.pageview .sheet .box.numbered.hot .bn{background:var(--bbox-manual);color:#fff;box-shadow:0 0 0 2px #fff,0 1px 3px rgba(0,0,0,.35)}
.pageview .thumbs{display:flex;gap:6px;padding:6px;overflow-x:auto;border-top:1px solid var(--rule);background:var(--sheet)}
.pageview .thumb{border:1px solid var(--rule);border-radius:4px;background:var(--sheet);padding:2px;cursor:pointer;font:inherit;font-size:11px;color:var(--ink-3);display:flex;flex-direction:column;align-items:center}
.pageview .thumb.sel{border-color:var(--accent);background:var(--accent-soft)}
.pageview .thumb img{display:block;width:46px;height:auto}
.pageview.error,.pageview.note{align-items:center;justify-content:center}
.pageview .msg{margin:auto;color:var(--ink-2);font-size:13px;text-align:center;padding:24px;max-width:420px}
.review .right{border-left:1px solid var(--rule);overflow:auto;font-size:13.5px}
.review .right details{border-bottom:1px solid var(--rule)}
.review .right details>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px;padding:10px 12px;font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);font-weight:600;background:var(--active)}
.review .right details>summary::before{content:"▸";font-size:11px}
.review .right details[open]>summary::before{content:"▾"}
.review .right details>summary .cnt{margin-left:auto;font-family:var(--mono);font-size:11.5px;letter-spacing:0;text-transform:none;color:var(--ink-2)}
.review .right details>summary select{margin-left:6px;height:24px;font-size:12px;border:1px solid var(--rule);border-radius:4px;text-transform:none;letter-spacing:0}
.review .right .body{padding:10px 12px}
.frow{border:1px solid var(--rule);border-radius:5px;padding:8px 10px;margin-bottom:8px;background:var(--sheet)}
.frow.sel{border-color:var(--accent);background:var(--accent-soft)}
.frow .hd{display:flex;gap:6px;align-items:center;flex-wrap:wrap;font-size:12.5px;cursor:pointer}
.frow .hd b{font-family:var(--mono);font-size:12px}
.frow .reason{margin:4px 0}
.frow .sopq{color:var(--ink-3);font-size:var(--fs-meta)}
/* Story 5.2 — เทียบรอบก่อน: the per-row mark and the summary line above the rows. Restyling never
   edits a component: the marks are drawn by P-017's row and the toggle is CompareToggle's own. */
.cmark{font-size:var(--fs-meta);padding:1px 6px;border-radius:9px;border:1px solid var(--rule);white-space:nowrap}
.cmark.new{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}
.cmark.same{color:var(--ink-3)}
.cmark.gone{color:var(--ink-3);border-style:dashed}
.cmp-line{font-size:var(--fs-meta);color:var(--ink-2);padding:4px 0 8px;border-bottom:1px solid var(--rule);margin-bottom:8px}
/* a *หายไป* row is the previous round's: read-only text, no page link and no control at all —
   its bytes and page images were purged at the verdict and again at start_round (FR20). */
.frow.gone{background:transparent;border-style:dashed;opacity:.85}
.frow.gone .hd{cursor:default}
.frow.gone .mem{color:var(--ink-3)}
.frow .decided{font-size:var(--fs-meta);margin-top:6px;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.frow .decide{margin-top:6px;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.frow .decide input{flex:1;min-width:120px;height:26px;padding:0 8px;border:1px solid var(--rule);border-radius:5px;font-size:12.5px}
.frow .decide .err{color:var(--fail);font-size:var(--fs-meta)}
.review .summary{grid-column:1/4;display:flex;align-items:center;gap:var(--s2);padding:10px 14px;border-top:1px solid var(--rule);background:var(--sheet);flex-wrap:wrap}
.review .summary .counts{display:flex;gap:12px;font-size:13.5px}
.review .summary .spacer{flex:1}
.review .summary .next .lbl{color:var(--ink-3);font-size:var(--fs-meta);margin-right:8px}
.compare{grid-column:1/4;padding:8px 14px;background:var(--active);border-top:1px solid var(--rule);font-size:13px}

/* ── P-022 deliver ── */
.deliver .outcome{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
.deliver .sheet{border:1px solid var(--rule);border-radius:var(--radius);padding:12px}
.deliver .sheet h4{font-size:13px;margin-bottom:6px;display:flex;gap:8px;align-items:center}
.deliver .sheet ul{padding-left:18px;font-size:13px;color:var(--ink-2)}
.verdict{display:flex;gap:var(--s2);align-items:center;margin-top:var(--s2);padding:12px 14px;background:var(--active);border-radius:var(--radius)}
.verdict .lbl{font-size:13.5px}
.verdict .btnrow{margin-left:auto}
.verdict .btnrow .gate{display:inline-flex;flex-direction:column;align-items:flex-end;gap:2px}
/* ── the letter (Story 2.16): P-017's compact draft, and P-022's whole page in the fund's layout ── */
.review .letter .foot{flex-wrap:wrap;row-gap:6px}
.review .letter .foot .btn{white-space:nowrap;margin-left:auto}
.review .letter .lhead{padding:6px 8px 4px;font-size:12.5px;line-height:1.4}
.review .letter .lhead .muted{color:var(--ink-3)}
.review .letter .deadline{padding:4px 8px 8px}
.review .letter .err{margin:0 8px 6px;font-size:12.5px}
.letterview{background:#fff;color:#000;border:1px solid var(--rule);border-radius:var(--radius);padding:26px 32px;max-width:820px;margin:0 auto;font-family:'Sarabun','TH Sarabun New','Thonburi','Tahoma',sans-serif;font-size:14px;line-height:1.5}
.letterview .fund{text-align:center}
.letterview .fund .th{font-weight:700;font-size:16px}
.letterview .fund .en{font-size:11px}
.letterview .title{text-align:center;font-weight:700;font-size:16px;margin:14px 0 2px}
.letterview .programme{text-align:center;font-weight:600;margin-bottom:8px}
.letterview .date{text-align:right}
.letterview table.fields{border-collapse:collapse;margin:6px 0 10px}
.letterview table.fields th{text-align:left;font-weight:600;padding:1px 12px 1px 0;white-space:nowrap;vertical-align:top}
.letterview p.body{text-indent:2.5em;text-align:justify;margin:6px 0}
.letterview table.items{width:100%;border-collapse:collapse;margin:10px 0 12px}
.letterview table.items th,.letterview table.items td{border:1px solid #000;padding:5px 8px;vertical-align:top;text-align:left}
.letterview table.items th{text-align:center;font-weight:700}
.letterview table.items td.n{text-align:center;width:3em}
.letterview table.items td.reply{width:38%}
.letterview .who{font-weight:600}
.letterview .txt{white-space:pre-wrap;margin-top:2px}
.letterview .hint{margin-top:8px}
.letterview .note{margin:12px 0 18px}
.letterview .signatures{display:flex;justify-content:space-between;gap:24px;margin:20px 0 14px}
.letterview .signatures .block{width:46%;text-align:center}
.letterview .signatures .name{margin-top:34px}
.letterview .closing{font-weight:700;margin-top:6px}
.letterview .closing .em{font-style:italic;font-weight:400}
.letterview .seal{margin-top:20px;text-align:right}
.letterview .attachment{margin-top:10px}
.deliver .card-title .meta{margin-left:8px}

/* ── SOP editor (P-006) — the approved document editor (design § 27) ── */
:root{--ed-bg:var(--sheet);--ed-fs:16px;--ed-head:var(--accent);--ed-val:var(--val);--ed-val-bg:var(--val-soft);--ed-hint:var(--hint);--ed-hint-bg:var(--hint-soft);--ed-badge:var(--badge);--ed-badge-bg:var(--badge-bg)}
.sop{display:grid;grid-template-columns:270px 1fr;gap:var(--s2);height:calc(100vh - var(--header-h) - 40px - 48px);min-height:0}
.sop.gate-open{grid-template-columns:270px 1fr 360px}
.rail{background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);overflow:auto;padding:8px 0;min-width:0;box-shadow:var(--shadow)}
.rail .grp{display:flex;justify-content:space-between;padding:12px 18px 4px;font-size:12px;font-weight:600;color:var(--ink-3);letter-spacing:.02em}
.rail a{display:flex;align-items:center;gap:8px;padding:6px 18px 6px 16px;text-decoration:none;color:var(--ink-2);border-left:3px solid transparent;font-size:14px}
.rail a:hover{background:var(--active)}
.rail a.on{color:var(--accent);background:var(--accent-soft);border-left-color:var(--accent);font-weight:500}
.rail a .n{color:var(--ink-3);min-width:40px;font-size:13px;font-variant-numeric:tabular-nums}
.rail a.on .n{color:var(--accent)}
.rail a .t{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail a.sub{padding-left:38px}                       /* Story 8.6: a ##### sub-table of ภาคผนวก ค, one indent deeper */
.rail a .pg{color:var(--ink-3);font-size:11.5px;font-family:var(--mono);white-space:nowrap;flex:none}   /* Story 8.9: the page the heading prints — the address a ค-6 sub-table has instead of our B-0N handle */
.rail a .c{color:var(--ink-3);font-size:12px;font-family:var(--mono);white-space:nowrap;flex:none}
.rail a .dot{width:7px;height:7px;border-radius:50%;background:var(--hint);display:none;flex:none}
.rail a.issues .dot{display:inline-block}
.edcard{background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden;box-shadow:var(--shadow)}
/* Story 8.9 — the toolbar is ONE row. It wrapped behind a long section title (ค-9's ข-3 pushed ดูไฟล์
   and + ข้อตรวจ onto a second line, walk-pre-2026-09-18 § D): a flex item's floor is its content, so a
   title that cannot shrink spends the row and the controls fall off it. The fix is `.page-title h1`'s,
   three hundred lines above and unchanged since Story 2.20 — the title takes the squeeze and ellipses,
   the controls keep their width. */
.edhead{display:flex;align-items:center;gap:6px;padding:10px 14px;border-bottom:1px solid var(--rule);flex-wrap:nowrap}
.edhead h2{font-size:var(--fs-title);margin:0 auto 0 0;font-weight:700;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.edhead .sep{width:1px;height:20px;background:var(--rule);margin:0 4px}
.editor{flex:1;min-height:0;min-width:0;position:relative;overflow:hidden}
.cm-editor{height:100%;width:100%;font-size:var(--ed-fs)}
.cm-editor.cm-focused{outline:none}
.cm-content{padding:12px 0 40vh}
.cm-line{padding:0 20px 0 12px}
.cm-gutters{font-family:var(--mono)}
.cm-lineNumbers .cm-gutterElement{padding:0 12px 0 8px;font-size:12px}
.cm-panel.cm-search{padding:8px 12px}
.cm-panel.cm-search input,.cm-panel.cm-search button{font:inherit;font-size:13px;border:1px solid var(--rule);border-radius:4px;padding:2px 8px;background:var(--sheet)}
.cm-searchMatch{background:var(--hint-soft)}
.sm-h2{font-size:1.45em;font-weight:700;color:var(--ed-head);padding-top:.9em}
.sm-h3{font-size:1.25em;font-weight:700;color:var(--ed-head);padding-top:.6em}
.sm-h4{font-size:1.1em;font-weight:700;color:var(--ed-head);padding-top:.4em}
.sm-h5{font-weight:700;color:var(--ed-head)}
.sm-pg{font-size:.75em;color:var(--ink-3);font-weight:400;margin-left:.6em;font-family:var(--mono)}
.sm-b{font-weight:700}
.sm-code{font-family:var(--mono);font-size:.88em;background:var(--rule-2);border-radius:3px;padding:0 3px}
.sm-badge{display:inline-block;font-family:var(--mono);font-size:.78em;color:var(--ed-badge);background:var(--ed-badge-bg);border:1px solid var(--rule);border-radius:4px;padding:0 6px;margin-right:8px;vertical-align:1px;user-select:none}
.sm-head{padding-top:.5em}
.sm-label{color:var(--ink-3)}
.sm-prop{padding-left:36px}
.sm-val{color:var(--ed-val);background:var(--ed-val-bg);border-bottom:1px dotted var(--ed-val);border-radius:2px;padding:0 2px;font-variant-numeric:tabular-nums}
.sm-bullet{color:var(--ink-3);display:inline-block;width:1.2em}
.sm-list{padding-left:28px}
.sm-hr{color:var(--rule);letter-spacing:.3em}
.sm-raw .cm-line{font-family:var(--mono);font-size:.92em}
/* Story 8.9 — the manual's own tables have up to eight columns and nothing under any of them, so when
   the columns' min-content widths add up to more than the table may be, the browser stops honouring
   min-content and breaks inside words. Thai has no spaces inside a word, so *มีในแบบฟอร์ม* came apart
   as มีใน/แบบ/ฟอร์/ม and `[[C015]]` over three lines (walk-pre-2026-09-18 § D). The floor goes under the
   things that are one word — the header cells, and a `[[…]]` reference — and the wide prose columns
   absorb the squeeze, which is what `table-layout:auto` does with the room that is left. No width is
   named and no `word-break` is set: `break-all` would be the same defect spelled deliberately. */
.sm-tbl{border-collapse:collapse;margin:8px 0 10px 12px;font-size:.92em;line-height:1.55;max-width:calc(100% - 32px)}
.sm-tbl th,.sm-tbl td{border:1px solid var(--rule);padding:5px 10px;vertical-align:top;text-align:left}
.sm-tbl th{background:var(--active);font-weight:600;color:var(--ink-2);white-space:nowrap}
.sm-tbl [contenteditable]:focus{outline:2px solid var(--accent);outline-offset:-2px;background:var(--accent-soft)}
.cm-lintRange-warning{background-image:none;text-decoration:underline wavy var(--ed-hint);text-decoration-skip-ink:none;text-underline-offset:3px}
.cm-tooltip{background:var(--sheet);border:1px solid var(--rule);border-radius:6px;box-shadow:var(--shadow);font-size:13.5px}
.cm-tooltip-lint{padding:4px 6px;max-width:360px}
.cm-diagnostic{padding:6px 8px;border-left:3px solid var(--ed-hint);margin:2px 0}
.cm-diagnosticSource{color:var(--ink-3);font-family:var(--mono);font-size:11px}
.cm-diagnosticAction{background:var(--accent-soft);color:var(--accent);border:1px solid transparent;border-radius:4px;padding:2px 9px;margin:6px 6px 0 0;font:inherit;font-size:13px;cursor:pointer}
.cm-diagnosticAction:hover{border-color:var(--accent)}
/* Story 8.6 — a `[[…]]` reference is marked (never hidden: GRAMMAR.md § 8 keeps the brackets in the
   file), and hovering one that resolves offers ไปที่เป้าหมาย. Ruling § 54. */
.sm-ref{color:var(--accent);border-bottom:1px dotted var(--accent);cursor:pointer;white-space:nowrap}
.sm-reftip{display:flex;align-items:center;gap:10px;padding:5px 8px;white-space:nowrap}
.sm-reftip-what{color:var(--ink-3);font-size:12.5px}
.sm-reftip-go{background:var(--accent-soft);color:var(--accent);border:1px solid transparent;border-radius:4px;padding:2px 9px;font:inherit;font-size:13px;cursor:pointer}
.sm-reftip-go:hover{border-color:var(--accent)}
.cm-lintPoint{display:none}
.gatepanel{background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);padding:14px;display:flex;flex-direction:column;gap:12px;overflow:auto;min-width:0;box-shadow:var(--shadow)}
.gatepanel .ghead{display:flex;align-items:center;justify-content:space-between}
.gatepanel .stage{font-size:var(--fs-meta);color:var(--ink-3)}
.gatepanel .stage .err{color:var(--ed-hint)}
.gatepanel .result{font-size:13px;padding:8px 10px;border-radius:var(--radius);background:var(--active)}
.gatepanel .result.ok{background:var(--ok-soft);color:var(--ok)}
.gatepanel .result.err{background:var(--fail-soft);color:var(--fail)}
.gatepanel .steps{display:grid;grid-template-columns:auto 1fr auto;gap:3px 10px;font-size:12.5px}
.gatepanel .steps .t{color:var(--ink-3)}
.gatepanel .diff{display:grid;grid-template-columns:auto 1fr;gap:3px 10px;margin-top:4px;font-variant-numeric:tabular-nums}
.gatepanel .diff .add{color:var(--ok);font-weight:600}
.gatepanel .diff .rem{color:var(--fail);font-weight:600}
.gatepanel .diff .same{color:var(--ink-3)}
.evalrow{display:flex;justify-content:space-between;font-size:12px;padding:2px 0}
.evalrow.bad{color:var(--fail)}
.fileview{font-family:var(--mono);font-size:12px;line-height:1.6;white-space:pre-wrap;counter-reset:ln;margin:0;max-height:75vh;overflow:auto}
.fileview span{display:block}
.fileview span::before{counter-increment:ln;content:counter(ln);display:inline-block;width:40px;color:var(--ink-3);opacity:.6}
.fileview span.chg{background:var(--ed-hint-bg)}

/* ── admin console (§ 41–§ 46): Credentials · Users · Models ── */
.trace{list-style:none;font-family:var(--mono);font-size:12px}
.trace li{padding:3px 0;border-bottom:1px dashed var(--rule)}

/* One content column for the whole console: the title, the checklist and every card share both edges */
.adminpage{max-width:980px}
.adminpage .card{max-width:none}

/* SetupChecklist — the same strip on all three pages; the only thing that says the instance is ready */
.checklist{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s1);margin-bottom:var(--s2)}
.checklist .cl-step{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1px solid var(--rule);border-radius:var(--radius);background:var(--sheet);text-decoration:none;color:var(--ink)}
.checklist .cl-step.here{border-color:var(--accent);background:var(--active)}
.checklist .cl-step .n{width:22px;height:22px;flex:none;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:600;background:var(--rule-2);color:var(--ink-3)}
.checklist .cl-step.done .n{background:var(--ok);color:#fff}
.checklist .cl-step b{font-weight:600;font-size:13.5px}
.checklist .cl-step .meta{margin-left:auto;font-size:12px;color:var(--ink-3)}

/* one row per secret / per model role: the state is stated in the head, never guessed from the fields */
.card.provider .card-title h3,.card.modelrole .card-title h3,.card.created .card-title h3{font-size:var(--fs-card);font-weight:600;margin:0}
.rowstate{font-size:12.5px;font-weight:600;color:var(--ink-3)}
.rowstate.ok{color:var(--ok)}
.rowstate.none{font-weight:400}
.card.modelrole .row>*{flex:1}
select.input option:disabled,.field select option:disabled{color:var(--ink-3)}

/* Create a user — the password sits with its Generate button, the primary action stands alone */
.card.createuser .pwfield{display:flex;gap:8px;align-items:flex-end}
.card.createuser .pwfield .field{flex:1;margin-bottom:0}
.card.createuser .pwfield .btn{margin-bottom:2px}

/* the created account's one-time password */
.card.created{border-color:var(--ok)}
.pwline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pwline b{font-size:15px;letter-spacing:.02em}
/* .kept — deleted with the KeptLine component (Story 2.25, ruling § 71) */

/* ProposedFactsTable (P-021, § 37) — lifted out of app.js by Story 2.3. Equal-width action cells so
   the two conflict buttons and the plain รับ / แก้ pair line up down the column. */
.facts-tbl td.src{white-space:normal}
.facts-tbl tr.blank td .none{font-style:italic}
.facts-tbl tr.warn td{background:var(--hint-soft)}
.facts-tbl td .actions{display:flex;gap:6px;justify-content:flex-end}
.facts-tbl td:last-child{width:1%;white-space:nowrap}
/* Story 2.28 ([[walk-pre-2026-09-18]] § D) — the columns were left to `table-layout:auto` over five
   columns, three of which have a fixed floor: the actions cell is `width:1%` + `nowrap` around two
   buttons of `min-width:110px`, so it claims ~230px whatever else needs the room. What gave way was
   the two narrow ones: *ชื่อโครงการ* and *เลขผู้เสียภาษี* broke over two lines in the label column
   and a file name in *ที่มา* broke over four. Both now hold a floor of their own — the label column
   shrinks to its longest label and never wraps, ที่มา keeps a fifth of the table and still wraps
   (a file name is longer than any sensible column) — and the slack comes out of เสนอจากเอกสาร and
   ปัจจุบัน, which are the two that can use it. */
.facts-tbl th:first-child,.facts-tbl td:first-child{width:1%;white-space:nowrap}
/* ST-19.2: a ✗ row's condition under its label wraps within the label's width (the twin's long conditions — the date after the last receipt,
   the amount on the three — would otherwise widen the column under the viewer and hide ผล) */
.fields-card .facts-tbl td:first-child .sub{white-space:normal}
.facts-tbl th:nth-child(4),.facts-tbl td.src{width:20%}
/* the `cannot_check` row (Story 2.5c): no P / F control — what it needs is the fact it names */
.frow .decide.cannot{color:var(--ink-3)}
/* Story 9.5 — NumberedList (W-013″): the manual's numbered places, in the manual's order. The row is
   a FindingRow in everything but its head — the number, the manual's words, one chip — so the decide
   and remark blocks below it are the `.frow` ones verbatim. */
.numbered .nrow{border:1px solid var(--rule);border-radius:5px;padding:7px 10px;margin-bottom:6px;background:var(--sheet);cursor:pointer}
.numbered .nrow.on{border-color:var(--bbox-manual);box-shadow:0 0 0 2px var(--bbox-manual-soft)}
.numbered .nrow.sel{border-color:var(--accent);background:var(--accent-soft)}
.numbered .nrow .hd{display:flex;gap:6px;align-items:center;flex-wrap:wrap;font-size:12.5px}
.numbered .nrow .hd .nn{flex:none;min-width:18px;height:18px;border-radius:9px;background:var(--badge-bg);color:var(--badge);font:600 11px/18px var(--mono);text-align:center}
.numbered .nrow.on .hd .nn{background:var(--bbox-manual);color:#fff}
/* Story 9.7b — **the printed number** (ADR-0020): the fund's own number for the same box, shown small
   beside the canonical one and only where the two differ (*3 · หน้านี้ 1*). */
.numbered .nrow .hd .np{flex:none;color:var(--ink-3);font-size:11px;font-family:var(--mono)}
/* Story 9.7b — **a row this form does not have** (ruling § 60, first): present so the list is the same
   nine everywhere, greyed, and carrying nothing to press. */
.numbered .nrow.na{background:var(--active);border-style:dashed;cursor:default}
.numbered .nrow.na .hd b{font-weight:500;color:var(--ink-3)}
.numbered .nrow.na .hd .nn{background:var(--rule-2);color:var(--ink-3)}
.numbered .nrow.na .hd .np{color:var(--ink-3)}
.numbered .nrow.na .na-note{color:var(--ink-3);font-size:var(--fs-meta)}
.numbered .nrow .hd b{font-weight:600}
.numbered .nrow .reason{margin:3px 0 0;color:var(--ink-2);font-size:12.5px}
.numbered .nrow .noplace{margin-top:3px;color:var(--ink-3);font-size:var(--fs-meta)}
/* Story 12.5 (ruling § 82) — item ①'s register block: two labelled names, the register's own
   standing word after a `·`, and the day it was asked. The sub-line pattern `.noplace` uses, given
   a label column. At 1366 px the viewer's right rail is ≈ 340–400 px, so the **value** is what
   wraps — `min-width:0` lets a flex item shrink below its content, `overflow-wrap:anywhere` breaks
   a long unspaced Thai name — and the standing word after the dot is never cut off or ellipsised.
   No width is declared and no breakpoint rule is added — nothing Story 2.22's measure
   adds up moves (`test_the_measure.py`, which counts that at-rule in the raw text, comments
   included, so this sentence may not spell it). */
.numbered .nrow .reg{margin:3px 0 0;font-size:12.5px;color:var(--ink-2)}
.numbered .nrow .reg .l{display:flex;gap:6px;align-items:baseline}
.numbered .nrow .reg .l .k{flex:none;color:var(--ink-3);font-size:var(--fs-meta)}
.numbered .nrow .reg .l .v{flex:1;min-width:0;overflow-wrap:anywhere}
.numbered .nrow .reg .when{margin-top:2px;color:var(--ink-3);font-size:var(--fs-meta);overflow-wrap:anywhere}
/* the *ตรวจไม่ได้* register row's own line, above the decision it now offers */
.numbered .nrow [data-register-self]{margin-top:6px}
.numbered .nrow .decided,.numbered .nrow .decide{font-size:var(--fs-meta);margin-top:6px;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.numbered .nrow .decide input{flex:1;min-width:120px;height:26px;padding:0 8px;border:1px solid var(--rule);border-radius:5px;font-size:12.5px}
.numbered .nrow .decide .err{color:var(--fail);font-size:var(--fs-meta)}
.numbered .nrow .decide.cannot{color:var(--ink-3)}


/* ============================================================================================
   MVP02 additions (2026-09-24, round 17 — the owner: "reuse and keep theme consistent").
   Everything above this line is MVP01's web/library.css, byte for byte. Below: only what MVP01
   has no rule for — the responsive shell, two page layouts, the receipt page's rows, the five-step
   stepper's extras. Every colour and size is a token or a value from the file above.
   scripts/proto_classes.py refuses any class the pages use that is defined in neither part.
   ============================================================================================ */

/* handles: the names the walk records and proto_check press — no style of their own */
.back-overview,.back-to-receipt,.nav-prev,.nav-next,.next-step,.close-round,.return-round,.not-a-receipt,.place-file,.mark-as-receipt,.rerun,.reload-page,.toggle,.used-with,.program-chip,.req-found,.req-missing,.req-unsure,.req-card,.project-card,.files-card,.fields-card,.copy-row,.payee-row,.line-table,.file-list,.receipt-table,.receipt-docs,.hide-narrow,.hide-mid,.narrow-only,.users,.ledger{}

/* the shell: fluid (DR-2) and responsive (rulings 2026-09-24); the crumb in the header; the drawer button */
.shell{min-width:0;height:auto;min-height:100vh}
.main>*{max-width:none}
.header .menu-btn{display:none}
.header .crumb{display:flex;gap:var(--s1);color:var(--ink-3);min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13.5px}
.header .crumb a{color:var(--ink-3);text-decoration:none}
.header .crumb b{color:var(--ink);font-weight:500}
.nav [data-role="admin"]{display:none}
.shell.role-admin .nav [data-role="admin"]{display:block}
.nav-backdrop{display:none}
.signin form .btnrow{margin-top:var(--s2)}

/* the segmented choice (P-003 the programme, P-004 the งวด): MVP01's .btn.on, the buttons joined, a ✓ on the chosen one (DR-12) */
.seg{display:inline-flex;margin-top:4px}
.seg .btn{border-radius:0;margin-left:-1px}
.seg .btn:first-child{border-radius:5px 0 0 5px;margin-left:0}
.seg .btn:last-child{border-radius:0 5px 5px 0}
.seg .btn.on{position:relative;z-index:1;font-weight:600}
.seg .btn.on::before{content:"✓"}
.seg .btn .meta{color:inherit;opacity:.7}
.field label .muted{margin-left:6px;font-weight:400}
.field input.num,.table input.num{text-align:right;font-variant-numeric:tabular-nums}   /* an amount in a table row lines up under its right-aligned head (P-003 งวด · แผนการเงิน, looked at 2026-09-26) */

/* เริ่มงวด (P-004, DR-15): one row of two cards at one height, then one column */
.start-layout{display:grid;grid-template-columns:1fr;grid-template-areas:"main" "side" "below";gap:var(--s2);align-items:stretch}
.start-main{grid-area:main;min-width:0}.start-side{grid-area:side;min-width:0}.start-below{grid-area:below;min-width:0;display:flex;flex-direction:column;gap:var(--s2)}
.start-main>.card,.start-side>.card{height:100%}
.card.folded>.table{display:none}
.card .lead.sa-line{margin:2px 0 6px}
.sa{font-family:var(--mono);font-size:12px;background:var(--badge-bg);color:var(--ink-2);padding:1px 6px;border-radius:3px}
.seen .btn{margin-left:auto}

/* the round's five pages: the counts card; a table inside a card without the card's padding */
.counts{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;font-size:var(--fs-card);font-weight:600}
.counts .meta{margin-left:auto;font-weight:400}
.card.flush{padding:0}
.card.flush>.card-title,.card.flush>h3{padding:10px 14px;margin:0;border-bottom:1px solid var(--rule)}
.card.flush.folded>h3{border-bottom:0}
.card.flush>h3>.toggle{font:inherit;color:inherit;height:auto;padding:0;white-space:normal;text-align:left}   /* ② เอกสารที่ต้องมี: the card's title is its fold line (ST-35.2) */
.card.flush>.empty{margin:0}
.table.hairline{border:0}
.table .sub{display:block;font-size:var(--fs-meta);color:var(--ink-3);font-weight:400}
.table .sub.narrow-only{display:none}
.table .sub.ok-t{color:var(--ok)}.table .sub.fail-t{color:var(--fail)}.table .sub.hint-t{color:var(--hint)}   /* a sub line's colour word wins over its grey (ST-39.4) */
.table td b{font-weight:600}
.table tr.total td{font-weight:600;border-top:1px solid var(--rule)}
.table tr.clickable td{cursor:pointer}
.ledger .table tr.dim td:first-child{padding-left:28px}
.ledger .table tr.dim td{font-size:var(--fs-meta);border-bottom:1px solid var(--rule-2)}

/* the receipt page (W-005): row 1 the bar, row 2 the head, then the field list left and the viewer card right */
.receipt-bar{display:flex;align-items:center;gap:var(--s1);margin-bottom:6px}
.receipt-bar .pos{margin-left:auto;display:flex;align-items:center;gap:var(--s1)}
.receipt-bar .where{color:var(--ink-3);font-size:13.5px;font-variant-numeric:tabular-nums;margin-right:4px}
.receipt-head{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;margin-bottom:var(--s2);padding-bottom:var(--s1);border-bottom:1px solid var(--rule)}
.receipt-head .title{font-size:var(--fs-title);font-weight:600}
.receipt-head .answer{margin-left:auto;display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:6px 10px}
.split{display:grid;grid-template-columns:minmax(420px,34%) 1fr;gap:var(--s2);align-items:start}
.split .left{display:flex;flex-direction:column;gap:var(--s2);min-width:0}
/* the split's widen toggle (05 § Delta 2026-09-26 — the owner's #5: "Left column should expandable to read on wider space (shrink right
   column to the right)"): ⇔ on the left card's head swaps the columns to ~60 % · ~40 %; below 1024 px the split is one column, so no toggle */
.split.wide{grid-template-columns:minmax(0,60%) minmax(0,1fr)}
.btn.small.split-toggle{font-family:var(--mono);min-width:30px;justify-content:center}
@media (max-width:1023px){.btn.small.split-toggle{display:none}}
/* the field list: MVP01's numbered rows (.numbered .nrow — P-017's item rows) in a flush card */
.card.flush>.numbered{padding:8px}
.nrow .val{margin-top:3px;color:var(--val);font-weight:500;font-size:12.5px}
.nrow .val.none{color:var(--ink-3);font-weight:400}
.nrow .hd .chip{margin-left:auto}
.nrow:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* the viewer card: MVP01's review viewer bar, unscoped, with its tabs; the page fits the height (the owner's W-005) */
.viewer{background:var(--sheet);border:1px solid var(--rule);border-radius:var(--radius);box-shadow:var(--shadow);overflow:hidden;position:sticky;top:calc(var(--header-h) + 12px);min-width:0;display:flex;flex-direction:column}
.viewer .bar{padding:8px 12px;border-bottom:1px solid var(--rule);display:flex;gap:10px;align-items:center;font-size:13px;background:var(--sheet);flex-wrap:wrap}
.viewer .bar .tabs{display:flex;gap:6px}
.viewer .bar .meta{margin-left:auto}
.viewer .pageview .stage{overflow:auto;max-height:calc(100vh - var(--header-h) - 150px);padding:8px;background:var(--ground)}
.viewer .pageview .sheet img{width:auto;height:calc(100vh - var(--header-h) - 200px);max-width:100%}
.viewer .pageview .sheet.zoomed img{height:auto;width:840px;max-width:none}
.viewer .pageview .sheet .box.numbered{pointer-events:auto;cursor:pointer}
.viewer .pageview .sheet .box.numbered.hot{opacity:1}
/* the required documents (RequiredDocs) rows in the second tab: .kv2's rhythm, the file at the right */
.reqdocs .lead{padding:8px 12px;border-bottom:1px solid var(--rule-2);font-size:var(--fs-meta)}
.req-row{display:grid;grid-template-columns:96px 1fr auto;gap:var(--s1);padding:8px 12px;border-bottom:1px solid var(--rule-2);align-items:center;font-size:13.5px}
.req-row:last-child{border-bottom:0}
.req-row .doc b{display:block;font-weight:500}
.req-row .doc span{font-size:var(--fs-meta);color:var(--ink-3)}
.req-row .act{display:flex;gap:var(--s1);align-items:center;justify-content:flex-end;flex-wrap:wrap}
.req-row .act a{font-family:var(--mono);font-size:12.5px}
.reqdocs .done{padding:10px 12px;color:var(--ok);font-weight:600}

/* the five-step stepper (MVP01's .stepper): a failed step, a disabled step, the compact form on the receipt's bar */
.stepper .step .m{min-height:1.4em}
.stepper .step.fail .n{background:var(--fail);border-color:var(--fail);color:#fff}
.stepper .step.fail .t,.stepper .step.fail .m{color:var(--fail)}
.stepper .step[aria-disabled="true"]{cursor:default}
.stepper.compact{margin:0 var(--s2);padding:4px;flex:1;max-width:560px;box-shadow:none;background:transparent;border:none}
.stepper.compact .step{gap:2px}
.stepper.compact .step .n{width:20px;height:20px;font-size:11px}
.stepper.compact .step .t{font-size:11.5px}
.stepper.compact .step:not(:last-child)::after{top:10px;left:calc(50% + 12px);right:calc(-50% + 12px)}

/* the receipt table between 1024 and 1279 px: six columns do not fit an 812 px main column */
@media (max-width:1279px){
  .receipt-table .hide-mid{display:none}
  .receipt-table .sub.narrow-only{display:block}
}
.adminpage .card{overflow-x:auto}
.table .actions .btn{min-width:0}

/* ---- narrow (< 1024 px): one block, last, so no rule above outranks it ---- */
@media (max-width:1023px){
  .shell{grid-template-columns:1fr}
  .header{padding:0 12px;gap:10px}
  .header .menu-btn{display:inline-flex;width:var(--btn-h);padding:0;font-size:18px}
  .header .who{display:none}
  .nav{position:fixed;top:var(--header-h);left:0;bottom:0;width:var(--nav-w);z-index:15;transform:translateX(-100%);transition:transform .15s;box-shadow:none}
  .shell.nav-open .nav{transform:none;box-shadow:var(--shadow)}
  .nav-backdrop{position:fixed;inset:var(--header-h) 0 0 0;background:rgba(20,24,32,.3);z-index:14}
  .shell.nav-open .nav-backdrop{display:block}
  .main{grid-column:1;padding:var(--s2)}
  .header .crumb > *{display:none} .header .crumb > :last-child{display:inline}
  .two{grid-template-columns:1fr}
  .table .hide-narrow{display:none}
  .table .sub.narrow-only{display:block}
  .req-row{grid-template-columns:90px 1fr;grid-auto-rows:auto}
  .req-row .act{grid-column:2;justify-content:flex-start}
  .stepper{padding:8px 4px}
  .stepper .step .t{font-size:11.5px;white-space:normal}
  .stepper .step .m{display:none}
  .stepper.compact{display:none}
  .split,.split.wide{grid-template-columns:1fr}
  .split .left{display:contents}
  .viewer{position:sticky;top:calc(var(--header-h) + 4px);z-index:4;order:-1}
  .viewer .pageview .stage{max-height:42vh}
  .viewer .pageview .sheet img{height:38vh}
  .sop,.sop.gate-open{grid-template-columns:1fr;height:auto}
  .rail{max-height:30vh}
  .editor{height:60vh}
  .checklist{grid-template-columns:1fr}
  .row{flex-direction:column}
  .modal{width:auto;max-width:96vw}
}

/* ---- phone width (< 768 px): the four things that break there ---- */
@media (max-width:767px){
  .seg{display:flex;flex-wrap:wrap}
  .seg .btn{flex:1 1 auto}
  .page-title h1{white-space:normal}
  .page-title .meta{white-space:normal;flex-shrink:1;width:100%}
  .page-title .actions{margin-left:0;width:100%;flex-wrap:wrap}
  .page-title .actions .btn{flex:1 1 auto}
  .kv{grid-template-columns:1fr;gap:2px 12px}
  .kv dd{overflow-wrap:anywhere;min-width:0;margin-bottom:6px}
  .nrow .hd{flex-wrap:wrap}
  .linkrow{flex-wrap:wrap}
  .linkrow .input{flex:1 1 100%}
  .seen{flex-wrap:wrap}
  .seen .btn{margin-left:0}
}

/* ---- revision round (2026-09-25, 05_components § Delta 2026-09-25): variants of MVP01 rules only ---- */
.differs,.fix,.return-letter,.checks,.timeline,.fit,.list-scroll,.point-kv,.doc-facts,.need-required,.need-optional,.need-skip{}
/* the plan bar: MVP01's .progress; ≥ 90 % of the budget in --hint, over it in --fail */
.progress.hint>i{background:var(--hint)}
.progress.fail>i{background:var(--fail)}
.table .progress{min-width:120px}
/* a table whose columns never move while rows fill (feedback row 3): widths from <col> */
.table.fixed{table-layout:fixed}
.table.fixed td{overflow-wrap:anywhere}
/* the งวด timeline on the dashboard is MVP01's stepper with several meta lines; on narrow it turns vertical and keeps them */
.stepper.timeline .step .m{white-space:normal}
/* the round's three checks: MVP01's .row of cards, one height, spaced as cards are */
.row.checks{margin:var(--s2) 0;align-items:stretch}
.row.checks>.card+.card{margin-top:0}
@media (max-width:1023px){
  .stepper.timeline{flex-direction:column;align-items:stretch;gap:10px;padding:12px}
  .stepper.timeline .step{flex-direction:row;flex-wrap:wrap;align-items:baseline;text-align:left;gap:4px 10px}
  .stepper.timeline .step .m{display:block;width:100%;padding-left:36px}
  .stepper.timeline .step:not(:last-child)::after{display:none}
}
/* the return letter prints alone */
@media print{
  .header,.nav,.nav-backdrop,.stepper,.page-title,.main>*:not(#content),#content>*:not(.letter-split),.letter-split>*:not(.return-letter),.return-letter .actions,.return-letter .btn{display:none!important}
  .letter-split{display:block!important}.letter-split>.return-letter{display:block!important;position:static;max-height:none;overflow:visible}
  .shell{display:block}.main{padding:0}.return-letter{box-shadow:none;border:0}
}

/* the page viewer fits the column's width (the owner: "proper zoom document level"); the zoom sets the sheet's width in % of the column */
.pageview .sheet.fit{flex:none;max-width:none;display:block;margin:0 auto}
.pageview .sheet.fit img,.viewer .pageview .sheet.fit img{width:100%;height:auto;max-width:none}
.viewer .pageview .stage{display:block;max-height:calc(100vh - var(--header-h) - 140px)}
/* the start page: the action and โครงการ side by side from 1024 px, one height (round 15); the file list scrolls after 8 rows */
@media (min-width:1024px){.start-layout{grid-template-columns:3fr 2fr;grid-template-areas:"main side" "below below"}}
.list-scroll{max-height:360px;overflow:auto}
.list-scroll thead th{position:sticky;top:0;z-index:1}
.table .input{width:100%;min-width:0}
/* Check Receipt A inside a point: MVP01's dl.kv with a narrower label column */
.nrow .point-kv{grid-template-columns:150px 1fr;gap:3px 10px;font-size:13px;margin-top:4px}
.nrow .point-kv dd{min-width:0}
/* section B: one row layout, three looks — required (accent bar), optional (dashed bar, softer ink), skip (grey) */
.doc-facts{grid-template-columns:110px 1fr;margin:0 0 10px;padding:8px 10px;background:var(--active);border-radius:5px}
.req-row.need-required{border-left:3px solid var(--accent);padding-left:8px}
.req-row.need-optional{border-left:3px dashed var(--ink-3);padding-left:8px;color:var(--ink-2)}
.req-row.need-skip{border-left:3px solid var(--rule);padding-left:8px;color:var(--ink-3)}
.req-row.need-skip .doc b{font-weight:500;color:var(--ink-3)}
/* เหตุผล: a point's rule lines one under another, never run together (Story 9.1, looked at on the engine's lines) */
.req-row .doc span{display:block}
@media (max-width:767px){.card .card-title{flex-wrap:wrap}}   /* a card title keeps its words on one line at 500 px; the meta and the actions flow below it (P-017 แผนการเงิน, looked at 2026-09-26) */

/* ---- the refinement (Story 10.0, 2026-09-26 — 04_wireframes W-003 · W-004 · W-005 · W-013 … W-021): variants of the rules above ---- */
.clickable{cursor:pointer}   /* MVP01's tr.clickable, on a column head and a stacked card too */

/* the stepper's sub-steps (W-004): a band joined under the five steps, a caret pointing up at the live step */
.stepper.with-subs{margin-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0;box-shadow:none}
.substeps{position:relative;background:var(--active);border:1px solid var(--rule);border-top:1px solid var(--rule-2);border-radius:0 0 var(--radius) var(--radius);padding:10px 12px 11px;margin-bottom:var(--s2);box-shadow:var(--shadow)}
.substeps::before{content:"";position:absolute;top:-8px;left:var(--caret,50%);width:14px;height:14px;background:var(--active);border-left:1px solid var(--rule-2);border-top:1px solid var(--rule-2);transform:rotate(45deg)}
.subgroup{display:flex;flex-wrap:wrap;gap:4px 6px;justify-content:center}
.substep{display:inline-flex;align-items:center;gap:8px;padding:4px 13px 4px 5px;border-radius:999px;text-decoration:none;color:var(--ink-2);font-size:13.5px;font-weight:500;border:1px solid transparent;white-space:nowrap;line-height:1.3}
.substep .n{font:600 11.5px/1 var(--mono);color:var(--ink-3);background:var(--sheet);border:1px solid var(--rule);border-radius:999px;padding:4px 7px}
.substep:hover{background:var(--sheet);border-color:var(--rule);color:var(--accent)}
.substep.live{background:var(--sheet);border-color:var(--accent);color:var(--accent);font-weight:600}
.substep.live .n{background:var(--accent);border-color:var(--accent);color:#fff}
.substep.done{color:var(--ink)}
.substep.done .n{background:var(--ok-soft);border-color:transparent;color:var(--ok)}
.substep.done .n::before{content:"✓ "}


/* 1.2 · 1.4 — receipts as columns (the workbook's layout): the row names stay put while the columns scroll */
.matrix-scroll{overflow-x:auto}
.table.matrix{border-collapse:separate;border-spacing:0}
.table.matrix th.rowhead{position:sticky;left:0;z-index:1;text-align:left;min-width:250px;border-right:1px solid var(--rule)}
.table.matrix tbody th.rowhead{background:var(--sheet);font-size:13.5px;font-weight:500;color:var(--ink);vertical-align:top}
.table.matrix thead th{vertical-align:bottom;padding:10px 12px}
.table.matrix .colhead{min-width:180px;font-size:13.5px;color:var(--ink);font-weight:600;border-left:1px solid var(--rule-2)}
.table.matrix .colhead .sub{font-weight:400}
.table.matrix .colhead:hover{background:var(--accent-soft)}
.table.matrix td{border-left:1px solid var(--rule-2);padding:9px 12px;vertical-align:top}
.table.matrix tbody tr:hover td,.table.matrix tbody tr:hover th.rowhead{background:var(--active)}
.table.matrix td.c-miss,.table.matrix tbody tr:hover td.c-miss{background:var(--fail-soft)}

/* 1.3 — C's three checks, one per line: RequiredDocs' .req-row (the verdict chip · the workbook's sentence · the numbers) */
.card.checks{margin-bottom:var(--s2)}
.req-row>.chip{justify-self:start}
.table tr.total td{background:var(--active)}

/* 500 px: tables become one .card per receipt with a dl.kv */
.narrow-stack{display:none}

/* the receipt (W-005) and the form (W-021): MVP01's Decision on the item's own line — the system's chip, her answer (.decided), the pair (.decide) */
.nrow .hd .decided,.nrow .hd .decide,.facts-tbl .decided,.facts-tbl .decide{margin:0;display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--ink-3);vertical-align:middle}
.nrow .hd .decided .chip{margin-left:0}
.facts-tbl .decided+.decide{margin-left:6px}
.nrow .hd .decide .btnrow,.facts-tbl .decide .btnrow{gap:4px}
.nrow .hd .decide .btn.small,.facts-tbl .decide .btn.small{height:22px;padding:0 8px;font-size:12px;color:var(--ink-3);background:transparent}
.nrow:hover .decide .btn,.nrow.sel .decide .btn,.facts-tbl tr:hover .decide .btn,.facts-tbl tr.sel .decide .btn{color:var(--ink-2);background:var(--sheet)}
.nrow .hd .decide .btn.on,.facts-tbl .decide .btn.on{color:var(--accent);background:var(--accent-soft);border-color:var(--accent)}
/* the whole receipt's / form's decision (owner 14:15): .btn.primary · .btn.danger; the chosen one keeps .btn.on's look on hover */
.receipt-head .answer .btn.on{font-weight:600}
.btn.primary.on:hover,.btn.danger.on:hover{background:var(--accent-soft);color:var(--accent);filter:none}

/* ④ one form: the rows on the left take the room, the form's page on the right; the rows are MVP01's .facts-tbl with FieldList's number */
.split.form-split{grid-template-columns:minmax(560px,60%) 1fr}
.facts-tbl td{vertical-align:top}
.facts-tbl .nn{display:inline-block;min-width:18px;height:18px;margin-right:8px;border-radius:9px;background:var(--badge-bg);color:var(--badge);font:600 11px/18px var(--mono);text-align:center;vertical-align:1px}
.facts-tbl tr.sel .nn{background:var(--bbox-manual);color:#fff}
.facts-tbl .sub{margin-left:26px}
.facts-tbl .val{color:var(--val);font-weight:500}
/* a signature / stamp image (P-003 picked · P-017 Master data · P-021 read and master) */
.crop{display:block;height:46px;width:auto;border:1px solid var(--rule);border-radius:4px;background:#fff}
.crop.sig{max-width:130px}.crop.stamp{height:62px}
.form-split .pageview .sheet .box.numbered{opacity:.28}
.form-split .pageview .sheet .box.numbered.hot{opacity:1}

/* ⑤ the letter, on its sheet; the fund's column is edited in place before it is sent */
.letterview.return-letter{box-shadow:var(--shadow);margin-bottom:var(--s3)}
.letterview p.body{line-height:1.7;text-align:left}
.letterview table.fields td{padding:1px 28px 1px 0}
.letterview td[contenteditable="true"]{cursor:text}
.letterview td[contenteditable="true"]:hover{background:var(--active)}
.letterview td[contenteditable="true"]:focus{outline:2px solid var(--accent);outline-offset:-2px;background:#fff}

/* ข้อมูลโครงการ (W-017): the plan's หมวด row (05 § Delta 2026-09-25: tr.group) */
.table tr.group td{background:var(--active);font-size:13px;color:var(--ink-2)}
.stepper.timeline .step .t{font-size:13.5px}

/* สร้างโครงการ (W-003): the one computed field */
.field.computed output{display:flex;align-items:center;justify-content:flex-end;height:var(--btn-h);padding:0 10px;border:1px dashed var(--rule);border-radius:5px;background:var(--active);font-variant-numeric:tabular-nums;font-weight:600}

/* ④ the form's own page, drawn as the fund's form looks (formSheets in library.js): sized in the page's width (cqw), so it follows the zoom */
.pageview .sheet .fpage{position:relative;container-type:inline-size;background:#fdfcf7;color:#26221c}
.pageview .sheet .fpage[hidden]{display:none}
.fpage.a4{aspect-ratio:1000/1414;overflow:hidden}
.fpage.xls{background:#fff}
.fp{font-family:Sarabun,"Noto Sans Thai",sans-serif;font-size:2.15cqw;line-height:1.6}
.fpage.a4 .fp{position:absolute;inset:0;padding:6cqw 7.5cqw 6cqw}
.fp p{margin:0}
.fp-lh{display:flex;justify-content:space-between;align-items:flex-start;padding-bottom:1.6cqw;border-bottom:.2cqw solid #2f5d8a}
.fp-logo{width:11cqw;height:11cqw}
.fp-addr{text-align:right;font-size:.9em;line-height:1.45}
.fp-addr b{font-size:1.15em}
.fp-date{text-align:right;margin:3.4cqw 0 2.6cqw}
.fp-line{display:grid;grid-template-columns:7cqw 1fr;margin-bottom:1cqw}
.fp-para{text-indent:8cqw;margin-top:1.8cqw!important}
.fp-signrow{display:flex;justify-content:space-between;align-items:flex-start;margin-top:3.6cqw;gap:4cqw}
.fp-signrow>div:first-child,.fp-dotbox{flex:none}
.fp-dotbox{position:relative;display:block;width:21cqw;height:21cqw;border:.3cqw dotted #6b6457;font-size:.78em;color:#6b6457;text-align:center;padding-top:.8cqw;line-height:1.3}
.fp-stamp{position:absolute;left:1.5cqw;top:2cqw;width:18cqw;height:18cqw}
.fp-signer{flex:1;text-align:center;max-width:46cqw}
.fp-sigline{display:block;width:30cqw;margin:.6cqw auto 0;border-bottom:.25cqw dotted #6b6457}
.fp-sig{display:block;width:100%;height:10cqw}
.fp-att{position:absolute;left:7.5cqw;bottom:6cqw;font-size:.9em;line-height:1.7}
.fp-cb{display:inline-block;width:1.9cqw;height:1.9cqw;border:.2cqw solid #26221c;margin-right:.8cqw;vertical-align:-.25cqw;font-size:1.7cqw;line-height:1.7cqw;text-align:center;font-weight:700}
.fp-head{display:flex;justify-content:space-between;align-items:flex-start;padding-bottom:1.2cqw;margin-bottom:2.4cqw;border-bottom:.25cqw solid #1f4e8c}
.fp-brand{display:flex;flex-direction:column;line-height:1.15}
.fp-brand b{font:800 4cqw/1 system-ui,sans-serif;letter-spacing:.2cqw;color:#1f4e8c}
.fp-brand span{font-size:1.35cqw;color:#1f4e8c}
.fp-conf{font-size:.82em;color:#9a1f1f}
.fp-footer{position:absolute;left:0;right:0;bottom:3cqw;text-align:center;font-size:.8em;color:#6b6457}
.fp-title{text-align:center;font-weight:700;font-size:1.2em;line-height:1.45;margin-bottom:1.6cqw}
.fp-kv{display:flex;flex-direction:column;gap:.5cqw;font-size:.95em}
.fp-two{display:grid;grid-template-columns:1fr 1fr;gap:3cqw}
.fp-ol{margin:0;padding-left:5cqw}
.fp-sec{margin-top:1.2cqw}
.fp-gap{margin-top:2.4cqw;gap:1.6cqw}
.fp-ind{padding-left:5cqw}
.fp-tbl{width:100%;border-collapse:collapse;table-layout:fixed;font-size:.7em;line-height:1.3;margin-top:1cqw}
.fp-tbl th,.fp-tbl td{border:.15cqw solid #4a4438;padding:.4cqw .6cqw;text-align:left;vertical-align:top;font-weight:400}
.fp-tbl th{background:#e9e4d4;font-weight:600;text-align:center;vertical-align:middle}
.fp-tbl td.fp-on{background:#7ea3cc}
.fp-note{margin-top:3cqw;font-size:.85em}
.fp-staff{border:.3cqw solid #26221c;padding:2.6cqw 3cqw;display:flex;flex-direction:column;gap:2.6cqw}
.fp-staff>div{display:flex;align-items:flex-end;gap:1cqw}
.fp-dots{flex:1;display:block;min-height:2.6cqw;border-bottom:.25cqw dotted #6b6457}
.fp-staffsign{justify-content:flex-end;gap:4cqw!important;margin-top:4cqw}
.fp-staffsign .fp-dots{flex:none;width:28cqw}
.fp-xls{width:100%;border-collapse:collapse;table-layout:fixed;font-size:1.62cqw;line-height:1.3}
.fp-xls td{border:.1cqw solid #d0d0d0;padding:.35cqw .6cqw;height:2.7cqw;vertical-align:bottom;overflow-wrap:anywhere}
.fp-xls td.fp-rh{background:#f1f1f1;color:#777;text-align:center;font-size:.85em;border-color:#c4c4c4}
.fp-xls .fp-colh td{height:2.2cqw}
.fp-xls .fp-ttl{font-weight:700;font-size:1.2em}
.fp-xls .fp-lbl{font-weight:600}
.fp-xls .fp-hd{background:#dfe8f3;font-weight:600;text-align:center;vertical-align:middle}
.fp-xls .fp-cat{background:#f6f1de;font-weight:600}
.fp-xls .fp-sub{font-weight:700;background:#fff7d6}
.fp-xls .fp-n,.fp-xls td.fp-n{text-align:right;font-variant-numeric:tabular-nums}
.fp-xls td .fp-n{display:block;text-align:right}
.fp-xls .fp-hd.fp-n{text-align:right}
.fp-xls .fp-tot td:not(.fp-rh){font-weight:700;border-top:.25cqw double #555}

@media (max-width:1279px){.split.form-split{grid-template-columns:1fr 1fr}}
@media (max-width:1023px){
  .pad-field{display:none}
  .split.form-split{grid-template-columns:1fr}
  .form-split .viewer{order:1;position:static}
}
@media (max-width:767px){
  .wide-only{display:none!important}
  .narrow-stack{display:block}
  .stepper:not(.timeline) .step:not(.live) .t{display:none}
  .subgroup{justify-content:flex-start}
  .substep:not(.live) .t{display:none}
  .substep{padding:4px 5px}
  .substep.live{padding-right:12px;white-space:normal}
  .letterview{padding:16px 14px}
  .letterview table.fields th{white-space:normal}
  .letterview table.items td.reply,.letterview table.items th:last-child{display:none}
  .facts-tbl thead{display:none}
  .facts-tbl tr{display:grid;grid-template-columns:1fr 1fr;border-bottom:1px solid var(--rule-2)}
  .facts-tbl td{border:0}
  .facts-tbl td:first-child,.facts-tbl td:last-child{grid-column:1/3;width:auto;white-space:normal}
  .receipt-head .answer{margin-left:0;width:100%;justify-content:flex-start}
  .btnrow.end>.next-step{flex:1}
}

/* ⑤ สรุปงวด (W-015, Delta 2026-09-26 13:50 — MVP01's review page): the cards of the letter's items left, the letter right, live;
   MVP01's InstructionBox (.instr > .row.between (label · ร่างโดยAI .chip.mdl) + .ed) in each card, unscoped from .review;
   an approved card folds to its .card-title */
.letter-split{display:grid;grid-template-columns:minmax(440px,40%) 1fr;gap:var(--s2);align-items:start}
.letter-cards{display:flex;flex-direction:column;gap:var(--s2);min-width:0}
.letter-split>.return-letter{max-width:none;width:100%;margin:0;position:sticky;top:calc(var(--header-h) + 12px);max-height:calc(100vh - var(--header-h) - 24px);overflow:auto}
.letter-card .card-title{font-weight:600;margin-bottom:8px}
.instr .row.between{justify-content:space-between;align-items:center;margin-bottom:6px}
.instr .row.between>*{flex:none}
.letter-card .chip.mdl{background:var(--val-soft);color:var(--val);border-color:transparent}
.letter-card.done{padding:10px var(--s2)}
.letter-card.done>.card-title{margin:0}
.letter-tabs{display:none}
/* Story 10.13 (the owner's #15): the left column's two tabs รายการแก้ไข · รายการถูกต้อง — the viewer bar's .tabs of .btn */
.letter-cards>.tabs{display:flex;gap:6px;flex-wrap:wrap}
.letter-foot{display:none}
@media (max-width:1023px){
  .letter-split{grid-template-columns:1fr}
  .letter-split>.return-letter{position:static;max-height:none}
}
@media (max-width:767px){
  .letter-tabs{display:flex;gap:6px;margin-bottom:var(--s2)}
  .letter-tabs .btn{flex:1}
  .letter-split:not(.show-letter)>.return-letter,.letter-split.show-letter>.letter-cards{display:none}
  .page-title .letter-actions{display:none}
  .letter-foot{display:flex;flex-direction:column;gap:8px;align-items:stretch}
  .letter-foot .btn{width:100%;flex:none}
  .letter-foot .stale{margin:0;text-align:center}
  .letter-card.done>.card-title{flex-wrap:wrap}
}
.letter-cards>.card+.card{margin-top:0}

/* ---- web's own (Story 10.1): the served pages' looks added these; the prototype's stylesheet above does not carry them ---- */
.seen{flex-wrap:wrap}   /* the account chip and the permission flow onto a second line in the 3/5 column rather than breaking inside the chip (Story 2.3b, looked at) */
.req-card td.mono{white-space:nowrap}   /* a form code never breaks across lines at 480 px (Story 2.3b, looked at) */
.files-card .card-title{flex-wrap:wrap}   /* the title, the chip and the meta flow onto two lines at 480 px instead of breaking the title (Story 2.3b, looked at) */
.req-row .act .err{color:var(--fail);font-size:var(--fs-meta)}
.req-row .act .err:empty{display:none}
/* P-006 (Story 4.4): the file's first page small in the modal's .empty slot — the placeholder text stays when the page cannot be shown */
.modal .two .empty{padding:12px}
.modal .two .empty img{display:block;max-width:100%;max-height:44vh;margin:0 auto;border:1px solid var(--rule)}
/* P-017 (Story 7.4) until Story 10.2 ports the prototype's page */
.next-card,.plan-card{}
.next-card{margin-bottom:var(--s2)}
@media (max-width:767px){
  .page-title{flex-wrap:wrap}
  .counts .btnrow{flex-wrap:wrap;justify-content:flex-end}   /* P-012's stopped line on two lines at 480 (Story 2.4b, looked at) */
  .table.users th,.table.users td{white-space:nowrap}   /* Story 1.5's look at 480: one line per row; .adminpage .card scrolls sideways */
}
/* Story 1.7's look at 600 and 480: .editor is `flex:1 1 0%` in .edcard, a column flex box with no definite height once .sop is
   `height:auto` — the island ran 71,000 px tall; flex:none lets the 60vh rule hold; the wide layout (>= 1024) is untouched. */
@media (max-width:1023px){
  .editor{flex:none}
}

/* ST-33.1 (09_release-3.6 § D): on the receipt page สิ่งที่ต้องทำต่อ / แก้ไข is the fifth column and สรุป the last — the wrapping 22 % moves
   to the fifth; สรุป takes the room its pair needs; above the release-3 block, which stays the prototype's byte for byte
   (tests/architecture/test_release3_stylesheet_block.py) — these selectors outrank its rules. ST-34.1 (09 § E "③'s and ④'s tables share one
   renderer"): the shared review table (round.js reviewTable, .six.review-tbl) on ③ and ④ alike; ④ keeps ST-19.10's narrow rule (F-339,
   RUL-2026-10-07-7 "at narrow widths the fix wraps under the row at full width") on its สิ่งที่ต้องทำต่อ / แก้ไข cell, and
   ผลการวิเคราะห์ above it full width too (no empty half beside it) */
main .facts-tbl.six.review-tbl .decided .muted{white-space:nowrap}
/* ST-41.1 (F-500 · F-507 · F-509; 09 § D · E): a decided row's สรุป (round.js decideCell, review mode, [data-review]) is one line — the
   system's word grey (.muted) only where hers differs, her mark, · the name — never wrapping, so the column is as wide as the line; the
   ผ่าน · ไม่ผ่าน pair on the line under it. On ③'s and ④'s review table and on 4.3's receipt table (a plain .table) alike */
/* ST-42.1 (F-515; RUL-2026-10-26-1 · -2): an undecided review row's first line, AI แนะนำ: and the mark's chip ([data-ai]), one line, and the
   pair the same place under it, while she writes too — the cell keeps one shape and one width */
main [data-review]>.decided,main .facts-tbl.six.review-tbl [data-review]>.decided{display:flex;flex-wrap:nowrap;white-space:nowrap;align-items:baseline;gap:4px;margin:0;font-size:12px;color:var(--ink-3)}
main [data-review]>.decided+.decide,main .facts-tbl.six.review-tbl [data-review]>.decided+.decide,main [data-review]>[data-ai]+.decide,main .facts-tbl.six.review-tbl [data-review]>[data-ai]+.decide{display:flex;margin:4px 0 0}
main [data-review]>[data-ai],main .facts-tbl.six.review-tbl [data-review]>[data-ai]{display:block;white-space:nowrap;margin:0;font-size:12px;color:var(--ink-3)}
main [data-review]>[data-ai] .chip{margin-left:0}
main [data-review]>.decide .btnrow{flex-wrap:nowrap;white-space:nowrap}
@media (min-width:768px){
  main .facts-tbl.six.review-tbl th:nth-child(5),main .facts-tbl.six.review-tbl td:nth-child(5){white-space:normal;width:22%}
  main .facts-tbl.six.review-tbl th:last-child,main .facts-tbl.six.review-tbl td:last-child{width:1%}
}
/* ST-34.3 (09 § E): 4.3's receipt-table card, eight columns, is a grid item that may shrink below its table — the table scrolls inside
   the card (.matrix-scroll) instead of widening the page at a narrow width */
main .form-split [data-section=receipt-table]{min-width:0}
@media (max-width:767px){
  main[data-page="P-021"] .facts-tbl.six.review-tbl td:nth-child(4),main[data-page="P-021"] .facts-tbl.six.review-tbl td[data-field=todo]{grid-column:1/-1;width:auto;white-space:normal}
}
/* ST-41.2 (RUL-2026-10-25-3; 09 § D): the receipt head's result in place of its ผ่าน / ไม่ผ่าน (round.js reviewHead) — the rows' result in
   the head's weight, beside ยืนยันผลการตรวจ › */
.receipt-head .answer [data-head-result]{font-weight:600;font-size:14px;font-variant-numeric:tabular-nums}
/* ---- Release 3 (2026-10-05, F-93 — the release-3 pages r3-*.html rebuilt on this library; 05_components Delta 2026-10-05) ----
   .indent — a page inside a file, its row indented under the file's row (live demo #1, the owner: "indent the rows only").
   .facts-tbl.six — the six key headers (the owner, 2026-09-28): the last column, สิ่งที่ต้องทำต่อ / แก้ไข, wraps instead of holding one line.
   .fund-letter · .fixline — the fund's real letter (live demo #5): the header row grey, the item heading plain, each fix line blue. */
.table td.indent{padding-left:32px}
.table td.slot{white-space:nowrap}   /* a slot's ID (R1-a) on one line */
.facts-tbl.six th:last-child,.facts-tbl.six td:last-child{white-space:normal;width:22%}
.facts-tbl.six th:nth-child(4){width:auto}
.facts-tbl.six td{vertical-align:top}
/* ST-19.10 (F-339; RUL-2026-10-07-7 "at narrow widths the fix wraps under the row at full width; 1728 unchanged"): the narrow grid gives the
   last cell the row's width — the 22 % above held it to a narrow column beside the selected row's band */
@media (max-width:767px){
  .facts-tbl.six td:last-child{grid-column:1/-1;width:auto;white-space:normal}
}
.letterview.fund-letter table.items th{background:#d9d9d9;font-weight:400}
.letterview.fund-letter .who{font-weight:400}
.letterview .fixline{color:#1f3fbf}
/* the UX review 2026-10-05 night (prototypes/mvp02/walks/ux-review-2026-10-05.md) — sizes a person can use
   tr.note-row — the advisor's เหตุผล in the InstructionBox (.instr > .ed), a full-width row under the item it answers (U1); the whole
   receipt's / form's เหตุผล the same box in a .card under the head (U2) */
.table tr.note-row td{padding:8px 12px 12px;background:var(--sheet)}
.table tr.note-row .instr .ed,[data-whole-note] .instr .ed{font-size:14px;min-height:72px}
[data-whole-note]{margin:0 0 12px}
[data-whole-note] .instr{padding:12px 14px}
/* the decision pair in the six columns — a 30 px target (U5) */
.facts-tbl.six .decide .btn.small{min-height:30px;padding:4px 12px}
/* รายการที่ขอเบิก — the line reads in either split (U4): the หมวด select capped, the line's text and amount given room, the deduction one line */
.line-table select{max-width:165px}
.line-table .input.grow{min-width:120px;width:100%}
.line-table .input.num{width:108px}
.line-table th,.line-table td{padding-left:8px;padding-right:8px}
.line-table tr[data-deduction] td{white-space:nowrap}
/* 3.3 ส่วนที่ออกเอง — a tick box a person can hit (U9) */
input[type=checkbox][data-field=own_share]{width:18px;height:18px}
/* 3.3 รายละเอียด — the columns hold still (ST-41.3; F-506): a fixed layout with set head widths; the amount box 130 px, and unticked the
   "—" in a box of the same width, so a tick, a typed amount or an untick moves no column. At 500 px the hide-narrow columns drop and the
   layout is the browser's again (fixed widths leave the plan and payee columns no room there); the own cell keeps one width either way */
.table.detail-table{table-layout:fixed}
.detail-table th.w-code{width:72px}
.detail-table th.w-date{width:150px}
.detail-table th.w-money{width:132px}
.detail-table th.w-own{width:186px}
.detail-table th.w-proof{width:190px}
.detail-table .own-cell{flex-wrap:nowrap}
.detail-table .own-cell .input.num,.detail-table .own-cell .own-none{width:130px;flex:none;box-sizing:border-box}
.detail-table .own-cell .own-none{display:inline-block;padding:0 10px;text-align:right}
@media (max-width:767px){
  .table.detail-table{table-layout:auto}
  .detail-table th.w-code,.detail-table th.w-money,.detail-table th.w-own{width:auto}
  .detail-table th,.detail-table td{padding-left:5px;padding-right:5px}
  .detail-table .own-cell{gap:4px}
  .detail-table .own-cell .input.num,.detail-table .own-cell .own-none{width:84px;padding:0 4px}
}
