/* Council Dark, in the surface. Nothing here reaches an external origin.

THE PALETTE AND THE TYPE ARE NOT OPEN. They are lifted from the 2026-08-11
mockup and from brands/council/brand-style.md, and they are already in the PDFs
ONO has been sent. Motion, state and layout are open; #f97316 is not.

TWO SHAPES, AND THEY ARE DIFFERENT ON PURPOSE.

  .doc      the index, the settings page, the operator's status page. A
            document: one column, centred, scrolls.
  .council  one request, once it is finished. An application: three panes,
            exactly one screen tall, each pane scrolling inside itself.

The second exists because of a measurement. A mockup card holds about 700
characters and a real lane writes about 3,183, four and a half times more.
Eight of those on one screen is unreadable in any arrangement; one of them in a
dedicated pane is comfortable. So the finished view shows one specialist at a
time, chosen by the reader, and the comparison grid lives behind a button.

NO SCRIPT. The tabs are radio inputs and labels, the grid is a checkbox. This
file is the whole interaction model until the streaming deliverable adds one.
*/

:root {
  --bg: #131316;
  --panel: #1c1c21;
  --panel-2: #18181c;
  --raised: #28282f;
  --border: #2d2d35;
  --border-2: #3f3f4a;
  --ink: #e5e7eb;
  --ink-dim: #9ca3af;
  --ink-faint: #6b7280;
  --accent: #f97316;
  --font-display: 'Secular One', 'Heebo', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Heebo', ui-sans-serif, system-ui, -apple-system, sans-serif;
  color-scheme: dark;
}

html, body { height: 100%; margin: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 400;
  font-synthesis: none;
  line-height: 1.65;
  direction: rtl;
  text-align: right;
}
h1, h2, h3, h4, h5, .display {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: 0;
  color: #fff;
}
strong { font-weight: 600; color: #fff; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
hr { border: 0; border-top: 1px solid var(--border); margin: 1.2rem 0; }

/* The ambient glow and the grain. Cheap, already written, and most of the
   difference between "designed" and "styled". */
body::before {
  content: "";
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(60rem 40rem at 75% -10%, rgba(249,115,22,.07), transparent 70%);
}
body > * { position: relative; z-index: 1; }

/* Chrome ------------------------------------------------------------------ */

.topbar {
  display: flex; align-items: center; gap: 1rem;
  padding: .7rem 1.2rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.topbar .mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: .55rem;
  background: rgba(249,115,22,.10); border: 1px solid rgba(249,115,22,.22);
  font-size: 1rem;
}
.topbar h1 { font-size: 1.05rem; margin: 0; font-weight: 600; }
.topbar nav { margin-inline-start: auto; display: flex; gap: 1rem; font-size: .85rem; }
.topbar nav a { color: var(--ink-dim); }

.banner {
  background: rgba(249,115,22,.08);
  border-bottom: 1px solid rgba(249,115,22,.20);
  color: #fcd9b6; padding: .55rem 1.2rem; font-size: .82rem;
}

.doc { max-width: 52rem; margin: 0 auto; padding: 1.6rem 1.2rem 4rem; }
.doc h1 { font-size: 1.6rem; margin: .2rem 0 1rem; }
.doc h2 { font-size: 1.05rem; margin: 2rem 0 .6rem; }

.meta { color: var(--ink-faint); font-size: .85rem; }
.hint { color: var(--ink-dim); font-size: .8rem; }
.he { direction: rtl; text-align: right; unicode-bidi: isolate; }
.ltr { direction: ltr; text-align: left; unicode-bidi: isolate;
       font-variant-numeric: tabular-nums; }

.note {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: .6rem; padding: .8rem 1rem; margin: 1rem 0; font-size: .9rem;
}
.note.bad  { background: rgba(239,68,68,.10); border-color: rgba(239,68,68,.35); color: #fecaca; }
.note.good { background: rgba(34,197,94,.10); border-color: rgba(34,197,94,.30); color: #bbf7d0; }
.note.warn { background: rgba(250,204,21,.09); border-color: rgba(250,204,21,.28); color: #fde68a; }

.estimate {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: .6rem; padding: .9rem 1.1rem; margin: 1.2rem 0;
}
.estimate pre {
  margin: .4rem 0 0; font-size: .78rem; white-space: pre-wrap;
  color: var(--ink-faint); direction: ltr; text-align: left;
}

table { border-collapse: collapse; font-size: .9rem; }
th, td { border: 1px solid var(--border); padding: .35rem .8rem; }
th { color: var(--ink-dim); font-weight: 500; }

/* Forms ------------------------------------------------------------------- */

form.ask { margin-top: 1.6rem; }
form.ask h2 { margin-top: 0; }
textarea, input[type=text], select {
  font: inherit; color: var(--ink);
  background: var(--raised); border: 1px solid var(--border-2);
  border-radius: .6rem; padding: .6rem .8rem;
}
textarea { width: 100%; min-height: 7rem; direction: rtl; text-align: right;
           resize: vertical; }
textarea:focus, input:focus, select:focus { outline: none; border-color: var(--accent); }
button {
  font: inherit; font-weight: 600; color: #fff;
  background: var(--accent); border: 0; border-radius: .6rem;
  padding: .55rem 1.2rem; margin-top: .7rem; cursor: pointer;
}
button:hover { background: #ea6a0c; }
button.secondary {
  background: transparent; color: var(--ink);
  border: 1px solid var(--border-2);
}
button.secondary:hover { background: var(--raised); }
fieldset { border: 1px solid var(--border); border-radius: .6rem;
           padding: .6rem .9rem; margin: .9rem 0; }
legend { font-size: .85rem; color: var(--ink-dim); padding: 0 .3rem; }
.choice { display: flex; gap: .5rem; align-items: baseline; padding: .3rem 0; }
.consent-state { font-size: .85rem; color: var(--ink-dim); }

form.delete { border-top: 1px solid var(--border); padding-top: 1rem;
              margin-top: 1.6rem; font-size: .9rem; color: var(--ink-dim); }
form.delete button { background: transparent; color: #fca5a5;
                     border: 1px solid rgba(239,68,68,.45); }
form.delete button:hover { background: rgba(239,68,68,.12); }
form.delete label {
  /* FLEX SO THE BOX COMES FIRST. As inline content the checkbox drifted to the
     far end of a right aligned line, which reads as a box belonging to the
     next thing rather than to this sentence. */
  display: flex; gap: .5rem; align-items: center; justify-content: flex-start;
  margin-top: .7rem; color: var(--ink);
}
details.request-details > summary {
  cursor: pointer; padding: .7rem 1.1rem; color: var(--ink-dim);
  border-top: 1px solid var(--border); font-size: .85rem;
}
details.request-details > summary:hover { color: #fff; }
details.request-details[open] > summary { color: #fff; }
details.request-details > div, details.request-details form { padding: 0 1.1rem; }
details.request-details form.delete { margin: 0 1.1rem 1.2rem; }

/* The index's list of deliberations ---------------------------------------- */

ul.queue { list-style: none; padding: 0; margin: .4rem 0 0; }
ul.queue li {
  border: 1px solid var(--border); border-radius: .6rem;
  background: var(--panel); margin-bottom: .5rem;
}
ul.queue li a { display: block; padding: .7rem .9rem; color: var(--ink); }
ul.queue li a:hover { background: var(--raised); text-decoration: none; }
ul.queue .q { display: block; font-size: .95rem; }
ul.queue .sub { display: block; color: var(--ink-faint); font-size: .75rem;
                margin-top: .2rem; }

/* The council view --------------------------------------------------------- */

body.app { height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
body.app .council { flex: 1; min-height: 0; }

.council {
  display: grid;
  grid-template-columns: 320px minmax(420px, 1fr) 460px;
  gap: 1rem; padding: 1rem;
}
.council > input { position: absolute; opacity: 0; pointer-events: none; }
.pane-box {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: .75rem; overflow: hidden;
  display: flex; flex-direction: column; min-height: 0;
}
.pane-box > header {
  flex: none; padding: .9rem 1.1rem; border-bottom: 1px solid var(--border);
}
.pane-box > header h2 { font-size: 1rem; margin: 0; font-weight: 600; }
.scroller { flex: 1; overflow-y: auto; min-height: 0; }
.scroller::-webkit-scrollbar { width: 6px; }
.scroller::-webkit-scrollbar-track { background: transparent; }
.scroller::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 20px; }

/* the ring */
.pane-box.centre { overflow-y: auto; }
.ring-wrap {
  /* A FLOOR, NOT A SHARE. `flex: 1; min-height: 0` let the ring be squeezed to
     nothing when the request details were opened underneath it, and the seats
     drew over the control below them. The circle has a size it stops being a
     circle below; anything that does not fit scrolls the pane. */
  position: relative; flex: 1 0 auto;
  /* Diameter plus a seat, because a seat is centred ON the circle and its name
     hangs below it. At 26rem the critic at the bottom of the ring drew over
     the control underneath the pane. */
  min-height: 32rem;
}
.ring {
  /* THE RADIUS IS A LENGTH, NOT A PERCENTAGE. A percentage inside translate()
     resolves against the element being moved, which is the seat, so the first
     version of this collapsed all ten seats into a heap in the middle of the
     circle. Named because it is the kind of bug a still would have caught and
     a stylesheet read would not. */
  --r: clamp(7rem, 22vh, 13rem);
  position: absolute; inset: 0;
}
.ring::before, .ring::after { pointer-events: none; }
.ring::before {
  content: ""; position: absolute;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: calc(var(--r) * 2); height: calc(var(--r) * 2); border-radius: 50%;
  border: 1px solid var(--border-2);
}
.ring::after {
  content: ""; position: absolute;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: calc(var(--r) * 2.6); height: calc(var(--r) * 2.6); border-radius: 50%;
  background: radial-gradient(circle, rgba(249,115,22,.07), transparent 62%);
}
.seat {
  position: absolute;
  left: calc(50% + var(--x) * var(--r));
  top: calc(50% + var(--y) * var(--r));
  transform: translate(-50%, -50%);
  width: 6.4rem; text-align: center; cursor: pointer;
}
.seat .disc {
  width: 3rem; height: 3rem; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; font-size: 1.25rem;
  background: var(--panel-2); border: 2px solid var(--seat);
  transition: box-shadow .25s ease, transform .25s ease;
}
.seat .name {
  display: block; margin-top: .35rem; font-size: .68rem; line-height: 1.25;
  color: var(--ink-dim);
}
.seat:hover .disc { transform: scale(1.06); }
.ring .crown { --seat: var(--accent); }

/* the reading pane */
/* ROW, AND SAID OUT LOUD. `.pane-box` above is `flex-direction: column`
   and this rule inherited it, which stacked the tab strip on top of the
   text and left the answer about 230px tall at the bottom of the column.
   Daniel, 2026-09-06, on the first real look at this screen: "way too
   short". The strip is a sidebar; say so here rather than rely on a
   default that the parent has already changed. */
.reader { display: flex; flex-direction: row; min-height: 0; }
.tabstrip {
  flex: none; width: 3.4rem; border-inline-start: 1px solid var(--border);
  background: var(--panel-2); overflow-y: auto;
}
.tabstrip label {
  display: flex; align-items: center; justify-content: center;
  height: 3.1rem; font-size: 1.1rem; cursor: pointer;
  border-inline-end: 2px solid transparent;
}
.tabstrip label:hover { background: var(--raised); }
.panes { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.pane { display: none; flex: 1; min-height: 0; flex-direction: column; }
.pane > .body { flex: 1; overflow-y: auto; padding: 1.1rem 1.2rem 2rem; }
.pane .who {
  flex: none; display: flex; align-items: center; gap: .6rem;
  padding: .8rem 1.2rem; border-bottom: 1px solid var(--border);
}
.pane .who .badge {
  width: 2rem; height: 2rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 2px solid var(--seat);
}
.pane .who h3 { margin: 0; font-size: .98rem; }
.pane .who .role { color: var(--ink-faint); font-size: .74rem; }

/* what a lane wrote */
.answer p { margin: 0 0 .85rem; }
.answer p.label { color: #fff; font-weight: 600; margin-top: 1.3rem; }
.answer h3, .answer h4, .answer h5, .answer h6 {
  font-size: .98rem; margin: 1.5rem 0 .5rem;
  padding-inline-start: .6rem; border-inline-start: 3px solid var(--seat);
}
.answer ul { margin: 0 0 .9rem; padding-inline-start: 1.2rem; }
.answer li { margin-bottom: .35rem; }
.answer strong { color: #fff; }

/* the synthesis is the destination, not one of nine */
.pane.synthesis .who { background: rgba(249,115,22,.07); }
.pane.synthesis .body { font-size: 1.02rem; }
.pane.synthesis .answer p.label { color: var(--accent); }

/* the grid, behind a button, for after the deliberation */
.gridtoggle { display: block; text-align: center; padding: .5rem;
              border-top: 1px solid var(--border); color: var(--ink-dim);
              font-size: .8rem; cursor: pointer; background: var(--panel-2); }
.gridtoggle:hover { color: #fff; }
.grid { display: none; }
#showgrid:checked ~ .grid {
  /* OPAQUE, NOT NEARLY OPAQUE. At .97 the page underneath still read through
     at the foot of the overlay, which on a projector looks like a rendering
     fault rather than a translucent panel. */
  display: grid; position: fixed; inset: 0; z-index: 40;
  background: var(--bg);
  grid-template-columns: repeat(3, 1fr); gap: .8rem;
  padding: 3.6rem 1rem 1rem; overflow-y: auto;
}
#showgrid:checked ~ .grid .cell {
  background: var(--panel); border: 1px solid var(--border);
  border-top: 3px solid var(--seat); border-radius: .6rem;
  padding: .8rem .9rem; overflow: hidden; max-height: 15rem;
  font-size: .78rem; line-height: 1.5; position: relative;
}
.grid .cell h3 { font-size: .85rem; margin: 0 0 .4rem; }
.grid .cell .fade {
  position: absolute; inset-block-end: 0; inset-inline: 0; height: 3rem;
  background: linear-gradient(to top, var(--panel), transparent);
}
.grid .close {
  position: fixed; inset-block-start: .9rem; inset-inline-start: 1.2rem;
  z-index: 41; color: var(--ink); cursor: pointer; font-size: .85rem;
  background: var(--raised); border: 1px solid var(--border-2);
  border-radius: .5rem; padding: .35rem .9rem;
}
.grid .close:hover { border-color: var(--accent); }

/* Selection. Ten seats, written out rather than generated, because a rule a
   person can read is worth more here than a loop. */
#seat-1:checked  ~ .reader .panes > .pane:nth-child(1),
#seat-2:checked  ~ .reader .panes > .pane:nth-child(2),
#seat-3:checked  ~ .reader .panes > .pane:nth-child(3),
#seat-4:checked  ~ .reader .panes > .pane:nth-child(4),
#seat-5:checked  ~ .reader .panes > .pane:nth-child(5),
#seat-6:checked  ~ .reader .panes > .pane:nth-child(6),
#seat-7:checked  ~ .reader .panes > .pane:nth-child(7),
#seat-8:checked  ~ .reader .panes > .pane:nth-child(8),
#seat-9:checked  ~ .reader .panes > .pane:nth-child(9),
#seat-10:checked ~ .reader .panes > .pane:nth-child(10),
#seat-11:checked ~ .reader .panes > .pane:nth-child(11) { display: flex; }

#seat-1:checked  ~ .centre .ring .seat:nth-of-type(1) .disc,
#seat-2:checked  ~ .centre .ring .seat:nth-of-type(2) .disc,
#seat-3:checked  ~ .centre .ring .seat:nth-of-type(3) .disc,
#seat-4:checked  ~ .centre .ring .seat:nth-of-type(4) .disc,
#seat-5:checked  ~ .centre .ring .seat:nth-of-type(5) .disc,
#seat-6:checked  ~ .centre .ring .seat:nth-of-type(6) .disc,
#seat-7:checked  ~ .centre .ring .seat:nth-of-type(7) .disc,
#seat-8:checked  ~ .centre .ring .seat:nth-of-type(8) .disc,
#seat-9:checked  ~ .centre .ring .seat:nth-of-type(9) .disc,
#seat-10:checked ~ .centre .ring .seat:nth-of-type(10) .disc,
#seat-11:checked ~ .centre .ring .seat:nth-of-type(11) .disc {
  box-shadow: 0 0 0 4px rgba(249,115,22,.14), 0 0 26px -4px var(--seat);
  transform: scale(1.1);
}
#seat-1:checked  ~ .centre .ring .seat:nth-of-type(1) .name,
#seat-2:checked  ~ .centre .ring .seat:nth-of-type(2) .name,
#seat-3:checked  ~ .centre .ring .seat:nth-of-type(3) .name,
#seat-4:checked  ~ .centre .ring .seat:nth-of-type(4) .name,
#seat-5:checked  ~ .centre .ring .seat:nth-of-type(5) .name,
#seat-6:checked  ~ .centre .ring .seat:nth-of-type(6) .name,
#seat-7:checked  ~ .centre .ring .seat:nth-of-type(7) .name,
#seat-8:checked  ~ .centre .ring .seat:nth-of-type(8) .name,
#seat-9:checked  ~ .centre .ring .seat:nth-of-type(9) .name,
#seat-10:checked ~ .centre .ring .seat:nth-of-type(10) .name,
#seat-11:checked ~ .centre .ring .seat:nth-of-type(11) .name { color: #fff; }

#seat-1:checked  ~ .reader .tabstrip label:nth-of-type(1),
#seat-2:checked  ~ .reader .tabstrip label:nth-of-type(2),
#seat-3:checked  ~ .reader .tabstrip label:nth-of-type(3),
#seat-4:checked  ~ .reader .tabstrip label:nth-of-type(4),
#seat-5:checked  ~ .reader .tabstrip label:nth-of-type(5),
#seat-6:checked  ~ .reader .tabstrip label:nth-of-type(6),
#seat-7:checked  ~ .reader .tabstrip label:nth-of-type(7),
#seat-8:checked  ~ .reader .tabstrip label:nth-of-type(8),
#seat-9:checked  ~ .reader .tabstrip label:nth-of-type(9),
#seat-10:checked ~ .reader .tabstrip label:nth-of-type(10),
#seat-11:checked ~ .reader .tabstrip label:nth-of-type(11) {
  background: var(--raised); border-inline-end-color: var(--accent);
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ---------------------------------------------------------------------------
   THE LIVE DELIBERATION. D3.

   The same screen as the finished one, filled in as the answers land. Every
   rule below is either a state a seat can be in or an animation that runs once
   when something arrives; there is no rule here that makes the wait look busier
   than it is.
   --------------------------------------------------------------------------- */

/* An empty seat is drawn as an empty seat. Dashed and dimmed rather than
   hidden, because the argument for the four and a half minutes is that the room
   can see who has not spoken yet. */
.seat[data-status="waiting"] .disc { opacity: .4; }
.seat[data-status="waiting"] .name { color: var(--ink-faint); }
.seat[data-status="landed"] .disc { opacity: 1; }
.seat[data-status="speaking"] .disc {
  opacity: 1;
  box-shadow: 0 0 0 3px rgba(249,115,22,.16), 0 0 20px var(--seat);
}
.seat .said {
  display: block; margin-top: .18rem;
  font-size: .6rem; letter-spacing: .02em; color: var(--ink-faint);
}
.seat[data-status="speaking"] .said { color: var(--accent); }
.seat[data-status="landed"] .said { color: #86efac; }

.tabstrip label[data-status="waiting"] { opacity: .38; }
.tabstrip label[data-status="speaking"] { box-shadow: inset 0 0 0 1px var(--seat); }

.pane .who .said {
  margin-inline-start: auto; font-size: .7rem; color: var(--ink-faint);
  align-self: center;
}
.pane[data-status="speaking"] .who .said { color: var(--accent); }
.pane[data-status="landed"] .who .said { color: #86efac; }
.pane[data-status="landed"] .awaiting { display: none; }
.awaiting { margin-top: .9rem; }

.progress {
  flex: none; margin: 0; padding: .75rem 1.1rem;
  border-top: 1px solid var(--border);
  color: var(--ink-dim); font-size: .88rem;
}

/* THE LOADING STATE, AND IT IS HONEST. The panel convening, drawn as the seats
   themselves breathing in the order they sit in. It counts toward nothing,
   because there is no number to count toward: first text is about nine seconds
   warm and about twenty-eight cold, and a bar pretending to know which would be
   a lie told to a room. Removed by the first chunk that arrives. */
.ring.convening .seat .disc {
  animation: convene 2.6s ease-in-out infinite;
  /* TWO SECONDS APART, NOT A FIFTH. At .17s the ten seats read as one
     object pulsing; the point is a seat lighting one after another so
     the wait carries a sense of progress until the first text lands.
     Asked for by Daniel, 2026-09-06. */
  animation-delay: calc(var(--i) * 2s);
}
@keyframes convene {
  0%, 100% { opacity: .3; }
  50%      { opacity: .85; box-shadow: 0 0 16px var(--seat); }
}

/* CHUNKS REVEAL BY OPACITY, ONCE. The animation is on the span the stream
   appends, so a run of text fades in exactly when it lands and never again:
   there is no rule here that can re-animate text already on the screen. */
.chunk { animation: council-fade .42s ease both; }
.arrive { animation: council-fade .45s ease both; }
@keyframes council-fade { from { opacity: 0; } to { opacity: 1; } }

/* Asked for by nobody in the room and owed to anyone in it who needs it. */
@media (prefers-reduced-motion: reduce) {
  .chunk, .arrive, .ring.convening .seat .disc { animation: none; }
  .seat[data-status="waiting"] .disc { opacity: .4; }
}

/* The stream has two halves: paragraphs that are finished and rendered, and the
   one still arriving, which stays as text until its blank line lands. */
.answer .stable { display: block; }
.answer .stable .block { display: block; }
.answer .tail { display: block; }
.answer .tail .chunk { display: inline; }

/* D4. The box that is touched first. */
.ask .field {
  display: block; margin: 1.2rem 0 .4rem;
  font-size: .82rem; color: var(--ink-dim);
}
.ask textarea::placeholder { color: var(--ink-faint); opacity: 1; }

/* The PDF export, on a finished request's page (queuelib/export.py) -------- */

form.export { display: flex; flex-wrap: wrap; align-items: center;
              gap: .4rem .9rem; margin-top: .6rem;
              font-size: .8rem; color: var(--ink-dim); }
form.export label { display: flex; gap: .45rem; align-items: center; }
form.export button { margin-top: 0; padding: .4rem 1rem; }
