/* ============================================================================
   setup.css — what the two setup surfaces add to `system.css`, and nothing more.

   Both of them are the session-view: same three columns, same rails, same
   card-over-document gesture. What they add is one object session-view has no
   use for — **the constitution at the head of the document** — plus the small
   vocabulary its cards are written in (choices, sliders, distributions, faces).

   It exists as a third file for the reason `system.css` exists as a second one:
   document-creation and founding-ceremony are now the same screen seen by two
   people, and two copies of one design system drift.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   THE SETUP BAND — the constitution, at the top of the document.

   **A setting card opens in the document** (Ed, 2026-08-18: *instead of modals
   they open cards in the document at the top, above the text, pushing it down
   like decision-cards do a clause*). A modal was the wrong object twice over.
   It lifted the question off the document at exactly the moment the question is
   *about* the document, and it made these cards the only ones on the surface
   that do not behave like cards. A decision card replaces the clause it is
   about; a setting is about the whole document, so it opens where the whole
   document begins.

   **They are clause-tabs, and they pile like clause-tabs** (Ed, 2026-08-18,
   overruling the flat group of the morning). Two piles, one per holder — the
   founder's settings above, the members' below — standing in the
   `chip-gutter` exactly where each card's strip will be, so a pile expands into
   its strip without the tab you clicked moving. Everything the gutter already
   knows applies unchanged: the front tab is what most wants you, the slivers
   carry hue and no count, one stack is one target.

   Two piles say something a flat row of fourteen could not: **who decides**.
   And handing a setting to the room moves its tab from the top pile to the
   bottom one, so delegation stops being a radio you ticked and becomes a thing
   you can watch happen.

   That is also what the whole screen leaves behind: two grey piles at the head
   of the document, holding the constitution. It is where you go to ask what the
   bar is.
   --------------------------------------------------------------------------- */
  .setupband { margin: 0 auto var(--s5); }
  /* Each row is the card's own box, so the pile stands in the gutter column the
     strip will occupy. There is no clause here to give the row a height, so
     `fitBand` floors it against the pile beside it. */
  .setrow {
    position: relative; box-sizing: border-box;
    max-width: calc(var(--measure) + 2 * var(--measure-gutter));
    margin: 0 auto var(--s4); padding: 0 var(--measure-gutter);
  }
  .setrow .pilelab { display: flex; flex-direction: column; gap: 2px; padding-top: 3px; }
  /* **Founder and Membership are document headings** (Ed, 2026-08-18: *the
     same size as “Part I — The Club”*). They had been eyebrows, which is the
     label treatment for naming a region *inside* a card — and these are not
     inside anything: they are the first two headings of the document, above
     Part I, and a reader scanning the charter should meet them at the weight
     every other top-level heading has. So they take `.docline.lvl1`'s own type
     and stop being eyebrows, since an eyebrow that is 16px is not one. */
  .setrow .pilehead {
    font-size: var(--t-body); font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.08em; color: var(--fg);
  }

  .sr { position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; }
  .setupcard { margin-top: 0; }
  /* the card's title sits where a clause sits, at the head, with the strip
     beside it — so it is set as the head's own text and not as a heading
     floating above a body */
  /* the rtext is a container since Phase 4 (clauseHeadHtml renders the
     head): the title look lives on .headtitle, the rule look on .headrule,
     and a clause-thing (the membership list) inherits document type */
  .setupcard .clausehead .rtext { margin: 0; }
  .setupcard .clausehead .headtitle { font-size: var(--t-lead); font-weight: 600; }
  .setupcard h2 { font-size: var(--t-lead); font-weight: 600; margin: 0 0 var(--s2); }
  .setupcard .why { color: var(--muted); font-size: var(--t-small); margin: 0 0 var(--s4); max-width: 60ch; }
  .setupcard .setnote { font-size: var(--t-cap); color: var(--muted); margin-top: var(--s3); }
  .setupcard .body { border-top: 1px solid var(--border); padding-top: var(--s3); margin-top: var(--s3); }
  /* the hairline between the constitution and the document proper, and the
     title as the charter's own heading (Ed, 2026-08-19). Both stand from the
     save (backlog 33), and the title stands there alone: the big heading
     above the constitution is the pre-save one and leaves at the save. */
  .cpara.docsep { border-top: 1px solid var(--border); margin: var(--s5) 0 var(--s4); padding: 0; }
  .unlocks { font-size: var(--t-cap); color: var(--primary-emphasis); background: var(--primary-subtle);
    border-radius: var(--r-sm); padding: var(--s2) var(--s3); margin: 0 0 var(--s4); }
  .lockline { font-size: var(--t-cap); color: var(--muted); margin: 0 0 var(--s4);
    display: flex; align-items: center; gap: var(--s2); }

/* ---------------------------------------------------------------------------
   THE RAIL — one rail, the session's own margin index.

   Until the merge (stage 8, 2026-08-21) this block put the setup tasks back
   into normal flow under a sticky column, on the reasoning that a setting
   belongs to no clause. Since the merge every setup task is an entry in
   session.js's rail, anchored to its own band paragraph and laid out by
   layoutQueue like everything else — ask, news and yours pin, wait flows —
   so system.css's absolute .qitem applies here unchanged and nothing is
   overridden.
   --------------------------------------------------------------------------- */
  .queue .qhead { font-size: var(--t-cap); color: var(--muted); margin: var(--s3) 0 0; padding: 0 10px; }
  .queue .qhead:first-child { margin-top: 0; }
  .queue .setmark { margin-left: auto; display: inline-flex; align-items: center; }
  /* scoped (2026-08-18): a global .mkg fought system.css's em-based rule
     for every drawn mark on the page */
  .queue .mkg, .achip .mkg, .cline .mkg, .constsec .mkg, .setupcard .mkg {
    width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.9;
    stroke-linecap: round; stroke-linejoin: round; }
  /* the **subject** glyph. A live rail marks lifecycle state, because every card
     there is a different state of one kind of thing; a setup rail is the
     reverse — one state, many kinds — so it marks subject instead. The two sets
     never share a column. */
  .queue.stack .ql { display: flex; align-items: baseline; gap: var(--s1); }
  .queue.stack .ql .subj { font-size: 1.05em; line-height: 1; }
  .queue.stack .ql > .qt { flex: 1; min-width: 0; }
  .railnote { font-size: var(--t-cap); color: var(--muted); margin-top: var(--s2); padding: 0 10px; }
  /* wait/yours/done entries used to wear session-view's .deciding, whose
     meaning there is *you already judged it* (drift fix, 2026-08-18):
     same quiet one-line look, honest name */
  .queue button.qwait { padding: var(--s1) 10px; color: var(--muted); }
  .queue button.qwait .ql { display: block; white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis; font-weight: 500; font-size: var(--t-small); }
  .queue button.qwait .ql .qv { display: inline; margin: 0; font-weight: 400; }

/* ---------------------------------------------------------------------------
   THE CHOICE — **the session-view's own radio** (Ed, 2026-08-18: *the
   non-slider choices in the cards are just radio buttons, and the session-view
   already has those*).

   Three controls became one. document-creation had `.opt` and
   founding-ceremony had `.rung` — the same bordered box with two names and two
   paddings — and both were a hand-rolled radio standing a millimetre away from
   `.lanepick`, which is the radio this design system already has and the one
   every member will have used a hundred times by the end of a session. A
   setting is exactly the judgment a lane bar puts: *one of these, or none of
   them yet*.

   The bordered box goes with it, and that is a gain rather than a loss: **open
   is said by depth, not by outline**, and a rule drawn round each option was
   competing with the radio for the job of saying which one is chosen.

   `.above` is the ceremony's own addition: on a consent question the rungs
   *above* your answer are dimmed rather than hidden, since *the most I will
   accept* only reads as a ladder if you can see what you are refusing.
   --------------------------------------------------------------------------- */
  .choice { display: flex; flex-direction: column; gap: var(--s3); }
  /* **A second radio group stacked under the first is set apart** (Q761).
     `.choice` spaces its own rungs, and nothing spaced the *containers* — so
     the delegate rung sat flush against the values above it, 0px, and the two
     pills simply touched. Loudest where the value group holds one rung, since
     then the --s3 gap never paints anywhere on the card and there is no
     internal rhythm for the seam to be read against: ⏱️, 🌡️ and 👥's number.
     --s4 exceeds --s3, which is what makes the second group read as *apart
     from* the first rather than as another rung of it — the relationship
     quorum's own eyebrow had been asserting with an inline style. One number
     for one relationship, and the users are named in the selector, per
     `.eyebrow` in system.css. */
  .choice.delegrung,
  .choice + .eyebrow.fieldlab { margin-top: var(--s4); }
  .pick .exp { display: block; color: var(--muted); font-size: var(--t-small);
    margin-top: var(--s1); padding-left: 2px; max-width: 58ch; }
  .pick .inner { display: none; margin-top: var(--s3); padding-left: 2px; }
  .pick.on .inner { display: block; }
  .pick.above { opacity: 0.5; }
  .pick.off { opacity: 0.42; }
  .pick.off .lanepick { pointer-events: none; }
  /* A power option that cannot be taken yet dims **whole**, the way .pick.off
     does. Since the rule moved out of the button and became the block's own
     document text, dimming the control alone would leave a live-looking
     sentence standing over a dead radio — and the sentence is now the larger
     half of the option. */
  .setupcard .propblock.off { opacity: 0.42; }
  .setupcard .propblock.off .lanepick { pointer-events: none; }
  /* a row of fields *inside* a card — distinct from `.setrow`, which is the
     band row a pile stands in */
  .setrow2 { display: flex; gap: var(--s3); align-items: baseline; flex-wrap: wrap; }
  .fld { display: flex; flex-direction: column; gap: var(--s1); }
  .fld > label { font-size: var(--t-cap); color: var(--muted); }
  .sugg input, .sugg textarea { font: inherit; font-size: var(--t-ui); color: var(--fg); background: var(--bg);
    border: 1px solid var(--border); border-radius: var(--r-md); padding: var(--s2) var(--s3); }
  input:focus-visible, button:focus-visible, textarea:focus-visible,
  [role="radio"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
  .num { width: 5.5rem; }
  .numrow { display: inline-flex; gap: var(--s2); align-items: baseline; }

/* ---------------------------------------------------------------------------
   THE CONSENT SLIDER — nothing preselected, and it must not look answered.
   --------------------------------------------------------------------------- */
  .cs { margin-bottom: var(--s2); }

  /* **Thicker, and ticked** (Ed, 2026-08-18: *sliders should be thicker and
     have tick-marks (since they're discrete)*). A hairline track under a small
     thumb is the control an operating system gives you for a **continuous**
     quantity, and this one is not: there are fourteen answers to *how much of
     this room*, and ten to *how sure*. The ticks say so before you touch it —
     you can count the answers, and the thumb lands **on** one rather than
     being read off a ruler. Which matters more here than on an ordinary
     control, because what you are stating is a minimum you will be held to.

     Drawn by hand rather than left to `accent-color`, which only applies to a
     range in its default appearance — so the fill, the ticks and the thumb are
     three background layers and a pseudo-element. `--pct` and `--n` come in on
     the element, because only the card knows how many answers there are. The
     ticks are painted over the fill and inset by half a thumb at each end, so
     tick and thumb-centre coincide at every stop. */
  .cs input[type=range] {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 26px; background: transparent; cursor: pointer;
    --th: 22px; --trk: 12px; --fillcol: var(--primary);
  }
  .cs input[type=range]::-webkit-slider-runnable-track {
    height: var(--trk); border-radius: calc(var(--trk) / 2);
    background-color: var(--light);
    background-image:
      repeating-linear-gradient(90deg, rgba(0,0,0,0.22) 0 2px, transparent 2px calc(100% / var(--n))),
      linear-gradient(90deg, rgba(0,0,0,0.22) 0 2px, transparent 2px),
      linear-gradient(var(--fillcol) 0 0);
    background-repeat: no-repeat;
    background-size:
      calc(100% - var(--th)) 100%,
      calc(100% - var(--th)) 100%,
      calc(var(--th) / 2 + (100% - var(--th)) * var(--pct) / 100) 100%;
    background-position:
      calc(var(--th) / 2 - 1px) 0,
      calc(100% - var(--th) / 2 - 1px) 0,
      left center;
    box-shadow: inset 0 0 0 1px var(--border);
  }
  .cs input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: var(--th); height: var(--th); border-radius: 50%;
    background: var(--primary); border: 2px solid var(--bg);
    box-shadow: var(--shadow-md);
    margin-top: calc((var(--trk) - var(--th)) / 2);
  }
  .cs input[type=range]::-moz-range-track {
    height: var(--trk); border-radius: calc(var(--trk) / 2);
    background: var(--light); box-shadow: inset 0 0 0 1px var(--border);
  }
  .cs input[type=range]::-moz-range-thumb {
    width: var(--th); height: var(--th); border-radius: 50%; border: 2px solid var(--bg);
    background: var(--primary); box-shadow: var(--shadow-md);
  }
  /* Nothing chosen yet: the thumb has to sit somewhere, so it sits in the
     middle and says nothing — grey, and with no fill behind it, because a
     fill running up to it would be an answer the member has not given. */
  .cs.unset input[type=range] { --fillcol: transparent; }
  .cs.unset input[type=range]::-webkit-slider-thumb { background: var(--muted); }
  .cs.unset input[type=range]::-moz-range-thumb { background: var(--muted); }
  .csval { font-size: var(--t-lead); font-weight: 600; min-height: 1.6em; }
  .csval.unset { color: var(--muted); font-weight: 400; font-size: var(--t-ui); }
  .csends { display: flex; justify-content: space-between; font-size: var(--t-cap); color: var(--muted); }
  .csmean { font-size: var(--t-small); color: var(--muted); margin-top: var(--s2); min-height: 3em; }
  /* a gate card's list of what it is waiting for: the rail's own objects,
     small, so it reads as “these cards, then you can write” */
  .gatelist { display: flex; flex-direction: column; gap: var(--s1); margin: var(--s3) 0; }
  .gaterow { display: flex; align-items: center; gap: var(--s2);
    font-size: var(--t-ui); color: var(--muted); }
  .gaterow .gg { font-size: 1.05rem; }

  .blindnote { font-size: var(--t-cap); color: var(--muted); margin-top: var(--s3); }

/* ---------------------------------------------------------------------------
   THE ROSTER, and the distribution it produces.

   `distribution-strip` is the published shape of what people asked for, without
   names — and it is now what a **completed** room card carries (Ed, 2026-08-18:
   *when the roster's cards are complete they have the roster statistics on
   them*). Which is the right end state for a consent question: while it runs
   the card can say only how many have answered, because anything else would let
   the room read itself before it had finished; once it has closed there is
   nothing left to anchor, and the shape of the answers is the most interesting
   thing about the result.
   --------------------------------------------------------------------------- */
  .whobox { border: 1px solid var(--border); border-radius: var(--r-md); background: var(--light);
    padding: var(--s3); margin-bottom: var(--s4); }
  .whobox .lab { font-size: var(--t-small); color: var(--muted); margin-bottom: var(--s2); }
  .faces { display: flex; flex-wrap: wrap; gap: var(--s2); }
  .pf { display: flex; align-items: center; gap: var(--s1); font-size: var(--t-cap); }
  .pf.me { font-weight: 600; }
  .av { width: 22px; height: 22px; border-radius: 50%; background: var(--light); vertical-align: middle;
    border: 1px solid var(--border); color: var(--muted); font-size: 8px; font-weight: 700;
    display: inline-grid; place-items: center; flex: none; overflow: hidden; }
  .av.big { width: 44px; height: 44px; font-size: var(--t-cap); }
  /* **An emoji is a glyph, not a disc** (Q735, Ed 2026-08-23). It used to be
     an `.av` wearing a ground, at a size fought for by specificity —
     `span.av.emoji` is (0,2,1) and every contextual avatar rule is three
     classes, so each of them silently re-sized the emoji to a value chosen
     for two initial letters, 7px on the Founded line. The fix is not another
     round of that: an emoji has no box at all, so no rule that sizes a disc
     can reach it, and it takes the size of the text it stands in at every
     site at once. Two places want it large and say so. */
  .emojiface { display: inline-block; font-size: 1em; line-height: 1;
    vertical-align: middle; }
  .emojiface.big { font-size: 38px; }
  .avopt.taken { opacity: 0.3; cursor: not-allowed; }
  .freemoji { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s2); }
  .emojin { width: 120px; padding: 3px 8px; border: 1px solid var(--border); border-radius: var(--r-sm); font-size: 20px; line-height: 1.3; }
  .emojinote { display: none; font-size: var(--t-small); }
  .freemoji.bad .emojinote { display: inline; }
  /* invited, but they have not opened it yet */
  .av.pending { opacity: 0.45; border-style: dashed; }
  .av svg { width: 100%; height: 100%; display: block; }

  .dist { display: flex; align-items: flex-end; gap: 3px; height: 54px; margin: var(--s3) 0 var(--s1); }
  .dist span { flex: 1; background: rgba(var(--lc-yours), 0.30); border-radius: 2px 2px 0 0; min-height: 2px; }
  .dist span.top { background: var(--primary); }
  .distx { display: flex; justify-content: space-between; font-size: var(--t-cap); color: var(--muted); }
  .statline { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s4);
    padding: var(--s2) 0; border-top: 1px solid var(--border); }
  .statline:first-child { border-top: 0; }
  .statline .k { font-size: var(--t-small); color: var(--muted); }
  .statline .v { font-size: var(--t-body); font-weight: 600; }
  .pips { display: flex; gap: var(--s2); flex-wrap: wrap; margin: var(--s3) 0; }
  .pip { width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--border); background: var(--light); }
  .pip.in { background: var(--ok-subtle); border-color: var(--ok); }

  .roster { border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; }
  .rperson { display: grid; grid-template-columns: 30px 1fr auto auto; gap: var(--s3);
    align-items: center; padding: var(--s2) var(--s3); border-top: 1px solid var(--border); }
  .rperson:first-child { border-top: 0; }
  .rperson .nm { font-size: var(--t-ui); }
  .rperson .em { font-size: var(--t-cap); color: var(--muted); }
  .chip { font-size: var(--t-cap); border: 1px solid var(--border); border-radius: 999px;
    padding: 2px var(--s2); color: var(--muted); background: var(--bg); cursor: pointer; font-family: inherit; }
  .chip.founder { border-color: var(--primary); color: var(--primary-emphasis);
    background: var(--primary-subtle); cursor: default; }
  .chip.pending { border-style: dashed; }
  /* the person a motion would remove */
  .rperson.picked { background: color-mix(in srgb, rgb(var(--lc-open)) 22%, var(--bg));
    border-radius: var(--r-sm); }
  .rperson .xdrop:hover { color: var(--fg); }
  .xdrop { border: 0; background: none; color: var(--muted); cursor: pointer; padding: 0 var(--s1); }
  .addrow { display: flex; gap: var(--s2); padding: var(--s3); background: var(--light);
    border-top: 1px solid var(--border); }
  .addrow input { flex: 1; }

/* ---------------------------------------------------------------------------
   THE IDENTITY CARD — how you appear in this room (Ed, 2026-08-18).
   --------------------------------------------------------------------------- */
  /* the uploader: a drop box that is mostly the picture it will hold */
  .picdrop { display: flex; align-items: center; gap: var(--s4);
    border: 1px dashed var(--border); border-radius: var(--r-md);
    padding: var(--s4); margin-bottom: var(--s4); }
  .picdrop.over { border-color: var(--primary); background: var(--light); }
  .picact { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
  .picact .btn { font: inherit; font-size: var(--t-cap); padding: var(--s1) var(--s3);
    cursor: pointer; border: 1px solid var(--border); background: var(--bg);
    border-radius: var(--r-sm); }
  .picact .btn:hover { border-color: var(--primary); color: var(--primary-emphasis); }
  .picact input[type=file] { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); }
  .picnote { font-size: var(--t-cap); color: var(--muted); }
  /* the white-on-colour treatment was `.av.set`, worn by every stored format;
     with the grounds and marks gone (Q734) a photograph is the only thing
     left that fills its own disc, so the rule folds into it */
  .av.photo { background-size: cover; background-position: center;
    border-color: transparent; color: transparent; }
  /* what you are wearing now, under the two ways of changing it */
  .piccur { display: flex; align-items: center; gap: var(--s3);
    margin-top: var(--s4); font-size: var(--t-ui); }
  .piccur .piccurlab { color: var(--muted); }

  .avpick { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s2); }
  .avopt { border: 2px solid transparent; border-radius: 50%; padding: 2px; background: none;
    cursor: pointer; line-height: 0; }
  .avopt[aria-pressed="true"] { border-color: var(--primary); }
  /* the title's composer. The same `.lanebox` the `editing-card` writes in, at
     the size the title is actually read at, because the whole point of writing
     in the place is that you see what you are making. */
  .titlelane { font-size: var(--t-lead); font-weight: 600; }
  .titlelane:empty::before, .titlelane.blank::before {
    content: attr(data-ph); color: var(--muted); font-weight: 400; }

  .idrow { display: flex; align-items: center; gap: var(--s4); margin-bottom: var(--s4); }
  .idrow .fld { flex: 1; }
  .idrow input { width: 100%; }

  /* **The pile headings are the people** (Ed, 2026-08-18). A row of faces under
     each heading, arriving as the people do — the founder under Founder, the
     roster under Membership. It is what turns the band at the head of the
     document from a list of settings into the room itself, and it costs nothing
     because both piles were already named after a holder. */
  /* the constitution, stated: one line per constitutional setting, the glyph
     doing the naming the tabs already taught */
  .setrow .constlist { display: flex; flex-direction: column; gap: 1px;
    margin: 4px 0 3px; font-size: var(--t-cap); color: var(--muted); }
  .setrow .constlist .cline { display: flex; gap: 6px; align-items: baseline; }
  .setrow .constlist .cg { flex: none; width: 18px; text-align: center; }
  .setrow .constlist b { color: var(--fg); font-weight: 600; }

  /* the Applicants subsection under Membership */
  .setrow .applicants { display: flex; align-items: baseline; gap: var(--s2);
    margin: 3px 0 2px; font-size: var(--t-cap); color: var(--muted); }
  .setrow .applicants .pf { display: inline-flex; align-items: center; gap: 5px; }
  .setrow .applicants .av { width: 20px; height: 20px; font-size: 7px; }
  .setrow .applicants .appnote { color: var(--muted); margin-left: 4px; }

  .setrow .pilewho { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); margin: 3px 0 2px; }
  .setrow .pilewho .pf { font-size: var(--t-cap); }
  .setrow .pilewho .pf.ghost { color: var(--muted); font-style: italic; }
  .setrow .pilewho .av { width: 20px; height: 20px; font-size: 7px; }

  /* the row that holds the open card keeps the pile's id, so the contents rail
     still lands on it */
  /* **The tab you click must not move** — the pile occupies exactly the gutter
     column its strip will (Ed, 2026-08-18: *why do my constitutional
     clause-tabs-piles jump around when I click on them?*). It was claimed in
     the glossary and never true in the code: a closed pile inherited
     `.chipcol`'s 14px gutter margin, which is the right distance from a
     paragraph and the wrong one from a card edge, so every tab stepped 14px
     right on opening. 2px puts the pile's right edge exactly where the open
     strip's is, and the active tab still overhangs by 2 to carry under the
     card with no seam. The vertical half of the jump is fixed in `fitBand`,
     since it depends on how tall the card's own label runs. */

  .setrow.open { position: static; padding: 0; max-width: none; margin: 0; min-height: 0 !important; }

  /* **The document's title, at the top of the document** (Ed, 2026-08-18),
     above Founder. It had lived only in the sticky topbar, which is chrome —
     so the charter itself began with a pile of glyphs and no name on it, and
     the first thing any reader looks for was the one thing not in the column
     they were reading. It is text and not a control: the 🏷️ card is where a
     title is written, and a second way in would be a second answer to a
     question this surface has already settled. */
  /* type comes from system.css's own .doctitle rule (--t-lead, 600) — the
     literal 1.5rem was drift (2026-08-18); only the box is ours. It sits on
     the document's own left edge (Ed's QA, 2026-08-19: it was indented —
     the s5 side padding and auto-centring were the indent). */
  /* the headings only: the fixture charter's own div.doctitle (session.js)
     keeps system.css's box, as it did on its own page */
  /* `--measure` rather than a second `70ch`: read at `--t-lead` the literal
     resolved to a wider column than the prose's and so never bound at all
     (Ed, 2026-08-25) — the row it sits in was the only thing holding it. */
  .doc h1.doctitle, .doc h2.doctitle { max-width: var(--measure); margin: 0 0 var(--s5);
    padding: 0; text-wrap: balance; }
  .doc h1.doctitle.ph { color: var(--muted); font-weight: 400; min-height: 1.15em; }

/* ===========================================================================
   NOT THE DESIGN SYSTEM. The mail modal stands for the reader's inbox: it
   previews another medium, so it is Arial, plain white, an email client's
   idea of a page — no tokens on purpose (Ed, 2026-08-18).
   ======================================================================== */
#mailmodal { position: fixed; inset: 0; z-index: 90; background: rgba(20,20,24,0.4);
  display: flex; align-items: center; justify-content: center; }
.mailwin { background: #fff; width: min(560px, 92vw); border-radius: 6px;
  font-family: Arial, Helvetica, sans-serif; color: #202124;
  box-shadow: 0 14px 44px rgba(0,0,0,0.35); overflow: hidden; }
.mw-head { display: flex; gap: 12px; align-items: baseline; padding: 12px 16px;
  background: #f2f2f2; font-size: 12px; color: #5f6368; }
.mw-head span:first-child { font-weight: bold; color: #202124; }
.mw-head button { margin-left: auto; border: 0; background: none; cursor: pointer;
  color: #5f6368; font-size: 14px; }
.mw-subj { padding: 14px 20px 0; font-size: 17px; font-weight: bold; }
.mw-body { padding: 10px 20px 24px; font-size: 14px; line-height: 1.5; }
.mw-act { display: inline-block; margin-top: 10px; padding: 10px 18px;
  background: #1a73e8; color: #fff; border-radius: 4px; cursor: pointer;
  font-weight: bold; text-decoration: none; }

/* ---------------------------------------------------------------------------
   Lifecycle marks (Ed, 2026-08-18: the session-view's own grammar). The
   subject glyph is the mark only while the question is asking; after that the
   state speaks — ⏳ waiting, drawn ✔ decided (green while it is news, grey
   once filed), ✏️ yours. One set of rules for tabs and rail entries, so the
   two columns cannot disagree about what a state looks like.
   ------------------------------------------------------------------------ */
.achip .mkg { width: 15px; height: 15px; stroke-width: 2.2; }
.achip.st-done, .achip.st-wait { color: rgb(var(--lc-closed)); }
.achip.st-news { color: var(--ok); }
.queue .subj .mkg { width: 13px; height: 13px; stroke-width: 2.1; }
.queue button.st-done .subj, .queue button.st-wait .subj { color: rgb(var(--lc-closed)); }
.queue button.st-news .subj { color: var(--ok); }
/* the constitution block's lines are the way to a settled card now that its
   tab says only ✔ — a button, but drawn as the line it always was */
button.cline { border: 0; background: none; padding: 0; text-align: left;
  cursor: pointer; font: inherit; color: inherit; }
button.cline:hover b { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   assembly-press (Ed, 2026-08-18). A constitutional motion goes in by a full
   ten-second hold, and the progress meter is the room: the members' avatars
   convene one by one into a circle around the 🏛️ button — the assembly is
   complete exactly when the motion is put. Release early and it disperses.
   ------------------------------------------------------------------------ */
#assembly { position: fixed; z-index: 120; width: 0; height: 0; pointer-events: none; }
#assembly .seat { position: absolute; opacity: 0;
  transform: translate(-50%, -50%) scale(0.3);
  transition: opacity 220ms ease, transform 320ms cubic-bezier(0.2, 1.45, 0.45, 1); }
#assembly .seat.in { opacity: 1; transform: translate(-50%, -50%) scale(1); }
#assembly .seat .av { width: 30px; height: 30px; font-size: 11px; box-shadow: var(--shadow-md); }
/* a seat is a token floating over the page with no text around it to take a
   size from, so an emoji face states one here, as it does in the navbar —
   *sized like the text around them* has nothing to mean in a ring */
#assembly .seat .emojiface { font-size: 26px; line-height: 30px; }
#assembly.done .seat { transform: translate(-50%, -50%) scale(1.14); }
#assembly.gone .seat { opacity: 0 !important;
  transform: translate(-50%, -50%) scale(0.3) !important; transition-duration: 160ms; }
.holdmotion { touch-action: none; user-select: none; }
@media (prefers-reduced-motion: reduce) {
  #assembly .seat { transition: opacity 120ms ease; transform: translate(-50%, -50%); }
  #assembly .seat.in, #assembly.done .seat { transform: translate(-50%, -50%); }
}

/* ---------------------------------------------------------------------------
   The constitution as document text (Ed, 2026-08-18): one paragraph per
   decision, its tab in the gutter to its left — the same geometry as a
   clause-tab beside a clause — and the open card replacing its own
   paragraph. A tabless paragraph (.notab) states a rule whose tab lives
   elsewhere (the ceremony's room questions are the membership's tasks).
   ------------------------------------------------------------------------ */
.constsec .cpara { position: relative; min-height: 32px; margin: 0 0 var(--s2); }
.constsec .cpara .chipcol { top: 0; }
.constsec .cptext { margin: 0; padding-top: 3px; }
.constsec .cptext b { font-weight: 600; }
.constsec .cpara.notab { min-height: 0; }
.constsec .cpara.notab .cptext { padding-top: 0; }
/* same margins as a closed paragraph — the measured shift does the rest */
.constsec .cpara.open { margin: 0 0 var(--s3); }
.constsec .pilelab { margin-bottom: var(--s3); }

/* the constitution's sections (Ed, 2026-08-18): a subtitle at the document's
   own second level, a line of prose saying what the section governs, then
   the decision paragraphs — the members' tasks standing among them. */
.constsec .csec { margin: var(--s4) 0 var(--s5); }
/* section headings are the document's own (docline lvl2/lvl3); the intro
   and state lines are plain document paragraphs */
.constsec .csintro { margin: 0 0 var(--s3); }
.constsec .csec .pilewho { margin: 0 0 var(--s3); }

/* each decision: its own heading, the decision in prose underneath (Ed,
   2026-08-18) — the tab keeps the gutter, the heading carries the name, and
   the state line says where the decision stands in whole sentences. */
.constsec .cptext { padding-top: 2px; }
.constsec .cph { margin: 0; font-size: inherit; font-weight: 600; }
.constsec .cpv { margin: 1px 0 0; }
.constsec .cpara { margin: 0 0 var(--s3); }

/* the title heading is the way into the title card */
.doctitle[data-card] { cursor: pointer; }
.doctitle[data-card]:hover { text-decoration: underline dotted 1.5px; text-underline-offset: 4px; }

/* Members / Applications subsections (Ed, 2026-08-18): Members IS the list,
   🪪 the invitations tab beside it, your own row first wearing ✋ 🖼️ 📧;
   Applicants is the list under the Applications decision.
   **The clearance is the list's, not the row's** (Q757). The Members block is
   one paragraph carrying two tab columns in one gutter — 🪪 (with ✉️ ❌ 🎩) at
   the paragraph's head, and your ✋🖼️📧 riding your own row, which is the
   first list row since you moved to the top (Ed, 2026-08-21: *membership tab
   and your name tab overlap*). At 12px they collided by 18px, and `fitStacks`
   cannot help: it shrinks a *pile's* peek and bails under two tabs, and a lone
   tab is 30px and cannot shrink (Q308's stated residual). So the whole list is
   dropped clear of the head pile — 42px is the tallest that pile gets (38px
   stacked) plus the gutter's own 4px. It hangs here rather than on the you-row
   because the placeholder now stands above you (Q753) and a margin on the row
   would double-count with it. **Padding, not margin**: the list is the first
   in-flow child of a `.cpara` with no top border or padding, so a top *margin*
   collapses straight out to the paragraph and carries the 🪪 pile down with
   it — the head tab is `position: absolute` against `.cpara` — leaving the gap
   exactly as it was. Measured: with a margin the clearance reads −3px.
   It is the **you-row** that needs clearing, so the padding hangs on lists
   that have one: a clerk founder has no row here (Q758) and a stranger reads
   a list with no identity tabs at all, and neither has a second tab column
   to clear — unscoped, both opened with 42px of nothing. */
.constsec .cpara .memlist:has(.memrow.meRow) { padding-top: 42px; }
.memlist { display: flex; flex-wrap: wrap; gap: 5px 18px; }
/* **The list's own subheadings** (Q868, Q869): Invitees, then Applicants —
   groups of people who are not members yet, under a Members heading that is
   about people who are. They take the eyebrow treatment from `.eyebrow` and
   nothing but layout here: a full-width break in a wrapping row of faces, with
   a little more air above than the 5px row gap, so a heading reads as belonging
   to what is under it rather than to what is over it. */
/* "you" — the one sanctioned per-reader difference (Ed): in the members list
   you are at the top, on your own line, your identity pile in the gutter
   beside you; the min-height is the 30px front tab of that pile */
.memrow.meRow { flex-basis: 100%; min-height: 30px; }
/* only avatars and names keep the compact dress (Ed) */
.memrow { display: flex; align-items: center; gap: 8px; font-size: var(--t-small);
  position: relative; }
.memrow .av { width: 22px; height: 22px; font-size: 8px; flex: none; }
/* the identity tabs are regular gutter clause tabs: a pile at your row */
.memrow .chipcol { top: -3px; }
/* nobody else yet (407a): a full-width muted row where the members would
   stand — list furniture, not a clause, so it speaks quietly. It stands
   **above** your row (Q753), where it is a statement about the list rather
   than a caption on you; the clearance job it used to do as well is the
   list's own padding now. */
.memrow.nobody { flex-basis: 100%; color: var(--muted); min-height: 22px; }
.memrow .chip { font-size: var(--t-micro); }

/* **The card overhangs the text axis** (Ed's QA, 2026-08-18: the tabs were
   touching the text, and fixing that must not bring back the tab-jump). A
   paragraph's tab keeps the document's own 14px gutter gap; when the card
   opens, its box extends 14px further left while its text stays on the
   document axis — session-view's own model — so the strip lands where the
   closed tab stood and the active tab still carries under the card edge. */
.constsec .cpara.open > .setupcard { margin-left: -14px; }

/* the starting-text task anchors the prose itself (Ed, 2026-08-18): a
   row at the band's end carrying the document's own name, its 📄 tab beside
   it. **The tab lines up with the title** (Ed, 2026-08-21), and the offset
   is a measurement rather than a taste: a tab is 30px and the title's line
   box is 30px, so flush tops centre one on the other. It had been `top:10px`,
   from when this row was empty and the tab hung beside the first block of
   prose below it — the title moved in and the constant stayed. Everywhere
   else the gutter's own -3px does the same job against a 24px line.
   **The pile is empty from the save until 📄's turn** (backlog 33), and the
   title must sit at the same x either way — which it does for free, the
   `.chipcol` being `position: absolute` out in the gutter, so nothing about
   the title's box depends on whether a tab is standing beside it. */
.cpara.textanchor { min-height: 0; margin: 0; }
.cpara.textanchor .dochead { margin: 0 0 var(--s3); padding-left: 0; }
.cpara.textanchor .chipcol { top: 0; }   /* see the note above: 30px tab, 30px title line */

/* the composer's rationale wears your avatar (Ed, 2026-08-18) — the same
   speaker slot the editing card gives a rationale, with you as the speaker */
.composeWhy { display: flex; gap: 10px; align-items: flex-start; margin-top: var(--s3); }
.composeWhy .av { width: 26px; height: 26px; font-size: 9px; flex: none; margin-top: 8px; }
.composeWhy .lanebox { flex: 1; }

/* the rule at a composer's head sits exactly on the text axis it stood on
   (card padding minus the 14px overhang) — the strip is anchored to the
   headclause and must not move with it, so the compensation is on the text */
.constsec .cpara.open .setupcard .clausehead .rtext { margin-left: calc(14px - var(--s5)); }

/* headings fold (Ed, 2026-08-19): hidden prose blocks, and the overlay rail
   that carries the prose triangles — outside the contenteditable region, so
   the ▸ never becomes text the harvest reads */
.prose > .pfolded { display: none; }
#prosefolds { position: relative; height: 0; overflow: visible; }
#prosefolds > span { position: absolute; left: -26px; }
#prosefolds .sectoggle[aria-expanded="true"] { opacity: 0; }
#prosefolds .sectoggle:hover, #prosefolds .sectoggle:focus-visible { opacity: 1; }

/* Founded by [avatar] [name] (at [time]) — the avatar rides in the line.
   `justify-content` because the override to `inline-flex` silently dropped
   half of the base rule's `place-items: center` (the justify half means
   nothing in flex), so the initials fell to `flex-start` inside a 20px disc
   with `overflow: hidden` and were shoved against its edge (Q732). */
.cpv.founded .av { width: 20px; height: 20px; font-size: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  margin: 0 2px; position: relative; top: -2px; }

/* a rule standing as a card's head is the clause, not a title: document size
   and colour, exactly as it stood on the page (Ed's QA, 2026-08-18) */
.setupcard .clausehead .headrule { font-size: 1rem; font-weight: 400; line-height: 1.55; }

/* the head-rule correction is a margin, and a block parent lets a child's
   top margin collapse straight through it — fitBand's pass measured,
   corrected, and changed nothing (found 2026-08-18, exposed by the Phase-4
   zero-move probe; the pass was written in the .setrow flex era, where child
   margins cannot collapse). flow-root makes the open paragraph a formatting
   root so the margin lands — without overflow:hidden's clipping of the
   14px tab overhang. */
.constsec .cpara.open { display: flow-root; }

/* the rail is a scroll container, and its entries sat flush against its
   edges — every cast shadow was clipped mid-air (Ed, 2026-08-18: *sidebar
   cards shadows seem to be broken*). Padding gives the shadows room; the
   negative margin keeps the column where it stood. */
.queue.stack { padding: 4px 14px 28px; margin: 0 -14px; }

/* the title card's head is the document title itself (Ed, 2026-08-18:
   *show me the current state of the title*), at the title's own type;
   muted while it is still the placeholder */
/* at the birth the title card's head IS the big heading; post-save it opens
   at its own clause and the title sits inside the sentence at document size
   (Ed, 2026-08-19) */
#titlepara .setupcard .clausehead .headrule .headdoct { font-size: var(--t-lead); }
.setupcard .clausehead .headrule .headdoct { font-weight: 600; }
.setupcard .clausehead .headrule .headdoct.ph { color: var(--muted); font-weight: 400; }

/* links in the constitution are real links (Ed, 2026-08-19): ink-coloured,
   underlined, the underline waking on hover */
.cpv a.doclink, .headrule a.doclink { color: inherit; text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 2.5px;
  text-decoration-color: var(--muted); }
.cpv a.doclink:hover, .headrule a.doclink:hover {
  text-decoration-color: currentColor; text-decoration-thickness: 1.5px; }

/* clicking a heading's text folds it (Ed, 2026-08-19) — the constitution's
   headings are not editable, so they may say so with the cursor; prose
   headings keep the text cursor, since they are still editable */
.constsec h2.docline[id^="cs-"], .constsec .pilehead { cursor: pointer; }
.constsec .pilehead { position: relative; }
.constsec .pilehead .sectoggle { position: absolute; right: 100%;
  margin-right: var(--s3); top: 4px; }
.constsec .pilelab:hover .sectoggle[aria-expanded="true"] { opacity: 1; }

/* **An emoji needs a quiet ground** (Ed, 2026-08-19: *icon button
   backgrounds shouldn't be very saturated; there's at least one ✒️ on a dark
   blue*). An emoji glyph is a coloured object in its own right, so a solid
   fill under it fights the glyph for the same pixels and muddies both — where
   the drawn ✔ is one stroke in currentColor and stays the one solid green
   thing on a card. Which also splits the two commits by hue rather than by
   accident: ✒️, a set of your own, wears the accent this surface already
   uses for your own work; ✓, an answer to a shared question, keeps the green
   that means decided. :not([disabled]) so system.css's greyed-out rule, at
   the same specificity, still wins where it should. */
/* the ground itself now lives in system.css as `.btn.glyphbtn.emojibtn`, so
   the charter’s ✏️ Propose wears it too (2026-08-22). */

/* the emoji picker (Ed, 2026-08-19): a normal picker rather than a row of
   faces, so it scrolls inside itself instead of pushing the card's own
   controls off the screen. Reserved and taken options are the .taken state
   the face row already had. */
.emojibox { max-height: 15rem; overflow-y: auto; padding-right: var(--s2);
  border: 1px solid var(--border); border-radius: var(--r-md);
  padding: var(--s2) var(--s3) var(--s3); }
.emojibox .emojilab { margin-top: var(--s3); }
.emojibox .emojilab:first-child { margin-top: 0; }
/* the search field and the category tabs (Q732). The tabs are chips rather
   than a second radio: nothing is being *chosen* by opening a category, so
   the `lanepick` would say the wrong thing about them. */
.emojisearch { margin-top: var(--s2); }
.emojisearch input { width: 100%; padding: var(--s2) var(--s3);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  font: inherit; font-size: var(--t-ui); }
.emojisearch input:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.emojitabs { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2);
  margin: var(--s2) 0; }
.emojitab { font: inherit; font-size: var(--t-cap); padding: 2px var(--s2);
  border: 1px solid var(--border); border-radius: 999px; background: var(--bg);
  color: var(--muted); cursor: pointer; }
.emojitab:hover { border-color: var(--primary); color: var(--primary-emphasis); }
.emojitab[aria-pressed="true"] { border-color: var(--primary);
  background: var(--primary-subtle); color: var(--primary-emphasis); }
/* the anonymous person: a disc with somebody in it, before there is a name
   to make initials of */
.av .anonav { width: 62%; height: 62%; color: #fff; opacity: 0.9; }
.av.anon { background: var(--light); }
.av.anon .anonav { color: var(--muted); }

/* **One left edge** (Ed's QA, 2026-08-19: on the 📍 card *tab and title and
   text are misaligned*). The head's text was pulled back onto the document's
   own axis while the body kept the card's own padding, so every card had its
   clause ten pixels left of its field — visible on 📍 because that card is
   nearly all field. The card's padding is now the document overhang itself,
   and the head needs no compensation to sit where a paragraph sits. */
.constsec .cpara.open > .setupcard > *:not(.clausehead):not(.chipcol) {
  margin-left: calc(14px - var(--s5)); }

/* **An emoji is an emoji wherever it sits** (Ed, 2026-08-19: *the ✒️ button
   in the initial titling is correct for emoji buttons, the rest are too
   colourful*). The quiet ground was scoped to glyph-only buttons, which left
   🏛️ and ✏️ Propose — labelled buttons carrying a glyph — on the full
   accent. Same treatment, whatever else is in the label. */
.btn.btn-approve.emojibtn:not([disabled]) {
  background: var(--primary-subtle); border-color: var(--primary);
  color: var(--primary-emphasis); font-weight: 600;
}
/* **A disabled commit is flat, and there is one flat** (Ed, 2026-08-21,
   asking for the card buttons to be consistent). Three grounds had grown on
   the same row: 🗑️ stayed white (it is not an approve, so no rule reached
   it), ✒️ went grey (the approve+glyph rule), and a labelled approve —
   🏛️ Hold to ask everyone, ✏️ Propose, ✒️ Begin — kept the **full accent**,
   because nothing had ever written a disabled rule for a commit with words
   on it. A dead button wearing a live button's colour is the worst of the
   three. This is the whole commit row, whatever the control: grey ground,
   grey border, muted ink, no lift. The pressed-and-disabled states that mean
   something (a submitted ✏️, a cast ✓) carry more classes and still win. */
.commitrow .btn[disabled], .race-mid .btn[disabled] {
  background: var(--light); border-color: var(--border); color: var(--muted);
  opacity: 1; box-shadow: none;
}
.btn.btn-approve.emojibtn:not([disabled]):hover {
  background: var(--light); border-color: var(--primary-hover);
}

/* ---- 🍾 and 🥂, and the closed page (Q443, Q468, Q470 — 2026-08-21) ----- */
  .setupcard .batch { margin: 0 0 var(--s3); padding-left: 18px; font-size: var(--t-small); color: var(--ink); }
  .setupcard .batch li { margin: 2px 0; }
  .setupcard .readiness .fieldlab { margin-top: var(--s3); }
  .setupcard .readiness .gaterow .rsub { color: var(--muted); font-weight: 400; }
  .setupcard .setnote.hold { color: var(--ink); }
  .setupcard .sigs .disc.small { width: 14px; height: 14px; margin-right: 6px; vertical-align: -2px; }
  .setupcard .edit-why[data-signwhy]:empty::before { content: attr(data-placeholder); color: var(--muted); pointer-events: none; }
  /* **The founder speaks in their own name** (Q530, Ed 2026-08-22). Every
     other rationale wears the featureless disc because authorship is sealed
     (§3.4); a ✒️ act is attributed by construction, so the avatar goes where
     the disc would be and the name and 👑 stand over the reason. The 👑 is
     what carries it when there is no name and no picture: an anonymous
     founder is ordinary, and the mark still says whose hand this was. */
  .founderspoke .spksaid { min-width: 0; }
  .founderspoke .who {
    display: block; font-weight: 600; font-size: var(--t-cap);
    color: var(--muted); margin-bottom: 2px;
  }
  .founderspoke .said { align-self: start; }
  /* the lane the founder writes it in: an editing surface, so it takes the
     editing card own placeholder treatment rather than sitting in the flow */
  .founderspoke .said.edit-why { outline: none; }
  .whyset .fieldlab { margin-bottom: var(--s2); }
  .changed .cpv { margin: 0 0 var(--s2); }
  /* the two-line form for a long value: the label is a fixed column so the
     two values line up and the eye can find what moved */
  .waswas { display: flex; gap: var(--s2); margin: 0 0 2px; font-size: var(--t-small); }
  .waswas span { flex: none; width: 2.4rem; color: var(--muted);
    font-size: var(--t-cap); text-transform: uppercase; letter-spacing: 0.06em;
    line-height: 1.6; }
  /* the speaker's revealed form: the disc stays, the name stands beside it */
  .speaker.revealed .who { font-weight: 600; font-size: var(--t-small); margin-right: 6px; }
  /* the closed page: every clause grey, every tab filed; nothing is asked */
  .doc.closedpage .prose, .doc.closedpage .cpv, .doc.closedpage .cptext { color: var(--muted); }
  .doc.closedpage .prose .anch { color: var(--muted); }
