
:root{--w-1:.25rem;--w-2:.5rem;--w-3:.75rem;--w-4:1rem;--w-5:1.25rem;--w-6:1.5rem;--w-fs-1:.72rem;--w-fs-2:.78rem;--w-fs-3:.85rem}
/* ── R1/R7 — .field, the ONE bound-pair component (Design §3.1 rule 4) ──────────
   A label and the control it names, a heading and the intro line it opens, a
   <summary> and the body it discloses: all the same relationship, all 8px, all
   WRAPPED rather than left adjacent. Wrapping is the point. While the label was a
   sibling of its control, "8px" depended on whether the parent was flex or a plain
   block and whether the label wrapped the control or sat beside it — which is how ONE
   relationship came to measure 8.0 / 7.1 / 0.0 / 0.0 on one page. Inside .field there
   is no sibling relationship left to get wrong.
   Destined for controller/pkg/webui (plan ae08b98e S2, a mesh-wide re-release); it
   lives here until then so plug-steps can be fixed without re-releasing 60 plugs. */
.field{display:flex;flex-direction:column;gap:var(--w-2)}
.field>*{margin:0}
/* A .field's label when the label is not a <label> element (a group's name, an entry's
   header row). Blockified by the flex column, so its box is the LINE box and the 8px
   below it is 8px of actual whitespace — not 8px minus half-leading. */
.field-label{font-weight:600}
/* ── R6 — .step-page, the page column ──────────────────────────────────────────
   Its children are SECTIONS, and a section break is where a heading's breathing room
   lives: 24px ABOVE the heading, never below it (Design §1.1). This is the answer to
   "below a subtitle there is less spacing than below text" — the binding under the
   heading stays tight (8px, R7) and the room goes above. */
.step-page{display:flex;flex-direction:column;gap:var(--w-6)}
.step-page>*{margin:0}
/* R4/R5/R9/R10 — the blocks inside one section, one rhythm, no exceptions. */
.section{display:flex;flex-direction:column;gap:var(--w-4)}
.section>*{margin:0}
/* R8b — a DIVIDED list (the twelve step rows): peers separated by a rule plus their own
   padding rather than by a gap, exactly the argument R10 makes for cards. Gap is 0 and
   the audit asserts both the 0 and the presence of the rule. */
.list-divided{display:flex;flex-direction:column;gap:0}
/* .step-form is the ONE layout every step widget's card uses. Its gap is the SINGLE
   source of vertical rhythm between the card's blocks (heading, hint, banner, list,
   form, footer link) — child margins are zeroed, exactly the trick BaseCSS already uses
   for .form-grid>label, and the reason the two old layout models can't drift apart
   again. Works identically whether the .card keeps its box (queue page) or has it
   neutralised (.step-widget-body on the all-steps view). */
.step-form{display:flex;flex-direction:column;gap:var(--w-4)}
.step-form>*{margin:0}
/* A widget's list of entries (R8, peers), and one entry's box. An entry's own blocks are
   16px apart like any other block pair — its header row and the "my part" line under it
   are a BOUND pair and are wrapped in a .field to say so, rather than the whole box
   being squeezed to 8 so that one pair inside it looks right. */
.step-form-list{display:flex;flex-direction:column;gap:var(--w-2)}
.step-form-item{border:1px solid var(--border2);padding:var(--w-2) var(--w-3);display:flex;flex-direction:column;gap:var(--w-4)}
.step-form-item>*{margin:0}
/* The row wraps, and its title takes a real flex BASIS rather than "auto + min-width:0".
   With min-width:0 alone the title could shrink to a sliver while its words kept their
   intrinsic width, so at 412px an amends entry's link ran UNDER the "Mark amends made"
   button. A basis makes the line genuinely overfull instead, so the control drops to its
   own line; overflow-wrap catches a single unbreakable word. */
.step-form-row{display:flex;align-items:center;gap:var(--w-2);flex-wrap:wrap}
.step-form-row>strong,.step-form-row>a{flex:1 1 8rem;min-width:0;overflow-wrap:anywhere}
/* The muted secondary line under an entry's header row (my-part, notes). */
.step-form-note{color:var(--muted);font-size:var(--w-fs-3);white-space:pre-wrap}
/* A stack of complete fields inside one form (R3, 16px) — NOT the label→control gap,
   which belongs to .field and is 8. Getting these two confused is what let R1's tight
   binding leak past the pair it owned: with this container at 8, the gap above a form's
   button row was 8 when a control preceded it and 16 when prose did, for the same button
   (Design §1.2). A button is never bound to what precedes it; at 16 here, it cannot be. */
.step-form-fields{display:flex;flex-direction:column;gap:var(--w-4)}
.step-form-fields>*{margin:0}
.step-form-fields textarea,.step-form-fields input{box-sizing:border-box;width:100%;font-family:inherit}
/* A wrapping row of small toggles/chips (Step 5's three admissions). It is a row of
   BUTTONS, so R9 applies above it: 16px, whatever precedes it. */
.step-form-chips{display:flex;flex-wrap:wrap;gap:var(--w-2)}
.step-form-chips>*{max-width:100%}
/* A form's trailing button row. Buttons take their NATURAL width here (as a flex row's
   children) instead of being stretched full-width by the surrounding column — which is
   why "Add entry" and "Save prayer" used to be different widths for no reason. The
   max-width/white-space override is load-bearing on a phone: .btn is nowrap, so a long
   label ("Schedule weekly inventory") measured 242.7px inside a 217.3px column at 412px
   and hung out of the card. */
.step-form-actions{display:flex;flex-wrap:wrap;gap:var(--w-2)}
/* .btn is white-space:nowrap by design (a button label should not break mid-word in a
   toolbar), but inside a widget the container is a phone-width column: "Schedule weekly
   inventory" measured 242.7px in a 217.3px column at 412px and "Admit to Another human
   being" 301.8px against a 281.2px right edge — both hung out of the card. Wrapping the
   label is the right trade here; the .btn component keeps its nowrap default everywhere
   else. */
.step-form .btn{max-width:100%;white-space:normal}
/* The house .field-row (webui FormControlsCSS) gives its input flex:1 1 12rem but leaves
   min-width:auto, so an <input>'s intrinsic ~20-character size wins over the flex line
   and overflows by a couple of px at phone widths. Fixed locally rather than in the
   shared component, which every plug in the mesh would have to be re-released for. */
.step-form .field-row>input{min-width:0}
/* The accent-bordered callout (Step 5 progress, the amends pacing line, a reflection
   task prompt) — one padding + one type size for all of them. */
.step-form-callout{padding:var(--w-2) var(--w-3);background:var(--panel2);border-left:3px solid var(--primary);font-size:var(--w-fs-3)}

.row{display:flex;align-items:center;gap:var(--w-2);flex-wrap:wrap}
.hint{color:var(--muted,#8b949e);font-size:var(--w-fs-3)}
.item{display:flex;gap:var(--w-3);align-items:flex-start;padding:var(--w-2) var(--w-1);border-bottom:1px solid var(--border2,#30363d)}
.item:last-child{border-bottom:none}
.num{flex:0 0 2rem;height:2rem;width:2rem;display:flex;align-items:center;justify-content:center;background:var(--panel2,#0d1117);border:1px solid var(--border2,#30363d);font-weight:600;font-size:.9rem}
.item.done .num,.focus-num.done{background:var(--primary);border-color:var(--primary);color:#06210f}
/* min-width:0 is load-bearing, not tidying. A flex item defaults to min-width:auto,
   i.e. "never shrink below my content's intrinsic minimum" — so when a step's details
   dropdown expands, any wide widget inside (the Step 10 weekly-schedule grid, a long
   unbroken word, an input's default size) forced .body wider than the row and pushed
   the Complete/Reopen button off the right of a phone screen. Measured at 412px: a
   600px-wide child put the button at 762px; with min-width:0 the row holds and the
   button stays at 409px. This decouples the row from whatever any future widget
   contains, rather than chasing each wide element one at a time. */
/* The row's content column owns its own rhythm (step text → tagged note → details
   dropdown) the same way every other block container here does, instead of leaving it
   to the children's margins. */
.item .body{flex:1 1 auto;min-width:0;line-height:1.55;display:flex;flex-direction:column;gap:var(--w-4)}
.item .body>*{margin:0}
.item .toggle{flex:0 0 auto}
/* The clean count on a program card: prominent enough to read at a glance, quiet
   enough not to compete with the program name above it. */
.sob-inline{display:flex;align-items:center;gap:var(--w-2);margin:var(--w-2) 0;font-size:var(--w-fs-3)}
.sob-inline strong{font-size:1.05rem;color:var(--primary)}
.prog-bar{height:var(--w-2);background:var(--panel2,#0d1117);border:1px solid var(--border2,#30363d);overflow:hidden}
.prog-bar>span{display:block;height:100%;background:var(--primary)}
/* Match/create + queue accent boxes. A bordered, padded, backgrounded box is a CARD by
   every test except its class name, so it takes the card radius (fallback form: a bare
   var() naming an undefined property invalidates the whole declaration, and this CSS is
   inlined into pages that may not carry the token block). Its blocks are a column on the
   section rhythm rather than each child carrying its own margin — that is what kept the
   "Generate my 12 steps" form hard against the sentence above it. */
.match-note{padding:var(--w-2) var(--w-3);background:rgba(46,160,67,.10);border:1px solid var(--primary);border-radius:var(--r-card,5px);display:flex;flex-direction:column;gap:var(--w-4)}
.match-note>*{margin:0}
.match-none{background:rgba(210,153,29,.10);border-color:#d2991d}
/* The focus card is a block column like every other card: its own outer margins are gone
   (the .section container's gap places it) and its inner rhythm is one gap, not three
   different child margins. */
.focus-card{border:1px solid var(--border);background:var(--card);box-shadow:0 1px 3px rgba(0,0,0,.3);padding:var(--w-5);display:flex;flex-direction:column;gap:var(--w-4)}
.focus-card>*{margin:0}
.focus-head{display:flex;align-items:center;gap:var(--w-3)}
.focus-num{flex:0 0 2.6rem;height:2.6rem;width:2.6rem;display:flex;align-items:center;justify-content:center;background:var(--panel2,#0d1117);border:1px solid var(--primary);color:var(--primary);font-weight:700;font-size:1.15rem}
.focus-body{font-size:1.1rem;line-height:1.6}
.focus-actions{display:flex;gap:var(--w-2);flex-wrap:wrap}
.done-banner{padding:var(--w-3) var(--w-4);border:1px solid var(--primary);background:rgba(46,160,67,.10)}
.tabs{display:flex;gap:var(--w-2);flex-wrap:wrap}
input[type=text].sub-input{width:100%;max-width:26rem}
/* Per-step tagged note shown under a step in the history/list. Its caption and its body
   are a bound pair, so the box IS a .field (8px) rather than a block with a 4px caption
   margin — the caption named the body all along, the markup just never said so. */
.step-note{padding:var(--w-2) var(--w-3);border-left:3px solid var(--primary);background:var(--panel2,#0d1117)}
.step-note-label{display:block;font-size:var(--w-fs-1);color:var(--muted,#8b949e);letter-spacing:.03em}
.step-note pre{margin:0;white-space:pre-wrap;word-break:break-word;font-family:inherit;font-size:var(--w-fs-3);line-height:1.5;color:var(--text,#c9d1d9)}
/* Sobriety counter card — clean, prominent, square, green accent. One column, one gap;
   the count + "clean since" line are a bound pair and sit in a .field. */
.sobriety{text-align:center;display:flex;flex-direction:column;gap:var(--w-4)}
.sobriety>*{margin:0}
.sob-count{font-weight:800;line-height:1;color:var(--text-hi,#f0f6fc)}
.sob-count .sob-days{font-size:3rem;color:var(--primary)}
.sob-count .sob-unit{font-size:1.2rem;text-transform:uppercase;letter-spacing:.08em}
.sob-count .sob-hours{font-size:1.2rem;color:var(--muted,#8b949e)}
.sob-count.sob-unset{font-size:1.05rem;font-weight:600;color:var(--muted,#8b949e)}
.sob-sub code{background:var(--panel2,#0d1117);border:1px solid var(--border2,#30363d);padding:0 var(--w-1)}
.sob-chips{display:flex;flex-wrap:wrap;gap:var(--w-2);justify-content:center}
.sob-chip{font-size:var(--w-fs-1);padding:var(--w-1) var(--w-2);border:1px solid var(--border2,#30363d);color:var(--muted,#8b949e);opacity:.65}
.sob-chip.reached{border-color:var(--primary);color:var(--primary);opacity:1;font-weight:600}
.sob-edit{text-align:left;display:flex;flex-direction:column;gap:var(--w-2)}
.sob-edit summary{cursor:pointer;color:var(--link,#58a6ff);font-size:var(--w-fs-3);text-align:center}
.sob-form{display:flex;flex-wrap:wrap;gap:var(--w-3);align-items:flex-end;justify-content:center}
.sob-form label{font-size:var(--w-fs-3);color:var(--muted,#8b949e)}
.sob-form input{}
.sob-or{font-size:var(--w-fs-2);color:var(--muted,#8b949e);align-self:center;padding-bottom:var(--w-2)}
.sob-actions{display:flex;gap:var(--w-2)}

.refl-flash{border:1px solid rgba(46,160,67,.4);background:rgba(46,160,67,.1);color:var(--green-soft);padding:.5rem .8rem;margin:.4rem 0 1rem;font-size:.9rem}
.refl-toggle{display:inline-flex;align-items:center;gap:var(--sp-2,.5rem);cursor:pointer;font-weight:500;color:var(--text-hi)}
.capture-badge{display:inline-flex;align-items:center;gap:var(--sp-1,.25rem);padding:.05rem .4rem;;font-size:.78rem;line-height:1.4;background:rgba(88,166,255,.14);color:inherit;text-decoration:none;white-space:nowrap}a.capture-badge:hover{background:rgba(88,166,255,.26)}.capture-diary{border:1px solid rgba(88,166,255,.35)}
/* The create page. Width comes from the page (flowweb.Page.Width), not from here —
   17 plugs had each hand-written their own main{max-width} and none of them agreed. */
.refl-new h1{font-size:1.25rem;margin-bottom:var(--sp-2)}
.refl-compose{margin:1rem 0;padding:.75rem .9rem;border:1px solid var(--border2,#30363d);background:var(--card)}
.refl-compose>label{display:block;margin:0 0 .4rem;font-weight:650}
.refl-compose .refl-editor{margin:.35rem 0 .65rem}
.refl-compose .refl-editor #se-mount .toastui-editor-defaultUI{}
.refl-compose-row{display:flex;align-items:center;gap:var(--sp-3,.75rem);flex-wrap:wrap}
.refl-compose-row .btn{flex:none}
.refl-compose-row .hint{flex:1}
.refl-compose-error{color:var(--red-hi,#f85149);font-size:.82rem;width:100%}
.refl-list{display:flex;flex-direction:column;gap:var(--sp-2,.5rem);margin:1rem 0}
.refl{padding:.7rem .9rem;border:1px solid var(--border2,#30363d);background:var(--card)}
.refl-text{line-height:1.55;white-space:pre-wrap;word-break:break-word}
/* Clamp the LIST PREVIEW only — scoped to .lv-table, so it never reaches the ⓘ
   details modal (which the shared ListView appends to <body>, outside the table) or
   the editor. This list puts no length limit on a reflection, and an unclamped
   multi-paragraph entry pushed every row after it — including its own action
   buttons — arbitrarily far down the page, worst on mobile where the same text wraps
   into far more lines. The full text stays one tap away via ⓘ (AlwaysDetails) or
   Edit, so the preview clamp hides nothing that can't be opened. */
.lv-table .refl-text{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.refl-meta{display:flex;align-items:center;gap:var(--sp-2,.5rem);flex-wrap:wrap}
.refl-step{font-size:.72rem;color:var(--muted,#8b949e);padding:.05rem .4rem;border:1px solid var(--border2,#30363d)}
@media(max-width:640px){.refl-compose-row{align-items:stretch;flex-direction:column}.refl-compose-row .btn{width:100%}}
/* Reflections can be a full paragraph, so their row is far taller than the plain
   Context badge cell next to it. A <td> vertical-aligns middle by default, so
   without this the badge drifts down into the middle of the paragraph instead of
   sitting level with its first line. Scoped to THIS table only — the merged
   Action column keeps the shared component's default vertical-align:middle
   (deliberate — see the "action" column's empty Label in reflectionListView),
   the same as every other multi-button action cell in the mesh.
   */
#reflections-lv td[data-k="context"]{vertical-align:top}
